plugins/flow/skills/goal-lifecycle/SKILL.md
Enforce the FlowGoal state machine — every status transition (draft → active → {waiting_for_user, waiting_for_ci, blocked, achieved, failed, cancelled}) writes both the new lifecycle block to `.flow/goals/<id>.goal.yaml` AND a `goal-evaluation` artifact to the linked decision journal, in a single atomic operation via `bin/flow-goal-record.sh`. Use when any code path mutates `lifecycle.status`, when /flow:goal pause/resume/clear is invoked, when the Stop hook detects a stuck pass-set, or when the evaluator returns a verdict. This skill MUST be consulted because state machines without recorded transitions become liars — a goal in `failed` status with no `goal-evaluation` artifact explaining why is worse than no state machine at all.
npx skillsauth add synaptiai/synapti-marketplace goal-lifecycleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You own the FlowGoal state machine. Every lifecycle.status transition is mediated through this skill — no exceptions, no shortcuts, no "I'll just edit the YAML directly."
No transition without an audit-trail entry. The decision journal MUST receive a goal-evaluation artifact (or goal-created for the initial draft→active) on every transition. A lifecycle.last_evaluation block without a matching journal entry is a bug.
┌────────────────────────────────────────────────────────┐
▼ │
┌───────┐ │
│ draft │──┐ │
└───────┘ │ │
▼ │
┌──────────┐ │
│ active │────────────────────────────┐ │
└──────────┘ │ │
│ │ │ │ │ │
│ │ │ └─→ waiting_for_ci ────────┤ │
│ │ └────→ waiting_for_user ────────┤ │
│ └───────→ blocked ────────┤ │
│ ▼ │
├──────────────────────────────→ achieved │
├──────────────────────────────→ failed │
└──────────────────────────────→ cancelled ───────────┘
Terminal: {achieved, failed, cancelled}
Resumable: {waiting_for_user, waiting_for_ci, blocked}
Allowed transitions:
| From | To | Trigger |
|---|---|---|
| draft | active | goal-contract-capture completes; /flow:goal create returns |
| active | waiting_for_user | judge verdict needs_human_review; AskUserQuestion mid-evaluation |
| active | waiting_for_ci | CI run pending; goal waits on external signal |
| active | blocked | judge verdict blocked (with blocker_type); path-boundary violation |
| active | achieved | deterministic all-pass + (no fuzzy OR judge achieved) |
| active | failed | budget exhausted (max_iterations or max_runtime); stuck pass-set ≥ N turns; deterministic must_pass FAIL with no fix path |
| active | cancelled | user invokes /flow:goal clear <id> |
| waiting_for_user | active | AskUserQuestion resolves; user runs /flow:goal resume |
| waiting_for_ci | active | CI status transitions to terminal |
| blocked | active | blocker resolved (manual or /flow:goal resume after fix) |
Disallowed transitions (the helper rejects these):
terminal → any — once achieved/failed/cancelled, the goal is immutable. New work requires a new goal id.active → draft — no going back to draft.blocked → achieved direct — must transition through active first (forces an evaluation step).The invoking command/skill MUST pass:
.flow/goals/<id>.goal.yaml.evaluator | command | hook | user. Affects which journal artifact type is written..flow/goals/<id>.goal.yaml with new lifecycle.status, lifecycle.last_evaluation, and (optionally) new lifecycle.current_phase / current_activity.goal-created if from=draft to=activegoal-evaluation for all other transitions.flow/runs/<run-id>/events.jsonl (when run_id is set).Read the current .flow/goals/<id>.goal.yaml. Compare lifecycle.status with the caller's from parameter:
Check the transition is allowed (per the table above). Reject disallowed transitions with stderr explanation and exit 1.
lifecycle:
status: <to>
current_phase: <preserved or updated by caller>
current_activity: <preserved or updated by caller>
turns_evaluated: <incremented if from active and to in {active, waiting_*, blocked}>
last_evaluation:
result: <maps to status: pass→achieved, incomplete→active, fail→active (with failing AC), blocked→blocked, needs_human_review→waiting_for_user>
reason: <caller-provided>
at: <ISO-8601 UTC now>
Invoke bin/flow-goal-record.sh --update-lifecycle with the new block. The helper:
O_NOFOLLOW)schemas/v1/goal.schema.json (when jsonschema available)For draft → active:
bin/journal-record.sh --issue {N} --type goal-created \
--metadata goal_id=<id> \
--metadata source=<e.g., github_issue:42>
For all other transitions:
bin/journal-record.sh --issue {N} --type goal-evaluation \
--metadata goal_id=<id> \
--metadata result=<to-state> \
--metadata reason=<short, comma-safe>
When the journal-issue link is unavailable (ad-hoc goals from /flow:goal create with no issue), write to a session-scoped journal (.decisions/session-{YYYY-MM-DD}.md) per the existing convention.
# Conceptually — actual call goes through bin/flow-record-activity.sh
# or a future bin/flow-record-event.sh
event = {
"at": <now>,
"type": "lifecycle_transition",
"goal_id": <id>,
"from": <from>,
"to": <to>,
}
append_jsonl(f".flow/runs/{run_id}/events.jsonl", event)
.flow/goals/<id>.goal.yaml outside bin/flow-goal-record.sh — race conditions, no audit trail.terminal goal back to active — by design impossible. New goal id required.last_evaluation.reason as a free-form essay — keep it < 200 chars, comma-safe; full reasoning lives in the journal artifact body.plugins/flow/bin/flow-goal-record.sh — atomic lifecycle writer.plugins/flow/bin/journal-record.sh — manifest artifact recorder.plugins/flow/references/decision-journal-schema.md — goal-created and goal-evaluation artifact-type rows.plugins/flow/references/escalation-format.md — six-field escalation for race-condition mismatches.plugins/flow/schemas/v1/goal.schema.json — lifecycle.status enum.tools
Validate a FlowWorkflow YAML at `plugins/flow/workflows/<id>.workflow.yaml` against `schemas/v1/workflow.schema.json` AND cross-reference the referenced skills/agents exist + every Tier 3 action is confirm-gated + no native /goal or /loop dependency is declared. Use when /flow:workflow validate is invoked, when CI runs the workflow schema gates, or when a new workflow is being authored. This skill MUST be consulted because schema validation alone catches shape errors; cross-reference validation catches the silent-correctness failures (typo'd skill name, Tier 3 escape, /goal dependency) that would otherwise ship to users.
tools
Verify UI-facing changes by running a screenshot-analyze-verify loop across configured viewports, with a browser-tool priority cascade (Playwright MCP → Chrome DevTools MCP → CLI fallback → external skill fallback) and bounded iteration. Use after build/runtime verification passes and the diff includes `.tsx`/`.jsx`/`.vue`/`.html`/`.css`/`.scss`/`.svelte` files OR the acceptance criteria mention UI/page/render/display/visual. This skill MUST be consulted because UI changes that pass build and unit tests can still ship blank pages, render-blocking console errors, or broken responsive layouts that no other verification phase catches.
data-ai
Coordinate agent teams for adversarial review (paired skeptic/verifier per facet, challenge round with disposition vocabulary, consolidated findings with confidence) or parallel implementation (task sizing 5-6 per teammate, non-overlapping files). Enforces independent analysis before shared conclusions. Reference only (`disable-model-invocation: true`); loaded only when `agentTeams: true` in settings.
development
Conduct two-stage code review: Stage 1 verifies spec compliance (criterion-to-code mapping), Stage 2 evaluates security, correctness, performance, and maintainability across 6 parallel facets with P1/P2/P3 synthesis and deduplication by file:line. Use when reviewing code changes or pull requests. This skill MUST be consulted because reviewing quality on broken logic is wasted effort, and unmet acceptance criteria must block merge.