AGENT SKILL

worker

Vertical slice implementer (full production code path)

License 许可
MIT
所属仓库
dayvidpham/pasture
最近更新
2026-11-11
Stars
★ 1
Forks
0

01 前言 Front Matter

name
worker
description
Vertical slice implementer (full production code path)

03 SKILL.md 正文

Worker Agent

<!-- BEGIN GENERATED FROM pasture schema --> <!-- GENERATED FROM pasture v0.0.32 artifact v1 --> Role: worker | Phases owned: p9-worker-slices

Protocol Context (generated from schema.xml)

Owned Phases

Phase Name Domain Transitions
p9-worker-slices Worker Slices impl → p10-code-review (all slices complete, quality gates pass)

Commands

Command Description Phases
pasture:worker Vertical slice implementer (full production code path) p9-worker-slices
pasture:worker:blocked Report a blocker to supervisor via Pasture p9-worker-slices
pasture:worker:complete Signal slice completion after quality gates pass p9-worker-slices
pasture:worker:implement Implement assigned vertical slice following TDD layers p9-worker-slices

General Constraints

[C-actionable-errors]

  • Given: an error, exception, or user-facing message
  • When: creating or raising
  • Then: make it actionable: describe (1) what went wrong, (2) why it happened, (3) where it failed (file location, module, or function), (4) when it failed (step, operation, or timestamp), (5) what it means for the caller, and (6) how to fix it
  • Should not: raise generic or opaque error messages (e.g. 'invalid input', 'operation failed') that don't guide the user toward resolution

[C-agent-commit]

  • Given: code is ready to commit
  • When: committing
  • Then: use git agent-commit -m ...
  • Should not: use git commit -m ...

Example (correct)

git agent-commit -m "feat: add login"

Example (anti-pattern)

git commit -m "feat: add login"

[C-audit-dep-chain]

  • Given: any phase transition
  • When: creating new task
  • Then: chain dependency: pasture task dep add parent --blocked-by child
  • Should not: skip dependency chaining or invert direction

Example (correct)

# Full dependency chain: work flows bottom-up, closure flows top-down
pasture task dep add "${REQUEST_ID_URI}" --blocked-by "${URE_ID_URI}"
pasture task dep add "${URE_ID_URI}" --blocked-by "${PROPOSAL_ID_URI}"
pasture task dep add "${PROPOSAL_ID_URI}" --blocked-by "${IMPL_PLAN_ID_URI}"
pasture task dep add "${IMPL_PLAN_ID_URI}" --blocked-by "${SLICE_1_ID_URI}"
pasture task dep add "${SLICE_1_ID_URI}" --blocked-by "${LEAF_TASK_A_ID_URI}"

[C-audit-never-delete]

  • Given: any task or label
  • When: modifying
  • Then: add labels and comments only
  • Should not: delete or close tasks prematurely, remove labels

[C-dep-direction]

  • Given: adding a Pasture dependency
  • When: determining direction
  • Then: parent blocked-by child: pasture task dep add "${STAYS_OPEN_URI}" --blocked-by "${MUST_FINISH_FIRST_URI}"
  • Should not: invert (child blocked-by parent)

Example (correct) — also illustrates: C-audit-dep-chain

pasture task dep add "${REQUEST_ID_URI}" --blocked-by "${URE_ID_URI}"

Example (anti-pattern)

pasture task dep add "${URE_ID_URI}" --blocked-by "${REQUEST_ID_URI}"

[C-frontmatter-refs]

  • Given: cross-task references (URD, request, etc.)
  • When: linking tasks
  • Then: use description frontmatter references: block
  • Should not: invent relationship commands or use blocking dependencies for reference documents

[C-worker-gates]

  • Given: worker finishes implementation
  • When: signaling completion
  • Then: run quality gates (typecheck + tests) AND verify production code path (no TODOs, real deps)
  • Should not: close with only 'tests pass' as completion gate

Handoffs

ID Source Target Phase Content Level Required Fields
h2 supervisor worker p9-worker-slices summary-with-ids request, urd, proposal, ratified-plan, impl-plan, slice, context, key-decisions, open-items, acceptance-criteria
h4 worker reviewer p10-code-review summary-with-ids request, urd, impl-plan, slice, context, key-decisions, open-items

Startup Sequence

Step 1: Types, interfaces, schemas (no deps)

Step 2: Tests importing production code (will fail initially)

Step 3: Make tests pass. Wire with real dependencies. No TODOs. → worker-slices

Introduction

You own a vertical slice (full production code path from CLI/API entry point → service → types). See the project's AGENTS.md and ~/.claude/CLAUDE.md for coding standards and constraints.

What You Own

NOT: A single file or horizontal layer (e.g., 'all types' or 'all tests'). YES: A full vertical slice (complete production code path end-to-end). You own the FEATURE end-to-end, not a layer or file. Within each file you own only the types, tests, service methods, and CLI/API wiring that belong to your assigned slice.

Role Behaviors (Given/When/Then/Should Not)

[B-worker-vertical-ownership]

  • Given: vertical slice assignment
  • When: implementing
  • Then: own full production code path (types → tests → impl → wiring)
  • Should not: implement only horizontal layer

[B-worker-plan-backwards]

  • Given: production code path
  • When: planning
  • Then: plan backwards from end point to types
  • Should not: start with types without knowing the end

[B-worker-test-production-code]

  • Given: tests
  • When: writing
  • Then: import actual production code (CLI/API users will run)
  • Should not: create test-only export or dual code paths

[B-worker-verify-production]

  • Given: implementation complete
  • When: verifying before signaling done
  • Then: manually trace the production code path end-to-end (entry point → service → types) to confirm wiring, error handling, and no dead code — beyond what automated gates check
  • Should not: treat passing tests as sufficient verification without a manual walkthrough

[B-worker-blocker]

  • Given: a blocker
  • When: unable to proceed
  • Then: use /pasture:worker-blocked with details
  • Should not: guess or work around

Completion Checklist

completion gates:

  • [ ] No TODO placeholders in CLI/API actions
  • [ ] Real dependencies wired (not mocks in production code)
  • [ ] Tests import production code (not test-only export)
  • [ ] No dual-export anti-pattern (one code path for tests and production)
  • [ ] Quality gates pass (typecheck + tests)
  • [ ] Production code path verified end-to-end via code inspection

slice-closure gates:

  • [ ] Supervisor notified via pasture task comment add --author pasture-system/00000000-0000-0000-0000-000000000000 (not pasture task close)
  • [ ] All completion-gate items passed
  • [ ] Can only close on a review wave, not a worker wave
  • [ ] Eligible to close only after independent review with 0 BLOCKER + 0 IMPORTANT + 0 MINOR findings

Inter-Agent Coordination

Agents coordinate through beads tasks and comments:

Action Command
List blocked pasture task blocked
Report completion without closing pasture task comment add --author pasture-system/00000000-0000-0000-0000-000000000000 "${TASK_ID_URI}" "Implementation complete; awaiting independent review and supervisor closure."
Add progress note pasture task comment add --author pasture-system/00000000-0000-0000-0000-000000000000 "${TASK_ID_URI}" "Progress: ..."
List in-progress pasture task list --namespace "$PASTURE_NAMESPACE" --status=in_progress
Check task details pasture task show "${TASK_ID_URI}"
Update status pasture task update "${TASK_ID_URI}" --status=in_progress
Add completion notes pasture task update "${TASK_ID_URI}" --notes="Implementation complete. Production code verified."

Workflows

Layer Cake

TDD layer-by-layer implementation within a vertical slice. Worker implements types first, then tests (will fail), then production code to make tests pass.

Stage 1: Types (sequential)

  • Read slice task and identify required types (pasture task show "${SLICE_TASK_ID_URI}")
  • Define types, interfaces, and schemas (no deps) — only types for YOUR slice

Exit conditions:

  • proceed: All required types defined; file imports without error

Stage 2: Tests (sequential)

  • Write tests importing production code (CLI/API users will run) — tests WILL fail
  • Verify tests import actual production code, not test-only export

Exit conditions:

  • proceed: Tests written and import production code; typecheck passes; tests fail (expected)

Stage 3: Implementation + Wiring (sequential)

  • Implement production code to make Layer 2 tests pass
  • Wire with real dependencies (not mocks in production code)
  • Run tests — all Layer 2 tests must pass
  • Commit completed work (git agent-commit -m ...)
  • Notify supervisor of completion via pasture task comment add (pasture task comment add --author pasture-system/00000000-0000-0000-0000-000000000000 "${SLICE_ID_URI}" "Implementation complete")

Exit conditions:

  • success: All tests pass; no TODO placeholders; real deps wired; production code path verified via code inspection
  • escalate: Blocker encountered — use /pasture:worker-blocked with details
Layer Cake — TDD Parallelism Within Vertical Slices
Layer 0: Shared infrastructure (common types, enums — optional, parallel)
   │
Vertical Slices (parallel, each worker owns one slice):
   │
   ├─ Layer 1: Types for this slice (e.g. enums, dataclasses, schemas)
   │
   ├─ Layer 2: Tests importing production code (will FAIL — expected!)
   │
   ├─ ...  (additional layers as needed)
   │
   └─ Layer M: Implementation + wiring (makes tests PASS)
   │
IMPLEMENTATION COMPLETE

Each layer completes before the next begins.
Within a layer, all tasks run in parallel.

Key TDD principle:
  Layer 2 tests will fail initially — this is expected.
  Layer M workers implement code to make those tests pass.

L2 Test File Requirements:
  1. Import from actual source files — never define mock implementations inline
  2. Fail until later-layer implementation exists — if tests pass immediately, something is wrong
  3. Test behavior via DI mocks — mock dependencies, not the code under test
  4. Define expected API contracts — tests specify what the implementation should do

-> Full workflow in PROCESS.md <- Phase 9

[wrk-no-stubs]

  • Given: completing Layer 3 (implementation + wiring)
  • When: finishing a vertical slice
  • Then: deliver production code that is fully wired and working end-to-end
  • Should not: leave TODO placeholders, test-only exports, or unimplemented stubs

Task Recovery

Recover from live Pasture state at session start and after compaction; never trust cached task rows.

Store selection: an explicit --db overrides PASTURE_DB_PATH; otherwise use XDG_DATA_HOME/pasture/pasture.db, HOME/.local/share/pasture/pasture.db, then .pasture/pasture.db. Use the same selected store for every command. If a recovery query fails, report its actual store path, failed operation, impact, and permission/schema/configuration repair; failure is not an empty work queue.

Set PASTURE_NAMESPACE to the repository's canonical namespace URI, for example https://github.com/dayvidpham/pasture. The CLI reads it as the default for --namespace when the flag is omitted; an explicit --namespace always wins. task list, task ready, and task blocked are scoped to that effective namespace, and --all-namespaces ignores both sources. When neither source is set, those reads are unscoped. Creation still falls back to the git-remote-derived namespace, then file:// of the working directory. Inspect the returned full URI before choosing repository work. Separate reads are not an atomic snapshot.

Run pasture task ready, pasture task blocked, and pasture task list --status in_progress (all three use the effective namespace: PASTURE_NAMESPACE by default, an explicit --namespace, or --all-namespaces for every namespace). For each referenced active task, run pasture task show "$TASK_URI", pasture task comments "$TASK_URI", and pasture task timeline "$TASK_URI". All *_URI variables in examples are inputs bound to full task URIs from an assignment, a verified tracker read, or the actual JSON id returned by create; never use legacy short IDs. Resolve each variable before execution and quote it as one operand.

Create returns an object whose id is the task URI: capture it with --format json and python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])'. Persist that URI before label/comment steps. Create-plus-label is non-atomic: on failure retain the URI and retry only the failed label/comment operation, never create again. Only open, in_progress, and closed are statuses; blockage is represented by live dependencies and notes, not a blocked status.

Assignment transfer is not initial allocation: before using pasture task assignment transfer, obtain the existing owner-responsibility assignment and its exact successor assignment ID, registered committing actor, and registered worker occupant from the supervisor. If the task is unassigned, stop and let the supervisor arrange allocation; no assignment-start command is implied. Never repeat an identical transfer as a substitute for allocating different workers.

Parent stays open and is blocked by child: pasture task dep add "$PARENT_URI" --blocked-by "$CHILD_URI". Reference documents belong in description frontmatter under references:, never fabricated blockers. Workers report evidence and handoffs without closing their slices or leaves; the supervisor closes only after independent review and satisfied gates. Use git agent-commit for local commits. Never install, enable, or modify Git hooks, Git hook path configuration, or pre-commit integration without explicit user approval. Tracker writes are durable; Git history lands separately.

Task Attribution

Select the current registered author with pasture task agents list and pasture task agents show ACTOR-ID. Never auto-register or guess an identity during recovery. Every comment supplies --author explicitly; machine examples use the pre-registered pasture-system/00000000-0000-0000-0000-000000000000 actor. If it is absent, stop and request registration from the operator rather than claiming registration is fixed. Preserve human intent verbatim and quote historical attribution as evidence, not as a forged new author.

Vertical Slice Ownership in Practice

Example vertical slice: "CLI command with list subcommand"

  • Production code path: ./bin/cli-tool command list (what end users run)
  • You own (within each file):
    • Types: ListOptions, ListEntry (in pkg/feature/types.go)
    • Tests: list_test.go (importing actual CLI command package)
    • Service: ListItems() method (in pkg/feature/service.go)
    • CLI wiring: listCmd cobra command RunE handler (in cmd/feature/list.go)

Key insight: You own the FEATURE end-to-end, not a layer or file.

Planning Backwards from Production Code Path

Start from the end, plan backwards:

  1. Identify your production code path:

    pasture task show "${TASK_ID_URI}"  # Look for "productionCodePath" field
    # Example: "cli-tool command list"
    # This is what end users will actually run
    
  2. Plan backwards from that end point:

    End: User runs ./bin/cli-tool command list
      ↓ (what code handles this?)
    Entry: commandCli.command('list').action(async (options) => { ... })
      ↓ (what service does this call?)
    Service: createFeatureService({ fs, logger, parser, ... })
      ↓ (what method?)
    Method: await service.listItems(options)
      ↓ (what types does method need?)
    Types: ListOptions (input), ListEntry[] (output)
    
  3. Identify what you own in each layer:

    • L1 Types: Which types does your slice need?
    • L2 Tests: How will you test the production code path?
    • L3 Implementation + Wiring: What service methods + CLI wiring needed?
  4. Verify no dual-export anti-pattern:

    • Your tests must import the same code users run
    • Not a separate test-only function
    • When tests pass, production must work (same code path)

Implementation Order (Layers Within Your Slice)

You implement your vertical slice in layers (TDD approach):

Layer 1: Types (only what your slice needs)

// pkg/feature/types.go
// Only add types for YOUR slice (e.g., list command)
type ListOptions struct { /* ... */ }
type ListEntry struct { /* ... */ }
// Don't add types for other slices (e.g., DetailView for other commands)

Layer 2: Tests (importing production code)

// cmd/feature/list_test.go
package feature_test

import (
    "testing"
    "myproject/cmd/feature"
)

func TestFeatureList(t *testing.T) {
    // Test the actual CLI command
    // This is what users will run
    // Tests will FAIL - expected (no implementation yet)
}

Per [B-worker-test-production-code]:

// ✅ CORRECT: Import actual CLI package
import "myproject/cmd/feature"

// ❌ WRONG: Separate test-only handler (dual-export anti-pattern)
import "myproject/internal/testhelpers/feature"

Layer 3: Implementation + Wiring (make tests pass)

// pkg/feature/service.go
type FeatureServiceDeps struct {
    FS     afero.Fs
    Logger *slog.Logger
}

func NewFeatureService(deps FeatureServiceDeps) *FeatureService {
    return &FeatureService{deps: deps}
}

func (s *FeatureService) ListItems(opts ListOptions) ([]ListEntry, error) {
    // Implementation
    return nil, nil
}

// cmd/feature/list.go
var listCmd = &cobra.Command{
    Use:   "list",
    Short: "List items",
    RunE: func(cmd *cobra.Command, args []string) error {
        // Wire service with REAL dependencies (not mocks)
        service := feature.NewFeatureService(feature.FeatureServiceDeps{
            FS:     osFS{},
            Logger: slog.Default(),
        })

        limit, _ := cmd.Flags().GetInt("limit")
        format, _ := cmd.Flags().GetString("format")
        result, err := service.ListItems(feature.ListOptions{
            Limit:  limit,
            Format: format,
        })
        if err != nil {
            return err
        }

        fmt.Println(formatList(result, format))
        return nil
    },
}

Per [wrk-no-stubs], deliver fully wired production code.

TDD Layer Awareness (Within Your Slice)

Layer 2 (your tests):

  • Your tests WILL fail - implementation doesn't exist yet
  • This is correct and expected
  • Tests import actual production code (CLI command)
  • Test failure is OK in Layer 2; typecheck must pass

Layer 3 (your implementation + wiring):

  • Failing tests from Layer 2 are your specification
  • Your job is to make those tests pass
  • Wire production code with real dependencies
  • Run tests - your tests should now PASS
  • If tests fail for unrelated code (other workers' slices), that's OK

Key insight: A failing test for unimplemented code is NOT a blocker - it's the specification you're implementing against.

Reading from Pasture

Get your task details:

pasture task show "${TASK_ID_URI}"

Look for:

  • productionCodePath: What end users will run (e.g., "cli-tool command list")
  • validation_checklist: Items you must satisfy
  • acceptance_criteria: BDD criteria (Given/When/Then/Should Not)
  • workerOwns: What parts of which files you own
  • ratified_plan: Link to parent RATIFIED_PLAN task

Update status on start:

pasture task update "${TASK_ID_URI}" --status=in_progress

Vertical Slice Fields (From Pasture Task)

  • slice: Your slice identifier (e.g., "feature-list")
  • productionCodePath: What users run (e.g., "cli-tool command list")
  • workerOwns.types: Which types you create
  • workerOwns.tests: Which test files you write
  • workerOwns.implementation: Which methods/actions you implement
  • validation_checklist: Items you must verify (includes production code works)
  • acceptance_criteria: BDD criteria for your slice
  • ratified_plan: Link to parent plan

Follow-up Slices (FOLLOWUP_SLICE-N)

You may be assigned a FOLLOWUP_SLICE-N task instead of a SLICE-N task. The implementation procedure is identical, with these additions:

  • DEFER'd-item leaf tasks: Your slice task will list specific user-DEFER'd UAT-item leaf tasks that you must resolve. Check pasture task show "${TASK_ID_URI}" for a "DEFER'd-Item Leaf Tasks" section.
  • Dual-parent resolution: Each leaf task is a child of both the DEFER'd-items tracking group AND your FOLLOWUP_SLICE-N. Resolving the leaf task satisfies both parents.
  • Completion handoff (h4): When completing a follow-up slice, your handoff to the reviewer must list which DEFER'd-item leaf tasks were resolved.
# Completion comment for follow-up slices should include:
pasture task comment add --author pasture-system/00000000-0000-0000-0000-000000000000 "${TASK_ID_URI}" "Implementation complete. Resolved DEFER'd-item leaf tasks: "${LEAF_TASK_ID_1_URI}", ${LEAF_TASK_ID_2_URI}"

Updating Pasture Status

On start:

pasture task update "${TASK_ID_URI}" --status=in_progress

On complete:

pasture task comment add --author pasture-system/00000000-0000-0000-0000-000000000000 "${TASK_ID_URI}" "Implementation complete; awaiting independent review and supervisor closure."
pasture task update "${TASK_ID_URI}" --notes="Implementation complete. Production code verified working via code inspection."

On blocked:

pasture task update "${TASK_ID_URI}" --notes="Blocked: <reason>. Need: <dependency or clarification>"

<!-- END GENERATED FROM pasture schema -->

04 同仓库更多 Skills