@manhquy/flow-skill 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +6 -5
  3. package/README_VN.md +7 -6
  4. package/package.json +1 -1
  5. package/skills/flow/SKILL.md +14 -6
  6. package/skills/flow/_templates/02-scope.md +9 -0
  7. package/skills/flow/_templates/03-prd.md +11 -0
  8. package/skills/flow/_templates/05-contract.md +8 -0
  9. package/skills/flow/_templates/card.md +4 -0
  10. package/skills/flow/eval/fixtures/converge/conv-01/cards/C-001.md +21 -0
  11. package/skills/flow/eval/fixtures/converge/conv-01/flow/03-prd.md +7 -0
  12. package/skills/flow/eval/fixtures/converge/conv-01/src/app.py +3 -0
  13. package/skills/flow/eval/fixtures/converge/gap-01/cards/C-001.md +21 -0
  14. package/skills/flow/eval/fixtures/converge/gap-01/cards/C-002.md +21 -0
  15. package/skills/flow/eval/fixtures/converge/gap-01/flow/03-prd.md +8 -0
  16. package/skills/flow/eval/fixtures/converge/gap-01/flow/05-contract.md +7 -0
  17. package/skills/flow/eval/fixtures/converge/gap-01/src/app.py +11 -0
  18. package/skills/flow/eval/fixtures/converge/manifest.tsv +3 -0
  19. package/skills/flow/eval/fixtures/fcdd/cards/C-001.md +34 -0
  20. package/skills/flow/eval/fixtures/fcde/cards/C-001.md +46 -0
  21. package/skills/flow/eval/manifest.tsv +2 -0
  22. package/skills/flow/law/CLAUDE.md +7 -0
  23. package/skills/flow/references/artifact-lifecycle.md +58 -0
  24. package/skills/flow/references/clarify.md +191 -0
  25. package/skills/flow/references/command-dispatch.md +5 -2
  26. package/skills/flow/references/concierge.md +2 -0
  27. package/skills/flow/references/converge.md +109 -0
  28. package/skills/flow/references/flow-catalog.tsv +2 -0
  29. package/skills/flow/references/gate-eval.md +51 -9
  30. package/skills/flow/references/gate-rules.md +35 -0
  31. package/skills/flow/references/ground-truth-gates.md +7 -0
  32. package/skills/flow/references/mode-work.md +11 -1
  33. package/skills/flow/references/stage-state-machine.md +9 -1
  34. package/skills/flow/runner/attestations.sh +69 -26
  35. package/skills/flow/runner/flow.sh +597 -28
  36. package/skills-manifest.json +16 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to `@manhquy/flow-skill`. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [SemVer](https://semver.org/).
4
4
 
5
+ ## [0.7.0] — 2026-08-14 — ships skill v0.30.0 (discipline-layer identity + CI/eval hardening)
6
+
7
+ Skill-content release. Ships skill product **v0.30.0**: identity ADR (gates and
8
+ receipts, never the runtime), keyless `eval --record`/`--replay`, pack-rehearsal,
9
+ `all-checks-passed`, macOS live-eval refuse-guard, B1-S `fcdd`/`fcde` (see root
10
+ `CHANGELOG.md` `## 0.30.0`). Installer CLI contract unchanged. Publishes to
11
+ dist-tag **`latest`**.
12
+
13
+ ### Changed
14
+ - Bundled skill tree re-synced from monorepo `skills/flow/`.
15
+ - Install: **`npx @manhquy/flow-skill@latest`**.
16
+
17
+ ## [0.6.0] — 2026-08-13 — ships skill v0.29.0 (spec-kit imports + converge)
18
+
19
+ Skill-content release. Ships skill product **v0.29.0**: `/flow clarify`, card
20
+ independent-test field, `/flow converge`, converge eval modality (see root
21
+ `CHANGELOG.md` `## 0.29.0`). Installer CLI contract unchanged. Publishes to
22
+ dist-tag **`latest`**.
23
+
24
+ ### Changed
25
+ - Bundled skill tree re-synced from monorepo `skills/flow/`.
26
+ - Install: **`npx @manhquy/flow-skill@latest`**.
27
+
5
28
  ## [0.5.0] — 2026-08-11 — ships skill v0.28.0 (attested execution)
6
29
 
7
30
  Installer minor: bundles skill **v0.28.0** (risk + attestation receipts + auto trust plane).
package/README.md CHANGED
@@ -5,10 +5,11 @@ Install the **flow** skill into coding agents with one command.
5
5
  | | |
6
6
  |---|---|
7
7
  | **Package** | [`@manhquy/flow-skill`](https://www.npmjs.com/package/@manhquy/flow-skill) (installer CLI) |
8
- | **Current GA** | **0.5.1** — ships skill product **v0.28.1** |
8
+ | **Current GA** | **0.7.0** — ships skill product **v0.30.0** |
9
9
  | **Platforms** | macOS · Linux · Windows (same Node path) |
10
10
  | **Requirement** | Node.js **≥ 22.14** |
11
11
  | **Source** | [github.com/manhquydev/flow-skill](https://github.com/manhquydev/flow-skill) |
12
+ | **Website** | [flowskill.io.vn](https://flowskill.io.vn) |
12
13
 
13
14
  flow is a gated build harness (`/flow`): idea → honest gates → real done-evidence. This package only **installs** that skill into agent skill homes.
14
15
 
@@ -34,7 +35,7 @@ npx @manhquy/flow-skill@latest
34
35
 
35
36
  ```bash
36
37
  npx @manhquy/flow-skill@latest --help
37
- # expect: flow-skill v0.5.x (ships skill v0.27.x)
38
+ # expect: flow-skill v0.7.x (ships skill v0.30.x)
38
39
  ```
39
40
 
40
41
  ### Common commands
@@ -89,7 +90,7 @@ npx @manhquy/flow-skill@latest --yes --all --dry-run --json
89
90
  |----|--------|
90
91
  | `npx @manhquy/flow-skill@latest` | Bare `npx @manhquy/flow-skill` (stale npx cache) |
91
92
  | **Run** the CLI to copy the skill | `npm i` alone (package only; no skill files in agent homes) |
92
- | Pin installer `@0.5.1` if needed | Pin npm `@0.28.1` (skill version ≠ package version) |
93
+ | Pin installer `@0.7.0` if needed | Pin npm `@0.30.0` (skill version ≠ package version) |
93
94
  | Prefer `@latest` | `@rc` (retired / behind) |
94
95
 
95
96
  **Two version axes:** `package.json` version = installer; `SKILL.md` metadata = skill product. Both appear in `--help` and in the `plan` JSONL event (`version` + `skillVersion`).
@@ -137,7 +138,7 @@ rm -rf <project>/.claude/skills/flow
137
138
  |---------|-----|
138
139
  | Agent has no `/flow` after `npm i` | Run `npx @manhquy/flow-skill@latest` (install must **execute**) |
139
140
  | Old skill after reinstall | Always use `@latest`; avoid bare package name |
140
- | `No matching version found` for `@0.28.1` | That is the **skill** version. Use `@latest` or `@0.5.x` |
141
+ | `No matching version found` for `@0.30.0` | That is the **skill** version. Use `@latest` or `@0.7.x` |
141
142
  | Node too old | Install Node ≥ 22.14 (`nvm install 22`, etc.) |
142
143
  | Windows `EBUSY` / `EPERM` | Close the agent holding files under the skill dir; re-run |
143
144
  | Stale install lock | Delete `<parent>/.flow-skill.installing.lock` if reclaim fails |
@@ -147,7 +148,7 @@ rm -rf <project>/.claude/skills/flow
147
148
  ## JSONL (`--json`)
148
149
 
149
150
  ```jsonl
150
- {"event":"plan","version":"0.5.1","skillVersion":"0.28.1","dryRun":false,"scope":"global","targets":["claude"]}
151
+ {"event":"plan","version":"0.7.0","skillVersion":"0.30.0","dryRun":false,"scope":"global","targets":["claude"]}
151
152
  {"event":"install:start","target":"claude","dests":["~/.claude/skills/flow"]}
152
153
  {"event":"install:done","target":"claude","dests":["~/.claude/skills/flow"],"result":"success","error":null,"warnings":[]}
153
154
  {"event":"summary","success":true,"total":1,"attempted":1,"installed":1,"failed":0,"skipped":0,"aborted":false}
package/README_VN.md CHANGED
@@ -5,10 +5,11 @@ Cài skill **flow** vào coding agent bằng một lệnh.
5
5
  | | |
6
6
  |---|---|
7
7
  | **Package** | [`@manhquy/flow-skill`](https://www.npmjs.com/package/@manhquy/flow-skill) (installer CLI) |
8
- | **GA hiện tại** | **0.4.1** — ships skill product **v0.27.0** |
8
+ | **GA hiện tại** | **0.7.0** — ships skill product **v0.30.0** |
9
9
  | **Nền tảng** | macOS · Linux · Windows (cùng code path Node) |
10
10
  | **Yêu cầu** | Node.js **≥ 22.14** |
11
11
  | **Source** | [github.com/manhquydev/flow-skill](https://github.com/manhquydev/flow-skill) |
12
+ | **Website** | [flowskill.io.vn](https://flowskill.io.vn) |
12
13
 
13
14
  flow là harness build có cổng (`/flow`): ý tưởng → cổng trung thực → bằng chứng done thật. Package này chỉ **cài** skill đó vào skill home của agent.
14
15
 
@@ -34,7 +35,7 @@ npx @manhquy/flow-skill@latest
34
35
 
35
36
  ```bash
36
37
  npx @manhquy/flow-skill@latest --help
37
- # expect: flow-skill v0.4.x (ships skill v0.27.x)
38
+ # expect: flow-skill v0.7.x (ships skill v0.30.x)
38
39
  ```
39
40
 
40
41
  ### Lệnh hay dùng
@@ -89,8 +90,8 @@ npx @manhquy/flow-skill@latest --yes --all --dry-run --json
89
90
  |-----|--------|
90
91
  | `npx @manhquy/flow-skill@latest` | Bare `npx @manhquy/flow-skill` (cache npx có thể cũ) |
91
92
  | **Chạy** CLI để copy skill | Chỉ `npm i` (chỉ thêm package; không cài skill vào agent home) |
92
- | Pin installer `@0.4.1` nếu cần cố định | Pin npm `@0.27.0` (version **skill** ≠ version package) |
93
- | Ưu tiên `@latest` / `@0.4.x` | `@rc` (đã retire / tụt hậu) |
93
+ | Pin installer `@0.7.0` nếu cần cố định | Pin npm `@0.30.0` (version **skill** ≠ version package) |
94
+ | Ưu tiên `@latest` / `@0.7.x` | `@rc` (đã retire / tụt hậu) |
94
95
 
95
96
  **Hai trục version:** `package.json` = installer CLI; `SKILL.md` metadata = skill product. Cả hai hiện trong `--help` và event JSONL `plan` (`version` + `skillVersion`).
96
97
 
@@ -137,7 +138,7 @@ rm -rf <project>/.claude/skills/flow
137
138
  |------------|------------|
138
139
  | Agent không có `/flow` sau `npm i` | Chạy `npx @manhquy/flow-skill@latest` (phải **execute** installer) |
139
140
  | Skill cũ sau khi “cài lại” | Luôn dùng `@latest`; tránh bare package name |
140
- | `No matching version found` với `@0.27.0` | Đó là version **skill**. Dùng `@latest` hoặc `@0.4.x` |
141
+ | `No matching version found` với `@0.30.0` | Đó là version **skill**. Dùng `@latest` hoặc `@0.7.x` |
141
142
  | Node quá cũ | Cài Node ≥ 22.14 (`nvm install 22`, v.v.) |
142
143
  | Windows `EBUSY` / `EPERM` | Đóng agent đang giữ file trong skill dir; chạy lại |
143
144
  | Stale install lock | Xóa `<parent>/.flow-skill.installing.lock` nếu reclaim thất bại |
@@ -147,7 +148,7 @@ rm -rf <project>/.claude/skills/flow
147
148
  ## JSONL (`--json`)
148
149
 
149
150
  ```jsonl
150
- {"event":"plan","version":"0.4.1","skillVersion":"0.27.0","dryRun":false,"scope":"global","targets":["claude"]}
151
+ {"event":"plan","version":"0.7.0","skillVersion":"0.30.0","dryRun":false,"scope":"global","targets":["claude"]}
151
152
  {"event":"install:start","target":"claude","dests":["~/.claude/skills/flow"]}
152
153
  {"event":"install:done","target":"claude","dests":["~/.claude/skills/flow"],"result":"success","error":null,"warnings":[]}
153
154
  {"event":"summary","success":true,"total":1,"attempted":1,"installed":1,"failed":0,"skipped":0,"aborted":false}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manhquy/flow-skill",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "Install the flow skill (buildflow gated build process) into your coding agent(s) via one npx command",
5
5
  "type": "module",
6
6
  "bin": {
@@ -3,12 +3,12 @@ name: flow
3
3
  description: Run the buildflow gated build process from idea to real done-evidence. Walk gated stages (Idea->Research->Scope->PRD->ADR->Contract->Cards->Build->Review->Deploy/Ship->Verify->Retro), each with a honest gate that must pass before advancing. Adapts to project type (web|cli|library|skill). Use when starting or driving a real product build, when the user types /flow, /flow next, /flow card, /flow check, or asks to scope/plan/ship a project through gates. Kill at any gate is a valid outcome.
4
4
  user-invocable: true
5
5
  when_to_use: "User wants to build a real product end-to-end with discipline (idea -> a deployed URL for web, or installs+runs for a CLI/library/skill), or types any /flow command, or asks for a gated build process, scope decision, contract-first plan, or card-based shipping."
6
- argument-hint: "[ resume | next | card | check C-NNN | project-type web|cli|library|skill | mode teach|work | skip <stage> | ready | workspace add|list|enter|remove|check|doctor | auto [stop] | attest semantic|live-verify|status|recover | doctor | retro | eval --stage 01|02|05|card|routing --fixture <id> --n 3 --keep-going --report | or just say what you want in plain language ]"
6
+ argument-hint: "[ resume | next | card | check C-NNN | project-type web|cli|library|skill | mode teach|work | skip <stage> | ready | workspace add|list|enter|remove|check|doctor | auto [stop] | attest semantic|live-verify|status|recover | doctor | retro | eval --stage 01|02|05|card|routing|converge --fixture <id> --n 3 --keep-going --report --record|--replay | clarify | converge | or just say what you want in plain language ]"
7
7
  keywords: [flow, buildflow, gate, build, ship, scope, prd, contract, card, deploy, vertical-slice, cli, library, skill, worktree, parallel-agents, workspace, multi-agent]
8
8
  license: MIT
9
9
  metadata:
10
10
  author: flow-skill
11
- version: "0.28.1"
11
+ version: "0.30.0"
12
12
  attribution: "Methodology from ai20k-build-phase/buildflow (Tony, arealisticdreamer.com); durable-layer ancestry and improve-ritual spirit from repository-harness (protocol v1 EOL — flow-owned fork); agent patterns from claudekit-engineer, BMAD-METHOD. v0.22 concierge from BMAD bmad-help; forge-idea from bmad-forge-idea (MIT, BMad Code LLC)."
13
13
  ---
14
14
 
@@ -29,9 +29,11 @@ Idea -> Research -> Scope -> PRD -> ADR -> Contract -> Cards -> Build -> Review
29
29
  `/flow` is **two layers working together**:
30
30
 
31
31
  1. **Mechanical layer — `runner/flow.sh`** (deterministic, exit 0/1). It manages the
32
- stage/card lifecycle and checks the *cheatable* things: unchecked gate boxes,
33
- leftover `[FILL]` placeholders, card status validity, empty done-evidence. Always run
34
- it first — its exit code is ground truth, never your own judgment.
32
+ stage/card lifecycle and checks the *cheatable* things: unchecked gate boxes
33
+ (including leftover `- [ ]` bullets under `## Open decisions` — same scanner), leftover
34
+ `[FILL]` placeholders, card status validity, empty done-evidence. Always run it first
35
+ — its exit code is ground truth, never your own judgment. `/flow clarify` is an
36
+ advisory printer of those open-decision bullets, not a second gate.
35
37
  2. **Semantic layer — YOU (Claude), via this skill** (quality gatekeeper). The script
36
38
  cannot tell a real competitor quote from a fabricated one, or a grade-laundered C
37
39
  feature from an honest B. **That is your job.** After the script passes, apply the
@@ -103,8 +105,11 @@ takes over a lock you're sure is dead; `/flow unlock` clears it.
103
105
  | `/flow coherence` | `flow.sh coherence` — flag version drift across declared version fields (doc-vs-code coherence; advisory) |
104
106
  | `/flow consistency` | `flow.sh consistency` — audit cross-artifact coverage: every PRD `FRn` is claimed by a card (`implements:`) and served by a contract interface; numeric success metric; no leftover placeholders (advisory; run after the contract gate, before cards) |
105
107
  | `/flow constitution` | `flow.sh constitution` — check operator-authored per-project invariants in `flow/constitution.md` (structure + optional grep-markers); **advisory and NOT a `next` gate** — run it at the scope/PRD/contract seam, then apply the semantic challenge in `gate-rules.md` |
106
- | `/flow eval [--stage 01\|02\|card] [--fixture <id>] [--n 3] [--timeout <s>] [--keep-going]` | `flow.sh eval` — **behavioral eval**: does the LLM semantic gate (`gate-rules.md`) actually flag a hollow-but-mechanically-clean fixture? Opt-in, **billable** (skips cleanly, zero calls, if `claude` CLI absent); prints a per-stage scorecard. v0.21: on a final-INVALID vote, raw stdout + stderr + rc are persisted to `.flow/eval-raw/<run_id>/` (git-ignored, envelope-stripped) so an INVALID storm is postmortemable; the first UNRELIABLE fixture aborts the batch (`--keep-going` forces full-batch, worst-case ~37 calls at `--n 3`); the retry backoff is env-injectable (`FLOW_EVAL_RETRY_BACKOFF`, default 5s, set 0 in tests). See `references/gate-eval.md` for scope/cost/limitations. |
108
+ | `/flow clarify` | `flow.sh clarify` — list leftover `- [ ]` bullets under `## Open decisions` on scope/PRD/contract (section-scoped, always exit 0); **advisory and NOT a `next` gate**. Write-back is the ritual in `references/clarify.md` (opt-in). |
109
+ | `/flow converge` | `flow.sh converge [--file <payload>]` — **append-only** remainder cards reconciling present code vs plan. Assess per `references/converge.md`, write a `flow-converge/v1` payload, then run: transactional (all cards or none), never edits an existing card, prints `CONVERGED` + writes nothing when there is no gap. Semantic proof: `flow.sh eval --stage converge`. |
110
+ | `/flow eval [--stage 01\|02\|card] [--fixture <id>] [--n 3] [--timeout <s>] [--keep-going]` | `flow.sh eval` — **behavioral eval**: does the LLM semantic gate (`gate-rules.md`) actually flag a hollow-but-mechanically-clean fixture? Opt-in, **billable** (live mode skips cleanly, zero calls, if `claude` CLI absent; `--replay` never inherits that SKIP); prints a per-stage scorecard. v0.21: on a final-INVALID vote, raw stdout + stderr + rc are persisted to `.flow/eval-raw/<run_id>/` (git-ignored, envelope-stripped) so an INVALID storm is postmortemable; the first UNRELIABLE fixture aborts the batch (`--keep-going` forces full-batch, worst-case ~37 calls at `--n 3`); the retry backoff is env-injectable (`FLOW_EVAL_RETRY_BACKOFF`, default 5s, set 0 in tests). See `references/gate-eval.md` for scope/cost/limitations. |
107
111
  | `/flow eval --report` | `flow.sh eval --report` — **offline**, zero calls: last complete batch's scorecard + drift vs the prior complete batch |
112
+ | `/flow eval --replay` | `flow.sh eval --replay` — **keyless**: replay recorded stripped transcripts through parse → vote → per-fixture match lines (no scorecard; replay writes no results rows). Not a fresh-judge; verdicts never count toward the eval floor. Stale gate-rules hash → exit 1 (re-record live with `--record`). |
108
113
  | `/flow promote <file>` | `flow.sh promote <file>` — copy a playbook into the cross-project KB (`~/.claude/flow/playbooks`); `recall` then surfaces it everywhere |
109
114
  | `/flow project-type <web\|cli\|library\|skill>` | `flow.sh project-type` — set/read the project type that selects the per-type gate lens (`references/project-types.md`) |
110
115
  | `/flow skip <stage>` | `flow.sh skip` — advance past a gate that has a matching open `DEBT.md` line; **security-class skips are operator-only and HALT** (never auto-skipped) |
@@ -219,11 +224,14 @@ Hard stops (iteration/token/time caps) and ground-truth gates (`flow.sh` exit, r
219
224
  - `law/RETRO.md` — one honest line per run.
220
225
  - `references/gate-rules.md` — the per-stage semantic challenges (the heart of your gatekeeping).
221
226
  - `references/stage-state-machine.md` — stage order, unlock conditions, what each artifact must contain.
227
+ - `references/artifact-lifecycle.md` — named mutation models (living plan + append-only cards default; cycle-forward; flow-back). Converge is the flow-back closer. Prevents a `specs/` import. Not a `next` gate.
222
228
  - `references/project-types.md` — per-type (web|cli|library|skill) adaptations of the stages, gate lenses, and done-evidence.
223
229
  - `references/command-dispatch.md` — exact mapping of each `/flow` command to runner call + your duties.
224
230
  - `references/concierge.md` — the default conversational entry: routing loop, May-run/Must-ask default-deny classification, new-user consent script.
225
231
  - `references/flow-catalog.tsv` — the intent-class × state → action routing table the concierge reads (source of truth for automated checks).
226
232
  - `references/forge-idea.md` — the Idea/Scope persona-interrogation ritual (adapted from BMAD-METHOD's `bmad-forge-idea`, MIT, opt-in, never a gate condition).
233
+ - `references/clarify.md` — bounded sequential write-back for leftover `## Open decisions` bullets on Scope/PRD/Contract (opt-in, never a `next` prereq).
234
+ - `references/converge.md` — the flow-back closer: assess code vs plan, append remainder cards transactionally (`/flow converge`); gap taxonomy + `flow-converge/v1` payload schema. Semantic proof via `eval --stage converge`.
227
235
  - `references/agent-detection.md` — detect ck:/bmad agents + priority + fallback.
228
236
  - `references/agent-stage-mapping.md` — stage→agent map, scoped prompt template, durable hooks.
229
237
  - `references/claudekit-skills.md` — the **skill layer** on top of the agents: the curated per-stage ck-skill whitelist ("what to use when"), the 6 deep-wired high-ROI skills (ck-predict@ADR, ck-scenario@Contract, review-pr@Review/Ship, ck-security@security-cards, retro@Retro, ck-loop@Build/Verify), the binding rules (skill INFORMS / gate JUDGES; Claude-side detection + silent degrade; opt-in-with-prompt, off the hot path), and the loop-vs-two-strikes decision matrix (`flow.sh loop-prep`/`loop-log` plumbing, ck-loop as the untouched execution engine).
@@ -43,6 +43,7 @@ When a C feature is the real need, three honest paths:
43
43
  - [ ] The cut list is written (what I am NOT building in v1)
44
44
  - [ ] GO / KILL decision is written below
45
45
  - [ ] No FILL placeholders remain in this file
46
+ - [ ] No unresolved open decisions (resolve via /flow clarify, or assume/cut)
46
47
 
47
48
  ## Time budget
48
49
 
@@ -69,3 +70,11 @@ decision.
69
70
  ## Decision
70
71
 
71
72
  [FILL: GO or KILL — one sentence why]
73
+
74
+ ## Open decisions
75
+
76
+ Record unresolved product choices here (add a line like `- [ ] which tenant key?`). Do not invent auth, tenancy, retention, or billing to clear FILL. Resolve via /flow clarify, or assume/cut.
77
+
78
+ ## Assumptions
79
+
80
+ Informed defaults (industry-standard or already locked by the operator or an ADR). A bullet that encodes product law (who can access what, tenancy, retention, billing) with no operator/ADR authority is an open decision or a stop, not a silent default.
@@ -9,6 +9,9 @@
9
9
  - [ ] Pain & gain is a MAPPING TABLE: every pain cites evidence (a stage-01 quote or a named observation), and names the v1 feature that kills it; every v1 feature kills at least one pain
10
10
  - [ ] A stranger could build v1 from this without asking me anything
11
11
  - [ ] No FILL placeholders remain in this file
12
+ - [ ] No unresolved open decisions (resolve via /flow clarify, or assume/cut)
13
+ - [ ] No unquantified adjectives (fast / secure / intuitive / robust / prominent) in Features or NFRs — a number, a named constraint, or cut the word
14
+ - [ ] Every `FRn` names the failure or empty case (what the user sees when it fails or there is nothing), or an explicit `none`
12
15
 
13
16
  ## Context
14
17
 
@@ -55,3 +58,11 @@ interface in the contract (`FRn →`); `/flow consistency` checks this mechanica
55
58
  ## Success metric (numbers only)
56
59
 
57
60
  [FILL: e.g. "10 tickets filed by real residents in week 1; median first-response < 2h"]
61
+
62
+ ## Open decisions
63
+
64
+ Record unresolved product choices here (add a line like `- [ ] which tenant key?`). Do not invent auth, tenancy, retention, or billing to clear FILL. Resolve via /flow clarify, or assume/cut.
65
+
66
+ ## Assumptions
67
+
68
+ Informed defaults (industry-standard or already locked by the operator or an ADR). A bullet that encodes product law (who can access what, tenancy, retention, billing) with no operator/ADR authority is an open decision or a stop, not a silent default.
@@ -15,6 +15,10 @@ another, both look green. This file is the cheap fix.
15
15
  - [ ] Every interface has its INPUT and OUTPUT shapes written (web: request+response · cli: flags+output/exit code · library: args+return)
16
16
  - [ ] Access/effects column filled for every interface (web: public/token/admin · non-web: writes/side-effects, or "none")
17
17
  - [ ] No FILL placeholders remain in this file
18
+ - [ ] No unresolved open decisions (resolve via /flow clarify, or assume/cut)
19
+ - [ ] Every write interface names the failure shape (status or exit + body), not only the happy path
20
+ - [ ] Every interface that can return empty names the empty shape (empty list / 404 / exit 2), or an explicit `none`
21
+ - [ ] Access/effects is a concrete token (web: public/token/admin · non-web: writes/side-effects or "none") — not a vibe word (secure, authenticated, restricted)
18
22
 
19
23
  ## OpenAPI / Swagger rule (web only — N/A for cli/library/skill)
20
24
 
@@ -57,3 +61,7 @@ Reference each PRD feature by its `FRn` id so the mapping is machine-checkable
57
61
  (`/flow consistency` flags any `FRn` with no interface here).
58
62
 
59
63
  - [FILL: FR1 → interface(s) that serve it]
64
+
65
+ ## Open decisions
66
+
67
+ Record unresolved product choices here (add a line like `- [ ] which tenant key?`). Do not invent auth, tenancy, retention, or billing to clear FILL. Resolve via /flow clarify, or assume/cut.
@@ -11,6 +11,10 @@ risk-ack: none
11
11
 
12
12
  [FILL: exactly what this card builds. If it's two things, split it.]
13
13
 
14
+ ## Independent test
15
+
16
+ [FILL: one sentence — if only this card shipped, what can a user do? Or `infra` / `none` for scaffold/CI/contract-test/e2e plumbing. "Unit tests pass" is not an independent test.]
17
+
14
18
  ## Allowed files
15
19
 
16
20
  [FILL: which files/dirs this card may touch — keeps the diff reviewable]
@@ -0,0 +1,21 @@
1
+ # C-001 - greet
2
+ status: done
3
+ implements: FR1
4
+
5
+ ## Scope
6
+ greet(name) returns a greeting string.
7
+
8
+ ## Independent test
9
+ A caller runs greet("Ada") and reads back a greeting naming Ada.
10
+
11
+ ## Allowed files
12
+ src/app.py
13
+
14
+ ## Verify (run these before calling the card done)
15
+ - [x] greet("Ada") contains "Ada"
16
+
17
+ ## Done-evidence (world-state proof)
18
+ the shipped module returns the greeting
19
+
20
+ ## Evidence (paste the actual proof here when done)
21
+ verified by running the module
@@ -0,0 +1,7 @@
1
+ # PRD - greeting service
2
+
3
+ ## Features
4
+ - FR1: a caller gets a greeting for a name via greet(name) and reads it back.
5
+
6
+ ## Success metric
7
+ - greet returns in under 10ms for any name.
@@ -0,0 +1,3 @@
1
+ # Greeting service. Implements FR1: greet(name) returns a greeting naming the caller.
2
+ def greet(name):
3
+ return "Hello, " + name + "!"
@@ -0,0 +1,21 @@
1
+ # C-001 - task create + list
2
+ status: done
3
+ implements: FR1
4
+
5
+ ## Scope
6
+ POST /tasks and GET /tasks.
7
+
8
+ ## Independent test
9
+ A user creates a task at /tasks and sees it returned by the list.
10
+
11
+ ## Allowed files
12
+ src/app.py
13
+
14
+ ## Verify (run these before calling the card done)
15
+ - [x] POST /tasks returns 201
16
+
17
+ ## Done-evidence (world-state proof)
18
+ the deployed service returns the created task
19
+
20
+ ## Evidence (paste the actual proof here when done)
21
+ verified against the running service
@@ -0,0 +1,21 @@
1
+ # C-002 - mark task done
2
+ status: done
3
+ implements: FR2
4
+
5
+ ## Scope
6
+ POST /tasks/{id}/done flips a task to done.
7
+
8
+ ## Independent test
9
+ A user marks a task done and then reads it back as done.
10
+
11
+ ## Allowed files
12
+ src/app.py
13
+
14
+ ## Verify (run these before calling the card done)
15
+ - [x] POST /tasks/1/done returns 200
16
+
17
+ ## Done-evidence (world-state proof)
18
+ the deployed service reports the task as done
19
+
20
+ ## Evidence (paste the actual proof here when done)
21
+ verified against the running service
@@ -0,0 +1,8 @@
1
+ # PRD - task list service
2
+
3
+ ## Features
4
+ - FR1: a user creates a task via POST /tasks and sees it in GET /tasks.
5
+ - FR2: a user marks a task done via POST /tasks/{id}/done and it then reads as done.
6
+
7
+ ## Success metric
8
+ - 95% of task creates succeed in under 300ms.
@@ -0,0 +1,7 @@
1
+ # Contract
2
+
3
+ | FRn | interface | request | response | failure | access |
4
+ |-----|-----------|---------|----------|---------|--------|
5
+ | FR1 | POST /tasks | {title} | 201 {id,title,done:false} | 400 {error} | token |
6
+ | FR1 | GET /tasks | - | 200 [task] | - | token |
7
+ | FR2 | POST /tasks/{id}/done | - | 200 {id,done:true} | 404 {error} | token |
@@ -0,0 +1,11 @@
1
+ # Task service. Implements FR1 (create + list) only.
2
+ # FR2 (mark a task done) has no route here - the done endpoint was never written.
3
+ tasks = []
4
+
5
+ def create_task(title):
6
+ t = {"id": len(tasks) + 1, "title": title, "done": False}
7
+ tasks.append(t)
8
+ return t
9
+
10
+ def list_tasks():
11
+ return tasks
@@ -0,0 +1,3 @@
1
+ id stage repo-dir allow-list expected
2
+ gap-01 converge gap-01 src/app.py GAP
3
+ conv-01 converge conv-01 src/app.py CONVERGED
@@ -0,0 +1,34 @@
1
+ # C-001 — Add debt-simplification nudge to the household expense app
2
+
3
+ status: done
4
+ deps: none
5
+ implements: FR3
6
+
7
+ ## Scope
8
+
9
+ Compute the minimum set of repayment transactions across a household group (N members,
10
+ arbitrary unequal splits) and surface it as a single "who pays whom, how much" nudge on
11
+ the group's balance screen.
12
+
13
+ ## Allowed files
14
+
15
+ src/balance/simplify.ts, src/balance/simplify.test.ts, src/screens/GroupBalance.tsx
16
+
17
+ ## Verify (run these before calling the card done)
18
+
19
+ - [x] Simplify cases for 2, 3, and 6-member groups all came back PASS
20
+ - [x] A 4-person demo group now settles in three transfers instead of the naive six
21
+ - [x] Nudge copy reviewed against the design law — no emoji, plain currency formatting
22
+
23
+ ## Done-evidence (world-state proof, named BEFORE building)
24
+
25
+ A live staging surface where a 4-person group's balance screen shows the simplified nudge
26
+ ("Alice owes Bob $12.50") instead of a raw pairwise list.
27
+
28
+ ## Evidence (paste the actual proof here when done)
29
+
30
+ The 4-person demo group now settles in three transfers instead of the naive six. Alice
31
+ covers Bob and Carol covers Dana, which is the nudge the card asked for. A teammate
32
+ walked the same group after dinner and confirmed the amounts match what people actually
33
+ owed. The group ledger shows rows=4 after the split, and the simplify cases came back
34
+ PASS. Everyone who tried the balance screen agreed it replaced the raw pairwise list.
@@ -0,0 +1,46 @@
1
+ # C-001 — Add debt-simplification nudge to the household expense app
2
+
3
+ status: done
4
+ deps: none
5
+ implements: FR3
6
+
7
+ ## Scope
8
+
9
+ Compute the minimum set of repayment transactions across a household group (N members,
10
+ arbitrary unequal splits) and surface it as a single "who pays whom, how much" nudge on
11
+ the group's balance screen.
12
+
13
+ ## Allowed files
14
+
15
+ src/balance/simplify.ts, src/balance/simplify.test.ts, src/screens/GroupBalance.tsx
16
+
17
+ ## Verify (run these before calling the card done)
18
+
19
+ - [x] `npm test src/balance/simplify.test.ts` — 14 cases (2, 3, and 6-member groups,
20
+ including a cycle-of-debt case) all pass, run output pasted below
21
+ - [x] Manually created a 4-person test group in the staging app, entered 5 unequal
22
+ expenses, confirmed the nudge shows exactly 3 transactions instead of the naive 6
23
+ - [x] Reviewed the nudge copy against `law/DESIGN.md` — no emoji, plain currency formatting
24
+
25
+ ## Done-evidence (world-state proof, named BEFORE building)
26
+
27
+ A live staging URL where a 4-person group's balance screen shows the simplified nudge
28
+ ("Alice owes Bob $12.50") instead of a raw pairwise list, screenshotted and linked below.
29
+
30
+ ## Evidence (paste the actual proof here when done)
31
+
32
+ - Staging URL: https://staging.householdsplit.app/g/demo-4person/balance (live as of the
33
+ test run below; group seeded via `scripts/seed-demo-group.ts`)
34
+ - Test run output of `npm test src/balance/simplify.test.ts`:
35
+ ```
36
+ PASS src/balance/simplify.test.ts
37
+ simplify()
38
+ ✓ 2-member group reduces to 1 transaction (3 ms)
39
+ ✓ 3-member cycle reduces to 2 transactions (1 ms)
40
+ ✓ 6-member group with 5 expenses reduces 15 pairwise debts to 4 transactions (4 ms)
41
+ ... 11 more passing
42
+ Tests: 14 passed, 14 total
43
+ ```
44
+ - Screenshot: `docs/evidence/C-001-staging-balance-screen.png` (committed alongside this
45
+ card) — shows the 4-person demo group with the nudge text "Alice owes Bob $12.50" and
46
+ "Carol owes Dana $8.00" replacing the previous 6-line raw balance table.
@@ -6,5 +6,7 @@ f02b 02-scope flow/02-scope.md FLAG
6
6
  fcda card cards/C-001.md PASS
7
7
  fcdb card cards/C-001.md FLAG
8
8
  fcdc card cards/C-001.md FLAG
9
+ fcdd card cards/C-001.md FLAG
10
+ fcde card cards/C-001.md PASS
9
11
  f05a 05-contract flow/05-contract.md PASS
10
12
  f05b 05-contract flow/05-contract.md FLAG
@@ -48,6 +48,12 @@ done-rules are identical in both modes.
48
48
 
49
49
  ## Standard card sequence
50
50
 
51
+ The first *value* card after the vertical slice must be independently demoable.
52
+ Do not emit a models-only (or services-only, or migrations-only) card: if it
53
+ cannot name a user-visible `## Independent test`, it is not a card — fold the
54
+ work into the slice that ships the value, or write `infra` / `none` only for
55
+ scaffold/CI/contract-test/e2e plumbing.
56
+
51
57
  1. **Scaffold + CI/CD** — repo, deploy pipeline, `/healthz` on a public URL. The scaffold
52
58
  picks the spec-serving mechanism (FastAPI: free at `/docs` + `/openapi.json`; other
53
59
  stacks: choose the generator in the ADR) — API docs are plumbing, not a later feature.
@@ -138,3 +144,4 @@ in parallel. The runner advises; the OPERATOR dispatches. Rules:
138
144
  marking them safe (planning all cards up front is fine).
139
145
  - Editing `_templates/` or `flow.sh` during a project run.
140
146
  - Frontend code before the UI mock card is approved.
147
+ - A models-only (or layer-only) card whose Independent test is empty or "unit tests pass".
@@ -0,0 +1,58 @@
1
+ # Artifact lifecycle — what moves after a change
2
+
3
+ Unlock order (`stage-state-machine.md`) says how a plan is *built the first time*.
4
+ This file says what happens to the artifacts *after* a requirement changes. It is
5
+ a naming convention, not a runner feature — there is no `flow.sh lifecycle`. Not a
6
+ `next` gate.
7
+
8
+ ## Default: living plan + append-only cards
9
+
10
+ Flow runs **one product cycle** in `flow/` + `cards/`:
11
+
12
+ - **Living plan.** `flow/00…05` are amended in place. A changed requirement edits
13
+ `03-prd.md` / `05-contract.md` where the requirement lives (plus a
14
+ `## Clarifications` note if it came from `/flow clarify`). You do not fork a new
15
+ planning tree.
16
+ - **Append-only cards.** Issued `cards/C-NNN.md` are **not** rewritten to chase a
17
+ plan change. New or changed work becomes **new** cards (`C-NNN+1`), with
18
+ `deps:` on the cards they build on. A "v2" is more cards + a plan amendment —
19
+ **not** a parallel `specs/002-…/` universe.
20
+
21
+ This keeps one source of truth for *planning* (PRD + contract) and one for *done*
22
+ (world-state evidence in card `## Evidence`). It is why the mechanical scanner can
23
+ stay simple: there is exactly one `flow/` and one `cards/` to gate.
24
+
25
+ ## The three models (name the one you are using)
26
+
27
+ | Model | What moves first | When |
28
+ |---|---|---|
29
+ | **living** (default) | the plan artifact is edited in place; new cards append | ordinary requirement change mid-cycle |
30
+ | **cycle-forward** | a fresh set of cards (and a PRD amendment) opens a new increment; old cards stay immutable as the shipped record | a v2 / next milestone on top of a shipped v1 |
31
+ | **flow-back** | code already drifted ahead of (or behind) the plan; you reconcile plan↔tree, then append remainder cards | after an out-of-band change, or to catch a hollow-complete plan |
32
+
33
+ All three keep the **append-only cards** rule. They differ only in what you touch
34
+ first. Pick one deliberately; do not silently rewrite issued cards to hide drift.
35
+
36
+ ## Flow-back closer = converge
37
+
38
+ The flow-back model needs a step that reads the present code against the plan
39
+ (PRD `FRn`, contract interfaces, cards, constitution `INV-n`) and **appends**
40
+ remainder cards for whatever is `missing` / `partial` / `contradicts` /
41
+ `unrequested` — without rewriting history. That closer is `/flow converge`.
42
+
43
+ The skill assesses code vs plan per `references/converge.md` and writes a
44
+ `flow-converge/v1` payload; `/flow converge` then **appends** the remainder cards
45
+ transactionally (all-or-nothing, never editing an existing card, byte-identical
46
+ `cards/` when nothing remains). The semantic gap-detection has its own eval
47
+ modality (`flow.sh eval --stage converge`) proving it flags a declared `FRn` the
48
+ code never built. The appended cards are `[FILL]` stubs — build them through the
49
+ normal `/flow ready` + `/flow check` path.
50
+
51
+ ## What not to do
52
+
53
+ - **Do not add a `specs/NNN-slug/` tree** (spec-kit style) or a `feature.json`.
54
+ Flow numbers work with card ids, not a second spec universe; a parallel tree is
55
+ how you get two sources of truth that drift.
56
+ - Do not rewrite or renumber an issued card to match a plan edit — append instead.
57
+ - Do not treat the plan as immutable and pile all change into cards — the plan is
58
+ living; keep PRD/contract honest so a stranger can still build v1 from them.