Claude Cursor opencode Skill

workflow-status

Read-only workflow sensor: run the deterministic script, read the fixed machine envelope, interpret the recommendation. Never edits. Triggers: "workflow-status", "workflow status", "what can I build next".

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download gtrabanco-agentic-workflow-skills_workflow-status-4b3a56b.zip · 23 KB
Part of gtrabanco/agentic-workflow — 33 skills

Install

skills CLI npx skills add https://github.com/gtrabanco/agentic-workflow/tree/main/skills/workflow-status
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install gtrabanco-agentic-workflow@llmmart
Git git clone https://github.com/gtrabanco/agentic-workflow.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole gtrabanco/agentic-workflow collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Workflow Status (the orchestrator's sensor)

One read-only pass that answers, in a single fixed JSON envelope: what exists, what is blocked on what, what is startable right now, and what the recommended next command is. The script is the deterministic producer: scripts/workflow-status.mjs executes the published SENSOR_CORE sequence (steps 1–9 including 6a) and prints the envelope. This skill runs the script, reads the JSON, interprets it against the references below, and prints the human report — it never assembles the envelope by hand.

Turn contract — verify before ending the turn

✓ The script was RUN — `bun scripts/workflow-status.mjs [--json-only]
  [--last-envelope <json|path>]` (node is the fallback when bun is absent, per
  the repository's runtime convention); the envelope is the script's stdout, never
  assembled by the model
✓ Nothing was edited, committed, pushed, or created — read-only, always
✓ `next.recommended` is non-bare (carries the unit's slug/NN, never a bare
  `/plan-feature`) AND the script computed it from the unit's resolved status
  **and** its current pre-execution evidence: `idea`/undesigned →
  `/design-feature <slug>`; `defined` → `/plan-feature <slug>` only on a current
  `SPEC-REVIEW-PASS`, else `/review-spec <slug>`; `planned`/`in-progress` → `/execute-phase <NN>` only on a
  current `PLAN-REVIEW-PASS`, else `/review-plan <NN>` (step 6a)
✓ `detail.crash_recovery` carries a verdict from the decision table and the
  envelope `state` matches it (CLEAN→OK, RESUMABLE→CONTINUE,
  AMBIGUOUS→NEEDS_INPUT)
✓ Every `detail.design_candidates[].next` begins with `/design-feature `
✓ Every degraded dimension is named in `detail.degradations` as
  `unavailable-<source>-<cause>` — and, when `--last-envelope` was supplied, the
  no-progress guard's `workflow_observations` note is present (never a silently
  repeated bland recommendation)
✓ The envelope is emitted on **every** invocation, including a same-session
  natural-language follow-up about state — never replaced by prose
✓ The human-readable summary is printed, then the machine envelope (the script's
  JSON) is the ABSOLUTE last output

With --json-only, skip the human-readable summary: print the envelope alone.

When to use

  • Between orchestration steps: an external driver runs it to decide the next command and model tier without parsing prose.
  • Before picking work manually: "what can I start right now?"
  • Not for judging quality (review-change/audit-pr) or product health (product-audit) — this skill reports state, it never judges.

Step 0 — Discover the project (always first)

Per the agent guide's Workflow conventions + documentation map. The script reads what THIS skill needs (docs/features/ROADMAP.md, the fix index docs/fix/README.md, every in-flight feature folder's TASKS.md + progress.md + review-findings.md, and docs/workflow/REPOSITORY_STATE.md); read them yourself only to interpret a field the script emitted.

Progressive loading — fixed sensor route

The reference allowlist is exactly the seven linked paths below. Never invent or read another references/ path. This skill is a read-only sensor.

  1. sensor core — the sequence the script executes
  2. crash recovery
  3. envelope core
  4. envelope fields
  5. pre-execution evidence
  6. guardrails

Add sensor signals only when a unit, issue, finding, or recommendation exists; an empty project skips that file but still emits the empty shapes defined by envelope fields. Add portability only when the platform actually lacks a named primitive. --json-only does not skip any baseline file.

Portability

The sensor uses repository and forge commands only. When a named agent feature is unavailable, follow portability without changing the JSON contract.

Relationship to other skills

  • The sensor counterpart to ship-roadmap's conductor: an external orchestrator calls workflow-status → routes on the envelope → invokes plan-feature / execute-phase / review-change / audit-pr / triage-issue directly, choosing the model per step — the same loop without the in-agent autopilot.
  • Read-only sibling of audit-docs (which judges coherence and can fix) and product-audit (which judges health): this one only reports state.
  • Schema owner: orchestration-envelope (internal).

Done when

  • The script ran and every claim in the report comes from its envelope — nothing inferred from memory, nothing assembled by hand.
  • detail.design_candidates, detail.features, detail.fixes, detail.startable_now, detail.blocked_units, detail.open_prs, detail.untriaged_issues, detail.urgent, detail.degradations, and detail.crash_recovery were read from the envelope, and the envelope state matches the crash-recovery verdict.
  • With --last-envelope supplied: the no-progress guard ran — a stalled /plan-feature//design-feature hint surfaces as a workflow_observations note, never a silent bland repeat, with no new write path introduced.
  • The human summary (unless --json-only) and the envelope are printed, envelope last.
  • Nothing was modified anywhere.
  • When the envelope carries next.continuation, the next-command echo quotes the emitted next.continuation (rendering for display), never author exact command tokens; the human-facing prose → Next: block below stays.

→ Next: the envelope's next.recommended command — it is computed from the actual state, so it IS the recommendation · a human overview → read the printed table · orchestrating programmatically → parse the script's JSON

Files (agentic-workflow)
  • references
    • CRASH_RECOVERY.md 3.7 KB
      ## Crash recovery (run every invocation)
      
      A driver process can die mid-turn; on restart, the persisted state it holds is
      a **hint, never a source** — everything below is recomputed from git, the
      forge, and the docs. Nothing is cleaned up here (read-only stands): this
      section *classifies*; the resume command it recommends does the acting.
      
      **Checklist:**
      
      - ✓ **Working tree per unit branch.** A dirty tree (`git status --porcelain`)
        or unpushed commits on a `feat/*`/`fix/*` branch → interrupted-turn
        candidate. Cite branch + files. Checking unpushed commits: **first check
        the branch has an upstream** (`git rev-parse --abbrev-ref <branch>@{u}` —
        non-zero exit = no upstream). No upstream → **every commit on the branch is
        unpushed by definition**, don't run `git log @{u}..` (it errors with
        `fatal: no upstream configured`, which is exactly the mid-crash
        never-pushed case, not an error to surface). Has an upstream → use
        `git log @{u}.. --oneline` / `git status -sb` as usual.
      - ✓ **Phase-ledger coherence.** Compare the unit's `progress.md`/`TASKS.md`
        against the branch's actual commits: commits after the last closed phase
        entry, or ticked tasks with no matching commit, are cited as evidence.
      - ✓ **Hint envelope (optional).** With `--last-envelope <json|path>`, diff the
        caller's persisted envelope against the recomputed state and report the
        divergence in one line. The hint never overrides recomputed state.
      - ✓ **No-progress guard (optional, requires `--last-envelope`).** When the
        hint's `next.recommended` was `/plan-feature <slug>` or `/design-feature
        <slug>` for a given unit, and this run's own recomputed status for that
        **same unit** is still at the **same pre-advance status** the hint expected
        to move it off of (`defined` for a `/plan-feature` hint; `idea` for a
        `/design-feature` hint) — either the recommended command ran but its status
        write was dropped, or it never ran at all; this guard cannot distinguish the
        two from the envelope alone, so the note names it as a **suspected** stall,
        not a confirmed dropped write. Emit a `workflow_observations` note (see
        `## Machine envelope` for the exact note shape). This is strictly additive:
        the same `next.recommended` /
        `next.tier` still fire per the normal classification (step 6) — the guard
        only stops the silent, bland repeat by making the stall visible. Still
        read-only: no write, no repair, no new persistence.
      
      **Classification (decision table — every row independently checkable; first
      matching row wins per branch):**
      
      | Evidence | Verdict |
      |---|---|
      | Clean tree, ledger coherent with commits | `CLEAN` |
      | Dirty/unpushed on a unit branch AND the ledger points to a unique next task/phase | `RESUMABLE` — resume command: `execute-phase <NN> <phase>` |
      | Dirty/unpushed AND ledger contradiction (ticks ahead of commits, unknown branch, detached HEAD) | `AMBIGUOUS` — a human looks first |
      
      **Return exactly (appended to the report):**
      
      ```
      CRASH RECOVERY — verdict: CLEAN | RESUMABLE | AMBIGUOUS
      | Branch | Evidence | Classification | Resume command |
      |---|---|---|---|
      | <branch> | <dirty: n files; ledger: <state>> | RESUMABLE | execute-phase <NN> <phase> |
      Hint envelope: matched | diverged: <one line> | not provided
      ```
      
      (`CLEAN` with no unit branches in play → the table body is a single
      `| — | clean tree, coherent ledgers | CLEAN | — |` row.)
      
      **Multiple unit branches, multiple verdicts → one envelope `state` (fixed
      precedence, worst wins):** `AMBIGUOUS` > `RESUMABLE` > `CLEAN`. A human
      decision pending on ANY branch outranks a mechanical resume on another, which
      outranks an all-clean state. The report's per-branch table still lists every
      verdict; only the envelope's single `state` is reduced to the worst one.
      
    • ENVELOPE_CORE.md 6.8 KB
      ## Machine envelope
      
      `scripts/workflow-status.mjs` is the **deterministic producer** of this
      envelope: it performs the assembly, runs the `validateEnvelope` self-check
      (diagnostic only, exit 0), and prints the one JSON document. The skill runs the
      script and interprets the JSON — it never assembles the envelope. Schema and
      placement per the installed `orchestration-envelope` skill. The
      `state` maps 1:1 from the crash-recovery verdict — **no new schema fields or
      states** (the schema package needs no release):
      
      - `CLEAN` → `state: OK` (the sensor default when the substrate is usable).
      - A missing or non-frozen repository-state ledger is a run-scoped substrate
        gate and overrides the crash-recovery state with `state: BLOCKED`; the
        blocker and concrete discovery/resolution command are emitted before
        readiness data.
      - `RESUMABLE` → `state: CONTINUE`, `next.recommended` = the resume command
        from the decision table.
      - `AMBIGUOUS` → `state: NEEDS_INPUT`, `needs_input.question` = what is
        contradictory, `needs_input.options` = the concrete choices (resume / redo
        the phase / discard the dirty work), evidence in `detail.crash_recovery`.
      
      `next` always carries the single best command for the project right now, and
      `detail` the full tree (plus `crash_recovery: {verdict, branches: [...]}`).
      **`detail.design_candidates`** is an array beside `detail.startable_now` /
      `detail.blocked_units` — every `idea`-status unit, deps-agnostic (design
      happens before dependency startability matters). It is never a top-level
      envelope key.
      
      **`detail.urgent`** — the injection-safe urgency channel (feature 15):
      `{issues: [...], interruptibility: {...}}`. `issues` lists every **open**
      issue carrying `urgent` or `fix-next`, read **only** from the `labels` object
      returned in step 2/3's `gh issue list --state open … --json … ,labels` call —
      never from title, body, or comments; an issue with "URGENT" only in its text
      never appears here (`urgent` wins when an issue somehow carries both labels).
      Scoping the list to `--state open` means a shipped fix's issue drops out of
      `detail.urgent` the moment it closes — automatically, on the next poll, with
      no manual label strip required (there is nothing to reconcile: this field is
      recomputed fresh every invocation, never persisted).
      `interruptibility` carries the in-flight unit's facts — `phase`, `dirty`
      (bool), `tasks_from_boundary` (count of unticked tasks left in the current
      phase) — reusing the same phase-progress and crash-recovery reconcile, not a
      new computation. This field is **presence-only reporting**; it never contains
      a pause-vs-finish verdict — that decision belongs entirely to the consumer's
      bounded judge (`docs/workflow/ORCHESTRATION.md`). An empty `issues` array
      means no urgency signal is in play; `next.recommended` may still be
      influenced by a non-empty one (e.g. surfaced as an `alternatives` entry), but
      is never silently replaced by it.
      
      **`detail.untriaged_issues`** — the plain open-issue backlog surfaced by
      step 15: `{count, oldest_open: [numbers]}` (oldest-first, capped at 5 numbers).
      `detail` is schema-unconstrained (`envelope.schema.json:170`, `"detail": {}`),
      so this field needs **no package change**. Kept strictly distinct from
      `detail.pending_triage`
      (findings pulled from `known-issues.md`/postponed-labeled issues, step 14) and
      `findings.untriaged` (review-finding routing) — none of the three subsumes
      another. `count: 0` means every open issue has a triage disposition; a
      non-zero `count` may drive `next.recommended`/`alternatives` toward a
      concrete `/triage-issue <numbers>` citing the listed issues.
      
      **Per-unit `review`/`closure`/`issues_born` (step 10–12) — carried on each
      `detail.features[]`/`detail.fixes[]` entry, not as new top-level keys.**
      `detail` is schema-unconstrained (`envelope.schema.json:170`, `"detail": {}`)
      — same precedent as `detail.urgent`/`detail.untriaged_issues` (fix `#52`), so
      these need **no package change**:
      - `review: {last_checkpoint_sha, unreviewed_diff: {lines, files},
        terminal_done, adversarial: {ran, n}}` — step 10. `adversarial.ran`/`n` are
        `null` unless real evidence exists (no skill persists that marker today —
        never guessed).
      - `closure: {state}` ∈ `present | absent-legacy | blocked` (feature units)
        or `n/a` (fix units) — step 11, reusing `audit-pr`'s own grep verbatim.
      - `issues_born: {n, with_descope_amendment}` — step 12, reusing `audit-pr`'s
        scope-bleed detection (widened by `#79`/`#89` to also match an issue
        linked from an `## Amendments` row).
      
      **Not yet mechanized (read this before consuming the three fields above).** The
      `scripts/workflow-status.mjs` sensor does **not** emit `review`, `closure`, or
      `issues_born` today: they are steps 10–12 of the published sequence and remain
      skill-side work, so no `detail.features[]`/`detail.fixes[]` entry carries them
      until a sensor phase owns them. A consumer must treat their absence as "not
      computed", never as "empty": absence is not a `closure: absent-legacy` verdict
      and not an `issues_born.n: 0`.
      
      **`next.suggested[]`** — step 13's trigger-attributed suggestion surface,
      `{command, trigger, source_skill}[]`, **optional** (mirrors
      `packages/agentic-workflow-schema` 2.1.0's optional `EnvelopeSuggestion[]`).
      Each `trigger` string quotes the owning skill's own condition — never a
      second, drifting copy of that skill's logic. Advisory only: it rides beside
      `next.recommended`/`next.tier`, never replaces them. No unit has a fired
      trigger this run → `next.suggested` is emitted as an empty array
      (`"suggested": []`), never an absent key: a consumer keys on the array, not on
      the key's presence.
      
      **Envelope shape reminders (the script validates these before printing — mirrors
      `packages/agentic-workflow-schema/envelope.schema.json`):**
      
      - `blockers[].scope` ∈ `{"unit","run"}` — there is **no** `"code"` value;
        doc/roadmap drift is always `"unit"`-scope (`envelope.schema.json:111`).
      - A `"run"`-scope blocker forces `state` ∈ `{BLOCKED, HALT}` — it is **never**
        compatible with `state: OK` (see `orchestration-envelope`).
      - `dependencies.unmet` is an **array of strings** (unit ids / `#issue` refs) —
        never an array of objects (`envelope.schema.json:120`); any richer detail
        belongs in a `blockers[].detail` string instead.
      
      **`next.tier` derivation — a fixed command→tier map, never guessed:**
      
      | Command | Tier |
      |---|---|
      | `/discover-repository-state` | `strong` |
      | `/resolve-repository-state` | `strong` |
      | `/plan-feature` | `strong` |
      | `/design-feature` | `strong` |
      | `/review-change` | `strong` |
      | `/audit-pr` | `strong` |
      | `/triage-issue` | `strong` |
      | `/product-audit` | `strong` |
      | `/execute-phase` | `cheap` |
      | `/review-spec` | `strong` |
      | `/review-plan` | `strong` |
      
      `next.tier` is read off this map by matching the resolved `next.recommended`
      command's name (ignoring its arguments) — never guessed and never copied from
      the invoking driver's own tier.
      
    • ENVELOPE_FIELDS.md 6 KB
      ## Envelope fields and example
      
      **No-progress guard note (`workflow_observations`, requires `--last-envelope`,
      see the crash-recovery checklist above)** — when the hint's `next.recommended`
      targeted `/plan-feature <slug>` or `/design-feature <slug>` and this run still
      classifies that same unit at the same pre-advance status, append a note of the
      exact shape:
      `"<slug> still 'defined' after the hint's /plan-feature <slug> recommendation — suspected dropped defined→planned write (see #51)"`
      (swap `defined`/`/plan-feature` for `idea`/`/design-feature` on the design
      side). The recommendation itself is unaffected — this only adds visibility.
      
      **Shape vs. current output — read this before trusting the example below.** The
      example is the envelope's **intended shape**, not everything the deterministic
      producer emits today: per-unit `review`, `closure`, and `issues_born` (steps
      10–12) are **not yet mechanized** by `scripts/workflow-status.mjs` and do not
      appear in its output (`next.suggested[]`, step 13, is emitted — as an empty
      array when nothing fired). A consumer
      must read their absence as "not computed", never as `closure:
      absent-legacy` or `issues_born.n: 0`; the owning note is
      `ENVELOPE_CORE.md` §Not yet mechanized.
      
      ```json
      {
        "skill": "workflow-status",
        "state": "OK",
        "summary": "2 features merged, 07 in-progress at P2/4 awaiting review, 05 startable, fix #43 pending triage, 08 needs design.",
        "unit": {"type": "none", "id": null, "issue": null, "branch": "main"},
        "phase": {"current": null, "total": null, "completed": null},
        "pr": {"number": null, "url": null, "state": "none", "head_sha": null, "merge_ready": null, "ci": null},
        "gates": {"verification": null, "review_pending": null, "audit_pending": null},
        "findings": {"fix_now": [{"id": "F1", "file": "src/export/handler.ts:88", "axis": "security", "severity": "high", "class": "fix-now", "route": "fold into phase", "suggested_tier": "strong"}], "issues_filed": [], "untriaged": 2, "decisions_recorded": 0},
        "blockers": [],
        "dependencies": {"unmet": [], "build_order": []},
        "recommendations": {"product_audit": false, "reason": null},
        "needs_input": null,
        "next": {"recommended": "/review-change", "alternatives": ["/plan-feature 05"], "tier": "strong",
                 "suggested": [{"command": "/review-change", "trigger": "accumulation: 420 changed lines since last-reviewed sha", "source_skill": "execute-phase"}]},
        "detail": {
          "design_candidates": [{"id": "08-billing-webhooks", "status": "idea", "next": "/design-feature 08-billing-webhooks"}],
          "pre_execution": [{"unit": "12-export-api", "stage": "plan", "label": "stale", "verdict": "PLAN-REVIEW-PASS", "boundDigest": "sha256:9f2c…", "observedDigest": "sha256:41ab…", "recommended": "/review-plan 12-export-api", "reason": "docs/features/12-export-api/ACCEPTANCE.md changed after the review"}],
          "features": [
            {"id": "07-csv-export", "status": "in-progress", "deps": ["01"], "deps_unmet": [],
             "phase": {"current": "P2", "total": 4}, "pr": null,
             "review_pending": true, "audit_pending": null, "merge_ready": null,
             "review": {"last_checkpoint_sha": "a1b2c3d", "unreviewed_diff": {"lines": 420, "files": 9},
                         "terminal_done": false, "adversarial": {"ran": null, "n": null}},
             "closure": {"state": "present"}, "issues_born": {"n": 0, "with_descope_amendment": 0}},
            {"id": "05-auth", "status": "defined", "deps": [], "deps_unmet": [],
             "phase": {"current": null, "total": null}, "pr": null,
             "review_pending": null, "audit_pending": null, "merge_ready": null,
             "review": {"last_checkpoint_sha": null, "unreviewed_diff": {"lines": null, "files": null},
                         "terminal_done": false, "adversarial": {"ran": null, "n": null}},
             "closure": {"state": "absent-legacy"}, "issues_born": {"n": 0, "with_descope_amendment": 0}}
          ],
          "fixes": [
            {"id": "43-null-crash", "issue": 43, "status": "planned", "deps_unmet": [], "pr": null,
             "review": {"last_checkpoint_sha": null, "unreviewed_diff": {"lines": null, "files": null},
                         "terminal_done": false, "adversarial": {"ran": null, "n": null}},
             "closure": {"state": "n/a"}, "issues_born": {"n": 0, "with_descope_amendment": 0}}
          ],
          "startable_now": ["05-auth", "fix-43"],
          "blocked_units": {"09-billing": {"unmet": ["05-auth"], "build_order": ["05-auth", "09-billing"]}},
          "open_prs": [{"number": 13, "unit": "07-csv-export", "ci": "green", "merge_ready": false}],
          "pending_triage": [{"source": "docs/features/07-csv-export/known-issues.md", "title": "empty-file edge"}],
          "untriaged_issues": {"count": 3, "oldest_open": [21, 33, 40]},
          "workflow_observations": ["branch feat/07-csv-export is 1 commit ahead of origin"],
          "urgent": {
            "issues": [{"number": 51, "title": "prod webhook signature check bypassed", "label": "urgent"}],
            "interruptibility": {"unit": "07-csv-export", "phase": "P2", "dirty": true, "tasks_from_boundary": 2}
          },
          "crash_recovery": {
            "verdict": "CLEAN",
            "branches": [
              {"branch": "feat/07-csv-export", "evidence": "1 commit ahead of origin; ledger coherent", "verdict": "CLEAN", "resume_command": null}
            ]
          }
        }
      }
      ```
      
      `detail.startable_now`, `detail.blocked_units` (with build orders),
      `detail.design_candidates`, `detail.pre_execution` (one row per sensed unit from step
      6a, `{unit, stage, label, verdict, boundDigest, observedDigest, recommended, reason}`,
      `verdict`/`reason` null when absent) and `detail.pending_triage` are the keys an
      orchestrator routes on; a unit appears in `startable_now` only when its
      `pre_execution[].label` is `current` for the stage it is about to enter; every id in `startable_now`/`blocked_units` must appear
      fully in `features`/`fixes` — an `idea` unit appears ONLY in
      `design_candidates` (and `detail.features`), never in `startable_now`, since
      it has no deps-met check to pass (design precedes dependency startability).
      `05-auth` above illustrates `defined` (not yet `planned`): startable, next
      `/plan-feature`, phase fields null (no planning artifacts yet).
      
    • GUARDRAILS.md 1 KB
      ## Guardrails
      
      - **Read-only, always.** No commit, push, issue, comment, label, or file edit —
        not even fixing an obviously stale roadmap row (report it as a blocker of
        kind `substrate` instead; `audit-docs` is the fixer).
      - Evidence discipline per the project's **Workflow conventions**: every status
        comes from a command's output or a file's content; unverifiable → `null` +
        a `workflow_observations` note, never a guess.
      - Forge unavailable → still report the git/docs view, with a `blockers` entry
        `{"kind": "substrate", "id": "forge", "scope": "run"}` so the orchestrator
        knows PR-dependent states are unknown.
      - **`detail.urgent` is presence-only and read-only, always.** Derive it
        **exclusively** from the `labels` object of `gh issue list … --json …
        ,labels` — never parse title, body, or comments, and never cross-check the
        labeling actor's permission via the issue timeline (presence is already
        triage+-gated by GitHub). This sensor never emits a pause-vs-finish
        decision — only the facts the consumer's judge needs.
      
    • PORTABILITY.md 812 B
      ## Portability (agents other than Claude Code)
      
      The workflow is the contract; Claude Code features are conveniences. This
      skill has no Claude Code dependency at all — it is the piece that lets ANY
      driver (a shell loop, a CI job, another agent) orchestrate the workflow:
      
      - **No slash-command menu** — open this `SKILL.md` and follow it literally in
        a fresh conversation, or invoke it headless (see
        `docs/workflow/ORCHESTRATION.md` for per-agent invocation patterns).
      - **No per-skill `model:`/`effort:`** — this is mechanical reading and
        counting: a **cheap** tier is enough; never spend a strong model here.
      - **No argument passing (`--last-envelope`)** — paste the persisted envelope
        JSON into the invocation message: the skill treats the last fenced json
        block of the *request* as the hint.
      
    • PRE_EXECUTION.md 5.7 KB
      ## Pre-execution receipt sensing (step 6a)
      
      Roadmap status says what exists; only a receipt bound to the current bytes says
      whether the unit may be executed. Sense it like every other signal — read the file,
      recompute the digest, never trust the prose sitting around the block.
      
      ### What is read
      
      For every unit whose resolved status is `defined`, `planned` or `in-progress`:
      
      1. The newest `## Pre-execution review receipt v1 — spec` and `… — plan` block in the
         unit's `progress.md` (no `progress.md`, or no block for that stage → `missing`).
      2. The `snapshot` line — the `sha256:` digest the receipt binds — and each bound
         artifact's current bytes: re-derive the digest with the recipe owner's verify
         mode — `bun scripts/pre-execution-snapshot.mjs verify --stage <spec|plan> --unit
         <id> [--parent <64-hex>]` (`pre-execution-review` owns the recipe; a feature plan
         check needs the Product digest it descended from, a fix check binds no parent).
         Read `structural.reasonCode` and `structural.changedPaths` out of the JSON — they
         name the dimension that stopped being true, which is what the sensor labels
         `stale`. A snapshot digest is a canonical
         SHA-256 over the snapshot object, so `git hash-object` is never a substitute: it
         stays correct only for the frozen `ACCEPTANCE.md` manifest blob.
      3. The verdict, the reviewed `unit`, the stage, and the author fields
         (`reviewer` and `authorId` — the receipt's `Reviewer:` / `Author:` lines — and
         `authorExclusion`).
      
      ### What proves a review ran (step 8)
      
      One artifact later, the same discipline: step 8's `review_pending` keys on the
      unit's **durable review mark** — the `REVIEW-RAN` row of its `review-findings.md`
      ledger, whose shape and writer `pre-execution-review`'s `LEDGERS.md` owns — and
      judges it by step 8's currency rule in `SENSOR_CORE.md`, never by a keying
      invented here. A findings ledger with rows and no mark leaves the unit
      review-pending: its rows prove findings were folded against
      some state, which is a different fact from *this* state being reviewed, so the
      sensor reports a missing gate, never a verdict that no review ever happened.
      
      ### One label per stage, and the command it recommends
      
      | Label | Evidence | Recommended |
      |---|---|---|
      | `current` | stage PASS verdict **and** recomputed digest = bound digest | spec: `/plan-feature <slug>` · plan: `/execute-phase <NN>` |
      | `missing` | no receipt block for the stage | `defined` → `/review-spec <slug>` · planned/in-progress → `/review-plan <NN>` |
      | `stale` | bound digest differs, or a bound context row moved | re-run **that stage's** review — quote the emitted planning-gate re-run continuation (`next.continuation`, `rendering` for display), never author exact tokens |
      | `wrong-stage` | the only PASS belongs to the other stage | the stage that is missing — never the stage that passed |
      | `substitute` | prose verdict, legacy block, or internal attestation stands where a receipt should be | that stage's review, and report the substitute as a blocker detail |
      | `self-approved` | the author of the artifact recorded the PASS | that stage's review in a clean context |
      | `author-readiness` | an authoring readiness result sits where a verdict should be | that stage's review — readiness never licenses execution |
      | `legacy` | `planned`/`in-progress` unit with no ledgers and no receipt (predates feature 28) | the adoption route below |
      | `impossible-timeline` | `structural.fresh: false`, `structural.reasonCode: impossible-timeline` — digest and revision match by construction; a receipt's own recorded timeline is physically impossible (finish predating source revision's commit date beyond the published skew); a legacy receipt with no parsable Started/finished: line, or a source revision git cannot resolve, stays unflagged (fail-open) | that stage's review — the timeline is self-refuting, not a stale source |
      
      A stale receipt re-runs the **review**, not the authoring skill: the artifacts may be
      exactly right and simply need re-judging in a clean context. The command to re-run is
      the **emitted** `next.continuation` (`rendering` for display) — quoted as-is, never
      authored as fresh command prose. A missing verdict block, or a verdict outside the
      stage's fixed set, is `missing` with the reason recorded — never a guess in the
      recommended direction.
      
      ### Envelope projection
      
      - A unit that is otherwise startable but lacks a current PASS for the stage it is
        about to enter becomes a `gate` blocker (`scope: unit`, detail names stage +
        label). `startable_now` keeps only units whose next command is genuinely runnable,
        so `next.recommended` never points a human at `execute-phase` on an unreviewed plan.
      - `detail.pre_execution[]` gains one row per sensed unit: `{unit, stage, label,
        verdict, boundDigest, observedDigest, recommended, reason}` — `verdict`/`reason`
        are `null` when absent, `observedDigest` is always the digest computed **now**.
        `detail` is opaque to the envelope schema, so no field outside it changes.
      - Nothing is inferred from the *absence* of a block: an unreadable artifact is
        `missing` with the failure in `reason`, never a carried-forward claim from the
        receipt itself.
      
      ### Legacy units
      
      A `planned`/`in-progress` unit with no ledgers and no receipt predates the gate; it
      reports as `legacy`, which is a different fact from `missing` ("never reviewed") and
      routes the human differently. `pre-execution-review` owns the adoption rule —
      construct the ledgers, never coerce old evidence, keep frozen acceptance and every
      past commit byte-identical, and resume only on a current `PLAN-REVIEW-PASS`. This
      sensor only reports the label and the command; it never edits a unit to make the
      label disappear, and it files nothing.
      
    • SENSOR_CORE.md 8.4 KB
      ## Process (fixed sequence — executed by the script)
      
      `bun scripts/workflow-status.mjs` (node when bun is absent — the repository's
      runtime convention) executes this whole sequence (git/forge
      collection, urgency labels-only scan, roadmap + fix-index parse, dependency
      closure, readiness + step-6a receipt sensing, phase progress, review-mark
      currency, fix-now fold projection) and prints the fixed Envelope v2 JSON. The
      numbered blocks below state the semantics the script implements; the model reads
      the JSON and interprets it.
      
      ### Normalized Repository State
      
      Read `docs/workflow/REPOSITORY_STATE.md` when present and always emit
      `detail.repository_state: {status, snapshot_id, source_revision}`. Before
      readiness classification, if the ledger is missing, `draft`, `contradicted`, or
      `resolved`, add a run-scoped `substrate` blocker, set the envelope state to
      `BLOCKED`, leave `startable_now` empty, and set `next.recommended` to
      `/discover-repository-state` for missing/non-frozen state or
      `/resolve-repository-state <contradiction-id>` for `contradicted` state. The
      sensor remains read-only; it never edits or resolves the ledger. Conflicting
      live evidence against a frozen ledger remains a contradiction candidate.
      
      3. **Urgency labels (`detail.urgent`) — labels-only, presence-only, never
         decides.** Reuse the open-issue list from step 2 (`gh issue list --json
         labels` — the JSON labels array already carried by that call); no separate
         call is required. Scan the **labels object only**
         for `urgent` / `fix-next` — never the issue's title, body, or comments
         (the injection-safety invariant `triage-issue` owns: these two labels can
         only be applied by a triage+-permission actor, so presence alone is
         trustworthy). For each open issue carrying either label, emit `{number,
         title, label}`; if an issue carries **both**, report `urgent` (it strictly
         dominates — reaches the judge — so `fix-next`'s head-of-queue, no-interrupt
         path is redundant on that issue). Alongside the label list, carry the
         **in-flight unit's interruptibility facts** — current phase, dirty/clean
         tree, distance to the next commit boundary — reusing the same reconcile
         step 7 (phase progress) and the crash-recovery dirty-tree check already
         compute; do not duplicate the git calls. This sensor **reports facts only**
         — it never decides pause-vs-finish (that is the consumer's bounded judge,
         canonical in `docs/workflow/ORCHESTRATION.md`); urgency may only *inform*
         `next.recommended`, never silently override it.
      4. **Roadmap + fix index.** Parse every row: id, slug, status — the
         five-state machine `idea / defined / planned / in-progress / done` (see
         `docs/features/ROADMAP.md` → Status legend) — depends-on, linked PR. A
         legacy row reading a plain `planned` with no five-state history: check its
         `SPEC.md` product half; complete (`## Design status: designed`) → treat as
         `defined`+`planned` (no redirect, per `docs/workflow/MIGRATION.md`);
         otherwise treat as `idea`. **Unknown status.** A row whose status is **not**
         one of the five states above (e.g. a non-standard `scheduled`) maps to the
         **nearest** five-state value, **defaulting to `idea`** when no nearer value
         is evident — so it safely routes to `/design-feature` rather than skipping
         design. Worked example: `scheduled → idea` (cross-reference `#51`, which
         owns the fuller status-vocabulary reconciliation). Note the raw status
         string in `workflow_observations` so the mapping is visible, never silent.
      5. **Compute the dependency tree.** For every non-merged unit, build the
         **transitive** depends-on closure and mark each edge met (dep's PR merged)
         or unmet — same rule as execute-phase's dependency gate: `done`-with-open-PR
         is NOT met. Detect inconsistencies (a "merged" row whose own deps aren't
         merged; cycles) and report them as `substrate` blockers.
      6. **Classify readiness — `startable_now` requires status ≥ `defined` AND deps
         met.** For every unit in the roadmap/fix index:
         - status `idea` → list under **`design_candidates`**, next command
           `/design-feature <slug>`. Never `startable_now`, regardless of deps.
         - status `defined` or `planned`, deps met → `startable_now`, with the next
           command matched to the exact status: `defined` → `/plan-feature <slug>`,
           `planned` → `/execute-phase <NN>`.
         - deps unmet (any status ≥ `defined`) → `blocked_units` (unchanged).
      6a. **Sense the pre-execution receipts** for every unit at `defined`, `planned`,
         `in-progress`, **or `done` with a linked PR that is still open (unmerged — merge
         state lives in the forge)** ([pre-execution evidence](PRE_EXECUTION.md)). A
         done-but-unmerged row is a lifecycle label, never merge-ready, so a stale or
         missing receipt there surfaces as a gate blocker; merged units stay excluded
         (the merge itself closes their gates). Read the stage's
         newest receipt block, re-derive the bound digest with the recipe owner's
         verify mode (`bun scripts/pre-execution-snapshot.mjs verify --stage
         <spec|plan> --unit <id> [--parent <64-hex>]` — a snapshot digest is a canonical SHA-256, never a
         git blob id; `structural.reasonCode` names the dimension that drifted), and
         label the stage `current`/`missing`/`stale`/`wrong-stage`/`substitute`/
         `self-approved`/`author-readiness`/`legacy`/`impossible-timeline` (unresolvable revision or unparsable timeline: fail-open → unflagged). The label **overrides step 6's
         status-only command**: a unit without a current PASS for the stage it is about to
         enter is demoted out of `startable_now` into a `gate` blocker naming the missing
         review, and `detail.pre_execution[]` records the row. A roadmap row is never
         edited here — sensing only reads.
      7. **Phase progress.** For each in-progress feature, read `TASKS.md`: current
         phase, total phases, per-phase checkbox completion.
      8. **Pending quality gates.** For each unit with commits: has the mandatory
         `review-change` for its current state run? The artifact is the unit's
         **durable review mark** — the `REVIEW-RAN` row of its `review-findings.md`
         fold ledger, whose shape and writer `pre-execution-review`'s `LEDGERS.md`
         owns — and it counts while the sha it names is an ancestor of the unit's head
         and no commit after it touched a bound input of that review, over the paths
         `pre-execution-review`'s `SNAPSHOT.md` binds:
         `git log <mark-sha>..HEAD -- <bound paths>` prints nothing. Equality with the
         head is not the test and cannot be: carrying the mark is a commit, and that
         commit moves the head, so a rule keyed on equality calls every review that
         finished its own turn unreviewed. The ledger's presence is never that proof: a
         review that found nothing writes no finding row, so presence would call a
         reviewed unit unreviewed and an unreviewed one reviewed. Has `audit-pr` a
         MERGE-READY bound to the PR's current head SHA (look for the audit
         comment marker on the PR)? Derive `review_pending` (no current mark) /
         `audit_pending` / `merge_ready` per unit.
      9. **Fix-now fold ledger → `findings.fix_now[]`.** For each in-flight unit
         (feature or fix) that has a `review-findings.md` ledger, read only its
         `folded: no` rows and emit each as a structured item:
         `{id, file, axis, severity, class, route, suggested_tier}` (`file` = the
         ledger's `file:line` column value, verbatim). Derive `suggested_tier` from
         this fixed table — mechanical, never guessed:
      
         | Condition | `suggested_tier` |
         |---|---|
         | `severity == "high"` | `strong` |
         | `axis` ∈ {security, correctness, logic, architecture, design, concurrency} | `strong` |
         | anything else | `cheap` |
      
         Reuses `next.tier`'s `strong`/`cheap` vocabulary — `next.tier`'s own
         derivation (below) is **unchanged**, this is a separate, per-finding field.
         No ledger for a unit → that unit contributes nothing to `fix_now` (not an
         error); no unit in the run has one → `findings.fix_now: []`, same as
         today. **Read-only**: this step only projects the ledger's current
         unfolded rows — never writes, ticks `folded`, or judges.
      
      ### Envelope fields the sensor projects (versioned grammar)
      
      Steps 1-9 print these keys and no others; each row must be a field the schema
      package's envelope validator declares for that object.
      
      ```text
      sensor-fields@1
      # machine: envelope
      object | field
      unit | type
      pr | merge_ready
      gates | review_pending
      gates | audit_pending
      findings | fix_now
      findings.fix_now | suggested_tier
      dependencies | unmet
      blockers | kind
      recommendations | product_audit
      ```
      
    • SENSOR_SIGNALS.md 9.8 KB
      ## Conditional sensor signals
      
      10. **Per-unit review signals (`detail.*.review`).** For each in-flight
          feature/fix, compute:
          - `last_checkpoint_sha` — feature-mode units only: read `progress.md`'s
            `Last reviewed: <sha>` header line (`execute-phase`'s per-phase
            checkpoint cadence, `#77`, "Last-reviewed marker"). Fix/single-pass
            units have no phase checkpoints — the cadence section is scoped
            "(feature mode)" only — so this is always `null` for them, not an
            error.
          - `unreviewed_diff: {lines, files}` — `git diff --stat <baseline>..HEAD`
            where `<baseline>` is `last_checkpoint_sha` if present, else
            `git merge-base <default-branch> HEAD` — the identical fallback
            `execute-phase`'s cadence triggers define (`#77`); never a new rule.
          - `terminal_done` — **reused, not recomputed**: `= !review_pending` (step
            8's existing computation) for any unit at or past `done`/PR-open status. Before that,
            `false` by contract — `execute-phase` always opens the PR **before**
            the mandatory review hand-off (see its *Workflows* close-out order), so
            a `done` status alone never implies the terminal review already ran.
          - `adversarial: {ran, n}` — **best-effort, evidence-gated; never
            guessed.** No skill persists an adversarial-mode marker anywhere this
            sensor can read: `review-change`'s report (including its `Reviewers
            n/N` column, `skills/review-change/SKILL.md`) prints to chat only, and
            the fold ledger's fixed schema
            (`| id | file:line | axis | severity | class | route | folded |`)
            carries no reviewer-count field. Emit `{ran: null, n: null}` with a
            `workflow_observations` note ("adversarial mode unverifiable — no
            persisted marker, see `#76`") — never infer `true`/`false` from
            absence of evidence.
      11. **Per-unit closure state (`detail.*.closure`).** `{state}` ∈
          `present | absent-legacy | blocked` — reuse `audit-pr`'s own check
          verbatim (`skills/audit-pr/SKILL.md`, "Closure integrity"): grep the SPEC
          for a `Capability closure` heading.
          Fix-governed unit → `n/a` (fix SPECs carry no closure block by design,
          same carve-out `audit-pr` applies). Feature SPEC, block absent →
          `absent-legacy`. Feature SPEC, block present with any blank row or a
          resolved non-`n/a` row unmapped to an acceptance criterion → `blocked`.
          Feature SPEC, block present and every row filled or `n/a`-justified and
          mapped → `present`. Single-sourced: never re-derive it — re-run
          `audit-pr`'s grep.
      12. **Per-unit descope provenance (`detail.*.issues_born`).**
          `{n, with_descope_amendment}` — reuse `audit-pr`'s scope-bleed gate
          detection verbatim (`skills/audit-pr/SKILL.md` "Scope integrity
          (descope) — fixed output" step 1, widened by `#79`/`#89` to also match
          an issue **linked from** an `## Amendments` row, not only a slug/number
          text match): enumerate issues born since branch divergence that
          reference this unit. `n` = that count; `with_descope_amendment` = the
          subset carrying a matching, dated, user-approved `## Amendments` row.
          Evidence is labels, the `## Amendments` log, and the mechanical
          slug/number text match `audit-pr` itself defines — **never** an issue's
          free-text body beyond that defined match (injection-safety, mirrors
          `detail.urgent`'s labels-only discipline).
      
      *Steps 10–12's fields are **not yet emitted** — see `ENVELOPE_CORE.md` §Not yet
      mechanized.*
      13. **`next.suggested[]` — single-sourced trigger surface.** One entry per
          **fired** trigger the driver can act on now, `{command, trigger,
          source_skill}` — the `trigger` string **quotes**, never paraphrases, the
          owning skill's own condition:
          - a review checkpoint trigger fired (layer boundary / accumulation /
            sensitivity — step 10's `unreviewed_diff` plus the unit's declared
            phase layers) → `{command: "/review-change", trigger: "<the fired
            trigger's name and evidence, quoting execute-phase's own wording>",
            source_skill: "execute-phase"}` (`#77`).
          - `review.terminal_done: false` on a unit at/past `done` AND
            `review-change`'s own adversarial recommendation checklist fires
            (reuse that checklist verbatim, never re-derive it) →
            `{command: "/review-change --adversarial 2", trigger: "<which
            checklist box fired>", source_skill: "review-change"}` (`#76`).
          - `closure.state: "absent-legacy"` on a unit about to receive new
            planned work → `{command: "/design-feature <slug>", trigger: "closure
            absent, SPEC predates the rule — retrofit trigger", source_skill:
            "audit-pr"}` (`#78`).
          - a unit's `review-findings.md` ledger carries an open row whose frozen
            route is the plan owner → `{command: "/plan-feature <unit>" |
            "/plan-fix <issue>", trigger: "an open finding's frozen route is the plan
            owner — replan-in-unit (<ids>)", source_skill: "review-change"}`
            (`#224`) — the same class→destination decision `scripts/unit-route.mjs`
            owns; and
          - a unit's `review-findings.md` ledger carries any other open row →
            `{command: "/fold-findings", trigger: "unfolded fix-now finding(s) on
            the ledger", source_skill: "fold-findings"}` (`#65`).
      
          A row is **open** under the router's own predicate (`scripts/unit-route.mjs`
          `isOpen`), never a re-derived one: `folded: yes`, `—`, `-`, `n/a` and an empty
          cell all close it. The id shapes `VF-<n>` (a finding's verification mark) and
          `REVIEW-RAN` (a review mark) are **never** findings — a ledger pads a mark row
          with empty cells, so it reaches the row parser looking like an open finding and
          would otherwise project a suggestion for a merged unit. A **decision-required**
          open row contributes **nothing**: it outranks the fold in the route table (which
          is first-match) and its work stops for the user, so it is not a driver command —
          the unit must not be sent to the fold on the strength of a co-resident plain row.
          The plan-entry ids ride the same 160-char cell bound (`CELL_MAX`) as every other
          echoed ledger cell.
      
          No trigger fired for a unit → it contributes nothing (not an error, same
          convention as `findings.fix_now`). **Additive advisory only**:
          `next.recommended`/`next.tier` (step 6/turn contract) are computed
          exactly as before — `next.suggested` never replaces or reorders them.
      14. **Findings awaiting a destination.** Scan the in-flight folders'
          `known-issues.md` for entries with no linked issue, and open issues labeled
          or titled as postponed findings. Count + list them.
      15. **Untriaged open-issue backlog (`detail.untriaged_issues`) — distinct from
          step 14's `pending_triage`.** Cross-reference the open-issue list already
          fetched in step 2 (`gh issue list --state open`) against triage
          disposition. The **authoritative** triaged signal is a `wontfix` /
          `postponed` / `promoted` disposition label — `triage-issue` is the sole
          owner/writer of that vocabulary (`skills/triage-issue/SKILL.md` →
          *Disposition label vocabulary*) and label mutation is triage+-permission-
          gated, so its presence cannot be forged by comment text. A dated
          `triage-issue` `VERDICT:` comment (the fixed-format block —
          `skills/triage-issue/SKILL.md:193-200`) is honored too, as a **legacy
          fallback** for issues triaged before disposition labels existed — kept for
          backward compatibility, not because it is as trustworthy as the label.
          **Accepted residual:** because the comment-text fallback stays active, a
          hand-authored `VERDICT:` string on an issue that was never actually
          triaged can still cause it to be excluded here — an under-count, not a
          privilege or content-injection issue (`detail.urgent` is unaffected).
          Revisit this residual only if exploitation evidence surfaces (see `#54`).
          An issue is **untriaged** iff it carries **neither** signal. Count the
          untriaged subset and list its oldest entries (cap: 5) by issue number.
          Emit the result as
          `detail.untriaged_issues: {count, oldest_open: [numbers]}` — kept
          separate from `pending_triage` (findings-derived, step 14) and
          `findings.untriaged` (review-finding routing); never merge the three. A
          non-zero `count` may surface a concrete, non-bare `/triage-issue
          <numbers>` in `next.recommended`/`alternatives` (ties the backlog into the
          routing decision from step 6/the turn contract) — it never silently
          replaces the resolved recommendation.
      16. **Product-audit recommendation — a mechanical two-condition checklist, no
          exception clause.** Set `recommendations.product_audit: true` with a stated
          `reason` when **either** condition holds — this is a count, not a judgment
          call. **No exception clause exists**: a "wait for a natural pause" or
          "wait for a bigger milestone" rationale is not defined anywhere in this
          checklist and must never be invented to skip a fired trigger:
          - ✓ `merged_count >= 3` — features/fixes merged since the last
            `SHIP_REPORT`/product-audit artifact (a literal count from the forge's
            merged-PR list in step 2)
          - ✓ the same drift kind recurs in **≥2** units' docs
          Otherwise `recommendations.product_audit: false`, `reason: null`. A fired
          trigger may additionally surface `/product-audit` as `next.recommended` or
          an `alternatives` entry (backlog/audit over net-new feature work) — never
          run it.
      17. **Crash recovery (run every invocation — cheap, see the section below).**
          Classify whether an interrupted turn is in evidence and append the fixed
          `CRASH RECOVERY` sub-block to the report.
      18. **Report.** Print a short human summary (table: unit | status | deps unmet |
          PR | next gate) plus a **design candidates** line (`idea` units and their
          `/design-feature` next command) plus the `CRASH RECOVERY` sub-block, then
          the envelope. With `--json-only`, envelope only.
      
  • SKILL.md 6.3 KB
    ---
    name: workflow-status
    user-invocable: true
    version: 3.7.0
    author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
    license: MIT
    argument-hint: "[--json-only] [--last-envelope <json|path>]"
    description: >
      Read-only workflow sensor: run the deterministic script, read the fixed
      machine envelope, interpret the recommendation. Never edits. Triggers:
      "workflow-status", "workflow status", "what can I build next".
    ---
    
    # Workflow Status (the orchestrator's sensor)
    
    One read-only pass that answers, in a single fixed JSON envelope: **what exists,
    what is blocked on what, what is startable right now, and what the recommended
    next command is.** The **script is the deterministic producer**:
    `scripts/workflow-status.mjs` executes the published `SENSOR_CORE` sequence
    (steps 1–9 including 6a) and prints the envelope. This skill runs the script,
    reads the JSON, interprets it against the references below, and prints the human
    report — it never assembles the envelope by hand.
    
    ## Turn contract — verify before ending the turn
    
    ```
    ✓ The script was RUN — `bun scripts/workflow-status.mjs [--json-only]
      [--last-envelope <json|path>]` (node is the fallback when bun is absent, per
      the repository's runtime convention); the envelope is the script's stdout, never
      assembled by the model
    ✓ Nothing was edited, committed, pushed, or created — read-only, always
    ✓ `next.recommended` is non-bare (carries the unit's slug/NN, never a bare
      `/plan-feature`) AND the script computed it from the unit's resolved status
      **and** its current pre-execution evidence: `idea`/undesigned →
      `/design-feature <slug>`; `defined` → `/plan-feature <slug>` only on a current
      `SPEC-REVIEW-PASS`, else `/review-spec <slug>`; `planned`/`in-progress` → `/execute-phase <NN>` only on a
      current `PLAN-REVIEW-PASS`, else `/review-plan <NN>` (step 6a)
    ✓ `detail.crash_recovery` carries a verdict from the decision table and the
      envelope `state` matches it (CLEAN→OK, RESUMABLE→CONTINUE,
      AMBIGUOUS→NEEDS_INPUT)
    ✓ Every `detail.design_candidates[].next` begins with `/design-feature `
    ✓ Every degraded dimension is named in `detail.degradations` as
      `unavailable-<source>-<cause>` — and, when `--last-envelope` was supplied, the
      no-progress guard's `workflow_observations` note is present (never a silently
      repeated bland recommendation)
    ✓ The envelope is emitted on **every** invocation, including a same-session
      natural-language follow-up about state — never replaced by prose
    ✓ The human-readable summary is printed, then the machine envelope (the script's
      JSON) is the ABSOLUTE last output
    ```
    
    With `--json-only`, skip the human-readable summary: print the envelope alone.
    
    ## When to use
    
    - Between orchestration steps: an external driver runs it to decide the next
      command and model tier without parsing prose.
    - Before picking work manually: "what can I start right now?"
    - **Not** for judging quality (`review-change`/`audit-pr`) or product health
      (`product-audit`) — this skill reports state, it never judges.
    
    ## Step 0 — Discover the project (always first)
    
    Per the agent guide's **Workflow conventions** + **documentation map**. The
    script reads what THIS skill needs (`docs/features/ROADMAP.md`, the fix index
    `docs/fix/README.md`, every in-flight feature folder's `TASKS.md` +
    `progress.md` + `review-findings.md`, and `docs/workflow/REPOSITORY_STATE.md`);
    read them yourself only to interpret a field the script emitted.
    
    ## Progressive loading — fixed sensor route
    
    The reference allowlist is exactly the seven linked paths below. Never invent or
    read another `references/` path. This skill is a read-only sensor.
    
    1. [sensor core](references/SENSOR_CORE.md) — the sequence the script executes
    2. [crash recovery](references/CRASH_RECOVERY.md)
    3. [envelope core](references/ENVELOPE_CORE.md)
    4. [envelope fields](references/ENVELOPE_FIELDS.md)
    5. [pre-execution evidence](references/PRE_EXECUTION.md)
    6. [guardrails](references/GUARDRAILS.md)
    
    Add [sensor signals](references/SENSOR_SIGNALS.md) only when a unit, issue,
    finding, or recommendation exists; an empty project skips that file but still
    emits the empty shapes defined by envelope fields. Add
    [portability](references/PORTABILITY.md) only when the platform actually lacks a
    named primitive. `--json-only` does not skip any baseline file.
    
    ## Portability
    
    The sensor uses repository and forge commands only. When a named agent feature
    is unavailable, follow [portability](references/PORTABILITY.md) without changing
    the JSON contract.
    
    ## Relationship to other skills
    
    - The **sensor** counterpart to `ship-roadmap`'s conductor: an external
      orchestrator calls `workflow-status` → routes on the envelope → invokes
      `plan-feature` / `execute-phase` / `review-change` / `audit-pr` /
      `triage-issue` directly, choosing the model per step — the same loop without
      the in-agent autopilot.
    - Read-only sibling of `audit-docs` (which judges coherence and can fix) and
      `product-audit` (which judges health): this one only reports state.
    - Schema owner: `orchestration-envelope` (internal).
    
    ## Done when
    
    - The script ran and every claim in the report comes from its envelope — nothing
      inferred from memory, nothing assembled by hand.
    - `detail.design_candidates`, `detail.features`, `detail.fixes`,
      `detail.startable_now`, `detail.blocked_units`, `detail.open_prs`,
      `detail.untriaged_issues`, `detail.urgent`, `detail.degradations`, and
      `detail.crash_recovery` were read from the envelope, and the envelope `state`
      matches the crash-recovery verdict.
    - With `--last-envelope` supplied: the no-progress guard ran — a stalled
      `/plan-feature`/`/design-feature` hint surfaces as a `workflow_observations`
      note, never a silent bland repeat, with no new write path introduced.
    - The human summary (unless `--json-only`) and the envelope are printed, envelope
      last.
    - Nothing was modified anywhere.
    - When the envelope carries `next.continuation`, the next-command echo **quotes the
      emitted `next.continuation`** (`rendering` for display), never author exact command
      tokens; the human-facing prose `→ Next:` block below stays.
    
    → Next: the envelope's `next.recommended` command — it is computed from the
      actual state, so it IS the recommendation
      · a human overview → read the printed table
      · orchestrating programmatically → parse the script's JSON
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related