2 Contract Phase Outcome
jbr870 edited this page 2026-04-30 10:10:53 +00:00
Status Last updated Parent Read before this
complete 2026-04-30
Design - Architecture Overview
Role - The Orchestrator

Phase Outcome

The structured handoff produced at the end of every skill run. It is the interface between skills and orchestrators, and the central primitive that makes the architecture work.

Current state

Every skill emits a Phase Outcome as its final action. Three sections, every time:

Produced lists what now exists — artifacts created, comments posted, code committed, status changed. The factual record of what the skill did.

Findings & observations captures things noticed during the phase that may or may not be in scope: out-of-scope items spotted in /requirements, stray QA findings beyond the SREQ's contract, learning insights in /closeout, pre-existing issues exposed by the work. Each finding carries a proposed categorisation (in-scope-blocking, in-scope-deferrable, out-of-scope, pre-existing) with a reason.

Pending decisions are the explicit choice points the orchestrator must resolve before the next phase. Each carries an ID, a question, options, a recommended option with reasoning, and a blocking flag.

The format is YAML for machine-readability with prose explanations. Same discipline as the journal frontmatter — agentic orchestrators must be able to parse without NLP.

phase: requirements
feature: feature-042
produced:
  - artifact: PREQ
    location: issue body
findings:
  - type: out-of-scope-item
    title: "User avatar upload sizing"
    reasoning: "Mentioned by user, not part of this feature's user stories"
    proposed_category: out-of-scope
pending_decisions:
  - id: D-001
    type: approval
    question: "Approve PREQ for technical planning?"
    options: [approve, request-changes, reject]
    blocking: true
  - id: D-002
    type: capture-out-of-scope
    question: "Capture 'User avatar upload sizing' as separate issue?"
    options: [capture, discard]
    recommended: capture
    blocking: false

Lifecycle

  • Each skill run produces a fresh Phase Outcome — never updates a previous one.
  • Phase Outcomes are immutable once posted; they are the historical record.
  • Decision resolutions are appended as follow-up comments referencing the decision ID — never edits to the original.
  • A skill that runs twice produces two Phase Outcomes; the older one stays as record.

Two audiences

The same Phase Outcome serves two readers:

  • Orchestrator-facing: pending decisions, findings, recommendations.
  • Next-skill-facing: structured handoff information the consuming skill needs to pick up where this one left off.

Skills read prior Phase Outcomes for context; orchestrators read them to resolve decisions.

What this absorbs

Several things across the SDLC that previously had bespoke mechanisms are now instances of this one primitive:

  • PREQ / plan / UAT approval → Pending Decisions of type approval.
  • Out-of-scope items from /requirements and /technical-plan → Findings with capture-as-issue recommendations.
  • Stray QA findings → Findings categorised by the validate skill, surfaced as Pending Decisions when ambiguous.
  • Learning insights from /closeout → Findings with proposed targets (skill update, CLAUDE.md, memory).
  • Skipped fixes in /qa-fix → Pending Decisions to defer or block release.

Categorization is a proposal, not an authority

When a skill classifies findings, it proposes with reasoning. The orchestrator can override. The safe default is "in-scope, blocking" — an over-eager skill reclassifying findings to skip work is the obvious failure mode. Bias toward blocking; require explicit orchestrator action to demote.

Rationale

The Phase Outcome is the change that made everything else fall into place. Before it, three things were tangled: the skill's deliverables, the skill's communication with the next skill, and the skill's request for a human decision. Tangled, those three are hard to evolve — every skill ends up with its own bespoke prompt-the-user logic, and "the orchestrator" can't be anything other than the running terminal.

Separating them gives each layer a clean job. Deliverables are just deliverables. Skill-to-skill handoff has a defined shape (the Produced section + handoff fields). Orchestrator decisions are explicit, listed, and impossible to lose (Pending Decisions blocks pipeline advancement).

The two-audience structure (orchestrator-facing + next-skill-facing) avoids needing two separate documents per phase. They share a substrate; the orchestrator reads what it cares about, the next skill reads what it cares about, and they don't trip over each other.

Immutability matters because resolutions reference decision IDs. If Phase Outcomes were editable, a resolution comment from yesterday could become incoherent when today's edit removes the decision it pointed at. Append-only is the only model that keeps the audit trail honest.

The "categorization is a proposal" principle exists because skills will sometimes get findings wrong — too eager to defer, too eager to include. Making the orchestrator the authority means errors in either direction are catchable; making the skill the authority would let an over-eager skill silently defer real problems.

Open questions

None at this level. The exact YAML schema is implicit in current skill code rather than spec'd in _shared/. Pinning it down is part of the broader migration; see the sdlc-architecture.md migration section.