Documentation
¶
Overview ¶
Package codegen — agent definition generation.
This file ports gen_agents.py to Go. It generates agents/{role}.md files from schema data for roles that have tools defined. Output files are fully generated (no marker-based partial replacement) and overwritten on each run.
GenerateOptions is declared in skills.go and shared with GenerateSkill. ownedPhaseDetails, buildPhaseSlug, buildFuncMap, and unifiedDiff are declared in skills.go and reused here.
Package codegen generates protocol documentation from canonical Go type definitions.
This package ports the Python codegen tooling (gen_skills.py, gen_schema.py, gen_agents.py, context_injection.py) to Go, using text/template for Markdown generation and encoding/xml for schema.xml.
Generated outputs:
- schema.xml: Protocol schema definition
- skills/{role}/SKILL.md: Role-level skill headers (marker-bounded)
- agents/{role}.md: Agent definition files (fully generated)
Package codegen — context injection for role- and phase-specific constraint prompting.
This file ports context_injection.py to Go. It provides static constraint mappings (role → constraint IDs, phase → constraint IDs) and builder functions that construct RoleContext and PhaseContext values for use by downstream codegen generators (schema.xml, SKILL.md, agent definitions).
Key types:
- RoleContext — populated by GetRoleContext(role)
- PhaseContext — populated by GetPhaseContext(phase)
Static maps:
- generalConstraints — applies to ALL roles and ALL phases
- roleConstraints — hand-authored: RoleId → set of constraint IDs
- phaseConstraints — hand-authored: PhaseId → set of constraint IDs
Package codegen — shared embed FS for all Go text/template files.
This file declares the single embed.FS that all generator functions in this package share (agents.go, skills.go, etc.). Keeping the embed directive here avoids duplicate //go:embed declarations across multiple files.
Package codegen — global-ID uniqueness enforcement (SLICE-2, URD R5+R7).
ValidateGlobalIds checks that every ID-bearing spec in the codegen registries is globally unique across ALL namespaces:
- SkillBodySpecs inline section / behavior IDs (skip FragRef-only markers)
- SharedFragmentSpecs fragment IDs
- agent IDs (RoleSpecs map keys, e.g. "supervisor", "worker")
- role-behavior IDs (RoleSpec.Behaviors[*].Id, e.g. "B-arch-elicit")
- handoff IDs (HandoffSpecs map keys, e.g. "h1" … "h6")
- command IDs (CommandSpecs map keys, e.g. "cmd-worker")
It also verifies structural validity of SharedFragmentSpecs entries:
- every FragRef placement marker in SkillBodySpecs resolves
- every fragment has exactly one payload (Prose XOR Behavior)
Parity check (AMENDMENT-2): set(AllFragmentIds) must equal set(keys(SharedFragmentSpecs)), catching both orphan directions (a declared constant with no spec, or a spec with no constant).
Call site: tools/codegen/main.go — wired after the generators so that go generate hard-fails on the first violation before writing any file.
Package codegen — goldmark-based markdown structure validation and extraction.
This file provides two production functions for validating and querying generated SKILL.md documents via goldmark's AST:
- ValidateSkillStructure — checks heading hierarchy for common errors
- ExtractSection — extracts content under a heading by title
These complement the unified skill generation pipeline by providing post-render structural validation.
Package codegen provides utilities for code generation over SKILL.md files.
It ports the marker parsing and replacement logic from gen_skills.py (Python) to Go, enabling the pasture codegen pipeline to operate on SKILL.md files that contain BEGIN/END marker pairs delimiting generated sections.
Package codegen — schema.xml generation.
This file ports gen_schema.py to Go. It generates schema.xml from the canonical Go spec data maps (ConstraintSpecs, PhaseSpecs, etc.) using manual XML building (bytes.Buffer + fmt.Fprintf) to achieve CDATA sections for <code> elements and fine-grained indentation control matching the Python output.
15 of 17 section builders use encoding/xml struct marshalling (SLICE-B). The remaining 2 (buildConstraints, buildProcedureSteps) use manual fmt.Fprintf because they contain CDATA sections that encoding/xml cannot produce.
Public API:
GenerateSchema(w io.Writer) error GenerateSchemaToFile(path string, opts GenerateOptions) (string, error)
Package codegen — encoding/xml annotated structs for schema.xml sections.
These structs define the canonical XML shapes for all 17 sections of the Pasture Protocol schema. They are used by SLICE-B to replace manual fmt.Fprintf calls with encoding/xml marshalling for 15 of the 17 sections.
ConstraintsSection and ProcedureStepsSection are defined here for type safety and documentation purposes but are NOT used for xml.Marshal: those sections contain CDATA elements that encoding/xml cannot emit, so buildConstraints and buildProcedureSteps remain manual fmt.Fprintf builders.
Package codegen — SKILL.md header generation via text/template.
This file ports gen_skills.py to Go. It provides GenerateSkill and GenerateSubSkill which render the generated section of SKILL.md files using Go text/template with Option("missingkey=error") for StrictUndefined parity.
Templates are embedded via go:embed so the binary is fully self-contained. The template context is built from GetRoleContext() + spec data lookups.
Package codegen provides types and canonical data maps for the Pasture protocol codegen system. These types are internal to the codegen package and are NOT exported outside of internal/codegen.
They mirror the Python types.py spec dataclasses for use by Go template generators (schema.xml generation, SKILL.md generation, agent definitions).
Import paths for referenced types:
- github.com/dayvidpham/pasture/internal/types — RoleId, Domain
- github.com/dayvidpham/pasture/pkg/protocol — PhaseId
Canonical data maps for the Pasture protocol codegen system.
These are package-level vars that mirror the Python canonical dicts in aura_protocol/types.py. They are the single source of truth for code generation (schema.xml, SKILL.md, agent definitions).
Integration with Python: test_schema_types_sync.py verifies the Python dicts match schema.xml; Go tests in specs_test.go verify Go maps are structurally complete (every RoleId, every PhaseId has an entry).
Canonical body content for all skill SKILL.md files.
This file consolidates body data for all 7 skills that have hand-authored body sections (rendered inside the BEGIN/END marker region by the unified templates). Each var encodes the body content for one skill directory.
SkillBodySpecs maps skill directory names to their body content. Keys are directory names (not types.RoleId) because sub-skills like "supervisor-plan-tasks" have no RoleId equivalent.
Body content for the architect-handoff skill SKILL.md. Ported from aura-plugins/skills/architect-handoff/SKILL.md.
Body content for the architect-propose-plan skill SKILL.md. Ported from aura-plugins/skills/architect-propose-plan/SKILL.md.
Body content for the architect-ratify skill SKILL.md. Ported from aura-plugins/skills/architect-ratify/SKILL.md.
Body content for the architect-request-review skill SKILL.md. Ported from aura-plugins/skills/architect-request-review/SKILL.md.
Body content for the epoch role SKILL.md. Ported from aura-plugins/skills/epoch/SKILL.md.
Body content for the explore skill SKILL.md. Ported from aura-plugins/skills/explore/SKILL.md.
Body content for the impl-slice command SKILL.md. Ported from aura-plugins/skills/impl-slice/SKILL.md.
Body content for the research skill SKILL.md. Ported from aura-plugins/skills/research/SKILL.md.
Body content for the reviewer-comment skill SKILL.md. Ported from aura-plugins/skills/reviewer-comment/SKILL.md.
Body content for the reviewer-review-code skill SKILL.md. Ported from aura-plugins/skills/reviewer-review-code/SKILL.md.
Body content for the reviewer-review-plan skill SKILL.md. Ported from aura-plugins/skills/reviewer-review-plan/SKILL.md.
Body content for the reviewer-vote skill SKILL.md. Ported from aura-plugins/skills/reviewer-vote/SKILL.md.
Body content for the status skill SKILL.md. Ported from aura-plugins/skills/status/SKILL.md.
Body content for the supervisor-commit skill SKILL.md. Ported from aura-plugins/skills/supervisor-commit/SKILL.md.
Body content for the supervisor-track-progress skill SKILL.md. Ported from aura-plugins/skills/supervisor-track-progress/SKILL.md.
Body content for the swarm command SKILL.md. Ported from aura-plugins/skills/swarm/SKILL.md.
Body content for the user-elicit skill SKILL.md. Ported from aura-plugins/skills/user-elicit/SKILL.md.
Body content for the user-request skill SKILL.md. Ported from aura-plugins/skills/user-request/SKILL.md.
Body content for the user-uat command SKILL.md. Ported from aura-plugins/skills/user-uat/SKILL.md.
Body content for the worker-blocked skill SKILL.md. Ported from aura-plugins/skills/worker-blocked/SKILL.md.
Body content for the worker-complete skill SKILL.md. Ported from aura-plugins/skills/worker-complete/SKILL.md.
Body content for the worker-implement skill SKILL.md. Ported from aura-plugins/skills/worker-implement/SKILL.md.
Canonical SharedFragment registry and helper constructors.
This file declares the SharedFragmentSpecs map, fragRef/behaviorRef marker constructors, and FragmentToOwnerRefs, which inverts the consumer-keyed SkillBodySpecs to produce a map from FragmentId to sorted owner skill-dir keys.
Mirror: ConstraintToRoleRefs() at context.go inverts the consumer-keyed roleConstraints map; FragmentToOwnerRefs mirrors that pattern exactly, operating over SkillBodySpecs instead.
Package codegen — 3-layer schema.xml validator.
This file provides the full implementation of the 3-layer schema.xml validator ported from scripts/validate_schema.py. It parses an XML document into a generic XMLNode tree and runs three validation passes:
- Structural (buildIndex) — required attributes, integer attrs, duplicate IDs.
- Referential (checkRefs) — all cross-references resolve to known IDs.
- Semantic (checkSemantics) — logical protocol-level rules (sequential phase numbers, domain consistency, label uniqueness, etc.).
Public API:
ValidateSchema(r io.Reader) ([]ValidationError, error) ValidateTree(root *XMLNode) []ValidationError
Index ¶
- Constants
- Variables
- func AppendMarkers(content string) string
- func ConstraintToPhaseRefs() map[string][]protocol.PhaseId
- func ConstraintToRoleRefs() map[string][]types.RoleId
- func ExtractSection(markdown []byte, headingTitle string) ([]byte, error)
- func FindMarkerPositions(lines []string, path string) (begin, end int, err error)
- func FragmentToOwnerRefs() map[FragmentId][]string
- func GenerateAgent(roleId types.RoleId, agentPath string, figuresDir string, opts GenerateOptions) (string, error)
- func GenerateSchema(w io.Writer) error
- func GenerateSchemaToFile(path string, opts GenerateOptions) (string, error)
- func GenerateSkill(roleId types.RoleId, skillPath string, figuresDir string, opts GenerateOptions) (string, error)
- func GenerateSubSkill(commandId string, skillPath string, figuresDir string, opts GenerateOptions) (string, error)
- func HasMarkers(content string) bool
- func HeadingTextFromAST(n ast.Node, src []byte) string
- func ParseXMLNode(r io.Reader, out *XMLNode) error
- func PrependMarkers(content string) string
- func ReplaceMarkerRegion(oldContent, rendered string, dropPrefix bool) (string, error)
- func ValidateGlobalIds() error
- func ValidateSkillStructure(markdown []byte) error
- type ActionElem
- type AxisRefElem
- type BehaviorElem
- type BehaviorSpec
- type BehaviorsElem
- type Checklist
- type ChecklistElem
- type ChecklistItem
- type ChecklistItemElem
- type ChecklistsSection
- type CommandElem
- type CommandPhasesElem
- type CommandSpec
- type CommandsSection
- type ConstraintContext
- type ConstraintElem
- type ConstraintSpec
- type ConstraintsSection
- type CoordCmdElem
- type CoordinationCommand
- type CoordinationCommandsSection
- type CoverEntityElem
- type CoversElem
- type CreatesLabelsElem
- type DelegateElem
- type DelegatesElem
- type DepChainElem
- type DepChainStepElem
- type DependencyModelSection
- type DocumentElem
- type DocumentsSection
- type EnumType
- type EnumValue
- type EnumsSection
- type ErrorLayer
- type Example
- type ExampleElem
- type ExitCondElem
- type ExitCondition
- type ExtraLabelElem
- type FigureElem
- type FigureSpec
- type FiguresSection
- type FollowupEpicElem
- type FollowupLifecycleSection
- type FollowupRefElem
- type FollowupRefsElem
- type FragmentId
- type FragmentKind
- type FragmentParityError
- type GenerateOptions
- type HandoffChainElem
- type HandoffChainTransElem
- type HandoffElem
- type HandoffNoteElem
- type HandoffSpec
- type HandoffsSection
- type IDCollision
- type InstancesElem
- type InvalidFragment
- type InvariantsElem
- type KeyQuestionsElem
- type LabelElem
- type LabelRefElem
- type LabelSpec
- type LabelsSection
- type LeafTaskAdoptElem
- type MarkerError
- type OwnedPhasesElem
- type PhaseContext
- type PhaseElem
- type PhaseRefElem
- type PhaseSpec
- type PhasesSection
- type ProcedureRoleGroup
- type ProcedureStep
- type ProcedureStepElem
- type ProcedureStepsSection
- type ProseSection
- type RecipeBlock
- type RefElem
- type ReferenceLinksElem
- type RequiredFieldsElem
- type ReviewAxesSection
- type ReviewAxisElem
- type ReviewAxisSpec
- type RoleContext
- type RoleElem
- type RoleSpec
- type RolesSection
- type SameActorAsElem
- type SameActorTransitionElem
- type SameActorTransitionsElem
- type SchemaIndex
- type SevGroupElem
- type SeverityTreeElem
- type SharedFragment
- type SkillBody
- type SkillInvocationElem
- type SkillStructureError
- type StageElem
- type StartupSequenceElem
- type SubstepData
- type SubstepElem
- type SubstepInstances
- type SubstepOrderEntry
- type SubstepsElem
- type TDDLayerElem
- type TDDLayersElem
- type TaskTitleElem
- type TaskTitlesSection
- type TitleConvention
- type TitleConventionElem
- type Transition
- type TransitionElem
- type TransitionsElem
- type UnresolvedMarker
- type UsesAxesElem
- type ValidationError
- type Workflow
- type WorkflowAction
- type WorkflowElem
- type WorkflowStage
- type WorkflowsSection
- type XMLNode
Constants ¶
const GeneratedBegin = "<!-- BEGIN GENERATED FROM pasture schema -->"
GeneratedBegin is the opening marker that delimits the generated section.
const GeneratedEnd = "<!-- END GENERATED FROM pasture schema -->"
GeneratedEnd is the closing marker that delimits the generated section.
Variables ¶
var AllFragmentIds = []FragmentId{ FragRevVoteOptions, FragSupReviewAllSlices, FragSupReviewCheckEach, FragSupReviewSeverityGroups, FragSupBlockerDualParent, FragSupDeferredFollowup, FragSupFollowupEpicTiming, FragSupSeverityTree, FragSupNamingConvention, FragRevPlanVoteOptions, FragValidationCases, FragReviewCleanExit, }
AllFragmentIds lists every declared FragmentId constant. It is maintained in sync with the constant declarations below and validated by ValidateGlobalIds (parity check: AllFragmentIds ↔ SharedFragmentSpecs keys). Mirrors AllRoleIds in internal/types/enums.go.
var ChecklistSpecs = map[string]Checklist{ "worker-completion": { RoleRef: types.RoleWorker, Gate: "completion", Items: []ChecklistItem{ {Id: "CL-worker-no-todos", Text: "No TODO placeholders in CLI/API actions", Required: true}, {Id: "CL-worker-real-deps", Text: "Real dependencies wired (not mocks in production code)", Required: true}, {Id: "CL-worker-test-import", Text: "Tests import production code (not test-only export)", Required: true}, {Id: "CL-worker-no-dual-export", Text: "No dual-export anti-pattern (one code path for tests and production)", Required: true}, {Id: "CL-worker-quality-gates", Text: "Quality gates pass (typecheck + tests)", Required: true}, {Id: "CL-worker-production-path", Text: "Production code path verified end-to-end via code inspection", Required: true}, }, }, "worker-slice-closure": { RoleRef: types.RoleWorker, Gate: "slice-closure", Items: []ChecklistItem{ {Id: "CL-worker-notified-supervisor", Text: "Supervisor notified via bd comments add (not bd close)", Required: true}, {Id: "CL-worker-completion-done", Text: "All completion-gate items passed", Required: true}, {Id: "CL-worker-close-on-review-wave", Text: "Can only close on a review wave, not a worker wave", Required: true}, {Id: "CL-worker-review-eligible", Text: "Eligible to close only after review by independent agents with no BLOCKERS or IMPORTANT findings", Required: true}, }, }, "supervisor-review-ready": { RoleRef: types.RoleSupervisor, Gate: "review-ready", Items: []ChecklistItem{ {Id: "CL-sup-all-slices-notified", Text: "All workers have notified completion via bd comments add", Required: true}, {Id: "CL-sup-reviewers-assigned", Text: "Ephemeral reviewers spawned for all slices", Required: true}, {Id: "CL-sup-severity-groups-created", Text: "Severity groups (BLOCKER/IMPORTANT/MINOR) eagerly created per slice", Required: true}, }, }, "supervisor-landing": { RoleRef: types.RoleSupervisor, Gate: "landing", Items: []ChecklistItem{ {Id: "CL-sup-all-accept", Text: "Fix-free clean re-review: 0 BLOCKER + 0 IMPORTANT + 0 MINOR from all 3 reviewers", Required: true}, {Id: "CL-sup-followup-created", Text: "FOLLOWUP epic created at UAT only if user-DEFER'd items exist (never from review severities)", Required: true}, {Id: "CL-sup-agent-commit", Text: "git agent-commit used (not git commit -m)", Required: true}, {Id: "CL-sup-tasks-closed", Text: "All upstream tasks closed or dependency-resolved", Required: true}, {Id: "CL-sup-close-on-review-wave", Text: "Can only close on a review wave, not a worker wave", Required: true}, {Id: "CL-sup-review-eligible", Text: "Eligible to close only after review by independent agents with 0 BLOCKER + 0 IMPORTANT + 0 MINOR findings", Required: true}, }, }, }
ChecklistSpecs maps "{role}-{gate}" keys to completion checklists. Mirrors Python CHECKLIST_SPECS dict.
var CommandSpecs = map[string]CommandSpec{ "cmd-epoch": { Id: "cmd-epoch", Name: "pasture:epoch", Description: "Master orchestrator for full 12-phase workflow", RoleRef: types.RoleEpoch, Phases: []protocol.PhaseId{ protocol.PhaseRequest, protocol.PhaseElicit, protocol.PhasePropose, protocol.PhaseReview, protocol.PhasePlanReview, protocol.PhaseRatify, protocol.PhaseHandoff, protocol.PhaseImplPlan, protocol.PhaseWorkerSlices, protocol.PhaseCodeReview, protocol.PhaseImplUAT, protocol.PhaseLanding, }, File: "skills/epoch/SKILL.md", }, "cmd-status": { Id: "cmd-status", Name: "pasture:status", Description: "Project status and monitoring via Beads queries", Title: "Pasture Status", File: "skills/status/SKILL.md", }, "cmd-user-request": { Id: "cmd-user-request", Name: "pasture:user:request", Description: "Capture user feature request verbatim (Phase 1)", Title: "User Request (Phase 1)", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{protocol.PhaseRequest}, File: "skills/user-request/SKILL.md", CreatesLabels: []string{"L-p1s1_1"}, }, "cmd-user-elicit": { Id: "cmd-user-elicit", Name: "pasture:user:elicit", Description: "User Requirements Elicitation survey (Phase 2)", Title: "User Requirements Elicitation (Phase 2)", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{protocol.PhaseElicit}, File: "skills/user-elicit/SKILL.md", CreatesLabels: []string{"L-p2s2_1", "L-p2s2_2", "L-urd"}, }, "cmd-user-uat": { Id: "cmd-user-uat", Name: "pasture:user:uat", Description: "User Acceptance Testing with demonstrative examples", Title: "User Acceptance Test (UAT)", Phases: []protocol.PhaseId{protocol.PhasePlanReview, protocol.PhaseImplUAT}, File: "skills/user-uat/SKILL.md", CreatesLabels: []string{"L-p5s5", "L-p11s11"}, }, "cmd-architect": { Id: "cmd-architect", Name: "pasture:architect", Description: "Specification writer and implementation designer", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{ protocol.PhaseRequest, protocol.PhaseElicit, protocol.PhasePropose, protocol.PhaseReview, protocol.PhasePlanReview, protocol.PhaseRatify, protocol.PhaseHandoff, }, File: "skills/architect/SKILL.md", }, "cmd-arch-propose": { Id: "cmd-arch-propose", Name: "pasture:architect:propose-plan", Description: "Create PROPOSAL-N task with full technical plan", Title: "Architect: Propose Plan", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{protocol.PhasePropose}, File: "skills/architect-propose-plan/SKILL.md", CreatesLabels: []string{"L-p3s3"}, }, "cmd-arch-review": { Id: "cmd-arch-review", Name: "pasture:architect:request-review", Description: "Spawn 3 axis-specific reviewers (A/B/C)", Title: "Architect: Request Review", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{protocol.PhaseReview}, File: "skills/architect-request-review/SKILL.md", CreatesLabels: []string{"L-p4s4"}, }, "cmd-arch-ratify": { Id: "cmd-arch-ratify", Name: "pasture:architect:ratify", Description: "Ratify proposal, mark old proposals pasture:superseded", Title: "Architect: Ratify Plan", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{protocol.PhaseRatify}, File: "skills/architect-ratify/SKILL.md", CreatesLabels: []string{"L-p6s6", "L-superseded"}, }, "cmd-arch-handoff": { Id: "cmd-arch-handoff", Name: "pasture:architect:handoff", Description: "Create handoff document and transfer to supervisor", Title: "Architect: Handoff to Supervisor", RoleRef: types.RoleArchitect, Phases: []protocol.PhaseId{protocol.PhaseHandoff}, File: "skills/architect-handoff/SKILL.md", CreatesLabels: []string{"L-p7s7"}, }, "cmd-supervisor": { Id: "cmd-supervisor", Name: "pasture:supervisor", Description: "Task coordinator, spawns workers, manages parallel execution", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{ protocol.PhaseHandoff, protocol.PhaseImplPlan, protocol.PhaseWorkerSlices, protocol.PhaseCodeReview, protocol.PhaseImplUAT, protocol.PhaseLanding, }, File: "skills/supervisor/SKILL.md", }, "cmd-sup-plan": { Id: "cmd-sup-plan", Name: "pasture:supervisor:plan-tasks", Description: "Decompose ratified plan into vertical slices (SLICE-N)", Title: "Supervisor Plan Tasks", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{protocol.PhaseImplPlan}, File: "skills/supervisor-plan-tasks/SKILL.md", CreatesLabels: []string{"L-p8s8", "L-p9s9"}, }, "cmd-sup-spawn": { Id: "cmd-sup-spawn", Name: "pasture:supervisor:spawn-worker", Description: "Launch a worker agent for an assigned slice", Title: "Supervisor Spawn Worker", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, File: "skills/supervisor-spawn-worker/SKILL.md", CreatesLabels: []string{"L-p9s9"}, }, "cmd-sup-track": { Id: "cmd-sup-track", Name: "pasture:supervisor:track-progress", Description: "Monitor worker status via Beads", Title: "Supervisor: Track Progress", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices, protocol.PhaseCodeReview}, File: "skills/supervisor-track-progress/SKILL.md", }, "cmd-sup-commit": { Id: "cmd-sup-commit", Name: "pasture:supervisor:commit", Description: "Atomic commit per completed layer/slice", Title: "Supervisor: Commit", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{protocol.PhaseLanding}, File: "skills/supervisor-commit/SKILL.md", CreatesLabels: []string{"L-p12s12"}, }, "cmd-worker": { Id: "cmd-worker", Name: "pasture:worker", Description: "Vertical slice implementer (full production code path)", RoleRef: types.RoleWorker, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, File: "skills/worker/SKILL.md", }, "cmd-work-impl": { Id: "cmd-work-impl", Name: "pasture:worker:implement", Description: "Implement assigned vertical slice following TDD layers", Title: "Worker: Implement Vertical Slice", RoleRef: types.RoleWorker, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, File: "skills/worker-implement/SKILL.md", CreatesLabels: []string{"L-p9s9"}, }, "cmd-work-complete": { Id: "cmd-work-complete", Name: "pasture:worker:complete", Description: "Signal slice completion after quality gates pass", Title: "Worker: Signal Completion", RoleRef: types.RoleWorker, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, File: "skills/worker-complete/SKILL.md", }, "cmd-work-blocked": { Id: "cmd-work-blocked", Name: "pasture:worker:blocked", Description: "Report a blocker to supervisor via Beads", Title: "Worker: Handle Blockers", RoleRef: types.RoleWorker, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, File: "skills/worker-blocked/SKILL.md", }, "cmd-reviewer": { Id: "cmd-reviewer", Name: "pasture:reviewer", Description: "End-user alignment reviewer for plans and code", RoleRef: types.RoleReviewer, Phases: []protocol.PhaseId{protocol.PhaseReview, protocol.PhaseCodeReview}, File: "skills/reviewer/SKILL.md", }, "cmd-rev-plan": { Id: "cmd-rev-plan", Name: "pasture:reviewer:review-plan", Description: "Evaluate proposal against one axis (binary ACCEPT/REVISE)", Title: "Review Plan", RoleRef: types.RoleReviewer, Phases: []protocol.PhaseId{protocol.PhaseReview}, File: "skills/reviewer-review-plan/SKILL.md", CreatesLabels: []string{"L-p4s4"}, }, "cmd-rev-code": { Id: "cmd-rev-code", Name: "pasture:reviewer:review-code", Description: "Review implementation slices with EAGER severity tree", Title: "Review Code Implementation", RoleRef: types.RoleReviewer, Phases: []protocol.PhaseId{protocol.PhaseCodeReview}, File: "skills/reviewer-review-code/SKILL.md", CreatesLabels: []string{"L-p10s10", "L-sev-blocker", "L-sev-import", "L-sev-minor"}, }, "cmd-rev-comment": { Id: "cmd-rev-comment", Name: "pasture:reviewer:comment", Description: "Leave structured review comment via Beads", Title: "Leave Structured Review Comment", RoleRef: types.RoleReviewer, Phases: []protocol.PhaseId{protocol.PhaseReview, protocol.PhaseCodeReview}, File: "skills/reviewer-comment/SKILL.md", }, "cmd-rev-vote": { Id: "cmd-rev-vote", Name: "pasture:reviewer:vote", Description: "Cast ACCEPT or REVISE vote (binary only)", Title: "Cast Review Vote", RoleRef: types.RoleReviewer, Phases: []protocol.PhaseId{protocol.PhaseReview, protocol.PhaseCodeReview}, File: "skills/reviewer-vote/SKILL.md", }, "cmd-impl-slice": { Id: "cmd-impl-slice", Name: "pasture:impl:slice", Description: "Vertical slice assignment and tracking", Title: "Implementation Slice (Phase 9)", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, File: "skills/impl-slice/SKILL.md", CreatesLabels: []string{"L-p9s9"}, }, "cmd-impl-review": { Id: "cmd-impl-review", Name: "pasture:impl:review", Description: "Code review coordination across all slices (Phase 10)", Title: "Implementation Code Review (Phase 10)", RoleRef: types.RoleSupervisor, Phases: []protocol.PhaseId{protocol.PhaseCodeReview}, File: "skills/impl-review/SKILL.md", CreatesLabels: []string{"L-p10s10", "L-sev-blocker", "L-sev-import", "L-sev-minor"}, }, "cmd-explore": { Id: "cmd-explore", Name: "pasture:explore", Description: "Codebase exploration — find integration points, existing patterns, and related code", Title: "Explore", Phases: []protocol.PhaseId{protocol.PhaseRequest, protocol.PhaseImplPlan}, File: "skills/explore/SKILL.md", CreatesLabels: []string{"L-p1s1_3"}, }, "cmd-research": { Id: "cmd-research", Name: "pasture:research", Description: "Domain research — find standards, prior art, and competing approaches", Title: "Research", Phases: []protocol.PhaseId{protocol.PhaseRequest}, File: "skills/research/SKILL.md", CreatesLabels: []string{"L-p1s1_2"}, }, "cmd-swarm": { Id: "cmd-swarm", Name: "pasture:swarm", Description: "Launch worktree-based or intree agent workflows using aura-swarm", Title: "Swarm — Unified Agent Orchestration", File: "skills/swarm/SKILL.md", }, }
CommandSpecs maps command IDs to their full specifications. Mirrors Python COMMAND_SPECS dict.
var ConstraintSpecs = map[string]ConstraintSpec{ "C-audit-never-delete": { Id: "C-audit-never-delete", Given: "any task or label", When: "modifying", Then: "add labels and comments only", ShouldNot: "delete or close tasks prematurely, remove labels", }, "C-audit-dep-chain": { Id: "C-audit-dep-chain", Given: "any phase transition", When: "creating new task", Then: "chain dependency: bd dep add parent --blocked-by child", ShouldNot: "skip dependency chaining or invert direction", Command: "bd dep add <parent> --blocked-by <child>", Examples: []Example{ { Id: "C-audit-dep-chain-full", Lang: "bash", Label: "correct", Code: "# Full dependency chain: work flows bottom-up, closure flows top-down\n" + "bd dep add request-id --blocked-by ure-id\n" + "bd dep add ure-id --blocked-by proposal-id\n" + "bd dep add proposal-id --blocked-by impl-plan-id\n" + "bd dep add impl-plan-id --blocked-by slice-1-id\n" + "bd dep add slice-1-id --blocked-by leaf-task-a-id", }, }, }, "C-review-consensus": { Id: "C-review-consensus", Given: "review cycle (p4 or p10)", When: "evaluating", Then: "all 3 reviewers must ACCEPT before proceeding", ShouldNot: "proceed with any REVISE vote outstanding", }, "C-review-binary": { Id: "C-review-binary", Given: "a reviewer", When: "voting", Then: "use ACCEPT or REVISE only", ShouldNot: "use APPROVE, APPROVE_WITH_COMMENTS, REQUEST_CHANGES, or REJECT", }, "C-severity-eager": { Id: "C-severity-eager", Given: "code review round (p10 only)", When: "starting review", Then: "ALWAYS create 3 severity group tasks (BLOCKER, IMPORTANT, MINOR) immediately", ShouldNot: "lazily create severity groups only when findings exist", Examples: []Example{ { Id: "C-severity-eager-create", Lang: "bash", Label: "correct", Code: "# Create all 3 severity groups immediately (even if empty)\n" + "bd create --title \"SLICE-1-REVIEW-A-1 BLOCKER\" \\\n" + " --labels \"pasture:severity:blocker,pasture:p10-impl:s10-review\"\n" + "bd create --title \"SLICE-1-REVIEW-A-1 IMPORTANT\" \\\n" + " --labels \"pasture:severity:important,pasture:p10-impl:s10-review\"\n" + "bd create --title \"SLICE-1-REVIEW-A-1 MINOR\" \\\n" + " --labels \"pasture:severity:minor,pasture:p10-impl:s10-review\"\n\n" + "# Close empty groups immediately\n" + "bd close <empty-important-id>\n" + "bd close <empty-minor-id>", }, { Id: "C-severity-eager-anti", Lang: "bash", Label: "anti-pattern", Code: "# WRONG: only creating groups when findings exist\n" + "# This skips empty groups and breaks the audit trail\n" + "if blocker_findings:\n" + " bd create --title \"BLOCKER\" ...", }, }, }, "C-severity-not-plan": { Id: "C-severity-not-plan", Given: "plan review (p4)", When: "reviewing", Then: "use binary ACCEPT/REVISE only", ShouldNot: "create severity tree for plan reviews", }, "C-blocker-dual-parent": { Id: "C-blocker-dual-parent", Given: "a BLOCKER finding in code review", When: "recording", Then: "add as child of BOTH the severity group AND the slice it blocks", ShouldNot: "add to severity group only", }, "C-followup-timing": { Id: "C-followup-timing", Given: "UAT (Phase 5 or Phase 11) produces one or more user-DEFER'd items", When: "creating the FOLLOWUP epic", Then: "create the FOLLOWUP epic at UAT when user-DEFER'd items exist; " + "the FOLLOWUP epic is fed ONLY by user-DEFER'd UAT items", ShouldNot: "trigger FOLLOWUP from any review severity (BLOCKER/IMPORTANT/MINOR) — " + "all review findings must reach 0 before wave close, no severity is deferrable to FOLLOWUP", }, "C-vertical-slices": { Id: "C-vertical-slices", Given: "implementation decomposition", When: "assigning work", Then: "each production code path owned by exactly ONE worker (full vertical)", ShouldNot: "assign horizontal layers or same path to multiple workers", }, "C-supervisor-no-impl": { Id: "C-supervisor-no-impl", Given: "supervisor role", When: "implementation phase", Then: "spawn workers for all code changes", ShouldNot: "implement code directly", }, "C-supervisor-explore-ephemeral": { Id: "C-supervisor-explore-ephemeral", Given: "supervisor needs codebase exploration", When: "starting Phase 8 (IMPL_PLAN)", Then: "spawn ephemeral Explore subagents via Task tool for scoped codebase queries; " + "each subagent is short-lived and returns findings; no standing team overhead", ShouldNot: "explore the codebase directly as supervisor; " + "maintain a standing explore team", }, "C-clean-review-exit": { Id: "C-clean-review-exit", Given: "per-slice code review", When: "evaluating review results", Then: "iterate review -> fix -> re-review up to the chosen review-effort budget until a fix-free clean round " + "confirms 0 BLOCKER + 0 IMPORTANT + 0 MINOR within budget; " + "a clean round is one where the re-review applies no fixes and finds nothing across all three severities; " + "on budget exhaustion without a clean round, SURFACE the outstanding findings to the user at a gate for a decision", ShouldNot: "close a wave on a fix-applying round; " + "proceed with ANY finding (BLOCKER, IMPORTANT, or MINOR) outstanding without surfacing it to the user; " + "hardcode the budget; proceed past the chosen budget without surfacing to the user; " + "batch review across multiple slices", }, "C-review-effort-budget": { Id: "C-review-effort-budget", Given: "the start of Phase 8 (IMPL_PLAN), like the Phase-1 research-depth gate", When: "deciding how much review-and-fix effort to spend per slice", Then: "request a configurable review-effort budget from the user — defaults: " + "(1) three rounds, (2) one round, (3) zero rounds, (4) unlimited, (5) custom; " + "the review->fix->re-review loop iterates up to the chosen budget; " + "on budget exhaustion WITHOUT a clean 0/0/0 round, surface the outstanding findings to the user for a decision", ShouldNot: "hardcode the review-cycle budget (e.g. an unconditional fixed cap baked into the prose instead of asked); " + "proceed past the chosen budget without surfacing outstanding findings to the user; " + "loop forever when a finite budget was chosen", }, "C-autonomous-progression": { Id: "C-autonomous-progression", Given: "supervisor orchestrating phases", When: "deciding whether to proceed", Then: "5 user-gated phases only: (1) research depth decision, (2) URE survey, " + "(3) Plan UAT, (4) Phase 8 implementation-effort / review-effort budget request, " + "(5) Impl UAT; all other phase transitions are auto-ratified " + "by the supervisor; after Plan UAT ACCEPT, proceed directly to ratification " + "without user gate", ShouldNot: "add additional user gates beyond the 5 defined; " + "require user approval for ratification after UAT ACCEPT", }, "C-integration-points": { Id: "C-integration-points", Given: "multiple vertical slices share types, interfaces, or data flows", When: "decomposing IMPL_PLAN in Phase 8", Then: "identify horizontal Layer Integration Points and document them in IMPL_PLAN; " + "each integration point specifies: owning slice, consuming slices, shared contract, merge timing; " + "include integration points in slice descriptions so workers know what to export and import", ShouldNot: "leave cross-slice dependencies implicit; " + "assume workers will discover contracts on their own", }, "C-slice-review-before-close": { Id: "C-slice-review-before-close", Given: "workers complete their implementation slices", When: "slice implementation is done", Then: "workers notify supervisor with bd comments add (not bd close); " + "slices must be reviewed at least once by reviewers before closure; " + "only the supervisor closes slices, after review passes", ShouldNot: "close slices immediately upon worker completion; " + "allow workers to close their own slices", }, "C-slice-leaf-tasks": { Id: "C-slice-leaf-tasks", Given: "vertical slice created", When: "decomposing slice into implementation units", Then: "create one or more Beads leaf tasks per slice, named after the real work units they represent, " + "with bd dep add slice-id --blocked-by leaf-task-id; a slice may have ANY number of leaves " + "(the L1: types / L2: tests / L3: impl triple is ONE illustrative shape, not a required count)", ShouldNot: "create slices without leaf tasks — " + "a slice with no children is undecomposed and cannot be tracked; " + "force every slice into a fixed L1/L2/L3 triple when the real work units differ", Command: "bd dep add <slice-id> --blocked-by <leaf-task-id>", }, "C-handoff-skill-invocation": { Id: "C-handoff-skill-invocation", Given: "an agent is launched for a new phase (especially p7 to p8 handoff)", When: "composing the launch prompt", Then: "prompt MUST start with Skill(/pasture:{role}) invocation directive " + "so the agent loads its role instructions", ShouldNot: "launch agents without skill invocation — " + "they skip role-critical procedures like ephemeral exploration and leaf task creation", }, "C-dep-direction": { Id: "C-dep-direction", Given: "adding a Beads dependency", When: "determining direction", Then: "parent blocked-by child: bd dep add stays-open --blocked-by must-finish-first", ShouldNot: "invert (child blocked-by parent)", Command: "bd dep add <stays-open> --blocked-by <must-finish-first>", Examples: []Example{ { Id: "C-dep-direction-correct", Lang: "bash", Label: "correct", Code: "bd dep add request-id --blocked-by ure-id", AlsoIllustrates: "C-audit-dep-chain", }, { Id: "C-dep-direction-anti", Lang: "bash", Label: "anti-pattern", Code: "bd dep add ure-id --blocked-by request-id", }, }, }, "C-frontmatter-refs": { Id: "C-frontmatter-refs", Given: "cross-task references (URD, request, etc.)", When: "linking tasks", Then: "use description frontmatter references: block", ShouldNot: "use bd dep relate (buggy) or blocking dependencies for reference docs", }, "C-agent-commit": { Id: "C-agent-commit", Given: "code is ready to commit", When: "committing", Then: "use git agent-commit -m ...", ShouldNot: "use git commit -m ...", Command: "git agent-commit -m ...", Examples: []Example{ { Id: "C-agent-commit-correct", Lang: "bash", Label: "correct", Code: `git agent-commit -m "feat: add login"`, }, { Id: "C-agent-commit-anti", Lang: "bash", Label: "anti-pattern", Code: `git commit -m "feat: add login"`, }, }, }, "C-proposal-naming": { Id: "C-proposal-naming", Given: "a new or revised proposal", When: "creating task", Then: "title PROPOSAL-{N} where N increments; mark old as pasture:superseded", ShouldNot: "reuse N or delete old proposals", }, "C-review-naming": { Id: "C-review-naming", Given: "a review task", When: "creating", Then: "title {SCOPE}-REVIEW-{axis}-{round} where axis=A|B|C, round starts at 1", ShouldNot: "use numeric reviewer IDs (1/2/3) instead of axis letters", }, "C-ure-verbatim": { Id: "C-ure-verbatim", Given: "user interview (Request, URE, or UAT), URD update, or mid-implementation design decision", When: "recording in Beads", Then: "capture full question text, ALL option descriptions, AND user's verbatim response, " + "INCLUDING any code, snippets, or examples shown inside AskUserQuestion option labels, descriptions, " + "or definition blocks (the preview/stimulus the user actually saw); " + "the URD is the living document of ALL user requests, URE, UAT, and mid-implementation " + "design decisions and feedback — update it via bd comments add whenever user intent is captured", ShouldNot: "summarize options as (1)/(2)/(3) without option text, paraphrase user responses, " + "or omit code/snippets shown inside option previews", Examples: []Example{ { Id: "C-ure-verbatim-correct", Lang: "bash", Label: "correct", Code: "# Full question, all options with descriptions, verbatim response\n" + "bd create --title \"UAT: Plan acceptance for feature-X\" \\\n" + " --description \"## Component: Verbose fields\n" + "**Question:** Which verbose fields are useful?\n" + "**Options:**\n" + "- backupDir (full path): Shows where the backup landed\n" + "- session ID: Enables log correlation across events\n" + "- repo path + hash: Confirms which git repo was detected\n" + "**User response:** backupDir (full path), session ID\n" + "**Decision:** ACCEPT\"", }, { Id: "C-ure-verbatim-anti", Lang: "bash", Label: "anti-pattern", Code: "# WRONG: options summarized as numbers, response paraphrased\n" + "bd create --title \"UAT: Plan acceptance\" \\\n" + " --description \"Asked about verbose fields (1-4). User picked 1 and 2. Accepted.\"", }, }, }, "C-followup-lifecycle": { Id: "C-followup-lifecycle", Given: "follow-up epic created", When: "starting follow-up work", Then: "run same protocol phases with FOLLOWUP_* prefix: " + "FOLLOWUP_URE → FOLLOWUP_URD → FOLLOWUP_PROPOSAL → FOLLOWUP_IMPL_PLAN → FOLLOWUP_SLICE", ShouldNot: "skip the follow-up lifecycle or treat the follow-up epic as a flat task list", }, "C-followup-leaf-adoption": { Id: "C-followup-leaf-adoption", Given: "supervisor creates FOLLOWUP_SLICE-N", When: "assigning user-DEFER'd UAT-item leaf tasks to follow-up slices", Then: "add leaf task as child of follow-up slice " + "(dual-parent: leaf blocks both the DEFER'd-items tracking group AND follow-up slice)", ShouldNot: "remove the leaf task from its original DEFER'd-items tracking parent", }, "C-worker-gates": { Id: "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)", ShouldNot: "close with only 'tests pass' as completion gate", }, "C-actionable-errors": { Id: "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", ShouldNot: "raise generic or opaque error messages (e.g. 'invalid input', 'operation failed') " + "that don't guide the user toward resolution", }, "C-validation-cases": { Id: "C-validation-cases", Given: "any REQUEST (every request, not only fix-intent ones)", When: "eliciting (URE), acceptance-testing (UAT), or implementing", Then: "elicit concrete validation cases for the request — a definition of done plus correct and " + "incorrect behaviours (inputs/behaviors that must pass or must fail), " + "confirm the case set with the user in UAT, evaluate the implementation against them, " + "and store failing real-data cases as test fixtures", ShouldNot: "ship without validation cases; " + "treat validation cases as applying to fix-intent requests only; " + "introduce a request-type axis or enum to gate them (recognize what a request needs semantically instead)", }, "C-interview-skill-invocation": { Id: "C-interview-skill-invocation", Given: "a user-interview phase (Phase 2 URE, Phase 5 Plan UAT, or Phase 11 Impl UAT)", When: "conducting the phase", Then: "the agent MUST invoke the matching interview skill (Skill(/pasture:user-elicit) for URE, " + "Skill(/pasture:user-uat) for UAT) so the verbatim-capture and disposition procedures are loaded", ShouldNot: "conduct an interview phase without invoking its skill — " + "skipping it loses the verbatim-capture and FIX-NOW/DEFER disposition procedures", }, "C-uat-feedback-disposition": { Id: "C-uat-feedback-disposition", Given: "any UAT feedback item (Phase 5 or Phase 11) — flagged by the user OR a deferral proposed by the architect/supervisor", When: "recording each item", Then: "assign every item an explicit, user-confirmed disposition of FIX-NOW or DEFER; " + "deferrals may be agent-proposed, but ALL deferred items — whoever proposed them — MUST be raised to the user " + "at the next user gate (URE, Plan UAT, or Impl UAT) for confirmation; " + "FIX-NOW items are resolved in the current wave, DEFER'd items are the SOLE source feeding the FOLLOWUP epic", ShouldNot: "leave a feedback item without a confirmed disposition; " + "silently defer any item without raising it to the user at the next gate; " + "route any review severity (BLOCKER/IMPORTANT/MINOR) into FOLLOWUP — only DEFER'd UAT items feed it", }, "C-interface-first-slices": { Id: "C-interface-first-slices", Given: "decomposing a RATIFIED plan into vertical slices (Phase 8 IMPL_PLAN)", When: "ordering the slices", Then: "prefer an interface-first FOUNDATION slice that exports all shared identifiers " + "(types, constraints, fragments) and lands green BEFORE dependent slices (Strong SHOULD); " + "if a linear (non-interface-first) decomposition is chosen instead, justify it explicitly in the IMPL_PLAN", ShouldNot: "leave cross-slice contracts implicit; " + "choose a linear decomposition without recording the justification in the IMPL_PLAN", }, }
ConstraintSpecs maps constraint IDs to their full specifications. Mirrors Python CONSTRAINT_SPECS dict.
var CoordinationCommands = map[string]CoordinationCommand{ "cmd-coord-show": { Id: "cmd-coord-show", Action: "Check task details", Template: "bd show <task-id>", Shared: true, }, "cmd-coord-status": { Id: "cmd-coord-status", Action: "Update status", Template: "bd update <task-id> --status=in_progress", Shared: true, }, "cmd-coord-comment": { Id: "cmd-coord-comment", Action: "Add progress note", Template: `bd comments add <task-id> "Progress: ..."`, Shared: true, }, "cmd-coord-list": { Id: "cmd-coord-list", Action: "List in-progress", Template: "bd list --pretty --status=in_progress", Shared: true, }, "cmd-coord-blocked": { Id: "cmd-coord-blocked", Action: "List blocked", Template: "bd blocked", Shared: true, }, "cmd-coord-assign": { Id: "cmd-coord-assign", Action: "Assign task", Template: `bd update <task-id> --assignee "<worker-name>"`, RoleRef: types.RoleSupervisor, }, "cmd-coord-label": { Id: "cmd-coord-label", Action: "Label completed slice", Template: "bd label add <slice-id> pasture:p9-impl:slice-complete", RoleRef: types.RoleSupervisor, }, "cmd-coord-dep-add": { Id: "cmd-coord-dep-add", Action: "Chain dependency", Template: "bd dep add <parent> --blocked-by <child>", RoleRef: types.RoleSupervisor, }, "cmd-coord-close": { Id: "cmd-coord-close", Action: "Report completion", Template: "bd close <task-id>", RoleRef: types.RoleWorker, }, "cmd-coord-worker-notes": { Id: "cmd-coord-worker-notes", Action: "Add completion notes", Template: `bd update <task-id> --notes="Implementation complete. Production code verified."`, RoleRef: types.RoleWorker, }, }
CoordinationCommands maps command IDs to coordination command specs. Mirrors Python COORDINATION_COMMANDS dict.
var DefaultOptions = GenerateOptions{Diff: true, Write: true}
DefaultOptions is the default GenerateOptions used when the caller does not need to override any field.
var FigureSpecs = map[string]FigureSpec{ "layer-cake": { Id: "layer-cake", Title: "Layer Cake — TDD Parallelism Within Vertical Slices", Type: "ascii-diagram", RoleRefs: []types.RoleId{types.RoleWorker}, SectionRef: "workflows", WorkflowRefs: []string{"layer-cake"}, CommandRefs: []string{"cmd-sup-plan"}, }, "ride-the-wave": { Id: "ride-the-wave", Title: "Ride the Wave — Coordinated Phase 8-10 Execution", Type: "ascii-diagram", RoleRefs: []types.RoleId{types.RoleSupervisor}, SectionRef: "workflows", WorkflowRefs: []string{"ride-the-wave"}, CommandRefs: []string{"cmd-sup-spawn"}, }, "architect-state-flow": { Id: "architect-state-flow", Title: "Architect State Flow — Sequential Planning Phases 1-7", Type: "ascii-diagram", RoleRefs: []types.RoleId{types.RoleArchitect}, SectionRef: "workflows", WorkflowRefs: []string{"architect-state-flow"}, }, }
FigureSpecs maps figure IDs to their full specifications. Mirrors Python FIGURE_SPECS dict. Content is loaded at generation time.
var HandoffSpecs = map[string]HandoffSpec{ "h1": { Id: "h1", SourceRole: types.RoleArchitect, TargetRole: types.RoleSupervisor, AtPhase: protocol.PhaseHandoff, ContentLevel: "full-provenance", RequiredFields: []string{ "request", "urd", "proposal", "ratified-plan", "context", "key-decisions", "open-items", "acceptance-criteria", }, }, "h2": { Id: "h2", SourceRole: types.RoleSupervisor, TargetRole: types.RoleWorker, AtPhase: protocol.PhaseWorkerSlices, ContentLevel: "summary-with-ids", RequiredFields: []string{ "request", "urd", "proposal", "ratified-plan", "impl-plan", "slice", "context", "key-decisions", "open-items", "acceptance-criteria", }, }, "h3": { Id: "h3", SourceRole: types.RoleSupervisor, TargetRole: types.RoleReviewer, AtPhase: protocol.PhaseCodeReview, ContentLevel: "summary-with-ids", RequiredFields: []string{ "request", "urd", "proposal", "ratified-plan", "impl-plan", "context", "key-decisions", "acceptance-criteria", }, }, "h4": { Id: "h4", SourceRole: types.RoleWorker, TargetRole: types.RoleReviewer, AtPhase: protocol.PhaseCodeReview, ContentLevel: "summary-with-ids", RequiredFields: []string{ "request", "urd", "impl-plan", "slice", "context", "key-decisions", "open-items", }, }, "h5": { Id: "h5", SourceRole: types.RoleReviewer, TargetRole: types.RoleSupervisor, AtPhase: protocol.PhaseCodeReview, ContentLevel: "summary-with-ids", RequiredFields: []string{ "request", "urd", "proposal", "context", "key-decisions", "open-items", "acceptance-criteria", }, }, "h6": { Id: "h6", SourceRole: types.RoleSupervisor, TargetRole: types.RoleArchitect, AtPhase: protocol.PhasePropose, ContentLevel: "summary-with-ids", RequiredFields: []string{ "request", "urd", "followup-epic", "followup-ure", "followup-urd", "context", "key-decisions", "findings-summary", "acceptance-criteria", }, }, }
HandoffSpecs maps handoff IDs to their full specifications. Mirrors Python HANDOFF_SPECS dict.
var LabelSpecs = map[string]LabelSpec{ "L-p1s1_1": {Id: "L-p1s1_1", Value: "pasture:p1-user:s1_1-classify", Special: false, PhaseRef: "p1", SubstepRef: "s1_1"}, "L-p1s1_2": {Id: "L-p1s1_2", Value: "pasture:p1-user:s1_2-research", Special: false, PhaseRef: "p1", SubstepRef: "s1_2"}, "L-p1s1_3": {Id: "L-p1s1_3", Value: "pasture:p1-user:s1_3-explore", Special: false, PhaseRef: "p1", SubstepRef: "s1_3"}, "L-p2s2_1": {Id: "L-p2s2_1", Value: "pasture:p2-user:s2_1-elicit", Special: false, PhaseRef: "p2", SubstepRef: "s2_1"}, "L-p2s2_2": {Id: "L-p2s2_2", Value: "pasture:p2-user:s2_2-urd", Special: false, PhaseRef: "p2", SubstepRef: "s2_2"}, "L-p3s3": {Id: "L-p3s3", Value: "pasture:p3-plan:s3-propose", Special: false, PhaseRef: "p3", SubstepRef: "s3"}, "L-p4s4": {Id: "L-p4s4", Value: "pasture:p4-plan:s4-review", Special: false, PhaseRef: "p4", SubstepRef: "s4"}, "L-p5s5": {Id: "L-p5s5", Value: "pasture:p5-user:s5-uat", Special: false, PhaseRef: "p5", SubstepRef: "s5"}, "L-p6s6": {Id: "L-p6s6", Value: "pasture:p6-plan:s6-ratify", Special: false, PhaseRef: "p6", SubstepRef: "s6"}, "L-p7s7": {Id: "L-p7s7", Value: "pasture:p7-plan:s7-handoff", Special: false, PhaseRef: "p7", SubstepRef: "s7"}, "L-p8s8": {Id: "L-p8s8", Value: "pasture:p8-impl:s8-plan", Special: false, PhaseRef: "p8", SubstepRef: "s8"}, "L-p9s9": {Id: "L-p9s9", Value: "pasture:p9-impl:s9-slice", Special: false, PhaseRef: "p9", SubstepRef: "s9"}, "L-p10s10": {Id: "L-p10s10", Value: "pasture:p10-impl:s10-review", Special: false, PhaseRef: "p10", SubstepRef: "s10"}, "L-p11s11": {Id: "L-p11s11", Value: "pasture:p11-user:s11-uat", Special: false, PhaseRef: "p11", SubstepRef: "s11"}, "L-p12s12": {Id: "L-p12s12", Value: "pasture:p12-impl:s12-landing", Special: false, PhaseRef: "p12", SubstepRef: "s12"}, "L-urd": {Id: "L-urd", Value: "pasture:urd", Special: true, Description: "User Requirements Document"}, "L-superseded": {Id: "L-superseded", Value: "pasture:superseded", Special: true, Description: "Superseded proposal or plan"}, "L-sev-blocker": {Id: "L-sev-blocker", Value: "pasture:severity:blocker", Special: true, SeverityRef: "BLOCKER"}, "L-sev-import": {Id: "L-sev-import", Value: "pasture:severity:important", Special: true, SeverityRef: "IMPORTANT"}, "L-sev-minor": {Id: "L-sev-minor", Value: "pasture:severity:minor", Special: true, SeverityRef: "MINOR"}, "L-followup": {Id: "L-followup", Value: "pasture:epic-followup", Special: true, Description: "Follow-up epic for non-blocking findings"}, }
LabelSpecs maps label IDs to their full specifications. Mirrors Python LABEL_SPECS dict.
var PhaseSpecs = map[protocol.PhaseId]PhaseSpec{ protocol.PhaseRequest: { Id: protocol.PhaseRequest, Name: "Request", Number: 1, Domain: types.DomainUser, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect}, Transitions: []Transition{ { ToPhase: protocol.PhaseElicit, Condition: "classification confirmed, research and explore complete", }, }, }, protocol.PhaseElicit: { Id: protocol.PhaseElicit, Name: "Elicit", Number: 2, Domain: types.DomainUser, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect}, Transitions: []Transition{ { ToPhase: protocol.PhasePropose, Condition: "URD created with structured requirements", }, }, }, protocol.PhasePropose: { Id: protocol.PhasePropose, Name: "Propose", Number: 3, Domain: types.DomainPlan, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect}, Transitions: []Transition{ { ToPhase: protocol.PhaseReview, Condition: "proposal created", }, }, }, protocol.PhaseReview: { Id: protocol.PhaseReview, Name: "Review", Number: 4, Domain: types.DomainPlan, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect, types.RoleReviewer}, Transitions: []Transition{ { ToPhase: protocol.PhasePlanReview, Condition: "all 3 reviewers vote ACCEPT", }, { ToPhase: protocol.PhasePropose, Condition: "any reviewer votes REVISE", Action: "create PROPOSAL-{N+1}, mark current pasture:superseded", }, }, }, protocol.PhasePlanReview: { Id: protocol.PhasePlanReview, Name: "Plan UAT", Number: 5, Domain: types.DomainUser, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect}, Transitions: []Transition{ { ToPhase: protocol.PhaseRatify, Condition: "user accepts plan", }, { ToPhase: protocol.PhasePropose, Condition: "user requests changes", Action: "create PROPOSAL-{N+1}", }, }, }, protocol.PhaseRatify: { Id: protocol.PhaseRatify, Name: "Ratify", Number: 6, Domain: types.DomainPlan, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect}, Transitions: []Transition{ { ToPhase: protocol.PhaseHandoff, Condition: "proposal ratified, IMPL_PLAN placeholder created", }, }, }, protocol.PhaseHandoff: { Id: protocol.PhaseHandoff, Name: "Handoff", Number: 7, Domain: types.DomainPlan, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleArchitect, types.RoleSupervisor}, Transitions: []Transition{ { ToPhase: protocol.PhaseImplPlan, Condition: "handoff authored in the HANDOFF Beads task body", }, }, }, protocol.PhaseImplPlan: { Id: protocol.PhaseImplPlan, Name: "Impl Plan", Number: 8, Domain: types.DomainImpl, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleSupervisor}, Transitions: []Transition{ { ToPhase: protocol.PhaseWorkerSlices, Condition: "all slices created with leaf tasks, assigned, and dependency-chained", }, }, }, protocol.PhaseWorkerSlices: { Id: protocol.PhaseWorkerSlices, Name: "Worker Slices", Number: 9, Domain: types.DomainImpl, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleSupervisor, types.RoleWorker}, Transitions: []Transition{ { ToPhase: protocol.PhaseCodeReview, Condition: "all slices complete, quality gates pass", }, }, }, protocol.PhaseCodeReview: { Id: protocol.PhaseCodeReview, Name: "Code Review", Number: 10, Domain: types.DomainImpl, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleSupervisor, types.RoleReviewer}, Transitions: []Transition{ { ToPhase: protocol.PhaseImplUAT, Condition: "all 3 reviewers ACCEPT, all BLOCKERs resolved", }, { ToPhase: protocol.PhaseWorkerSlices, Condition: "any reviewer votes REVISE", Action: "fix BLOCKERs in affected slices, then re-review", }, }, }, protocol.PhaseImplUAT: { Id: protocol.PhaseImplUAT, Name: "Impl UAT", Number: 11, Domain: types.DomainUser, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleSupervisor}, Transitions: []Transition{ { ToPhase: protocol.PhaseLanding, Condition: "user accepts implementation", }, { ToPhase: protocol.PhaseWorkerSlices, Condition: "user requests changes", Action: "create fix tasks in affected slices", }, }, }, protocol.PhaseLanding: { Id: protocol.PhaseLanding, Name: "Landing", Number: 12, Domain: types.DomainImpl, OwnerRoles: []types.RoleId{types.RoleEpoch, types.RoleSupervisor}, Transitions: []Transition{ { ToPhase: protocol.PhaseComplete, Condition: "git push succeeds, all tasks closed or dependency-resolved", }, }, }, }
PhaseSpecs maps each PhaseId to its full specification. Mirrors Python PHASE_SPECS dict.
var ProcedureSteps = map[types.RoleId][]ProcedureStep{ types.RoleEpoch: {}, types.RoleArchitect: {}, types.RoleReviewer: {}, types.RoleSupervisor: { { Id: "S-supervisor-call-skill", Order: 1, Instruction: "Call Skill(/pasture:supervisor) to load role instructions", Command: "Skill(/pasture:supervisor)", }, { Id: "S-supervisor-read-plan", Order: 2, Instruction: "Read RATIFIED_PLAN, URD, UAT, and elicit tasks via bd show for full context", Command: "bd show <ratified-plan-id> && bd show <urd-id> && bd show <uat-id> && bd show <elicit-id>", }, { Id: "S-supervisor-explore-ephemeral", Order: 3, Instruction: "Spawn ephemeral Explore subagents via Task tool for scoped codebase queries", Context: "Each subagent is short-lived and returns findings; no standing team overhead", }, { Id: "S-supervisor-decompose-slices", Order: 4, Instruction: "Decompose into vertical slices", Context: "Vertical slices give one worker end-to-end ownership of a feature path " + "(types → tests → impl → wiring) with clear file boundaries", NextState: protocol.PhaseImplPlan, }, { Id: "S-supervisor-create-leaf-tasks", Order: 5, Instruction: "Create leaf tasks (L1/L2/L3) for every slice", Command: `bd create --labels pasture:p9-impl:s9-slice --title "SLICE-{K}-L{1,2,3}: <description>" ...`, Examples: []Example{ { Id: "S-supervisor-create-leaf-tasks-frontmatter", Lang: "bash", Label: "template", Code: "bd create --labels pasture:p9-impl:s9-slice \\\n" + " --title \"SLICE-1-L1: Types -- <slice name>\" \\\n" + " --description \"---\n" + "references:\n" + " slice: <slice-1-id>\n" + " impl_plan: <impl-plan-task-id>\n" + " urd: <urd-task-id>\n" + "---\n" + "Layer 1: types and interfaces for <slice name>.\"", AlsoIllustrates: "C-frontmatter-refs", }, }, }, { Id: "S-supervisor-spawn-workers", Order: 6, Instruction: "Spawn workers via the Agent tool — " + "set `name` for a named teammate, leave `name` empty for a backgrounded subagent " + "(NOT aura-swarm). " + "Choose model: sonnet for non-trivial slices, haiku for trivial changes. " + "Set thinking effort to match slice complexity.", NextState: protocol.PhaseWorkerSlices, }, }, types.RoleWorker: { { Id: "S-worker-types", Order: 1, Instruction: "Types, interfaces, schemas (no deps)", }, { Id: "S-worker-tests", Order: 2, Instruction: "Tests importing production code (will fail initially)", }, { Id: "S-worker-impl", Order: 3, Instruction: "Make tests pass. Wire with real dependencies. No TODOs.", NextState: protocol.PhaseWorkerSlices, }, }, }
ProcedureSteps maps each RoleId to its ordered startup procedure steps. Mirrors Python PROCEDURE_STEPS dict.
var ReviewAxisSpecs = map[string]ReviewAxisSpec{ "axis-correctness": { Id: "axis-correctness", Letter: "correctness", Name: "Correctness", Short: "Spirit and technicality", KeyQuestions: []string{ "Does the implementation faithfully serve the user's original request?", "Are technical decisions consistent with the rationale in the proposal?", "Are there gaps where the proposal says one thing but the code does another?", }, }, "axis-test_quality": { Id: "axis-test_quality", Letter: "test_quality", Name: "Test quality", Short: "Test strategy adequacy", KeyQuestions: []string{ "Favour integration tests over brittle unit tests?", "System under test NOT mocked — mock dependencies only?", "Shared fixtures for common test values?", "Assert observable outcomes, not internal state?", }, }, "axis-elegance": { Id: "axis-elegance", Letter: "elegance", Name: "Elegance", Short: "Complexity matching", KeyQuestions: []string{ "Design the API you know you will need?", "No over-engineering (premature abstractions, plugin systems)?", "No under-engineering (cutting corners on security or correctness)?", "Complexity proportional to innate problem complexity?", }, }, }
ReviewAxisSpecs maps axis IDs to their full specifications. Mirrors Python REVIEW_AXIS_SPECS dict.
var RoleSpecs = map[types.RoleId]RoleSpec{ types.RoleEpoch: { Id: types.RoleEpoch, Name: "Epoch", Description: "Master orchestrator for full 12-phase workflow", Model: "opus", Thinking: "medium", Tools: []string{"Read", "Glob", "Grep", "Bash", "Skill", "Agent", "Task", "SendMessage"}, OwnedPhases: []protocol.PhaseId{ protocol.PhaseRequest, protocol.PhaseElicit, protocol.PhasePropose, protocol.PhaseReview, protocol.PhasePlanReview, protocol.PhaseRatify, protocol.PhaseHandoff, protocol.PhaseImplPlan, protocol.PhaseWorkerSlices, protocol.PhaseCodeReview, protocol.PhaseImplUAT, protocol.PhaseLanding, }, Introduction: "You are the master orchestrator for the full 12-phase epoch lifecycle. " + "You delegate planning phases (1-7) to the architect and implementation phases (7-12) " + "to the supervisor.", OwnershipNarrative: "You own the full 12-phase lifecycle from Request to Landing. " + "You delegate phases 1-7 to the architect and phases 7-12 to the supervisor. " + "The epoch role coordinates the complete workflow end-to-end and is the only role " + "that spans all phases.", }, types.RoleArchitect: { Id: types.RoleArchitect, Name: "Architect", Description: "Specification writer and implementation designer", Model: "opus", Thinking: "medium", Tools: []string{"Read", "Glob", "Grep", "Bash", "Skill", "Agent", "Task", "SendMessage"}, OwnedPhases: []protocol.PhaseId{ protocol.PhaseRequest, protocol.PhaseElicit, protocol.PhasePropose, protocol.PhaseReview, protocol.PhasePlanReview, protocol.PhaseRatify, protocol.PhaseHandoff, }, Introduction: "You design specifications and coordinate the planning phases of epochs. " + "See the project's AGENTS.md and ~/.claude/CLAUDE.md for coding standards and constraints.", OwnershipNarrative: "You own Phases 1-7 of the epoch: " + "capture and classify user request (p1), " + "run requirements elicitation URE survey (p2), " + "create PROPOSAL-N with full technical plan (p3), " + "spawn 3 axis-specific reviewers and loop until consensus (p4), " + "present plan to user for acceptance test (p5), " + "add ratify label to accepted PROPOSAL-N (p6), " + "create handoff document and transfer to supervisor (p7).", Behaviors: []BehaviorSpec{ { Id: "B-arch-elicit", Given: "user request captured", When: "starting", Then: "run /pasture:user-elicit for URE survey", ShouldNot: "skip elicitation phase", }, { Id: "B-arch-bdd", Given: "a feature request", When: "writing plan", Then: "use BDD Given/When/Then format with acceptance criteria", ShouldNot: "write vague requirements", }, { Id: "B-arch-reviewers", Given: "plan ready", When: "requesting review", Then: "spawn 3 axis-specific reviewers (A=Correctness, B=Test quality, C=Elegance)", ShouldNot: "spawn reviewers without axis assignment", }, { Id: "B-arch-uat", Given: "consensus reached (all 3 ACCEPT)", When: "proceeding", Then: "run /pasture:user-uat before ratifying", ShouldNot: "skip user acceptance test", }, { Id: "B-arch-ratify", Given: "UAT passed", When: "ratifying", Then: "add pasture:p6-plan:s6-ratify label to PROPOSAL-N", ShouldNot: "close or delete the proposal task", }, }, }, types.RoleReviewer: { Id: types.RoleReviewer, Name: "Reviewer", Description: "End-user alignment reviewer for plans and code", Model: "sonnet", Tools: []string{"Read", "Glob", "Grep", "Bash", "Skill", "SendMessage"}, OwnedPhases: []protocol.PhaseId{ protocol.PhaseReview, protocol.PhaseCodeReview, }, Introduction: "You review from an end-user alignment perspective. " + "See the project's protocol/CONSTRAINTS.md for coding standards.", OwnershipNarrative: "You participate in two phases: " + "Phase 4 (plan review) — evaluate PROPOSAL-N against one axis using binary ACCEPT/REVISE, " + "NO severity tree; " + "Phase 10 (code review) — review ALL implementation slices against your axis using " + "full severity tree (BLOCKER/IMPORTANT/MINOR), EAGER creation of all 3 severity groups.", Behaviors: []BehaviorSpec{ { Id: "B-rev-end-user", Given: "a review assignment", When: "reviewing", Then: "apply end-user alignment criteria", ShouldNot: "focus only on technical details", }, { Id: "B-rev-revise-feedback", Given: "issues found", When: "voting", Then: "vote REVISE with specific actionable feedback", ShouldNot: "vote REVISE without suggestions", }, { Id: "B-rev-accept", Given: "all criteria met", When: "voting", Then: "vote ACCEPT with brief rationale", ShouldNot: "delay consensus unnecessarily", }, { Id: "B-rev-all-slices", Given: "impl review (Phase 10)", When: "assigned", Then: "review ALL slices (not just one)", ShouldNot: "skip any slice", }, }, }, types.RoleSupervisor: { Id: types.RoleSupervisor, Name: "Supervisor", Description: "Task coordinator, spawns workers, manages parallel execution", Model: "opus", Thinking: "medium", Tools: []string{"Read", "Glob", "Grep", "Bash", "Skill", "Agent", "Task", "SendMessage"}, OwnedPhases: []protocol.PhaseId{ protocol.PhaseHandoff, protocol.PhaseImplPlan, protocol.PhaseWorkerSlices, protocol.PhaseCodeReview, protocol.PhaseImplUAT, protocol.PhaseLanding, }, Introduction: "You coordinate parallel task execution. " + "See the project's AGENTS.md and ~/.claude/CLAUDE.md for coding standards and constraints.", OwnershipNarrative: "You own Phases 7-12 of the epoch: " + "receive handoff from architect (p7), " + "create vertical slice decomposition IMPL_PLAN (p8), " + "spawn workers for parallel implementation SLICE-N (p9), " + "spawn reviewers for per-slice code review with severity tree (p10), " + "coordinate user acceptance test (p11), " + "commit, push, and hand off (p12). " + "You NEVER implement code directly — all implementation is delegated to workers.", Behaviors: []BehaviorSpec{ { Id: "B-sup-read-context", Given: "handoff received", When: "starting", Then: "read ratified plan, URD, UAT, and elicit tasks for full context", ShouldNot: "start without reading all four", }, { Id: "B-sup-model-trivial", Given: "trivial changes (single-file edits, config tweaks, typo fixes)", When: "spawning a worker", Then: "use model: haiku to minimize cost and latency", ShouldNot: "use a heavyweight model for trivial work", }, { Id: "B-sup-model-nontrivial", Given: "non-trivial changes (multi-file, architectural, logic-heavy)", When: "spawning a worker", Then: "prefer model: sonnet for the Task tool to ensure quality", ShouldNot: "default to haiku for complex work", }, { Id: "B-sup-ride-the-wave", Given: "Phase 8-10 execution", When: "starting implementation", Then: "follow the Ride the Wave cycle: plan tasks with integration points, " + "launch the wave of workers, spawn reviewers for per-slice review " + "(clean exit = 0 BLOCKER + 0 IMPORTANT + 0 MINOR), workers fix per-slice with atomic commits, " + "and iterate review -> fix -> re-review up to the chosen review-effort budget until a fix-free clean round confirms 0/0/0; on budget exhaustion without clean, surface outstanding findings to the user at a gate", ShouldNot: "skip any stage; batch review across slices; hardcode the budget; proceed past the chosen budget without surfacing to the user; " + "close a wave with any finding silently outstanding", }, }, }, types.RoleWorker: { Id: types.RoleWorker, Name: "Worker", Description: "Vertical slice implementer (full production code path)", Model: "sonnet", Tools: []string{"Read", "Glob", "Grep", "Bash", "Skill", "Edit", "Write", "SendMessage"}, OwnedPhases: []protocol.PhaseId{protocol.PhaseWorkerSlices}, 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.", OwnershipNarrative: "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.", Behaviors: []BehaviorSpec{ { Id: "B-worker-vertical-ownership", Given: "vertical slice assignment", When: "implementing", Then: "own full production code path (types → tests → impl → wiring)", ShouldNot: "implement only horizontal layer", }, { Id: "B-worker-plan-backwards", Given: "production code path", When: "planning", Then: "plan backwards from end point to types", ShouldNot: "start with types without knowing the end", }, { Id: "B-worker-test-production-code", Given: "tests", When: "writing", Then: "import actual production code (CLI/API users will run)", ShouldNot: "create test-only export or dual code paths", }, { Id: "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", ShouldNot: "treat passing tests as sufficient verification without a manual walkthrough", }, { Id: "B-worker-blocker", Given: "a blocker", When: "unable to proceed", Then: "use /pasture:worker-blocked with details", ShouldNot: "guess or work around", }, }, }, }
RoleSpecs maps each RoleId to its full specification. Mirrors Python ROLE_SPECS dict.
FragRevVoteOptions: func() SharedFragment { prose := ProseSection{ Id: string(FragRevVoteOptions), Title: "Vote Options", Content: `| Vote | When | |------|------| | ACCEPT | All review criteria satisfied; no BLOCKER items | | REVISE | BLOCKER issues found; must provide actionable feedback | Binary only. No intermediate levels.`, } return SharedFragment{ Id: FragRevVoteOptions, Kind: FragmentKindProse, Prose: &prose, } }(), FragSupReviewAllSlices: { Id: FragSupReviewAllSlices, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragSupReviewAllSlices), Given: "all slices complete", When: "starting review", Then: "spawn 3 reviewers for ALL slices", ShouldNot: "assign reviewers to single slices", }, }, FragSupReviewCheckEach: { Id: FragSupReviewCheckEach, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragSupReviewCheckEach), Given: "reviewer assigned", When: "reviewing", Then: "check each slice against criteria", ShouldNot: "skip any slice", }, }, FragSupReviewSeverityGroups: { Id: FragSupReviewSeverityGroups, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragSupReviewSeverityGroups), Given: "review round", When: "creating severity groups", Then: "ALWAYS create 3 severity groups (BLOCKER, IMPORTANT, MINOR) per round even if empty", ShouldNot: "lazily create groups only when findings exist", }, }, FragSupBlockerDualParent: { Id: FragSupBlockerDualParent, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragSupBlockerDualParent), Given: "BLOCKER finding", When: "wiring dependencies", Then: "add dual-parent: blocks BOTH the severity group AND the slice", ShouldNot: "wire BLOCKER to only one parent", }, }, FragSupDeferredFollowup: { Id: FragSupDeferredFollowup, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragSupDeferredFollowup), Given: "a review finding (BLOCKER, IMPORTANT, or MINOR)", When: "categorizing", Then: "track it in its severity group; ALL severity groups must reach 0 before wave close — the FOLLOWUP epic is fed ONLY by user-DEFER'd UAT items, never by any review severity", ShouldNot: "route any review severity (BLOCKER/IMPORTANT/MINOR) to the FOLLOWUP epic; close a wave with any finding outstanding", }, }, FragSupFollowupEpicTiming: { Id: FragSupFollowupEpicTiming, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragSupFollowupEpicTiming), Given: "UAT (Phase 5 or 11) produces one or more user-DEFER'd items", When: "finishing UAT", Then: "supervisor creates the FOLLOWUP epic from the user-DEFER'd UAT items only", ShouldNot: "create a FOLLOWUP epic from any review severity (BLOCKER/IMPORTANT/MINOR)", }, }, FragSupSeverityTree: func() SharedFragment { namingConvention := ProseSection{ Id: string(FragSupNamingConvention), Title: "Naming Convention", Content: "```" + ` SLICE-{N}-REVIEW-{axis}-{round} ` + "```" + ` Where axis = A (Correctness), B (Test quality), C (Elegance). Examples: - ` + "`SLICE-1-REVIEW-A-1`" + ` — Reviewer A (Correctness), Round 1, SLICE-1 - ` + "`SLICE-2-REVIEW-C-2`" + ` — Reviewer C (Elegance), Round 2, SLICE-2 Severity groups: - ` + "`SLICE-1-REVIEW-A-1 BLOCKER`" + ` - ` + "`SLICE-1-REVIEW-A-1 IMPORTANT`" + ` - ` + "`SLICE-1-REVIEW-A-1 MINOR`", } prose := ProseSection{ Id: string(FragSupSeverityTree), Title: "Severity Tree (EAGER Creation)", Content: `Per [frag--sup-review-severity-groups], create all 3 severity groups immediately: ` + "```" + `bash # Step 1: Create all 3 severity groups immediately (EAGER) BLOCKER_ID=$(bd create --title "SLICE-1-REVIEW-A-1 BLOCKER" \ --labels "pasture:severity:blocker,pasture:p10-impl:s10-review" \ --description "--- references: slice: <slice-1-id> review_round: 1 --- BLOCKER findings from Reviewer A (Correctness) on SLICE-1.") IMPORTANT_ID=$(bd create --title "SLICE-1-REVIEW-A-1 IMPORTANT" \ --labels "pasture:severity:important,pasture:p10-impl:s10-review" \ --description "--- references: slice: <slice-1-id> review_round: 1 --- IMPORTANT findings from Reviewer A (Correctness) on SLICE-1.") MINOR_ID=$(bd create --title "SLICE-1-REVIEW-A-1 MINOR" \ --labels "pasture:severity:minor,pasture:p10-impl:s10-review" \ --description "--- references: slice: <slice-1-id> review_round: 1 --- MINOR findings from Reviewer A (Correctness) on SLICE-1.") # Step 2: Wire severity groups to the review round task bd dep add <review-round-id> --blocked-by $BLOCKER_ID bd dep add <review-round-id> --blocked-by $IMPORTANT_ID bd dep add <review-round-id> --blocked-by $MINOR_ID # NEVER wire severity groups to IMPL_PLAN or slices directly. # BLOCKER findings block slices via dual-parent (see below). # IMPORTANT/MINOR must ALSO reach 0 before wave close — they are NOT routed to FOLLOWUP. # The FOLLOWUP epic is fed ONLY by user-DEFER'd UAT items (see Follow-up Epic section). # Step 3: Close empty groups immediately # If a group has no findings, close it right away bd close $IMPORTANT_ID # if no IMPORTANT findings bd close $MINOR_ID # if no MINOR findings ` + "```", Subsections: []ProseSection{namingConvention}, } return SharedFragment{ Id: FragSupSeverityTree, Kind: FragmentKindProse, Prose: &prose, } }(), FragSupNamingConvention: func() SharedFragment { prose := ProseSection{ Id: string(FragSupNamingConvention), Title: "Naming Convention", Content: "```" + ` SLICE-{N}-REVIEW-{axis}-{round} ` + "```" + ` Where axis = A (Correctness), B (Test quality), C (Elegance). Examples: - ` + "`SLICE-1-REVIEW-A-1`" + ` — Reviewer A (Correctness), Round 1, SLICE-1 - ` + "`SLICE-2-REVIEW-C-2`" + ` — Reviewer C (Elegance), Round 2, SLICE-2 Severity groups: - ` + "`SLICE-1-REVIEW-A-1 BLOCKER`" + ` - ` + "`SLICE-1-REVIEW-A-1 IMPORTANT`" + ` - ` + "`SLICE-1-REVIEW-A-1 MINOR`", } return SharedFragment{ Id: FragSupNamingConvention, Kind: FragmentKindProse, Prose: &prose, } }(), FragRevPlanVoteOptions: func() SharedFragment { prose := ProseSection{ Id: string(FragRevPlanVoteOptions), Title: "Vote Options", Content: `| Vote | When | |------|------| | ACCEPT | All review criteria satisfied; no BLOCKER items | | REVISE | BLOCKER issues found; must provide actionable feedback | Binary only. No severity tree for plan reviews.`, } return SharedFragment{ Id: FragRevPlanVoteOptions, Kind: FragmentKindProse, Prose: &prose, } }(), FragValidationCases: { Id: FragValidationCases, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragValidationCases), Given: "any REQUEST (every request, not only fix-intent ones)", When: "eliciting (URE), acceptance-testing (UAT), or implementing", Then: "elicit concrete validation cases — a definition of done plus correct and incorrect behaviours (inputs/behaviors that must pass or must fail), confirm the case set with the user in UAT, evaluate the implementation against them, and store failing real-data cases as test fixtures", ShouldNot: "ship without validation cases; treat validation cases as applying to fix-intent requests only; introduce a request-type axis or enum to gate them", }, }, FragReviewCleanExit: { Id: FragReviewCleanExit, Kind: FragmentKindBehavior, Behavior: &BehaviorSpec{ Id: string(FragReviewCleanExit), Given: "per-slice code review", When: "evaluating review results", Then: "iterate review -> fix -> re-review up to the chosen review-effort budget; clean = 0 BLOCKER + 0 IMPORTANT + 0 MINOR within budget; on budget exhaustion without clean, SURFACE the outstanding findings to the user at a gate for a decision", ShouldNot: "hardcode the budget; proceed past the chosen budget without surfacing outstanding findings to the user; loop forever when a finite budget was chosen", }, }, }
SharedFragmentSpecs is the canonical registry of reusable shared fragments. Keyed by FragmentId typed constant (must match the FragRef field used in placement marker entries).
SLICE-2 adds: FragRevVoteOptions (green-enabler; resolves the sole pre-existing same-id collision between reviewer-vote and reviewer skill bodies). Canonical content per D3 (UAT-ratified): ACCEPT row = "All review criteria satisfied; no BLOCKER items". Both consumer bodies carry fragRef markers. Set keys MUST equal AllFragmentIds (validated by ValidateGlobalIds).
SLICE-3 adds: 6 supervisor review-wave behavior fragments (FragSupReview*, FragSupBlockerDualParent, FragSupDeferredFollowup, FragSupFollowupEpicTiming) and 2 prose fragments (FragSupSeverityTree, FragSupNamingConvention). These replace identical inline definitions in both the supervisor and impl-review skill bodies, eliminating the last same-id collision group. Canonical content = supervisor text.
SLICE-1 (epoch improvements) adds: FragValidationCases (R6, wired into user-elicit/user-uat/worker-implement bodies by SLICE-2) and FragReviewCleanExit (R7, wired into supervisor/impl-review bodies by SLICE-3). It also renames FragSupImportantMinorFollowup -> FragSupDeferredFollowup (R7/A1): review severities no longer feed FOLLOWUP; the FOLLOWUP epic is fed solely by user-DEFER'd UAT items.
var SkillBodySpecs = map[string]SkillBody{
"supervisor": supervisorBody,
"supervisor-plan-tasks": supervisorPlanTasksBody,
"supervisor-spawn-worker": supervisorSpawnWorkerBody,
"worker": workerBody,
"architect": architectBody,
"reviewer": reviewerBody,
"impl-review": implReviewBody,
"architect-handoff": architectHandoffBody,
"architect-propose-plan": architectProposePlanBody,
"architect-ratify": architectRatifyBody,
"architect-request-review": architectRequestReviewBody,
"epoch": epochBody,
"explore": exploreBody,
"impl-slice": implSliceBody,
"research": researchBody,
"reviewer-comment": reviewerCommentBody,
"reviewer-review-code": reviewerReviewCodeBody,
"reviewer-review-plan": reviewerReviewPlanBody,
"reviewer-vote": reviewerVoteBody,
"status": statusBody,
"supervisor-commit": supervisorCommitBody,
"supervisor-track-progress": supervisorTrackProgressBody,
"swarm": swarmBody,
"user-elicit": userElicitBody,
"user-request": userRequestBody,
"user-uat": userUatBody,
"worker-blocked": workerBlockedBody,
"worker-complete": workerCompleteBody,
"worker-implement": workerImplementBody,
}
var SubstepDataMap = map[string][]SubstepData{ "p1": { { Id: "s1_1", Type: "classify", Execution: "sequential", Order: 1, LabelRef: "L-p1s1_1", Description: "Classify request along 4 axes: scope, complexity, risk, domain novelty", }, { Id: "s1_2", Type: "research", Execution: "parallel", Order: 2, ParallelGroup: "p1-discovery", LabelRef: "L-p1s1_2", Description: "Find domain standards, prior art, relevant documentation", }, { Id: "s1_3", Type: "explore", Execution: "parallel", Order: 2, ParallelGroup: "p1-discovery", LabelRef: "L-p1s1_3", Description: "Codebase exploration for integration points", }, }, "p2": { { Id: "s2_1", Type: "elicit", Execution: "sequential", Order: 1, LabelRef: "L-p2s2_1", Description: "URE survey: structured Q&A with user to capture requirements", }, { Id: "s2_2", Type: "urd", Execution: "sequential", Order: 2, LabelRef: "L-p2s2_2", Description: "Create URD as single source of truth for requirements", ExtraLabel: "L-urd", }, }, "p3": { { Id: "s3", Type: "propose", Execution: "sequential", Order: 1, LabelRef: "L-p3s3", Description: "Full technical proposal: interfaces, approach, validation checklist, BDD criteria", }, }, "p4": { { Id: "s4", Type: "review", Execution: "parallel", Order: 1, LabelRef: "L-p4s4", Description: "Each reviewer assesses one axis (A/B/C). All 3 must ACCEPT.", Instances: &SubstepInstances{Count: "3", Per: "review-axis"}, }, }, "p5": { { Id: "s5", Type: "uat", Execution: "sequential", Order: 1, LabelRef: "L-p5s5", Description: "Present plan to user with demonstrative examples. User approves or requests changes.", }, }, "p6": { { Id: "s6", Type: "ratify", Execution: "sequential", Order: 1, LabelRef: "L-p6s6", Description: "Add ratify label. Mark prior proposals pasture:superseded. Create placeholder IMPL_PLAN.", }, }, "p7": { { Id: "s7", Type: "handoff", Execution: "sequential", Order: 1, LabelRef: "L-p7s7", Description: "Create handoff document with full inline provenance. Transfer to supervisor.", }, }, "p8": { { Id: "s8", Type: "plan", Execution: "sequential", Order: 1, LabelRef: "L-p8s8", Description: "Identify production code paths. Create SLICE-N tasks with leaf tasks. Assign workers.", StartupSequence: true, }, }, "p9": { { Id: "s9", Type: "slice", Execution: "parallel", Order: 1, LabelRef: "L-p9s9", Description: "Each worker owns full vertical: types, tests, implementation, wiring", Instances: &SubstepInstances{Count: "N", Per: "production-code-path"}, }, }, "p10": { { Id: "s10", Type: "review", Execution: "parallel", Order: 1, LabelRef: "L-p10s10", Description: "Each reviewer reviews ALL slices against their axis. EAGER severity tree.", Instances: &SubstepInstances{Count: "3", Per: "review-axis"}, }, }, "p11": { { Id: "s11", Type: "uat", Execution: "sequential", Order: 1, LabelRef: "L-p11s11", Description: "Present implementation to user. User approves or requests fixes.", }, }, "p12": { { Id: "s12", Type: "landing", Execution: "sequential", Order: 1, LabelRef: "L-p12s12", Description: "git agent-commit, bd sync, git push. Close upstream tasks.", }, }, }
SubstepDataMap maps phase ID strings to their ordered substep data. Mirrors Python SUBSTEP_DATA dict.
var TitleConventions = []TitleConvention{
{Pattern: "REQUEST: {description}", LabelRef: "L-p1s1_1", CreatedBy: "epoch,architect", PhaseRef: "p1"},
{Pattern: "ELICIT: {description}", LabelRef: "L-p2s2_1", CreatedBy: "architect", PhaseRef: "p2"},
{Pattern: "URD: {description}", LabelRef: "L-p2s2_2", CreatedBy: "architect", PhaseRef: "p2", ExtraLabelRef: "L-urd"},
{
Pattern: "PROPOSAL-{N}: {description}", LabelRef: "L-p3s3", CreatedBy: "architect", PhaseRef: "p3",
Note: "N increments per revision. Old proposals marked pasture:superseded.",
},
{
Pattern: "PROPOSAL-{N}-REVIEW-{axis}-{round}: {description}", LabelRef: "L-p4s4", CreatedBy: "reviewer", PhaseRef: "p4",
Note: "axis=A|B|C, round starts at 1",
},
{Pattern: "UAT-{N}: {description}", LabelRef: "L-p5s5", CreatedBy: "architect", PhaseRef: "p5"},
{Pattern: "IMPL_PLAN: {description}", LabelRef: "L-p8s8", CreatedBy: "supervisor", PhaseRef: "p8"},
{
Pattern: "SLICE-{N}: {description}", LabelRef: "L-p9s9", CreatedBy: "supervisor", PhaseRef: "p9",
Note: "N identifies slice within the implementation plan",
},
{
Pattern: "SLICE-{N}-REVIEW-{axis}-{round}: {description}", LabelRef: "L-p10s10", CreatedBy: "reviewer", PhaseRef: "p10",
Note: "axis=A|B|C, round starts at 1",
},
{
Pattern: "IMPL-REVIEW-{axis}-{round}: {description}", LabelRef: "L-p10s10", CreatedBy: "supervisor", PhaseRef: "p10",
Note: "When reviewing all slices collectively",
},
{
Pattern: "FOLLOWUP: {description}", LabelRef: "L-followup", CreatedBy: "supervisor",
Note: "Follow-up epic created at UAT when user-DEFER'd items exist (never from review severities; " +
"all review findings must reach 0 before wave close). " +
"Single-parent epic relationship — no followup-of-followup.",
},
{
Pattern: "FOLLOWUP_URE: {description}", LabelRef: "L-p2s2_1", CreatedBy: "supervisor", PhaseRef: "p2",
Note: "Scoping URE to determine which user-DEFER'd UAT items to address",
},
{
Pattern: "FOLLOWUP_URD: {description}", LabelRef: "L-p2s2_2", CreatedBy: "supervisor", PhaseRef: "p2",
ExtraLabelRef: "L-urd",
Note: "Requirements doc for follow-up scope. References original URD.",
},
{
Pattern: "FOLLOWUP_PROPOSAL-{N}: {description}", LabelRef: "L-p3s3", CreatedBy: "architect", PhaseRef: "p3",
Note: "Proposal accounting for original URD + FOLLOWUP_URD + outstanding findings",
},
{
Pattern: "FOLLOWUP_IMPL_PLAN: {description}", LabelRef: "L-p8s8", CreatedBy: "supervisor", PhaseRef: "p8",
Note: "Implementation plan for follow-up slices",
},
{
Pattern: "FOLLOWUP_SLICE-{N}: {description}", LabelRef: "L-p9s9", CreatedBy: "supervisor", PhaseRef: "p9",
Note: "Follow-up slice. Adopts user-DEFER'd UAT-item leaf tasks as children " +
"(dual-parent: leaf blocks both the DEFER'd-items tracking group AND follow-up slice).",
},
}
TitleConventions is the ordered list of task title naming conventions. Mirrors Python TITLE_CONVENTIONS list. Note: In Go we use a slice (not a map) to preserve order, matching Python.
var WorkflowSpecs = map[string]Workflow{ "ride-the-wave": { Id: "ride-the-wave", Name: "Ride the Wave", RoleRef: types.RoleSupervisor, Description: "Coordinated Phase 8-10 execution pattern. The supervisor orchestrates " + "the full cycle: plan slices, launch workers, " + "spawn reviewers for per-slice review, workers fix, and re-review up to the chosen review-effort budget " + "until a fix-free clean round confirms 0 BLOCKER + 0 IMPORTANT + 0 MINOR; on budget exhaustion without clean, surface outstanding findings to the user at a gate.", Stages: []WorkflowStage{ { Id: "rtw-plan", Name: "Plan", Order: 1, Execution: "sequential", PhaseRef: protocol.PhaseImplPlan, Actions: []WorkflowAction{ { Id: "rtw-plan-read", Instruction: "Read RATIFIED_PLAN and URD via bd show", Command: "bd show <ratified-plan-id> && bd show <urd-id>", }, { Id: "rtw-plan-explore", Instruction: "Spawn ephemeral Explore subagents (`subagent_type=Explore`) for scoped codebase queries — NOT standing teams", }, { Id: "rtw-plan-decompose", Instruction: "Use Explore findings to decompose into vertical slices with integration points", }, { Id: "rtw-plan-leaf-tasks", Instruction: "Create leaf tasks (L1/L2/L3) for every slice", Command: "bd dep add <slice-id> --blocked-by <leaf-task-id>", }, }, OperationalDetail: "", ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "All slices created with leaf tasks, dependency-chained, assigned", }, }, }, { Id: "rtw-build", Name: "Build", Order: 2, Execution: "parallel", PhaseRef: protocol.PhaseWorkerSlices, Actions: []WorkflowAction{ { Id: "rtw-build-spawn", Instruction: "Spawn workers via the Agent tool — " + "set `name` for a named teammate, leave `name` empty for a backgrounded subagent " + "(NOT aura-swarm). " + "Choose model: sonnet for non-trivial slices, haiku for trivial changes. " + "Set thinking effort to match slice complexity.", }, { Id: "rtw-build-monitor", Instruction: "Monitor worker progress via bd list and bd show", Command: `bd list --labels="pasture:p9-impl:s9-slice" --status=in_progress`, }, { Id: "rtw-build-integrate", Instruction: "Supervisor commits at integration points (atomic commits) — commit small, integrate early and often", }, }, OperationalDetail: "", ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "All workers have notified completion via bd comments add", }, }, }, { Id: "rtw-review-fix", Name: "Review + Fix Cycles", Order: 3, Execution: "conditional-loop", PhaseRef: protocol.PhaseCodeReview, Actions: []WorkflowAction{ { Id: "rtw-review-spawn", Instruction: "Spawn reviewers via Task tool for per-slice code review", }, { Id: "rtw-review-severity", Instruction: "Reviewers create severity groups (BLOCKER/IMPORTANT/MINOR) per slice", }, { Id: "rtw-review-severity-track", Instruction: "Track findings in the 3 severity groups; ALL groups must reach 0 before wave close (FOLLOWUP is created later at UAT, fed only by user-DEFER'd items)", }, { Id: "rtw-review-fix", Instruction: "Workers fix ALL findings (BLOCKER, IMPORTANT, and MINOR)", }, }, OperationalDetail: "- Spawn 3 ephemeral reviewer subagents per round (same pattern as Phase 4 plan review)\n" + "- **CLEAN REVIEW** = 0 BLOCKER + 0 IMPORTANT + 0 MINOR from ALL reviewers on a fix-free round\n" + "- Per-slice fix+review; iterate up to the chosen review-effort budget\n" + "- Fix flow: Stage 3 (dirty review) -> Stage 2 (worker fixes) -> Stage 3 (re-review)\n" + "- Configurable review-effort budget (chosen at Phase 8: 3 rounds / 1 round / 0 rounds / unlimited / custom) — repeat review -> fix -> re-review until the slice is clean (0/0/0); on budget exhaustion without clean, surface outstanding findings to the user at a gate\n" + "- **MUST end on a review wave** — cannot proceed after a worker wave without review\n" + "\n" + "```text\n" + "Stage 3 Flow (per-slice):\n" + "\n" + " \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n" + " \u2502 Spawn 3 ephemeral reviewers \u2502\n" + " \u2502 Review slice (severity: BLOCKER/IMP/MIN)\u2502\n" + " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n" + " \u2502\n" + " CLEAN? \u251c\u2500\u2500 YES (0/0/0) \u2192 slice passes, proceed\n" + " \u2502\n" + " \u2514\u2500\u2500 NO (any finding remains)\n" + " \u2502\n" + " \u25bc\n" + " \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n" + " \u2502 Stage 2: worker \u2502\n" + " \u2502 fixes ALL findings \u2502\n" + " \u2502 (BLOCK/IMP/MINOR) \u2502\n" + " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n" + " \u2502\n" + " \u25bc\n" + " \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n" + " \u2502 Stage 3: re-review \u2502\n" + " \u2502 (new ephemeral \u2502\n" + " \u2502 reviewers) \u2502\n" + " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n" + " \u2502\n" + " loop (re-review)\n" + " \u2502\n" + " repeat until clean (0/0/0) \u2014 up to the chosen budget, else surface to user\n" + "```", ExitConditions: []ExitCondition{ { Type: "success", Condition: "All reviewers report 0 BLOCKER + 0 IMPORTANT + 0 MINOR on a fix-free clean round — proceed to Phase 11 UAT", }, { Type: "continue", Condition: "Any finding (BLOCKER, IMPORTANT, or MINOR) remains within budget — workers fix, spawn new ephemeral reviewers (up to the chosen review-effort budget; on exhaustion, surface to the user)", }, }, }, }, }, "layer-cake": { Id: "layer-cake", Name: "Layer Cake", RoleRef: types.RoleWorker, Description: "TDD layer-by-layer implementation within a vertical slice. " + "Worker implements types first, then tests (will fail), " + "then production code to make tests pass.", Stages: []WorkflowStage{ { Id: "lc-types", Name: "Types", Order: 1, Execution: "sequential", PhaseRef: protocol.PhaseWorkerSlices, Actions: []WorkflowAction{ { Id: "lc-types-read", Instruction: "Read slice task and identify required types", Command: "bd show <slice-task-id>", }, { Id: "lc-types-define", Instruction: "Define types, interfaces, and schemas (no deps) — only types for YOUR slice", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "All required types defined; file imports without error", }, }, }, { Id: "lc-tests", Name: "Tests", Order: 2, Execution: "sequential", PhaseRef: protocol.PhaseWorkerSlices, Actions: []WorkflowAction{ { Id: "lc-tests-write", Instruction: "Write tests importing production code (CLI/API users will run) — tests WILL fail", }, { Id: "lc-tests-verify-import", Instruction: "Verify tests import actual production code, not test-only export", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "Tests written and import production code; typecheck passes; tests fail (expected)", }, }, }, { Id: "lc-impl", Name: "Implementation + Wiring", Order: 3, Execution: "sequential", PhaseRef: protocol.PhaseWorkerSlices, Actions: []WorkflowAction{ { Id: "lc-impl-code", Instruction: "Implement production code to make Layer 2 tests pass", }, { Id: "lc-impl-wire", Instruction: "Wire with real dependencies (not mocks in production code)", }, { Id: "lc-impl-run-tests", Instruction: "Run tests — all Layer 2 tests must pass", }, { Id: "lc-impl-commit", Instruction: "Commit completed work", Command: "git agent-commit -m ...", }, { Id: "lc-impl-notify", Instruction: "Notify supervisor of completion via bd comments add", Command: `bd comments add <slice-id> "Implementation complete"`, }, }, ExitConditions: []ExitCondition{ { Type: "success", Condition: "All tests pass; no TODO placeholders; real deps wired; " + "production code path verified via code inspection", }, { Type: "escalate", Condition: "Blocker encountered — use /pasture:worker-blocked with details", }, }, }, }, }, "architect-state-flow": { Id: "architect-state-flow", Name: "Architect State Flow", RoleRef: types.RoleArchitect, Description: "Sequential planning phases 1-7. The architect captures requirements, " + "writes proposals, coordinates review consensus, and hands off to supervisor.", Stages: []WorkflowStage{ { Id: "asf-request", Name: "Request", Order: 1, Execution: "sequential", PhaseRef: protocol.PhaseRequest, Actions: []WorkflowAction{ { Id: "asf-request-capture", Instruction: "Capture user request verbatim via /pasture:user-request", }, { Id: "asf-request-classify", Instruction: "Classify request along 4 axes: scope, complexity, risk, domain novelty", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "Classification confirmed, research and explore complete", }, }, }, { Id: "asf-elicit", Name: "Elicit", Order: 2, Execution: "sequential", PhaseRef: protocol.PhaseElicit, Actions: []WorkflowAction{ { Id: "asf-elicit-ure", Instruction: "Run URE survey with user via /pasture:user-elicit", }, { Id: "asf-elicit-urd", Instruction: "Create URD as single source of truth for requirements", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "URD created with structured requirements", }, }, }, { Id: "asf-propose", Name: "Propose", Order: 3, Execution: "sequential", PhaseRef: protocol.PhasePropose, Actions: []WorkflowAction{ { Id: "asf-propose-write", Instruction: "Write full technical proposal: interfaces, approach, validation checklist, BDD criteria", }, { Id: "asf-propose-create", Instruction: "Create PROPOSAL-N task via /pasture:architect:propose-plan", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "Proposal created", }, }, }, { Id: "asf-review", Name: "Review", Order: 4, Execution: "conditional-loop", PhaseRef: protocol.PhaseReview, Actions: []WorkflowAction{ { Id: "asf-review-spawn", Instruction: "Spawn 3 axis-specific reviewers (A=Correctness, B=Test quality, C=Elegance)", }, { Id: "asf-review-wait", Instruction: "Wait for all 3 reviewers to vote", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "All 3 reviewers vote ACCEPT", }, { Type: "continue", Condition: "Any reviewer votes REVISE — create PROPOSAL-N+1, mark old as superseded, re-spawn reviewers", }, }, }, { Id: "asf-uat", Name: "Plan UAT", Order: 5, Execution: "sequential", PhaseRef: protocol.PhasePlanReview, Actions: []WorkflowAction{ { Id: "asf-uat-present", Instruction: "Present plan to user with demonstrative examples via /pasture:user-uat", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "User accepts plan", }, { Type: "continue", Condition: "User requests changes — create PROPOSAL-N+1", }, }, }, { Id: "asf-ratify", Name: "Ratify", Order: 6, Execution: "sequential", PhaseRef: protocol.PhaseRatify, Actions: []WorkflowAction{ { Id: "asf-ratify-label", Instruction: "Add ratify label to accepted PROPOSAL-N", }, { Id: "asf-ratify-supersede", Instruction: "Mark all prior proposals pasture:superseded", }, { Id: "asf-ratify-placeholder", Instruction: "Create placeholder IMPL_PLAN task", }, }, ExitConditions: []ExitCondition{ { Type: "proceed", Condition: "Proposal ratified, IMPL_PLAN placeholder created", }, }, }, { Id: "asf-handoff", Name: "Handoff", Order: 7, Execution: "sequential", PhaseRef: protocol.PhaseHandoff, Actions: []WorkflowAction{ { Id: "asf-handoff-doc", Instruction: "Author the HANDOFF in its Beads task body with full inline provenance (include the HANDOFF task ID)", }, { Id: "asf-handoff-transfer", Instruction: "Transfer to supervisor via /pasture:architect:handoff", }, }, ExitConditions: []ExitCondition{ { Type: "success", Condition: "Handoff authored in the HANDOFF Beads task body, supervisor notified", }, }, }, }, }, }
WorkflowSpecs maps workflow IDs to their full specifications. Mirrors Python WORKFLOW_SPECS dict.
Functions ¶
func AppendMarkers ¶
AppendMarkers adds the BEGIN/END marker pair to the end of content when content does not already contain the markers.
Historically this was used by --init mode for sub-skill SKILL.md files when GenerateSubSkill ran with dropPrefix=false (preserving a hand-authored H1 heading before BEGIN). Since D5/SLICE-3, sub-skills run with dropPrefix=true: the generator owns the full header (frontmatter + curated H1), so GenerateSubSkill now uses PrependMarkers (mirroring GenerateSkill for roles). AppendMarkers is retained as a public helper for callers that still want append-after-body marker insertion (e.g. appending a generated section below existing hand-authored content).
If content already contains both markers (as reported by HasMarkers), it is returned unchanged to avoid double-appending.
func ConstraintToPhaseRefs ¶
ConstraintToPhaseRefs returns a map from constraint ID to the sorted list of PhaseIds that reference it in phaseConstraints.
This inversion is used by S5 schema generation to emit phase-ref attributes into schema.xml for each constraint element.
func ConstraintToRoleRefs ¶
ConstraintToRoleRefs returns a map from constraint ID to the sorted list of RoleIds that reference it in roleConstraints.
This inversion is used by S5 schema generation to emit role-ref attributes into schema.xml for each constraint element.
func ExtractSection ¶
ExtractSection extracts a section's content by heading title from rendered markdown.
It returns the content under the matching heading, starting after the heading line and extending up to (but not including) the next heading at the same or higher (lower number) level.
Heading-level ambiguity: if the same title appears at H2 and H3, the H2 match is returned (first highest-level match). More generally, when multiple headings share the same title, the one at the shallowest (lowest-numbered) level wins.
Returns an error if no heading with the given title is found.
func FindMarkerPositions ¶
FindMarkerPositions returns the (beginIdx, endIdx) line indices for the BEGIN/END marker pair within lines.
Indices are 0-based into the lines slice. The marker lines themselves are included (i.e., lines[beginIdx] == GeneratedBegin and lines[endIdx] == GeneratedEnd after stripping trailing newlines).
path is used only for error messages and does not affect parsing.
Returns a *MarkerError for each of the 6 failure cases:
- Missing both markers — neither BEGIN nor END is present.
- Missing BEGIN — END is present but BEGIN is absent.
- Missing END — BEGIN is present but END is absent.
- Duplicate BEGIN — BEGIN appears more than once.
- Duplicate END — END appears more than once.
- END before BEGIN — both markers present but in reversed order.
func FragmentToOwnerRefs ¶
func FragmentToOwnerRefs() map[FragmentId][]string
FragmentToOwnerRefs returns a map from FragmentId to the sorted list of skill-dir keys (SkillBodySpecs keys) whose body sections or behaviors reference that fragment via a placement marker.
It mirrors ConstraintToRoleRefs: iterate the consumer-keyed map, invert to fragment-keyed, sort owner slices for deterministic output.
func GenerateAgent ¶
func GenerateAgent(roleId types.RoleId, agentPath string, figuresDir string, opts GenerateOptions) (string, error)
GenerateAgent generates agents/{role}.md for a role.
Only generates for roles that have Tools defined (non-empty slice). If the role has no tools, GenerateAgent returns an empty string and a nil error — the caller should check the returned string before acting on it.
The output file is fully generated — no marker-based partial replacement.
Parameters:
- roleId: The role to generate for (must be in RoleSpecs).
- agentPath: Path to write the generated .md file to.
- figuresDir: Path to the directory containing figure YAML files (e.g. skills/protocol/figures). When non-empty, figure content is loaded from disk and embedded in the output. When empty, figures are rendered as ID + Title references only.
- opts: Controls diff output and whether to write to disk. Note: opts.Init is not used by GenerateAgent (agents are fully generated).
Returns:
- The rendered agent definition content (empty string if role has no tools).
- An error if rendering or file I/O fails.
Error conditions:
- Role not found in RoleSpecs → error with diagnostic message.
- Template parse/execution failure → error with template context.
- Parent directory creation failure → error with OS error.
- File write failure → error with OS error and path.
func GenerateSchema ¶
GenerateSchema generates schema.xml from canonical Go spec data and writes the result to w.
The output matches the structure of the Python gen_schema.py output:
- XML declaration with UTF-8 encoding
- <pasture-protocol version="2.0"> root element
- All sections with section-divider comments
- CDATA sections for <code> element content
- 2-space indentation throughout
Returns an error only if writing to w fails.
func GenerateSchemaToFile ¶
func GenerateSchemaToFile(path string, opts GenerateOptions) (string, error)
GenerateSchemaToFile generates schema.xml, optionally prints a diff if the file already exists and opts.Diff is true, and writes if opts.Write is true.
Returns the generated XML content as a string, and any error encountered during file I/O. Returns an error if:
- opts.Write is true and the parent directory does not exist or is not writable
- reading the existing file for diff comparison fails
func GenerateSkill ¶
func GenerateSkill(roleId types.RoleId, skillPath string, figuresDir string, opts GenerateOptions) (string, error)
GenerateSkill generates the SKILL.md for a role and optionally writes it.
It uses a single-pass pipeline: the unified template (skill.go.tmpl) renders ALL content (header + body) inside the BEGIN/END markers. After marker replacement, any content after the END marker is explicitly truncated when a SkillBody entry exists (R3: nothing after END).
ReplaceMarkerRegion is called with dropPrefix=true — the template owns the full frontmatter and heading (everything before BEGIN is dropped and replaced by the rendered template output which starts with YAML frontmatter).
figuresDir is an optional path to the directory containing figure YAML files. When empty, figures will have no content (useful for testing without figure files).
Returns the complete new file content.
Returns a *MarkerError if skillPath is missing the BEGIN/END marker pair (and Init is false), or if the markers are malformed.
func GenerateSubSkill ¶
func GenerateSubSkill(commandId string, skillPath string, figuresDir string, opts GenerateOptions) (string, error)
GenerateSubSkill generates the SKILL.md for a sub-skill command.
It uses a single-pass pipeline: the unified template (skill_sub.go.tmpl) renders ALL content (YAML frontmatter + curated H1 + figures + body) starting with the frontmatter ABOVE the BEGIN marker. After marker replacement, any content after END is truncated when a SkillBody entry exists (R3: nothing after END).
ReplaceMarkerRegion is called with dropPrefix=true — the template owns the full file header (frontmatter + H1), mirroring GenerateSkill for roles. The frontmatter `name` is the sub-skill directory key (so the skill registers as /pasture:<name>) and `description` is CommandSpec.Description; the curated H1 is CommandSpec.Title, captured statically so the hand-authored title is preserved.
figuresDir is an optional path to the directory containing figure YAML files. When empty, figures will have no content (useful for testing without figure files).
Returns the complete new file content.
Returns a *MarkerError if skillPath is missing the BEGIN/END marker pair (and Init is false), or if the markers are malformed.
func HasMarkers ¶
HasMarkers returns true if content contains both the BEGIN and END markers.
This is a fast pre-check used by --init mode to decide whether to prepend markers before calling FindMarkerPositions. It does not validate ordering or uniqueness.
func HeadingTextFromAST ¶
HeadingTextFromAST extracts the full text of a heading AST node by concatenating its child Text and String segment values.
func ParseXMLNode ¶
ParseXMLNode decodes a single XML document from r into out using the standard xml.Decoder. This is the same decode step used by ValidateSchema and is exported primarily for testing purposes.
func PrependMarkers ¶
PrependMarkers adds the BEGIN/END marker pair to the top of content when content does not already contain the markers.
It is used by --init mode for role SKILL.md files (where GenerateSkill uses dropPrefix=true, so the template owns the full heading and frontmatter). The returned string has the markers on the first two lines, followed by a blank line, followed by the original content.
If content already contains both markers (as reported by HasMarkers), it is returned unchanged to avoid double-prepending.
func ReplaceMarkerRegion ¶
ReplaceMarkerRegion replaces the content between (and including) the BEGIN/END markers in oldContent with rendered.
The dropPrefix parameter controls how the content before the BEGIN marker is handled:
dropPrefix=true: everything before BEGIN is dropped. The generated content (rendered) owns the full frontmatter and heading. This matches gen_skill behaviour where the template owns the complete file header.
dropPrefix=false: everything before BEGIN is preserved. The content before the BEGIN marker (e.g., a hand-authored h1 heading) is kept verbatim. This matches gen_sub_skill behaviour.
In both modes everything after the END marker is preserved — that is the hand-authored body that lives below the generated section.
rendered must already include the BEGIN and END marker lines themselves (as the Python template renders the full BEGIN…END block).
Returns a *MarkerError if oldContent has malformed markers.
func ValidateGlobalIds ¶
func ValidateGlobalIds() error
ValidateGlobalIds validates global ID uniqueness, structural integrity, and AllFragmentIds↔SharedFragmentSpecs parity across all codegen registries. Returns nil on success; returns the first violation as an error on failure.
Validation order (deterministic):
- AllFragmentIds ↔ SharedFragmentSpecs parity
- SharedFragmentSpecs: exactly-one-payload rule per fragment
- Cross-namespace uniqueness: agent → role-behavior → handoff → command → SharedFragmentSpecs → SkillBodySpecs inline IDs
- FragRef marker resolution: every marker resolves in SharedFragmentSpecs
func ValidateSkillStructure ¶
ValidateSkillStructure validates the heading hierarchy of generated markdown.
It parses the markdown into an AST via goldmark and checks for:
- Duplicate H2 titles (same title text at level 2)
- Orphan H3 headings (H3 that appear before any H2)
Returns nil if the structure is valid. Returns a *SkillStructureError containing all violations found. Returns a plain error if goldmark parsing fails.
Empty or whitespace-only markdown is considered valid (no headings to validate).
Types ¶
type ActionElem ¶
type ActionElem struct {
Id string `xml:"id,attr"`
Instruction string `xml:"instruction,attr"`
Command string `xml:"command,attr,omitempty"`
}
ActionElem is <action id="..." instruction="..." .../> inside a stage.
type AxisRefElem ¶
type AxisRefElem struct {
Ref string `xml:"ref,attr"`
}
AxisRefElem is <axis-ref ref="..."/>.
type BehaviorElem ¶
type BehaviorElem struct {
Id string `xml:"id,attr"`
Given string `xml:"given,attr"`
When string `xml:"when,attr"`
Then string `xml:"then,attr"`
ShouldNot string `xml:"should-not,attr"`
}
BehaviorElem is a single <behavior id="..." given="..." when="..." then="..." should-not="..."/> element.
type BehaviorSpec ¶
type BehaviorSpec struct {
Id string
Given string
When string
Then string
ShouldNot string
FragRef FragmentId // non-zero → marker; resolved pre-render from SharedFragmentSpecs
}
BehaviorSpec is a role-tactical behavior in Given/When/Then/Should-Not format. Distinct from ConstraintSpec: behaviors are role-specific guidance, not formal protocol constraints. Mirrors Python BehaviorSpec dataclass.
A non-zero FragRef marks this entry as a placement MARKER: all other fields are left zero and the entry is resolved to the SharedFragment payload pre-render by the resolution pass in skills.go.
type BehaviorsElem ¶
type BehaviorsElem struct {
Behaviors []BehaviorElem `xml:"behavior"`
}
BehaviorsElem wraps <behaviors>.
type Checklist ¶
type Checklist struct {
Gate string // GateType wire value: "completion", "slice-closure", etc.
RoleRef types.RoleId
Items []ChecklistItem
}
Checklist is a completion checklist for a role at a specific quality gate. Keyed in ChecklistSpecs by "{role}-{gate}". Mirrors Python Checklist dataclass.
type ChecklistElem ¶
type ChecklistElem struct {
Id string `xml:"id,attr"`
RoleRef string `xml:"role-ref,attr"`
Gate string `xml:"gate,attr"`
Items []ChecklistItemElem `xml:"item"`
}
ChecklistElem is a single <checklist id="..." role-ref="..." gate="..."> element.
type ChecklistItem ¶
ChecklistItem is a single item in a completion checklist. Mirrors Python ChecklistItem dataclass.
type ChecklistItemElem ¶
type ChecklistItemElem struct {
Id string `xml:"id,attr"`
Required string `xml:"required,attr"`
Text string `xml:",chardata"`
}
ChecklistItemElem is an <item id="..." required="...">text</item> element.
type ChecklistsSection ¶
type ChecklistsSection struct {
XMLName xml.Name `xml:"checklists"`
Checklists []ChecklistElem `xml:"checklist"`
}
ChecklistsSection is the top-level <checklists> element.
type CommandElem ¶
type CommandElem struct {
Id string `xml:"id,attr"`
Name string `xml:"name,attr"`
RoleRef string `xml:"role-ref,attr,omitempty"`
Description string `xml:"description,attr"`
Phases *CommandPhasesElem `xml:"phases"`
CreatesLabels *CreatesLabelsElem `xml:"creates-labels"`
File string `xml:"file"`
Note string `xml:"note,omitempty"`
}
CommandElem is a single <command id="..." name="..." ...> element.
type CommandPhasesElem ¶
type CommandPhasesElem struct {
PhaseRefs []PhaseRefElem `xml:"phase-ref"`
}
CommandPhasesElem wraps <phases> inside a <command>.
type CommandSpec ¶
type CommandSpec struct {
Id string // CommandId wire value e.g. "cmd-worker"
Name string // e.g. "pasture:worker"
Description string
// Title is the curated H1 heading text for the command's sub-skill SKILL.md
// (WITHOUT the leading "# "). It is captured statically from each sub-skill's
// curated on-disk H1 (e.g. "User Acceptance Test (UAT)" for cmd-user-uat) so
// that the generator can emit YAML frontmatter ABOVE the heading via
// skill_sub.go.tmpl while PRESERVING the hand-authored title verbatim.
//
// Only sub-skill commands (those listed in commandSkillDirs in
// tools/codegen/main.go) need Title populated; role-level commands
// (cmd-supervisor, cmd-worker, etc.) render through skill.go.tmpl which
// derives its H1 from RoleSpec.Name, so their Title is left empty.
Title string
RoleRef types.RoleId // may be zero value if unassigned
Phases []protocol.PhaseId
File string // relative path to skill file
CreatesLabels []string // label IDs this command creates
}
CommandSpec is the complete specification for a protocol command (skill). Mirrors Python CommandSpec dataclass.
type CommandsSection ¶
type CommandsSection struct {
XMLName xml.Name `xml:"commands"`
Commands []CommandElem `xml:"command"`
}
CommandsSection is the top-level <commands> element.
type ConstraintContext ¶
ConstraintContext is a resolved constraint with its Given/When/Then/ShouldNot fields populated from ConstraintSpecs. Used inside RoleContext and PhaseContext.
type ConstraintElem ¶
type ConstraintElem struct {
Id string
Given string
When string
Then string
ShouldNot string
RoleRef string
PhaseRef string
Command string
Examples []Example // see Example in specs.go
}
ConstraintElem documents a single <constraint ...> element. NOT used for xml.Marshal.
type ConstraintSpec ¶
type ConstraintSpec struct {
Id string
Given string
When string
Then string
ShouldNot string
Command string // optional primary command to run
Examples []Example // optional code examples
}
ConstraintSpec is a single protocol constraint in Given/When/Then/Should-Not format. Mirrors Python ConstraintSpec dataclass.
type ConstraintsSection ¶
type ConstraintsSection struct {
Constraints []ConstraintElem
}
ConstraintsSection documents the <constraints> element shape. NOT used for xml.Marshal.
type CoordCmdElem ¶
type CoordCmdElem struct {
Id string `xml:"id,attr"`
Action string `xml:"action,attr"`
Template string `xml:"template,attr"`
RoleRef string `xml:"role-ref,attr,omitempty"`
}
CoordCmdElem is a single <coord-cmd id="..." action="..." template="..." .../> element.
type CoordinationCommand ¶
type CoordinationCommand struct {
Id string
Action string
Template string
RoleRef types.RoleId // zero value means shared across all roles
}
CoordinationCommand is a coordination command for inter-agent communication via Beads. Mirrors Python CoordinationCommand dataclass.
type CoordinationCommandsSection ¶
type CoordinationCommandsSection struct {
XMLName xml.Name `xml:"coordination-commands"`
Commands []CoordCmdElem `xml:"coord-cmd"`
}
CoordinationCommandsSection is the top-level <coordination-commands> element.
type CoverEntityElem ¶
type CoverEntityElem struct {
Type string `xml:"type,attr"`
Depth string `xml:"depth,attr"`
Refs string `xml:"refs,attr,omitempty"`
Note string `xml:"note,attr,omitempty"`
}
CoverEntityElem is <entity type="..." depth="..." .../> inside <covers>.
type CoversElem ¶
type CoversElem struct {
Entities []CoverEntityElem `xml:"entity"`
}
CoversElem wraps <covers>.
type CreatesLabelsElem ¶
type CreatesLabelsElem struct {
LabelRefs []LabelRefElem `xml:"label-ref"`
}
CreatesLabelsElem wraps <creates-labels>.
type DelegateElem ¶
DelegateElem is <delegate to-role="..." phases="..."/>.
type DelegatesElem ¶
type DelegatesElem struct {
Delegates []DelegateElem `xml:"delegate"`
}
DelegatesElem wraps <delegates>.
type DepChainElem ¶
type DepChainElem struct {
Note string `xml:"note,attr"`
Steps []DepChainStepElem `xml:"step"`
}
DepChainElem is <dependency-chain note="...">.
type DepChainStepElem ¶
type DepChainStepElem struct {
TaskTitle string `xml:"task-title,attr"`
PhaseRef string `xml:"phase-ref,attr"`
Description string `xml:"description,attr"`
}
DepChainStepElem is <step task-title="..." phase-ref="..." description="..."/>.
type DependencyModelSection ¶
type DependencyModelSection struct {
XMLName xml.Name `xml:"dependency-model"`
Rule string `xml:"rule"`
CanonicalChain string `xml:"canonical-chain"`
Command string `xml:"command"`
AntiPattern string `xml:"anti-pattern"`
ReferenceLinks *ReferenceLinksElem `xml:"reference-links"`
}
DependencyModelSection is the top-level <dependency-model> element. Content is mixed text/element — kept as raw text since it uses free-form prose and nested elements with no fixed structure.
type DocumentElem ¶
type DocumentElem struct {
Id string `xml:"id,attr"`
Path string `xml:"path,attr"`
Purpose string `xml:"purpose,attr"`
Covers *CoversElem `xml:"covers"`
}
DocumentElem is a single <document id="..." path="..." purpose="..."> element.
type DocumentsSection ¶
type DocumentsSection struct {
XMLName xml.Name `xml:"documents"`
Documents []DocumentElem `xml:"document"`
}
DocumentsSection is the top-level <documents> element.
type EnumValue ¶
type EnumValue struct {
Id string `xml:"id,attr"`
Description string `xml:"description,attr"`
// Optional attrs present on SeverityLevel values only.
Blocks string `xml:"blocks,attr,omitempty"`
Label string `xml:"label,attr,omitempty"`
}
EnumValue is a single <value id="..." .../> element inside an <enum>.
type EnumsSection ¶
EnumsSection is the top-level <enums> element.
type ErrorLayer ¶
type ErrorLayer string
ErrorLayer categorizes validation errors by their detection layer. Values match the Python ErrorLayer enum wire values.
const ( // LayerStructural covers missing required attributes, duplicate IDs, // and malformed XML. LayerStructural ErrorLayer = "Structural" // LayerReferential covers references (phase-ref, role-ref, etc.) that // point to IDs not defined elsewhere in the document. LayerReferential ErrorLayer = "Referential Integrity" // LayerSemantic covers logical inconsistencies such as out-of-order // phase numbers, duplicate axis letters, or invalid enum values. LayerSemantic ErrorLayer = "Semantic" )
type Example ¶
type Example struct {
Id string
Lang string // ExampleLang wire value: "bash", "go", "python", etc.
Label string // ExampleLabel wire value: "correct", "anti-pattern", etc.
Code string
AlsoIllustrates string // optional cross-reference to another constraint
}
Example is a labeled code example for a constraint or procedure step. Mirrors Python CodeExample dataclass.
type ExampleElem ¶
type ExampleElem struct {
Id string `xml:"id,attr"`
Lang string `xml:"lang,attr"`
Label string `xml:"label,attr"`
AlsoIllustrates string `xml:"also-illustrates,attr,omitempty"`
}
ExampleElem is an <example id="..." lang="..." label="..."> element. The <code> child contains CDATA and is handled by manual fmt.Fprintf.
type ExitCondElem ¶
ExitCondElem is <exit-condition type="..." condition="..."/> inside a stage.
type ExitCondition ¶
type ExitCondition struct {
Type string // ExitConditionType: "success", "continue", "escalate", "proceed"
Condition string
}
ExitCondition is an exit condition for a workflow stage. Type must be one of the ExitConditionType wire values. Mirrors Python ExitCondition dataclass.
type ExtraLabelElem ¶
type ExtraLabelElem struct {
Ref string `xml:"ref,attr"`
}
ExtraLabelElem is <extra-label ref="..."/>.
type FigureElem ¶
type FigureElem struct {
Id string `xml:"id,attr"`
Title string `xml:"title,attr"`
Type string `xml:"type,attr"`
SectionRef string `xml:"section-ref,attr"`
RoleRefs []RefElem `xml:"role-ref"`
WorkflowRefs []RefElem `xml:"workflow-ref"`
CommandRefs []RefElem `xml:"command-ref"`
}
FigureElem is a single <figure id="..." title="..." type="..." section-ref="..."> element.
type FigureSpec ¶
type FigureSpec struct {
Id string // FigureId wire value
Title string
Type string // FigureType wire value: "ascii-diagram"
RoleRefs []types.RoleId
SectionRef string // SectionRef wire value: "workflows"
WorkflowRefs []string
CommandRefs []string
Content string // loaded at generation time
}
FigureSpec is a figure specification (ASCII diagram or other visual). Mirrors Python Figure dataclass.
type FiguresSection ¶
type FiguresSection struct {
XMLName xml.Name `xml:"figures"`
Figures []FigureElem `xml:"figure"`
}
FiguresSection is the top-level <figures> element.
type FollowupEpicElem ¶
type FollowupEpicElem struct {
LabelRef string `xml:"label-ref,attr"`
Trigger string `xml:"trigger,attr"`
GatedOnBlocker string `xml:"gated-on-blocker,attr"`
OwnerRole string `xml:"owner-role,attr"`
}
FollowupEpicElem is <followup-epic label-ref="..." trigger="..." .../>.
type FollowupLifecycleSection ¶
type FollowupLifecycleSection struct {
XMLName xml.Name `xml:"followup-lifecycle"`
Trigger string `xml:"trigger"`
OwnerRole string `xml:"owner-role"`
GatedOnBlocker string `xml:"gated-on-blocker"`
DependencyChain *DepChainElem `xml:"dependency-chain"`
LeafTaskAdoption *LeafTaskAdoptElem `xml:"leaf-task-adoption"`
References *FollowupRefsElem `xml:"references"`
HandoffChain *HandoffChainElem `xml:"handoff-chain"`
}
FollowupLifecycleSection is the top-level <followup-lifecycle> element.
type FollowupRefElem ¶
type FollowupRefElem struct {
Type string `xml:"type,attr"`
Target string `xml:"target,attr"`
Note string `xml:"note,attr"`
}
FollowupRefElem is <ref type="..." target="..." note="..."/>.
type FollowupRefsElem ¶
type FollowupRefsElem struct {
Refs []FollowupRefElem `xml:"ref"`
}
FollowupRefsElem wraps <references> in followup-lifecycle.
type FragmentId ¶
type FragmentId string
FragmentId is the strongly-typed key for shared fragment registrations. Values match the frag--* canonical naming convention (e.g. "frag--rev-vote-options"). PascalCase constants are derived by dropping the "frag--" prefix, splitting on "-", and prefixing with "Frag".
Mirrors the RoleId / PhaseId / CommandId convention.
const ( // FragRevVoteOptions is the canonical vote-options table shared between the // reviewer and reviewer-vote skill bodies (D3-ratified ACCEPT row wording). FragRevVoteOptions FragmentId = "frag--rev-vote-options" // FragSupReviewAllSlices is the canonical "spawn 3 reviewers for ALL slices" // behavior shared between the supervisor and impl-review skill bodies. FragSupReviewAllSlices FragmentId = "frag--sup-review-all-slices" // FragSupReviewCheckEach is the canonical "check each slice against criteria" // behavior shared between the supervisor and impl-review skill bodies. FragSupReviewCheckEach FragmentId = "frag--sup-review-check-each" // FragSupReviewSeverityGroups is the canonical "ALWAYS create 3 severity groups" // behavior shared between the supervisor and impl-review skill bodies. FragSupReviewSeverityGroups FragmentId = "frag--sup-review-severity-groups" // FragSupBlockerDualParent is the canonical "dual-parent: blocks BOTH severity // group AND slice" behavior shared between the supervisor and impl-review skill // bodies. FragSupBlockerDualParent FragmentId = "frag--sup-blocker-dual-parent" // FragSupDeferredFollowup is the canonical "route ONLY user-DEFER'd UAT items // to the FOLLOWUP epic; all review severities must reach 0 before wave close" // behavior shared between the supervisor and impl-review skill bodies. // (Renamed from FragSupImportantMinorFollowup per R7/A1: review severities are // no longer deferrable; the FOLLOWUP epic is fed solely by DEFER'd UAT items.) FragSupDeferredFollowup FragmentId = "frag--sup-deferred-followup" // FragSupFollowupEpicTiming is the canonical "supervisor creates EPIC_FOLLOWUP // immediately" behavior shared between the supervisor and impl-review skill // bodies. FragSupFollowupEpicTiming FragmentId = "frag--sup-followup-epic-timing" // FragSupSeverityTree is the canonical Severity Tree (EAGER Creation) prose // section shared between the supervisor and impl-review skill bodies. FragSupSeverityTree FragmentId = "frag--sup-severity-tree" // FragSupNamingConvention is the canonical Naming Convention prose section // (SLICE-{N}-REVIEW-{axis}-{round} format) shared between the supervisor and // impl-review skill bodies. FragSupNamingConvention FragmentId = "frag--sup-naming-convention" // FragRevPlanVoteOptions is the vote-options table for PLAN reviews (Phase 3 // architect-request-review). DISTINCT from FragRevVoteOptions (code review) // by its final line: "Binary only. No severity tree for plan reviews." // (vs code review's "Binary only. No intermediate levels."); the ACCEPT-row // wording is shared (unified per UAT-2). Single-owner (reviewer-review-plan), // but promoted to a fragment for registry completeness and D2 distinctness // enforcement. FragRevPlanVoteOptions FragmentId = "frag--rev-plan-vote-options" // FragValidationCases is the canonical "elicit/confirm/evaluate concrete // validation cases for EVERY REQUEST — a definition of done plus correct and // incorrect behaviours, user-confirmed, with failing real-data cases stored as // test fixtures" behavior (R6/A2, generalized from fix-intent-only at v2-2). // Referenced via behaviorRef from the user-elicit, user-uat, and // worker-implement skill bodies (wired in SLICE-2). FragValidationCases FragmentId = "frag--validation-cases" // FragReviewCleanExit is the canonical "iterate review->fix->re-review up to the // chosen review-effort budget; clean = 0 BLOCKER + 0 IMPORTANT + 0 MINOR within // budget; on budget exhaustion without clean, surface outstanding findings to // the user at a gate" behavior (R7/A1, reworked to a configurable budget at // v2-2). Referenced via behaviorRef from the supervisor and impl-review skill // bodies (wired in SLICE-3). FragReviewCleanExit FragmentId = "frag--review-clean-exit" )
type FragmentKind ¶
type FragmentKind string
FragmentKind identifies the payload type stored in a SharedFragment.
const ( // FragmentKindBehavior indicates the fragment holds a *BehaviorSpec payload. FragmentKindBehavior FragmentKind = "behavior" // FragmentKindProse indicates the fragment holds a *ProseSection payload. FragmentKindProse FragmentKind = "prose" )
type FragmentParityError ¶
type FragmentParityError struct {
// OrphanConstant is non-empty when a FragmentId constant has no matching
// SharedFragmentSpecs entry.
OrphanConstant FragmentId
// OrphanSpec is non-empty when a SharedFragmentSpecs key has no matching
// FragmentId constant in AllFragmentIds.
OrphanSpec FragmentId
}
FragmentParityError describes a mismatch between AllFragmentIds (the declared typed constants) and the keys of SharedFragmentSpecs.
func (*FragmentParityError) Error ¶
func (e *FragmentParityError) Error() string
Error returns an actionable message.
type GenerateOptions ¶
type GenerateOptions struct {
// Diff prints a unified diff of old vs new content to stdout (default: true).
Diff bool
// Write writes the new content to the skill file (default: true).
Write bool
// Init prepends BEGIN/END markers to files that lack them before generating.
// When false (default), missing markers return a *MarkerError.
Init bool
}
GenerateOptions controls the behaviour of GenerateSkill and GenerateSubSkill.
type HandoffChainElem ¶
type HandoffChainElem struct {
Note string `xml:"note,attr"`
Transitions []HandoffChainTransElem `xml:"transition"`
}
HandoffChainElem is <handoff-chain note="...">.
type HandoffChainTransElem ¶
type HandoffChainTransElem struct {
Order string `xml:"order,attr"`
HandoffRef string `xml:"handoff-ref,attr"`
Description string `xml:"description,attr"`
SameActor string `xml:"same-actor,attr,omitempty"`
}
HandoffChainTransElem is <transition order="..." handoff-ref="..." description="..." .../>.
type HandoffElem ¶
type HandoffElem struct {
Id string `xml:"id,attr"`
SourceRole string `xml:"source-role,attr"`
TargetRole string `xml:"target-role,attr"`
AtPhase string `xml:"at-phase,attr"`
ContentLevel string `xml:"content-level,attr"`
FilePattern string `xml:"file-pattern,attr,omitempty"`
Trigger string `xml:"trigger,attr,omitempty"`
Context string `xml:"context,attr,omitempty"`
RequiredFields *RequiredFieldsElem `xml:"required-fields"`
SkillInvocation *SkillInvocationElem `xml:"skill-invocation"`
Note *HandoffNoteElem `xml:"note"`
}
HandoffElem is a single <handoff id="..." ...> element.
type HandoffNoteElem ¶
type HandoffNoteElem struct {
Text string `xml:",chardata"`
}
HandoffNoteElem wraps <note> text content in a handoff.
type HandoffSpec ¶
type HandoffSpec struct {
Id string
SourceRole types.RoleId
TargetRole types.RoleId
AtPhase protocol.PhaseId
ContentLevel string // ContentLevel wire value: "full-provenance", "summary-with-ids"
RequiredFields []string
}
HandoffSpec specifies an actor-change transition handoff document. Mirrors Python HandoffSpec dataclass.
type HandoffsSection ¶
type HandoffsSection struct {
XMLName xml.Name `xml:"handoffs"`
StoragePattern string `xml:"storage-pattern,attr"`
Handoffs []HandoffElem `xml:"handoff"`
SameActorTransitions *SameActorTransitionsElem `xml:"same-actor-transitions"`
}
HandoffsSection is the top-level <handoffs storage-pattern="..."> element.
type IDCollision ¶
type IDCollision struct {
// Id is the duplicate identifier string (e.g. "rev-vote-options").
Id string
// Namespace identifies which registry the collision spans
// (e.g. "SkillBodySpecs inline", "SharedFragmentSpecs", "role-behavior").
Namespace string
// LocationA is the first occurrence description (registry/skill-dir).
LocationA string
// LocationB is the second occurrence description.
LocationB string
}
IDCollision describes a global-ID uniqueness violation: the same string ID appears in two distinct locations across the codegen registries.
All fields are always populated so the error message is self-contained.
func (*IDCollision) Error ¶
func (e *IDCollision) Error() string
Error returns an actionable message: what/why/where/when/meaning/fix.
type InstancesElem ¶
InstancesElem is <instances count="..." per="..."/>.
type InvalidFragment ¶
type InvalidFragment struct {
// FragRef is the offending fragment's map key.
FragRef FragmentId
// Reason describes the specific violation.
Reason string
}
InvalidFragment describes a SharedFragmentSpecs entry that violates the exactly-one-payload rule (must have Prose XOR Behavior, never both/neither).
func (*InvalidFragment) Error ¶
func (e *InvalidFragment) Error() string
Error returns an actionable message.
type InvariantsElem ¶
type InvariantsElem struct {
Invariants []string `xml:"invariant"`
}
InvariantsElem wraps <invariants>.
type KeyQuestionsElem ¶
type KeyQuestionsElem struct {
Questions []string `xml:"q"`
}
KeyQuestionsElem wraps <key-questions><q>...</q></key-questions>.
type LabelElem ¶
type LabelElem struct {
Id string `xml:"id,attr"`
Value string `xml:"value,attr"`
Special string `xml:"special,attr,omitempty"`
PhaseRef string `xml:"phase-ref,attr,omitempty"`
SubstepRef string `xml:"substep-ref,attr,omitempty"`
SeverityRef string `xml:"severity-ref,attr,omitempty"`
Description string `xml:"description,attr,omitempty"`
}
LabelElem is a single <label .../> element.
type LabelRefElem ¶
type LabelRefElem struct {
Ref string `xml:"ref,attr"`
}
LabelRefElem is <label-ref ref="..."/>.
type LabelSpec ¶
type LabelSpec struct {
Id string
Value string // the actual label string e.g. "pasture:p9-impl:s9-slice"
Special bool
PhaseRef string // optional phase reference
SubstepRef string // optional substep reference
SeverityRef string // optional severity reference
Description string // optional description
}
LabelSpec is the complete specification for a protocol label. Mirrors Python LabelSpec dataclass.
type LabelsSection ¶
LabelsSection is the top-level <labels> element.
type LeafTaskAdoptElem ¶
type LeafTaskAdoptElem struct {
Rule string `xml:"rule"`
Command string `xml:"command"`
Note string `xml:"note"`
}
LeafTaskAdoptElem is <leaf-task-adoption>.
type MarkerError ¶
type MarkerError struct {
// Path is the file path where the marker problem was found.
Path string
// Problem is a short description of what went wrong.
// Examples: "missing both markers", "duplicate BEGIN", "END before BEGIN".
Problem string
// Line is the 1-based line number of the offending marker, or 0 when
// the problem is not associated with a specific line (e.g., both markers
// missing).
Line int
// Fix is an actionable remediation message that tells the user exactly
// what to do to resolve the problem.
Fix string
}
MarkerError is a typed error for marker validation failures.
It contains actionable diagnostic information: what went wrong, where it failed (file path and line number), and how to fix it. Using a dedicated type instead of fmt.Errorf allows callers to assert on the specific failure kind without string parsing.
func (*MarkerError) Error ¶
func (e *MarkerError) Error() string
Error implements the error interface.
The message follows the actionable-error convention:
(1) what went wrong — Problem field (2) where it failed — Path + Line (3) how to fix it — Fix field
type OwnedPhasesElem ¶
type OwnedPhasesElem struct {
PhaseRefs []PhaseRefElem `xml:"phase-ref"`
}
OwnedPhasesElem wraps <owns-phases>.
type PhaseContext ¶
type PhaseContext struct {
Phase protocol.PhaseId
Constraints []ConstraintContext
Labels []string
Transitions []Transition
}
PhaseContext is the context injection fragment for a specific protocol phase. Populated by GetPhaseContext and used by prompt construction to embed phase-appropriate constraints, labels, and valid transitions.
func GetPhaseContext ¶
func GetPhaseContext(phase protocol.PhaseId) PhaseContext
GetPhaseContext returns the context injection fragment for the given protocol phase.
It populates PhaseContext with:
- Constraints: resolved ConstraintContext objects from phaseConstraints[phase]
- Labels: label values from LabelSpecs where PhaseRef matches phase's p-number
- Transitions: valid transitions from PhaseSpecs[phase]
Panics if any constraint ID in phaseConstraints[phase] is not found in ConstraintSpecs. This is a programming error (stale mapping) that must be fixed in the source, not handled at runtime.
type PhaseElem ¶
type PhaseElem struct {
Id string `xml:"id,attr"`
Number string `xml:"number,attr"`
Domain string `xml:"domain,attr"`
Name string `xml:"name,attr"`
Description string `xml:"description"`
Substeps *SubstepsElem `xml:"substeps"`
TaskTitles []TaskTitleElem `xml:"task-title"`
Transitions *TransitionsElem `xml:"transitions"`
// Optional special elements (present on specific phases only).
SeverityTree *SeverityTreeElem `xml:"severity-tree"`
SameActorAs *SameActorAsElem `xml:"same-actor-as"`
TDDLayers *TDDLayersElem `xml:"tdd-layers"`
FollowupEpic *FollowupEpicElem `xml:"followup-epic"`
}
PhaseElem is a single <phase id="..." number="..." domain="..." name="..."> element.
type PhaseRefElem ¶
type PhaseRefElem struct {
Ref string `xml:"ref,attr"`
}
PhaseRefElem is <phase-ref ref="..."/>.
type PhaseSpec ¶
type PhaseSpec struct {
Id protocol.PhaseId
Name string
Number int
Domain types.Domain
OwnerRoles []types.RoleId
Transitions []Transition
}
PhaseSpec is the complete specification for a single protocol phase. Mirrors Python PhaseSpec dataclass.
type PhasesSection ¶
PhasesSection is the top-level <phases> element.
type ProcedureRoleGroup ¶
type ProcedureRoleGroup struct {
Ref string
Steps []ProcedureStepElem
}
ProcedureRoleGroup is a <role ref="..."> grouping inside <procedure-steps>. NOT used for xml.Marshal.
type ProcedureStep ¶
type ProcedureStep struct {
Id string
Order int
Instruction string
Command string // optional exact shell/bd command
Context string // optional situational context
NextState protocol.PhaseId // optional phase transition
Examples []Example
}
ProcedureStep is a single step in a role's startup or operational procedure. Mirrors Python ProcedureStep dataclass.
type ProcedureStepElem ¶
type ProcedureStepElem struct {
Order string `xml:"order,attr"`
Id string `xml:"id,attr"`
NextState string `xml:"next-state,attr,omitempty"`
Instruction string `xml:"instruction"`
Command string `xml:"command,omitempty"`
Context string `xml:"context,omitempty"`
// Examples contain CDATA — defined here for completeness but built manually.
Examples []ExampleElem `xml:"example"`
}
ProcedureStepElem is a <step order="..." id="..." ...> element used in both startup-sequence and procedure-steps sections.
type ProcedureStepsSection ¶
type ProcedureStepsSection struct {
RoleGroups []ProcedureRoleGroup
}
ProcedureStepsSection documents the <procedure-steps> element shape. NOT used for xml.Marshal.
type ProseSection ¶
type ProseSection struct {
Id string // unique within skill body; not used during template rendering — available for programmatic lookup via ExtractSection or future ID-based access
Title string // heading text, e.g. "What You Own"
Content string // pre-formatted markdown content below the heading
Subsections []ProseSection // optional nested sections (rendered as H3 under H2)
FragRef FragmentId // non-zero → marker; resolved pre-render from SharedFragmentSpecs
}
ProseSection is a titled block of markdown content for skill body rendering. Sections are rendered in slice order. Heading level is determined by the template (H2 for top-level, H3 for subsections).
A non-zero FragRef marks this entry as a placement MARKER: all other fields are left zero and the entry is resolved to the SharedFragment payload pre-render by the resolution pass in skills.go.
type RecipeBlock ¶
type RecipeBlock struct {
Id string // unique within skill body; not used during template rendering — available for programmatic lookup
Title string // e.g. "Phase 1: REQUEST Task"
Description string // context paragraph before the code block
Lang string // code block language, typically "bash"
Code string // the actual bd command template
}
RecipeBlock is a bd command recipe with context and code example.
type RefElem ¶
type RefElem struct {
Ref string `xml:"ref,attr"`
}
RefElem is a generic <*-ref ref="..."/> element used within a figure. encoding/xml resolves the element tag name from the slice field struct tag in FigureElem (role-ref, workflow-ref, or command-ref), so a single type serves all three reference collections.
type ReferenceLinksElem ¶
ReferenceLinksElem is the <reference-links note="..."> element.
type RequiredFieldsElem ¶
type RequiredFieldsElem struct {
Text string `xml:",chardata"`
}
RequiredFieldsElem wraps <required-fields> text content.
type ReviewAxesSection ¶
type ReviewAxesSection struct {
XMLName xml.Name `xml:"review-axes"`
Axes []ReviewAxisElem `xml:"axis"`
}
ReviewAxesSection is the top-level <review-axes> element.
type ReviewAxisElem ¶
type ReviewAxisElem struct {
Id string `xml:"id,attr"`
Letter string `xml:"letter,attr"`
Name string `xml:"name,attr"`
Short string `xml:"short,attr"`
KeyQuestions *KeyQuestionsElem `xml:"key-questions"`
}
ReviewAxisElem is a single <axis ...> element.
type ReviewAxisSpec ¶
type ReviewAxisSpec struct {
Id string
Letter string // ReviewAxis wire value: "correctness", "test_quality", "elegance"
Name string
Short string
KeyQuestions []string
}
ReviewAxisSpec is the complete specification for a code review axis. Mirrors Python ReviewAxisSpec dataclass.
type RoleContext ¶
type RoleContext struct {
Role types.RoleId
Phases []protocol.PhaseId
Constraints []ConstraintContext
Commands []string
Handoffs []string
Introduction string
OwnershipNarrative string
Behaviors []BehaviorSpec
Checklists []Checklist
CoordinationCommands []CoordinationCommand
Workflows []Workflow
ReviewAxes []ReviewAxisSpec
Figures []FigureSpec
}
RoleContext is the context injection fragment for a specific agent role. Populated by GetRoleContext and used by prompt construction to embed role-appropriate constraints, phases, commands, and handoffs.
func GetRoleContext ¶
func GetRoleContext(role types.RoleId) RoleContext
GetRoleContext returns the context injection fragment for the given agent role.
It populates RoleContext with:
- Phases: phases where this role is an owner role (inverted from PhaseSpecs)
- Constraints: resolved ConstraintContext objects from roleConstraints[role]
- Commands: command names from CommandSpecs where RoleRef == role
- Handoffs: handoff IDs from HandoffSpecs where role is source or target
- Introduction: from RoleSpecs[role].Introduction
- OwnershipNarrative: from RoleSpecs[role].OwnershipNarrative
- Behaviors: from RoleSpecs[role].Behaviors
- Checklists: from ChecklistSpecs where RoleRef == role
- CoordinationCommands: role-specific + shared from CoordinationCommands
- Workflows: from WorkflowSpecs where RoleRef == role
- ReviewAxes: from ReviewAxisSpecs (reviewer only; empty for all others)
- Figures: from FigureSpecs where role in RoleRefs
Panics if any constraint ID in roleConstraints[role] is not found in ConstraintSpecs. This is a programming error (stale mapping) that must be fixed in the source, not handled at runtime.
type RoleElem ¶
type RoleElem struct {
Id string `xml:"id,attr"`
Name string `xml:"name,attr"`
Description string `xml:"description,attr"`
OwnedPhases *OwnedPhasesElem `xml:"owns-phases"`
Delegates *DelegatesElem `xml:"delegates"`
LabelAwareness string `xml:"label-awareness"`
UsesAxes *UsesAxesElem `xml:"uses-axes"`
Invariants *InvariantsElem `xml:"invariants"`
Tools string `xml:"tools"`
Model string `xml:"model"`
Thinking string `xml:"thinking"`
OwnershipModel string `xml:"ownership-model"`
Introduction string `xml:"introduction"`
OwnershipNarrative string `xml:"ownership-narrative"`
Behaviors *BehaviorsElem `xml:"behaviors"`
}
RoleElem is a single <role id="..." name="..." description="..."> element.
type RoleSpec ¶
type RoleSpec struct {
Id types.RoleId
Name string
Description string
Model string // e.g. "opus", "sonnet", "haiku"
Thinking string // e.g. "medium"
Tools []string
OwnedPhases []protocol.PhaseId
Introduction string
OwnershipNarrative string
Behaviors []BehaviorSpec
}
RoleSpec is the complete specification for an agent role. Mirrors Python RoleSpec dataclass.
type RolesSection ¶
RolesSection is the top-level <roles> element.
type SameActorAsElem ¶
type SameActorAsElem struct {
PhaseRef string `xml:"phase-ref,attr"`
Note string `xml:"note,attr"`
}
SameActorAsElem is <same-actor-as phase-ref="..." note="..."/>.
type SameActorTransitionElem ¶
type SameActorTransitionElem struct {
FromPhase string `xml:"from-phase,attr"`
ToPhase string `xml:"to-phase,attr"`
Actor string `xml:"actor,attr"`
}
SameActorTransitionElem is <transition from-phase="..." to-phase="..." actor="..."/>.
type SameActorTransitionsElem ¶
type SameActorTransitionsElem struct {
Note string `xml:"note,attr"`
Transitions []SameActorTransitionElem `xml:"transition"`
}
SameActorTransitionsElem wraps <same-actor-transitions>.
type SchemaIndex ¶
type SchemaIndex struct {
PhaseIds map[string]bool
SubstepIDs map[string]bool
LabelIDs map[string]bool
RoleIds map[string]bool
CommandIds map[string]bool
AxisIDs map[string]bool
HandoffIDs map[string]bool
ConstraintIDs map[string]bool
DocumentIDs map[string]bool
TeamIDs map[string]bool
WorkflowIDs map[string]bool
SeverityIDs map[string]bool
// EnumValueIDs maps enum name → set of value IDs defined within it.
EnumValueIDs map[string]map[string]bool
// PhaseNumbers maps phase_id → numeric order (e.g. "p1" → 1).
PhaseNumbers map[string]int
// PhaseDomains maps phase_id → domain string (e.g. "p1" → "user").
PhaseDomains map[string]string
// PhaseSubstepOrders maps phase_id → ordered list of substep entries.
PhaseSubstepOrders map[string][]SubstepOrderEntry
// LabelValues maps label_id → value string (e.g. "L-p1s1_1" → "pasture:p1-user:s1_1-request").
LabelValues map[string]string
// AxisLetters maps axis_id → letter string (e.g. "axis-correctness" → "A").
AxisLetters map[string]string
// RolePhaseRefs maps role_id → set of phase_ids that role owns.
RolePhaseRefs map[string]map[string]bool
// StartupStepOrders maps substep_id → slice of step order values found
// inside that substep's <startup-sequence>.
StartupStepOrders map[string][]int
}
SchemaIndex holds all IDs and metadata extracted during structural validation. It is populated by buildIndex and consumed by checkRefs and checkSemantics. Mirrors the Python SchemaIndex dataclass.
type SevGroupElem ¶
type SevGroupElem struct {
SeverityRef string `xml:"severity-ref,attr"`
LabelRef string `xml:"label-ref,attr"`
DualParent string `xml:"dual-parent,attr,omitempty"`
}
SevGroupElem is a <group severity-ref="..." label-ref="..." .../> element.
type SeverityTreeElem ¶
type SeverityTreeElem struct {
Enabled string `xml:"enabled,attr"`
Creation string `xml:"creation,attr,omitempty"`
Reason string `xml:"reason,attr,omitempty"`
Rules []string `xml:"rule"`
Groups []SevGroupElem `xml:"group"`
}
SeverityTreeElem is the <severity-tree ...> element.
type SharedFragment ¶
type SharedFragment struct {
}
SharedFragment is a reusable payload (either a BehaviorSpec or a ProseSection) stored in SharedFragmentSpecs and referenced by placement markers in SkillBody entries.
Exactly one of Behavior or Prose must be non-nil. Owners are not stored directly — they are derived via FragmentToOwnerRefs() (D1: owners derived from consumer markers, not embedded).
type SkillBody ¶
type SkillBody struct {
Preamble string // optional intro (e.g., PROCESS.md link)
Sections []ProseSection // ordered prose sections (rendered as H2)
Recipes []RecipeBlock // ordered code recipes
Behaviors []BehaviorSpec // body-specific G/W/T behaviors (NOT ConstraintSpec)
}
SkillBody is the complete body content for a role or sub-skill. Rendered inside the BEGIN/END marker region by the unified skill.go.tmpl and skill_sub.go.tmpl templates.
type SkillInvocationElem ¶
type SkillInvocationElem struct {
TargetRole string `xml:"target-role,attr,omitempty"`
CommandRef string `xml:"command-ref,attr,omitempty"`
Directive string `xml:"directive,attr"`
Note string `xml:"note,attr,omitempty"`
}
SkillInvocationElem is <skill-invocation target-role="..." command-ref="..." directive="..."/>. target-role and command-ref are omitempty so they can be omitted when only directive (and optionally note) are needed (e.g., in handoff skill-invocation elements).
type SkillStructureError ¶
type SkillStructureError struct {
// Problems is a list of structural violations found.
Problems []string
}
SkillStructureError describes a structural problem in a generated SKILL.md.
func (*SkillStructureError) Error ¶
func (e *SkillStructureError) Error() string
Error implements the error interface.
type StageElem ¶
type StageElem struct {
Id string `xml:"id,attr"`
Name string `xml:"name,attr"`
Order string `xml:"order,attr"`
Execution string `xml:"execution,attr"`
PhaseRef string `xml:"phase-ref,attr,omitempty"`
Actions []ActionElem `xml:"action"`
ExitConditions []ExitCondElem `xml:"exit-condition"`
}
StageElem is a single <stage id="..." name="..." order="..." execution="..." ...> element.
type StartupSequenceElem ¶
type StartupSequenceElem struct {
Steps []ProcedureStepElem `xml:"step"`
}
StartupSequenceElem wraps <startup-sequence> containing procedure steps.
type SubstepData ¶
type SubstepData struct {
Id string
Type string // SubstepType wire value
Execution string // ExecutionMode wire value
Order int
LabelRef string
ParallelGroup string // optional parallel group name
Description string
ExtraLabel string // optional extra label ref
// Instances specifies repeated substep instantiation metadata.
Instances *SubstepInstances
// StartupSequence signals that PROCEDURE_STEPS[supervisor] should be embedded.
StartupSequence bool
}
SubstepData holds canonical per-phase substep specifications. Mirrors the inner dicts in Python SUBSTEP_DATA.
type SubstepElem ¶
type SubstepElem struct {
Id string `xml:"id,attr"`
Type string `xml:"type,attr"`
Execution string `xml:"execution,attr"`
Order string `xml:"order,attr"`
ParallelGroup string `xml:"parallel-group,attr,omitempty"`
LabelRef string `xml:"label-ref,attr"`
Description string `xml:"description"`
ExtraLabel *ExtraLabelElem `xml:"extra-label"`
Instances *InstancesElem `xml:"instances"`
Startup *StartupSequenceElem `xml:"startup-sequence"`
}
SubstepElem is a single <substep ...> element.
type SubstepInstances ¶
type SubstepInstances struct {
Count string // e.g. "3", "N"
Per string // e.g. "review-axis", "production-code-path"
}
SubstepInstances describes how many times a substep is instantiated.
type SubstepOrderEntry ¶
type SubstepOrderEntry struct {
Id string
Order int
Execution string // "sequential" or "parallel"
}
SubstepOrderEntry holds ordering metadata for a single substep within a phase. Mirrors the Python tuple (id, order, execution) from phase_substep_orders.
type SubstepsElem ¶
type SubstepsElem struct {
Substeps []SubstepElem `xml:"substep"`
}
SubstepsElem wraps <substeps>.
type TDDLayerElem ¶
type TDDLayerElem struct {
Number string `xml:"number,attr"`
Name string `xml:"name,attr"`
Description string `xml:"description,attr"`
}
TDDLayerElem is <layer number="..." name="..." description="..."/>.
type TDDLayersElem ¶
type TDDLayersElem struct {
Layers []TDDLayerElem `xml:"layer"`
}
TDDLayersElem wraps <tdd-layers>.
type TaskTitleElem ¶
type TaskTitleElem struct {
Pattern string `xml:"pattern,attr"`
Substep string `xml:"substep,attr,omitempty"`
Convention string `xml:"convention"`
}
TaskTitleElem is a <task-title pattern="..." .../> or block element.
type TaskTitlesSection ¶
type TaskTitlesSection struct {
XMLName xml.Name `xml:"task-titles"`
Conventions []TitleConventionElem `xml:"title-convention"`
}
TaskTitlesSection is the top-level <task-titles> element.
type TitleConvention ¶
type TitleConvention struct {
Pattern string
LabelRef string
CreatedBy string
PhaseRef string // optional phase reference
ExtraLabelRef string // optional extra label reference
Note string // optional note
}
TitleConvention is a task title naming convention for a phase/substep type. Mirrors Python TitleConvention dataclass.
type TitleConventionElem ¶
type TitleConventionElem struct {
Pattern string `xml:"pattern,attr"`
LabelRef string `xml:"label-ref,attr"`
CreatedBy string `xml:"created-by,attr"`
PhaseRef string `xml:"phase-ref,attr,omitempty"`
ExtraLabelRef string `xml:"extra-label-ref,attr,omitempty"`
Note string `xml:"note,attr,omitempty"`
}
TitleConventionElem is a single <title-convention .../> element.
type Transition ¶
type Transition struct {
ToPhase protocol.PhaseId
Condition string
Action string // optional action on transition
}
Transition is a single valid phase transition. Mirrors Python Transition dataclass.
type TransitionElem ¶
type TransitionElem struct {
ToPhase string `xml:"to-phase,attr"`
Condition string `xml:"condition,attr"`
Action string `xml:"action,attr,omitempty"`
SkillInvocation *SkillInvocationElem `xml:"skill-invocation"`
}
TransitionElem is a single <transition to-phase="..." condition="..." ...> element.
type TransitionsElem ¶
type TransitionsElem struct {
Transitions []TransitionElem `xml:"transition"`
}
TransitionsElem wraps <transitions>.
type UnresolvedMarker ¶
type UnresolvedMarker struct {
// FragRef is the unresolvable marker reference.
FragRef FragmentId
// ConsumerSkill is the SkillBodySpecs key where the marker appears.
ConsumerSkill string
// MarkerKind is "ProseSection" or "BehaviorSpec".
MarkerKind string
}
UnresolvedMarker describes a FragRef placement marker that references a fragment not present in SharedFragmentSpecs.
func (*UnresolvedMarker) Error ¶
func (e *UnresolvedMarker) Error() string
Error returns an actionable message.
type UsesAxesElem ¶
type UsesAxesElem struct {
AxisRefs []AxisRefElem `xml:"axis-ref"`
}
UsesAxesElem wraps <uses-axes>.
type ValidationError ¶
type ValidationError struct {
// Layer is the detection layer that produced this error.
Layer ErrorLayer
// ElementPath is the XPath-style description of the offending element,
// e.g. "phase[@id='p1']/substep[@id='s1_1']".
ElementPath string
// Message describes what is wrong, why, and how to fix it.
Message string
}
ValidationError represents a single schema validation finding. All three fields are always populated; an empty ElementPath indicates the error is at the document root level.
func ValidateSchema ¶
func ValidateSchema(r io.Reader) ([]ValidationError, error)
ValidateSchema reads XML from r and validates it against the 3-layer Pasture Protocol schema rules.
Error contract:
- io.Reader read failure → (nil, error)
- XML parse failure → ([]ValidationError{{Layer: LayerStructural, ...}}, nil)
- Violations found → ([]ValidationError{...}, nil) with len > 0
- Valid schema → (nil, nil)
func ValidateTree ¶
func ValidateTree(root *XMLNode) []ValidationError
ValidateTree validates a parsed XMLNode tree against the 3-layer Aura Protocol schema rules and returns all violations found.
Returns nil when the tree is valid. A nil root is treated as an empty document with no violations.
type Workflow ¶
type Workflow struct {
Id string
Name string
Description string
RoleRef types.RoleId
Stages []WorkflowStage
}
Workflow is a complete workflow specification for an agent role. Keyed in WorkflowSpecs by workflow id. Mirrors Python Workflow dataclass.
type WorkflowAction ¶
type WorkflowAction struct {
Id string
Instruction string
Command string // optional concrete shell/tool command
}
WorkflowAction is a single action within a workflow stage. Mirrors Python WorkflowAction dataclass.
type WorkflowElem ¶
type WorkflowElem struct {
Id string `xml:"id,attr"`
Name string `xml:"name,attr"`
RoleRef string `xml:"role-ref,attr"`
Description string `xml:"description,attr"`
Stages []StageElem `xml:"stage"`
}
WorkflowElem is a single <workflow id="..." name="..." role-ref="..." description="..."> element.
type WorkflowStage ¶
type WorkflowStage struct {
Id string
Name string
Order int
Execution string // WorkflowExecution: "sequential", "parallel", "conditional-loop"
PhaseRef protocol.PhaseId // optional phase this stage maps to
Actions []WorkflowAction
ExitConditions []ExitCondition
OperationalDetail string // optional prose rendered immediately after formal actions, before exit conditions
}
WorkflowStage is a single stage in an agent workflow. Mirrors Python WorkflowStage dataclass.
type WorkflowsSection ¶
type WorkflowsSection struct {
XMLName xml.Name `xml:"workflows"`
Workflows []WorkflowElem `xml:"workflow"`
}
WorkflowsSection is the top-level <workflows> element.
type XMLNode ¶
type XMLNode struct {
XMLName xml.Name
Attrs []xml.Attr `xml:",any,attr"`
Children []*XMLNode `xml:",any"`
Text string `xml:",chardata"`
}
XMLNode is a generic XML tree node for validator tree operations. It can represent any element in the schema document and is used by ValidateTree to walk the document without requiring concrete struct types.
func (*XMLNode) Iter ¶
Iter recursively finds all descendant nodes (including self) whose local tag matches tag, in document order.
func (*XMLNode) UnmarshalXML ¶
UnmarshalXML implements xml.Unmarshaler to parse an XMLNode tree from an XML decoder. This gives us a fully recursive generic tree without needing concrete struct types for every element.
Source Files
¶
- agents.go
- codegen.go
- context.go
- embed.go
- global_ids.go
- markdown.go
- markers.go
- schema.go
- schema_types.go
- skills.go
- specs.go
- specs_data.go
- specs_data_body.go
- specs_data_body_architect_handoff.go
- specs_data_body_architect_propose_plan.go
- specs_data_body_architect_ratify.go
- specs_data_body_architect_request_review.go
- specs_data_body_epoch.go
- specs_data_body_explore.go
- specs_data_body_impl_slice.go
- specs_data_body_research.go
- specs_data_body_reviewer_comment.go
- specs_data_body_reviewer_review_code.go
- specs_data_body_reviewer_review_plan.go
- specs_data_body_reviewer_vote.go
- specs_data_body_status.go
- specs_data_body_supervisor_commit.go
- specs_data_body_supervisor_track_progress.go
- specs_data_body_swarm.go
- specs_data_body_user_elicit.go
- specs_data_body_user_request.go
- specs_data_body_user_uat.go
- specs_data_body_worker_blocked.go
- specs_data_body_worker_complete.go
- specs_data_body_worker_implement.go
- specs_data_fragments.go
- validate.go