Goal contract capture
Skill synaptiai/synapti-marketplace/plugins/flow/skills/goal-contract-capture
Capture a FlowGoal contract as a project-local `.flow/goals/<id>.goal.yaml` file with outcome, acceptance criteria (with verification commands), specification elements (non-goals, failure modes, interface contracts), constraints, evaluator binding, continuation policy, and lifecycle frontmatter. Use when /flow:start passes the Spec Validation Gate, when /flow:goal create is invoked, or when /flow:review and /flow:address need a completion contract for a PR. This skill MUST be consulted because acceptance criteria alone do not constitute a contract — without an evaluator binding, boundaries, and lifecycle state, downstream phases cannot detect premature completion, the Stop hook cannot enforce evidence, and goals cannot resume across sessions.From its SKILL.md
npx -y skills add synaptiai/synapti-marketplace --skill goal-contract-captureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.9 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
Goal Contract Capture
You produce a FlowGoal contract — a durable completion contract that turns acceptance criteria + specification into a machine-readable, file-backed artifact. This skill is the 5th invoker of the existing specification-capture pattern; it wraps that skill (does NOT replace it) and adds the goal-specific fields needed for evaluator/Stop-hook enforcement.
Iron Law
No /flow:goal create without a complete contract. No .flow/goals/<id>.goal.yaml without an evaluator binding. The contract is the source of truth for the Stop hook and /flow:goal evaluate; gaps here cascade into silent premature completion.
Relationship to existing skills
This skill is a wrapper, not a fork:
| Existing skill | What it gives us | What this skill adds |
|---|---|---|
specification-capture | non-goals, failure modes, interface contracts | the specification block in the goal YAML |
criterion-verification-map | per-AC verification commands + expected evidence | the objective.acceptance_criteria[].verification_command field |
evidence-based-development | ASSERTION/EVIDENCE/VERIFIED discipline | the evidence_ref linking the AC back to a FlowEvidence sidecar |
If those skills have already produced their outputs (decision journal manifest entries), this skill reads from them rather than re-asking the user.
Inputs
The invoking command MUST pass:
- Goal id — typically
issue-{N},pr-{N}-review,pr-{N}-address, or an ad-hoc slug. Validated against the schema's^[a-z0-9][a-z0-9-]{0,63}$pattern. - Scope —
repo,branch, optionallyissueand/orpr, optionally ajournalpath (.decisions/issue-{N}.md). - Source — typically the GitHub issue body (parsed for AC) or the PR description (parsed for review/address scope).
- Invocation reason —
start | goal-create | review | address. Used to choose the right outcome template and the rightevaluator.type.
Outputs
Single file: .flow/goals/<id>.goal.yaml conforming to plugins/flow/schemas/v1/goal.schema.json. Written via bin/flow-goal-record.sh (atomic, O_NOFOLLOW-defended).
Plus: one goal-created artifact appended to the linked decision journal via bin/journal-record.sh --type goal-created --metadata goal_id=<id> --metadata source=<src>.
Workflow
-
Pre-flight check — refuse if
.flow/goals/<id>.goal.yamlalready exists andlifecycle.statusis not in{cancelled, failed}. Surface the existing goal to the user via the six-field escalation; never silently overwrite an active goal. -
Compose
metadata:metadata: id: <derived-from-invocation> created_at: <ISO-8601 UTC now> created_by: <invoking command, e.g. /flow:start> owner: <git user.email or @me> -
Compose
scope— from inputs. Setjournalto the linked decision journal path. Leaverun_idempty untilrun-state-managementwires FlowRun creation. -
Compose
objective— pull AC text + verification commands from the existingcriterion-verification-mapoutput. Each AC is one entry withstatus: pendingandevidence_ref: nullinitially. Theoutcomeis a one-sentence statement derived from invocation reason:start→ "Issue #{N} is implemented and verified."goal-create→ user-supplied via AskUserQuestion.review→ "PR #{N} review completed with findings posted or no-finding evidence recorded."address→ "All unresolved findings on PR #{N} are resolved, commented, or escalated."
-
Compose
specification— lift fromspecification-capture's journal entries:non_goalsfrom the## Specification > ### Non-goalsbodyfailure_modesfrom### Failure modesinterface_contractsfrom### Interface contracts
If any block is empty, raise the six-field escalation per
references/escalation-format.md— do NOT silently fill with placeholders. -
Compose
constraints— default totdd_required: true,require_all_pass: true,no_calendar_estimates: true,no_tier3_without_confirmation: true. Adddenied_pathsfrom settings (flow.goals.denied_pathscascade key); addallowed_pathsonly if the goal narrows the tier model (e.g., a focused refactor). -
Compose
evaluator:evaluator: type: flow_verdict_judge # hybrid for fuzzy criteria; deterministic for command-only command: /flow:goal evaluate judge_agent: goal-evaluator-judge evidence_bundle_format: plugins/flow/references/evidence-bundle-format.md denied_context: - implementation_rationale - self_review_findings -
Compose
continuation— defaults:mode: flow_managed,on_incomplete: continue_next_activity,on_blocked: six_field_escalation,on_complete: mark_achieved,max_iterations: <from settings, default 20>. -
Compose
lifecycle— initial state:lifecycle: status: active current_phase: <derived; start→explore, review→fan-out, address→categorize> current_activity: <first activity id> turns_evaluated: 0 last_evaluation: result: incomplete reason: "Goal created; evidence not yet collected." at: <now> -
Write atomically — call
bin/flow-goal-record.shwith the composed YAML. Verify exit 0; surface stderr on any failure. -
Record journal artifact —
bin/journal-record.sh --issue {N} --type goal-created --metadata goal_id=<id> --metadata source=<src>. -
Verify the artifact — read back
.flow/goals/<id>.goal.yamland validate against the schema (Python jsonschema if available). A schema mismatch here means the skill or the schema is broken; fail hard.
Per-invoker scope
| Invoker | Captures | Skips |
|---|---|---|
start | All blocks; outcome derived from issue title | nothing |
goal-create | All blocks; outcome from AskUserQuestion | journal manifest if no issue |
review | Outcome + AC (= review checklist) + constraints | specification (use issue's existing capture) |
address | Outcome + AC (= one per unresolved PR comment) + constraints | specification (inherit from review goal) |
Anti-patterns
- ❌ Silently overwriting an active goal — always surface and escalate.
- ❌ Filling in empty specification blocks with placeholders — escalate via six-field.
- ❌ Bypassing
bin/flow-goal-record.shfor "speed" — atomicity + symlink defense matters. - ❌ Setting
lifecycle.status: achievedat creation — the only way toachievedis through/flow:goal evaluate.
Reuse map
plugins/flow/skills/specification-capture/SKILL.md— read the per-invoker scope table; this skill adds row 5 (goal-create).plugins/flow/skills/criterion-verification-map/SKILL.md— read for the AC verification-command shape.plugins/flow/schemas/v1/goal.schema.json— the canonical schema this skill writes against.plugins/flow/bin/flow-goal-record.sh— atomic writer.plugins/flow/bin/journal-record.sh— for thegoal-createdmanifest artifact.plugins/flow/references/escalation-format.md— six-field escalation for any empty/ambiguous block.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.