yadflow 3.19.0-next.2 → 4.0.0-next.3

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 (158) hide show
  1. package/CHANGELOG.md +371 -0
  2. package/README.md +160 -22
  3. package/bin/commands.mjs +46 -0
  4. package/bin/yad.mjs +506 -117
  5. package/cli/artifact-status.mjs +30 -11
  6. package/cli/capture.mjs +417 -0
  7. package/cli/checkpoint.mjs +47 -27
  8. package/cli/claims.mjs +165 -0
  9. package/cli/codeowners-command.mjs +170 -0
  10. package/cli/codeowners.mjs +397 -0
  11. package/cli/commit.mjs +13 -9
  12. package/cli/dial.mjs +183 -0
  13. package/cli/docs.mjs +88 -32
  14. package/cli/doctor.mjs +1682 -90
  15. package/cli/epic-state.mjs +3460 -211
  16. package/cli/epic.mjs +506 -0
  17. package/cli/errors.mjs +3 -0
  18. package/cli/fold.mjs +247 -0
  19. package/cli/gate-local.mjs +296 -0
  20. package/cli/gate.mjs +977 -183
  21. package/cli/history.mjs +556 -0
  22. package/cli/hook.mjs +264 -53
  23. package/cli/hubcommit.mjs +9 -19
  24. package/cli/index-command.mjs +87 -0
  25. package/cli/ledger.mjs +54 -4
  26. package/cli/lib.mjs +161 -9
  27. package/cli/manifest.mjs +376 -38
  28. package/cli/migrate.mjs +683 -52
  29. package/cli/mode.mjs +170 -0
  30. package/cli/next.mjs +365 -86
  31. package/cli/openpr.mjs +193 -34
  32. package/cli/owners.mjs +266 -0
  33. package/cli/people.mjs +657 -0
  34. package/cli/plan.mjs +466 -125
  35. package/cli/platform.mjs +109 -128
  36. package/cli/product-index.mjs +287 -0
  37. package/cli/protection.mjs +706 -0
  38. package/cli/reconcile.mjs +40 -12
  39. package/cli/repo-publish.mjs +24 -26
  40. package/cli/repo.mjs +23 -14
  41. package/cli/report.mjs +24 -14
  42. package/cli/review.mjs +19 -22
  43. package/cli/riskmap-command.mjs +289 -0
  44. package/cli/riskmap.mjs +373 -0
  45. package/cli/setup.mjs +127 -279
  46. package/cli/ship.mjs +6 -5
  47. package/cli/skill.mjs +180 -0
  48. package/cli/skip.mjs +211 -30
  49. package/cli/thread.mjs +41 -16
  50. package/cli/tidy.mjs +18 -18
  51. package/cli/update-commit.mjs +21 -21
  52. package/cli/usage.mjs +115 -109
  53. package/package.json +3 -3
  54. package/skills/sdlc/config.yaml +149 -70
  55. package/skills/sdlc/module-help.csv +24 -24
  56. package/skills/yad-analysis/SKILL.md +121 -59
  57. package/skills/yad-architecture/SKILL.md +30 -18
  58. package/skills/yad-architecture/references/contract-format.md +8 -5
  59. package/skills/yad-backfill/SKILL.md +10 -4
  60. package/skills/yad-backfill/references/backfill.md +8 -1
  61. package/skills/yad-backfill/templates/checks/backfill-check.sh +10 -2
  62. package/skills/yad-change/SKILL.md +119 -42
  63. package/skills/yad-change/references/triage.md +42 -27
  64. package/skills/yad-checks/SKILL.md +68 -35
  65. package/skills/yad-checks/references/check-gates.md +310 -85
  66. package/skills/yad-checks/templates/checks/commit-message.sh +17 -3
  67. package/skills/yad-checks/templates/checks/contract-check.sh +130 -9
  68. package/skills/yad-checks/templates/checks/epic-open.sh +2 -2
  69. package/skills/yad-checks/templates/checks/ledger-guard.sh +55 -8
  70. package/skills/yad-checks/templates/checks/lineage-check.sh +23 -9
  71. package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +1 -1
  72. package/skills/yad-checks/templates/checks/risk-map-check.sh +438 -0
  73. package/skills/yad-checks/templates/checks/verified-commits.sh +20 -46
  74. package/skills/yad-checks/templates/github/yad-checks.yml +13 -2
  75. package/skills/yad-checks/templates/github/yad-hub-checks.yml +5 -5
  76. package/skills/yad-checks/templates/github/yad-update-guard.yml +7 -5
  77. package/skills/yad-checks/templates/github/yad-verified-commits.yml +4 -4
  78. package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +10 -1
  79. package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +5 -5
  80. package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +3 -3
  81. package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +91 -0
  82. package/skills/yad-checks/templates/hooks/ledger-guard.sh +37 -6
  83. package/skills/yad-checks/templates/hooks/yad-capture.sh +53 -0
  84. package/skills/yad-commit/SKILL.md +4 -4
  85. package/skills/yad-connect-design/SKILL.md +5 -5
  86. package/skills/yad-connect-design/references/design-context.md +1 -1
  87. package/skills/yad-connect-design/references/design-registry.md +2 -2
  88. package/skills/yad-connect-docs/SKILL.md +11 -11
  89. package/skills/yad-connect-docs/references/docs-registry.md +1 -1
  90. package/skills/yad-connect-learning/SKILL.md +5 -5
  91. package/skills/yad-connect-learning/references/learning-registry.md +2 -2
  92. package/skills/yad-connect-repos/SKILL.md +66 -45
  93. package/skills/yad-connect-repos/references/code-context.md +4 -4
  94. package/skills/yad-connect-repos/references/hub-config.md +47 -51
  95. package/skills/yad-connect-repos/references/repos-registry.md +8 -7
  96. package/skills/yad-connect-repos/references/risk-map.md +81 -0
  97. package/skills/yad-connect-testing/SKILL.md +5 -5
  98. package/skills/yad-connect-testing/references/testing-context.md +3 -4
  99. package/skills/yad-connect-testing/references/testing-registry.md +2 -2
  100. package/skills/yad-defects/SKILL.md +7 -7
  101. package/skills/yad-discovery/SKILL.md +131 -94
  102. package/skills/yad-discovery/references/discovery-schema.md +22 -6
  103. package/skills/yad-discovery/references/foundation-schema.md +374 -0
  104. package/skills/yad-docs/SKILL.md +13 -8
  105. package/skills/yad-docs/references/data-mapping.md +9 -7
  106. package/skills/yad-docs/templates/app/package-lock.json +3 -3
  107. package/skills/yad-docs-overview/SKILL.md +30 -15
  108. package/skills/yad-docs-overview/references/pipeline-model.md +33 -20
  109. package/skills/yad-docs-sync/SKILL.md +10 -5
  110. package/skills/yad-docs-sync/references/staleness.md +8 -7
  111. package/skills/yad-engineer-review/SKILL.md +81 -17
  112. package/skills/yad-engineer-review/references/ship-and-record.md +17 -8
  113. package/skills/yad-epic/SKILL.md +173 -92
  114. package/skills/yad-epic/references/state-schema.md +610 -94
  115. package/skills/yad-hub-bridge/SKILL.md +57 -38
  116. package/skills/yad-hub-bridge/references/bridge.md +94 -67
  117. package/skills/yad-hub-bridge/references/login-roster.md +163 -70
  118. package/skills/yad-hub-bridge/templates/checks/hub-route.sh +22 -19
  119. package/skills/yad-hub-bridge/templates/github/yad-gate-sync.yml +34 -14
  120. package/skills/yad-hub-bridge/templates/gitlab/gitlab-ci.include-root.yml +2 -2
  121. package/skills/yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml +21 -11
  122. package/skills/yad-implement/SKILL.md +27 -13
  123. package/skills/yad-implement/references/implement-conventions.md +2 -2
  124. package/skills/yad-learn/SKILL.md +9 -9
  125. package/skills/yad-learn/references/learning-state.md +2 -2
  126. package/skills/yad-open-pr/SKILL.md +61 -26
  127. package/skills/yad-pair-review/SKILL.md +7 -5
  128. package/skills/yad-pair-review/references/session-state.md +1 -1
  129. package/skills/yad-pr-template/SKILL.md +47 -26
  130. package/skills/yad-pr-template/references/risk-routing.md +97 -24
  131. package/skills/yad-pr-template/templates/checks/pr-template.sh +34 -11
  132. package/skills/yad-pr-template/templates/checks/pr-title.sh +32 -9
  133. package/skills/yad-pr-template/templates/checks/risk-route.sh +107 -14
  134. package/skills/yad-pr-template/templates/github/pull_request_template.md +7 -5
  135. package/skills/yad-pr-template/templates/gitlab/merge_request_templates/Default.md +7 -5
  136. package/skills/yad-pr-template/templates/hub/github/pull_request_template.md +14 -13
  137. package/skills/yad-pr-template/templates/hub/gitlab/merge_request_templates/Default.md +14 -12
  138. package/skills/yad-reconcile/SKILL.md +3 -3
  139. package/skills/yad-report/SKILL.md +5 -5
  140. package/skills/yad-review-companion/SKILL.md +6 -3
  141. package/skills/yad-review-gate/SKILL.md +203 -93
  142. package/skills/yad-review-gate/references/gating.md +232 -54
  143. package/skills/yad-run/SKILL.md +81 -51
  144. package/skills/yad-run/references/run-loop.md +61 -39
  145. package/skills/yad-ship/SKILL.md +15 -11
  146. package/skills/yad-spec/SKILL.md +21 -6
  147. package/skills/yad-spec/references/spec-handoff.md +17 -5
  148. package/skills/yad-status/SKILL.md +115 -50
  149. package/skills/yad-stories/SKILL.md +37 -21
  150. package/skills/yad-stories/references/story-schema.md +7 -6
  151. package/skills/yad-stub/SKILL.md +58 -47
  152. package/skills/yad-sync-repos/SKILL.md +2 -2
  153. package/skills/yad-test-cases/SKILL.md +32 -23
  154. package/skills/yad-test-cases/references/test-cases-schema.md +7 -4
  155. package/skills/yad-timeline/SKILL.md +8 -7
  156. package/skills/yad-ui/SKILL.md +41 -18
  157. package/cli/roster.mjs +0 -164
  158. package/skills/sdlc/install.sh +0 -68
package/README.md CHANGED
@@ -13,8 +13,8 @@ AI builds and a human clears every gate.**
13
13
  > Yadflow doesn't write your code; it governs how AI-written code ships. Keep Cursor, GitHub Copilot,
14
14
  > Claude Code, Continue — or hand-written commits. The zero-dependency `yad` CLI and the CI gates
15
15
  > review the work **no matter who or what produced it.** The workflow skills run today in
16
- > **Claude Code** (plus `.agents`, Zencoder, and OpenCode), and **BMAD is the default packaging,
17
- > not a limitation.**
16
+ > **Claude Code, Codex CLI, Cursor, Gemini CLI, GitHub Copilot, Zencoder and opencode** — see
17
+ > [which agent reads which directory](#which-ai-agents-are-supported).
18
18
 
19
19
  ## The problem
20
20
 
@@ -27,26 +27,26 @@ AI, the harder it gets to keep control of quality, architecture, and accountabil
27
27
 
28
28
  Yadflow puts a **human gate on every step** of the lifecycle. Each step does its work, writes its
29
29
  output to a plain file, and **waits** — it never advances until a human clears its gate (by approving,
30
- or in solo mode by merging your own PR), or, later, once a step has *earned* the right to auto-advance.
30
+ or in solo mode, switched with `yad mode`, by merging your own PR) — or, for a Build step the team set to `auto`, on its own after a clean run.
31
31
  Reviews ride real PR/MRs; all state lives in files you
32
32
  can read, diff, and edit — no database, nothing hidden. The result is a paper trail for every decision
33
33
  and a hard wall between "AI proposed" and "we shipped it."
34
34
 
35
- It installs as a custom [BMAD](https://github.com/bmad-code-org/BMAD-METHOD) module and works across
36
- one product hub + many code repos, solo or team.
35
+ It installs with one command (`npx yadflow setup`) and works across one Product + many code repos,
36
+ solo or team.
37
37
 
38
38
  ## How the workflow looks
39
39
 
40
40
  <!-- Source: docs/diagrams/sdlc-overview.mmd — edit the .mmd and run `npm run diagrams` to regenerate -->
41
- ![Yadflow SDLC overview — setup, human-gated Shape, per-story Build, earned automation](https://raw.githubusercontent.com/abdelrahmannasr/yadflow/main/docs/diagrams/sdlc-overview.svg)
41
+ ![Yadflow SDLC overview — setup, human-gated Shape, per-story Build, automation you switch on](https://raw.githubusercontent.com/abdelrahmannasr/yadflow/main/docs/diagrams/sdlc-overview.svg)
42
42
 
43
43
  **Legend:** 🟨 **artifact** (a step writes a file and stops) · 🟧 **gate** (a human review that must
44
- pass) · 🟦 **earns automation** (a Build step that can later auto-advance once it proves itself) ·
45
- ⬜ **locked** (the engineer review and every Shape step — permanently human).
44
+ pass) · 🟦 **can run on auto** (a Build step the team may set to advance on its own, with `yad dial`) ·
45
+ ⬜ **locked** (the engineer review — always a person).
46
46
 
47
47
  ## Quickstart
48
48
 
49
- From your **product hub** repo (an empty git repo is fine):
49
+ From your **Product** repo (an empty git repo is fine):
50
50
 
51
51
  ```bash
52
52
  npx yadflow setup # 1. guided wizard: install skills, connect repos, wire CI gates
@@ -80,23 +80,160 @@ In one pass it produces:
80
80
 
81
81
  - **The `yad` CLI** — zero-dependency Node (`setup`, `gate`, `commit`, `open-pr`, `ship`, `repo`,
82
82
  `thread`, `reconcile`, `usage`, `doctor`), run via `npx` or a global install.
83
- - **38 workflow skills** installed into your AI assistant — **Claude Code** (`.claude/`) first-class,
84
- plus `.agents`, Zencoder, and OpenCode.
85
- - **`.sdlc/` config** — the product hub, connected repos, reviewer roster, and tool connections
83
+ - **38 workflow skills** installed into your AI assistant — Claude Code, Codex CLI, Cursor,
84
+ Gemini CLI, GitHub Copilot, Zencoder and opencode. See
85
+ [which agent reads which directory](#which-ai-agents-are-supported).
86
+ - **`.sdlc/` config** — the Product, connected repos, and tool connections
86
87
  (design, testing, learning), all as plain JSON you can read and diff.
87
- - **CI gates**, wired into every connected repo and the hub as **GitHub Actions or GitLab CI** —
88
- spec-link, contract-check, verified-commits, build/test/lint, the feature-thread gates, and the
89
- push-on-main **`yad-update-guard`** (which re-checks any direct-to-default commit — e.g. from
88
+ - **CI gates**, wired into every connected repo and the Product as **GitHub Actions or GitLab CI** —
89
+ spec-link, contract-check, verified-commits, build/test/lint, the feature-thread gates, the advisory
90
+ risk-map check (warns when a code repo's `.sdlc/risk-map` — a risk level per directory, no names — is
91
+ stale, says how many approvers a PR asks for — one more when it touches a `high` directory — and names
92
+ who has worked in that directory in the last 30 days), and the push-on-main **`yad-update-guard`** (which re-checks any direct-to-default commit — e.g. from
90
93
  `yad update --push` — with just `verified-commits` + `commit-message`), shipped as CI-agnostic bash
91
94
  under `checks/`.
92
- - **An agent guardrail** on a verified hub — `hooks/ledger-guard.sh`, a harness hook that refuses an
95
+ - **An agent guardrail** on a verified Product — `hooks/ledger-guard.sh`, a harness hook that refuses an
93
96
  agent the CI-owned gate-ledger write at the moment it tries it and names the command that owns the
94
97
  transition, instead of letting it surface as a CI failure twenty minutes later. Harness-agnostic
95
98
  (stdin payload, exit 0 allows / 2 denies) and fails open — the CI gate stays the authority.
99
+ - **Background capture** on every Product, in both ledger modes (E43) — `hooks/yad-capture.sh`, a
100
+ harness hook that runs `yad capture` after each agent edit. It snapshots every changed Shape artifact
101
+ onto your private `yad/wip/<you>/<epic>` branches, so a draft is never lost and nobody types a git
102
+ command. See [Background capture](#background-capture) below.
96
103
  - **PR/MR templates** and an opt-in CodeRabbit config.
97
104
 
98
105
  Your first `yad-epic` seeds the `epics/EP-<slug>/` ledger — state, approvals, and the contract lock —
99
- so the audit trail starts the moment you begin real work.
106
+ so the audit trail starts the moment you begin real work. `yad epic new <slug>` does the same seeding
107
+ from the CLI when you would rather lay the track before the writing starts.
108
+
109
+ Before any epic, you can also frame the whole product once: `yad foundation new` seeds the
110
+ **Foundation** — the Product level, in `foundation/` — and the `yad-discovery` skill writes its
111
+ sections (purpose, scope, MVP, roadmap, stack, repos). It is optional, and each epic reads its approved
112
+ roadmap.
113
+
114
+ ## Which AI agents are supported
115
+
116
+ An **agent skill** is a folder holding a `SKILL.md` file — instructions the agent loads when the task
117
+ matches. `SKILL.md` is now a format several agents read, and `.agents/skills/` is the directory
118
+ several of them agreed to look in. So one install can serve more than one agent.
119
+
120
+ `yad setup` asks which directories to install into. Pick by the agent you use:
121
+
122
+ | Directory | Agents that read it |
123
+ | --- | --- |
124
+ | `.claude/` | Claude Code. Cursor also reads it for compatibility. |
125
+ | `.agents/` | Codex CLI, Gemini CLI, Cursor, GitHub Copilot |
126
+ | `.cursor/` | Cursor — its own directory. Not needed if you install `.agents/`. |
127
+ | `.gemini/` | Gemini CLI — its own directory. Not needed if you install `.agents/`. |
128
+ | `.zencoder/` | Zencoder |
129
+ | `.opencode/` | opencode — installed as flat `commands/<skill>.md` files, not folders |
130
+
131
+ A fresh setup offers **`.claude,.agents`**, which together cover every agent in the table. A project that already
132
+ has an INSTALL in one of them — a `skills/` folder, or an armed hook entry — is offered that one
133
+ instead; a `.cursor/` holding only Cursor rules is not an install, and is offered the default. Checked against each agent's
134
+ own documentation on 2026-09-16; `yad doctor` prints the same table's verdict for your project.
135
+
136
+ ### Background capture
137
+
138
+ `yad capture` saves your work in progress without touching your checkout (E43). It takes every changed
139
+ file under `epics/` and `foundation/` — except the ledger (any `.sdlc/` folder and `reviews/`; the four
140
+ files a person or a skill writes there, `contract-lock.json`, `change.json`, `design-links.json` and
141
+ `test-links.json`, are included) — and commits it onto
142
+ a private branch per epic, `yad/wip/<your git name>/<epic>`. It uses git's low-level commands in a
143
+ throwaway index, so your branch, your staged changes and your files stay exactly as they were, and no
144
+ git hook runs.
145
+
146
+ | What | How |
147
+ | --- | --- |
148
+ | When | After every agent edit, by a hook yad wires in both ledger modes: Claude Code `PostToolUse` in `.claude/settings.json`, Cursor `afterFileEdit` in `.cursor/hooks.json`. Any other agent or editor: run `yad capture` yourself. Each capture takes every changed artifact, so your own editor's edits ride along |
149
+ | Push | A capture commits at once, locally. The hook pushes your capture branches (and fetches everyone else's, for claims) in the background at most once every 5 minutes, with no password prompt and a short timeout, so an edit never waits on the network. `yad capture` by hand pushes straight away. With no remote, or offline, the captures stay local and nothing fails |
150
+ | CI | yadflow's own push workflow skips `yad/wip/**`. `yad doctor` names any of **your** workflows a push to `yad/wip/*` would start (no branch filter, `branches: ["**"]`, or a `branches-ignore` that does not name it), so you can add `branches-ignore: ["yad/wip/**"]` |
151
+ | Off | `"capture": false` in the Product config (`yad check --fix` then removes the hook), or `YAD_CAPTURE=0` for one shell |
152
+
153
+ The capture commits are unsigned on purpose — a signing prompt inside a hook would hang the agent — and
154
+ each carries `Yad-Epic`, `Yad-Base` and `Yad-Branch` lines. They are drafts: the commit your history
155
+ keeps is the fold, below. The push is never forced: if you capture the same epic on two machines, the second push is refused rather than overwriting the first, and a `yad capture` you run by hand says so and names the branch (delete one copy with `git branch -D` to continue the other) — the hook's background push cannot report it. **To remove a capture branch for good** — say a secret was captured — delete it on origin first, then on every machine that has it run `git branch -D yad/wip/<you>/<epic>` **and** `git branch -dr origin/yad/wip/<you>/<epic>` (the second deletes that machine's saved copy of origin's branch; it says so if there is none): a machine that still holds either one rebuilds the branch and pushes it back. On a fresh clone, a capture continues the branch already on origin. Two people with the same git name share branches. The people count that caps review gates
156
+ (E71) does not count capture commits.
157
+
158
+ ### Who else is editing a file (claims)
159
+
160
+ `yad claims` lists who else is editing which artifact right now (E46). It is **advice, not a lock**:
161
+ nothing stops anyone, because with no server a real lock is impossible. There is nothing to record by
162
+ hand — a claim is read from the capture branches: someone's `yad/wip/<name>/<epic>` branch holds a
163
+ saved change to that file that is not on the default branch yet.
164
+
165
+ | What | How |
166
+ | --- | --- |
167
+ | A claim | A file of the epic that differs between the capture branch's last save and the commit that save was built on — the person's own edits, never what a pull brought in |
168
+ | Ends | 4 hours after that branch's last save, or at once when the file on the default branch matches the saved one (the work was merged) |
169
+ | `yad claims [<epic>]` | Fetches everyone's capture branches first (short timeout, no prompts), then lists each claim: file, person, last save. `--no-fetch` reads what is already here; `--json` too |
170
+ | At edit time | When an edit changes a file someone else has a claim on, the capture hook says so. Under Claude Code the agent reads it (and you see it); under Cursor it is a line on stderr. It never blocks, never waits on the network, and names the same person and file at most once an hour |
171
+ | Fresh enough | The hook's background push (at most every 5 minutes) also fetches everyone's capture branches in the background |
172
+
173
+ **Limits.** Someone with capture off, or offline, is invisible. A claim can be up to about 5 minutes
174
+ late. Two people with the same git name share capture branches, so they never see each other. Times
175
+ are the saver's own clock, shown in UTC.
176
+
177
+ ### Who owns a step (assign)
178
+
179
+ `yad assign` gives one authoring step to one person (E47) — for example "Bob writes the
180
+ architecture". It is stronger advice than a claim, because it is decided in advance, but it is still
181
+ **advice, not a lock**: it never blocks an edit, never holds a review gate and never stops a fold.
182
+
183
+ | What | How |
184
+ | --- | --- |
185
+ | `yad assign <epic> <step> [--to <name>]` | Assigns the step to you, or to the person whose **git name** you give (the name they commit with). Only authoring steps that write an artifact (`epic`, `architecture`, `stories`, …); review steps are not assigned, because the platform and the gate count decide who approves. If someone else already owns the step it is refused and names them; `--force` replaces them |
186
+ | `yad unassign <epic> <step>` | Removes the assignment. Your own freely; someone else's needs `--force` |
187
+ | `yad owners [<epic>]` | Lists every assignment, whether it is live, and any owner file that cannot be read. `--json` too |
188
+ | Where it is kept | One small file per step: `epics/<epic>/.sdlc/owners/<step>.json` (`foundation/.sdlc/owners/` for the Foundation). It is not a ledger file, so you can write it in both ledger modes. `yad assign` does not commit it, and `yad fold` never takes it (an assignment is not authoring): commit it on its own — on a `verified` Product, in a PR of its own (the Product checks let a PR that changes only owner files through, since E47; run `yad update` so your copies of the checks and of the hub-checks workflow have that rule; `yad doctor` warns `owners:rename-blind` if a hand-edited workflow was kept) — so the team sees it when they pull. It is captured to your `yad/wip/…` branch like any artifact, but it is not counted as a claim |
189
+ | Live | While the step's work is open: the step is not finished, or its review has not passed yet. After that the file stays as a record; re-opening the step makes it live again. There is no time limit |
190
+ | Shown | `yad next` prints `owner: <name>` under the step (and under its review) while it is live |
191
+ | At edit time | When your edit changes a file of a step someone else owns, the capture hook says so — to the agent under Claude Code, on stderr under Cursor — at most once an hour per step. One note carries both this and any claim warning |
192
+
193
+ **Limits.** The name is the git name, made branch-safe the way capture branch names are — so it matches
194
+ the capture hook without asking GitHub or GitLab. Two people with the same git name look like one owner.
195
+ A git name with no Latin letters is branch-safe only through the person's email, so someone else can
196
+ assign it only once that person has a capture branch here (`--to` finds it by the git name the branch was
197
+ saved under). With capture off, there is no edit-time warning.
198
+
199
+ ### Folding a step into one commit
200
+
201
+ `yad fold <epic> <step>` ends an authoring step (E44). It makes the one commit the record keeps,
202
+ `docs(<epic>): author <step>` — for example `docs(EP-checkout): author architecture`. The authoring
203
+ skills run it at the end of their step; you can run it yourself too.
204
+
205
+ | What | How |
206
+ | --- | --- |
207
+ | Files | Only that step's files: the ones its review covers (architecture is `architecture.md`, `contract.md` and `.sdlc/contract-lock.json`; stories is everything under `stories/`), plus what the step's skill writes beside them (`DESIGN.md` and `.sdlc/design-links.json` for the UI step, `.sdlc/test-links.json` for test cases). Other changed files of the epic are named and left on disk, so a half-written draft of another step never lands in this commit |
208
+ | The ledger | Follows `ledger` mode. `local`: the epic's changed ledger files go in the same commit — one step, one commit. `verified`: CI writes the ledger at merge, so the fold leaves those files for CI — except while the epic is brand new (no `.sdlc/state.json` in HEAD yet): then its new ledger files are its seed, which is the case `ledger-guard` allows and the only way a seed reaches the default branch. Once the epic is seeded, even a NEW ledger file (a `reviews/*.md` written by hand) is left for CI, because the guard would reject it |
209
+ | The seed | While the epic is brand new, the first fold also takes the new person-written `.sdlc/` files beside the ledger — a change-epic's `change.json` and its pointer `contract-lock.json` — in both modes |
210
+ | The commit | A normal `git commit`, so it is signed if your git signs (with `ledger: verified` it warns when signing is off: the review PR's signature check would fail), and your commit hooks run. Only the step's files are committed; anything else you staged stays staged. It ends with `Yad-Epic`, `Yad-Step` and `Yad-Folded` lines — the last is the tip of your capture branch, the drafts this commit folds (`none` with capture off) |
211
+ | Where | With `ledger: verified`, never on the default branch — artifacts reach it only through the review PR. With `ledger: local`, anywhere |
212
+ | The drafts | Your `yad/wip/<you>/<epic>` branch is left as it is: the draft history stays for the later rework measurement (E95), and nothing has to be deleted on other machines. The next capture has nothing new to save |
213
+
214
+ A step with no changed files has nothing to fold, and says so. `yad open-pr` on a review branch warns
215
+ when that step's files have changes no fold has committed — they are not in the review.
216
+
217
+ ### The local ledger guard, per agent
218
+
219
+ In **verified mode** — where CI owns the gate ledger — yadflow installs a local guardrail that stops
220
+ an agent hand-editing the gate files, at the moment of the edit rather than twenty minutes later in a
221
+ failed pipeline. It needs a hook that can run *before* a write and refuse it. Two agents have one:
222
+
223
+ | Agent | Wired into | Event |
224
+ | --- | --- | --- |
225
+ | Claude Code | `.claude/settings.json` | `PreToolUse` |
226
+ | Cursor | `.cursor/hooks.json` | `preToolUse` |
227
+
228
+ Cursor answers this kind of hook in JSON rather than by exit code, and treats an empty answer as a
229
+ refusal — so a `.cursor` project also gets a small adapter script, `hooks/ledger-guard-cursor.sh`,
230
+ which always replies properly. Without it the guard would have blocked every file write instead of
231
+ just the gate files.
232
+
233
+ Every other directory gets the script (`hooks/ledger-guard.sh`) and no wiring — they have no such
234
+ hook, so those agents are guarded by CI alone. `yad doctor` says so by name rather than staying
235
+ silent. The Cursor wiring follows Cursor's published hook protocol and has not yet been exercised
236
+ against a live Cursor session.
100
237
 
101
238
  ## Your first five minutes
102
239
 
@@ -116,14 +253,14 @@ Every step is the same contract: *AI proposes → a human decides → the trail
116
253
 
117
254
  ## How it works (in five points)
118
255
 
119
- - **Shape = decide.** Once per epic, in the product hub: epic, architecture + a locked contract,
256
+ - **Shape = decide.** Once per epic, in the Product: epic, architecture + a locked contract,
120
257
  UI, stories, test cases. Always human-gated — nothing auto-advances.
121
258
  - **Build = make it real.** Once per story per code repo: spec → implement → checks → ship.
122
259
  - **Every step stops at a gate.** A human moves it forward (local, or by merging a review PR/MR).
123
260
  <!-- IMAGE: docs/media/pr-gate.png — "The review gate rides a real PR/MR: approve to advance, comment to block." -->
124
- - **Automation is opt-in and earned.** A safe Build step can earn auto-advance after it proves
125
- itself — and a one-command kill switch reverts everything to manual. The engineer review and all
126
- Shape steps are never automatable.
261
+ - **Automation is opt-in.** The team switches a Build step to auto with `yad dial`, which shows that
262
+ step's run record as advice — and `yad kill` holds everything at manual in one command. A review
263
+ gate — the engineer review and every Shape review — is never automatic.
127
264
  - **Everything is files.** State, approvals, the contract lock, the build log — all plain files under
128
265
  `epics/EP-<slug>/`. No database. The audit trail *is* the repo.
129
266
 
@@ -139,7 +276,7 @@ complementary: bring your favorite, and Yadflow wraps the engineering process ar
139
276
  | **Layer** | Writes the code | Governs how it ships |
140
277
  | **Output** | Diffs, completions | Gated artifacts + a file-based audit trail |
141
278
  | **Answers** | "Write this for me" | "Should this merge — and who approved it?" |
142
- | **Review** | You eyeball the diff | Human-gated PR/MR, contract lock, earned automation |
279
+ | **Review** | You eyeball the diff | Human-gated PR/MR, contract lock, switchable automation |
143
280
  | **Fit** | Bring your own | Wraps around all of them |
144
281
 
145
282
  ## Review, made a pairing — and a lesson
@@ -174,6 +311,7 @@ workflow-hygiene flags — derived read-only, so an EM can see how the team actu
174
311
  - **[docs/SKILLS.md](docs/SKILLS.md)** — the catalogue of all 38 agent skills.
175
312
  - **[docs/WALKTHROUGH.md](docs/WALKTHROUGH.md)** — the by-hand, end-to-end path through every phase.
176
313
  - **[CONTRIBUTING.md](CONTRIBUTING.md)** · **[RESEARCH-NOTES.md](RESEARCH-NOTES.md)** · **[RELEASING.md](RELEASING.md)**
314
+ - **[SECURITY.md](SECURITY.md)** — how to report a vulnerability, which versions get fixes, and the supply-chain stance. **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)** — the community standards for taking part.
177
315
 
178
316
  ---
179
317
 
@@ -0,0 +1,46 @@
1
+ // Every command module, behind ONE dynamic import (E11 review).
2
+ //
3
+ // `yad hook ledger-guard` runs on EVERY file-editing tool call an agent makes, inside its tool
4
+ // loop. It needs `cli/hook.mjs` and nothing else, but a static import list in `bin/yad.mjs` is
5
+ // hoisted and evaluated before any code runs — so the hook was loading all 29 modules of the CLI,
6
+ // measured at ~30ms against ~14ms for what it actually uses, on every single edit.
7
+ //
8
+ // Re-exporting through one module keeps that mechanical: `bin/yad.mjs` awaits this once, after it
9
+ // has already handled `hook`, and every command reads off the result. Nothing here is lazy in
10
+ // itself — importing this file still loads everything, which is exactly right for a command that
11
+ // is about to do real work.
12
+
13
+ export { runSetup } from '../cli/setup.mjs';
14
+ export { reconcile } from '../cli/reconcile.mjs';
15
+ export { gateOpen, gateSync, gateComments, gateStatus, gateCi, gateReview, gateTrailer, gateWalkthrough, gateRepair } from '../cli/gate.mjs';
16
+ export { gateApprove, gateComment, gateAdvance } from '../cli/gate-local.mjs';
17
+ export { isValidEpicId, seedableProfiles } from '../cli/epic-state.mjs';
18
+ export { runEpicNew, runFoundationNew, runFoundationStatus } from '../cli/epic.mjs';
19
+ export { runSkillBind, runSkillList, runSkillUnbind } from '../cli/skill.mjs';
20
+ export { runCommit } from '../cli/commit.mjs';
21
+ export { runOpenPr } from '../cli/openpr.mjs';
22
+ export { reviewTrailer, reviewContext, reviewNudge, reviewReconcile, reviewWalkthrough } from '../cli/review.mjs';
23
+ export { runShip } from '../cli/ship.mjs';
24
+ export { runCheckpoint } from '../cli/checkpoint.mjs';
25
+ export { runTidy } from '../cli/tidy.mjs';
26
+ export { runCapture } from '../cli/capture.mjs';
27
+ export { runFold } from '../cli/fold.mjs';
28
+ export { runClaims } from '../cli/claims.mjs';
29
+ export { runAssign, runUnassign, runOwners } from '../cli/owners.mjs';
30
+ export { runIndex } from '../cli/index-command.mjs';
31
+ export { runHistory, HISTORY_FLAGS } from '../cli/history.mjs';
32
+ export { runRepo } from '../cli/repo.mjs';
33
+ export { runRiskMap } from '../cli/riskmap-command.mjs';
34
+ export { runCodeowners } from '../cli/codeowners-command.mjs';
35
+ export { runDocs } from '../cli/docs.mjs';
36
+ export { runDoctor } from '../cli/doctor.mjs';
37
+ export { runMigrate, warnIfProjectAhead } from '../cli/migrate.mjs';
38
+ export { runNext } from '../cli/next.mjs';
39
+ export { runSkip, runDefer, runUnblock, runLaneSkip } from '../cli/skip.mjs';
40
+ export { runDial, runKill } from '../cli/dial.mjs';
41
+ export { runMode } from '../cli/mode.mjs';
42
+ export { syncStatuses } from '../cli/artifact-status.mjs';
43
+ export { runThread, runReconcile } from '../cli/thread.mjs';
44
+ export { runReport } from '../cli/report.mjs';
45
+ export { runUsage } from '../cli/usage.mjs';
46
+ export { maybeNotifyUpdate } from '../cli/update-notice.mjs';