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.
- package/CHANGELOG.md +371 -0
- package/README.md +160 -22
- package/bin/commands.mjs +46 -0
- package/bin/yad.mjs +506 -117
- package/cli/artifact-status.mjs +30 -11
- package/cli/capture.mjs +417 -0
- package/cli/checkpoint.mjs +47 -27
- package/cli/claims.mjs +165 -0
- package/cli/codeowners-command.mjs +170 -0
- package/cli/codeowners.mjs +397 -0
- package/cli/commit.mjs +13 -9
- package/cli/dial.mjs +183 -0
- package/cli/docs.mjs +88 -32
- package/cli/doctor.mjs +1682 -90
- package/cli/epic-state.mjs +3460 -211
- package/cli/epic.mjs +506 -0
- package/cli/errors.mjs +3 -0
- package/cli/fold.mjs +247 -0
- package/cli/gate-local.mjs +296 -0
- package/cli/gate.mjs +977 -183
- package/cli/history.mjs +556 -0
- package/cli/hook.mjs +264 -53
- package/cli/hubcommit.mjs +9 -19
- package/cli/index-command.mjs +87 -0
- package/cli/ledger.mjs +54 -4
- package/cli/lib.mjs +161 -9
- package/cli/manifest.mjs +376 -38
- package/cli/migrate.mjs +683 -52
- package/cli/mode.mjs +170 -0
- package/cli/next.mjs +365 -86
- package/cli/openpr.mjs +193 -34
- package/cli/owners.mjs +266 -0
- package/cli/people.mjs +657 -0
- package/cli/plan.mjs +466 -125
- package/cli/platform.mjs +109 -128
- package/cli/product-index.mjs +287 -0
- package/cli/protection.mjs +706 -0
- package/cli/reconcile.mjs +40 -12
- package/cli/repo-publish.mjs +24 -26
- package/cli/repo.mjs +23 -14
- package/cli/report.mjs +24 -14
- package/cli/review.mjs +19 -22
- package/cli/riskmap-command.mjs +289 -0
- package/cli/riskmap.mjs +373 -0
- package/cli/setup.mjs +127 -279
- package/cli/ship.mjs +6 -5
- package/cli/skill.mjs +180 -0
- package/cli/skip.mjs +211 -30
- package/cli/thread.mjs +41 -16
- package/cli/tidy.mjs +18 -18
- package/cli/update-commit.mjs +21 -21
- package/cli/usage.mjs +115 -109
- package/package.json +3 -3
- package/skills/sdlc/config.yaml +149 -70
- package/skills/sdlc/module-help.csv +24 -24
- package/skills/yad-analysis/SKILL.md +121 -59
- package/skills/yad-architecture/SKILL.md +30 -18
- package/skills/yad-architecture/references/contract-format.md +8 -5
- package/skills/yad-backfill/SKILL.md +10 -4
- package/skills/yad-backfill/references/backfill.md +8 -1
- package/skills/yad-backfill/templates/checks/backfill-check.sh +10 -2
- package/skills/yad-change/SKILL.md +119 -42
- package/skills/yad-change/references/triage.md +42 -27
- package/skills/yad-checks/SKILL.md +68 -35
- package/skills/yad-checks/references/check-gates.md +310 -85
- package/skills/yad-checks/templates/checks/commit-message.sh +17 -3
- package/skills/yad-checks/templates/checks/contract-check.sh +130 -9
- package/skills/yad-checks/templates/checks/epic-open.sh +2 -2
- package/skills/yad-checks/templates/checks/ledger-guard.sh +55 -8
- package/skills/yad-checks/templates/checks/lineage-check.sh +23 -9
- package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +1 -1
- package/skills/yad-checks/templates/checks/risk-map-check.sh +438 -0
- package/skills/yad-checks/templates/checks/verified-commits.sh +20 -46
- package/skills/yad-checks/templates/github/yad-checks.yml +13 -2
- package/skills/yad-checks/templates/github/yad-hub-checks.yml +5 -5
- package/skills/yad-checks/templates/github/yad-update-guard.yml +7 -5
- package/skills/yad-checks/templates/github/yad-verified-commits.yml +4 -4
- package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +10 -1
- package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +5 -5
- package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +3 -3
- package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +91 -0
- package/skills/yad-checks/templates/hooks/ledger-guard.sh +37 -6
- package/skills/yad-checks/templates/hooks/yad-capture.sh +53 -0
- package/skills/yad-commit/SKILL.md +4 -4
- package/skills/yad-connect-design/SKILL.md +5 -5
- package/skills/yad-connect-design/references/design-context.md +1 -1
- package/skills/yad-connect-design/references/design-registry.md +2 -2
- package/skills/yad-connect-docs/SKILL.md +11 -11
- package/skills/yad-connect-docs/references/docs-registry.md +1 -1
- package/skills/yad-connect-learning/SKILL.md +5 -5
- package/skills/yad-connect-learning/references/learning-registry.md +2 -2
- package/skills/yad-connect-repos/SKILL.md +66 -45
- package/skills/yad-connect-repos/references/code-context.md +4 -4
- package/skills/yad-connect-repos/references/hub-config.md +47 -51
- package/skills/yad-connect-repos/references/repos-registry.md +8 -7
- package/skills/yad-connect-repos/references/risk-map.md +81 -0
- package/skills/yad-connect-testing/SKILL.md +5 -5
- package/skills/yad-connect-testing/references/testing-context.md +3 -4
- package/skills/yad-connect-testing/references/testing-registry.md +2 -2
- package/skills/yad-defects/SKILL.md +7 -7
- package/skills/yad-discovery/SKILL.md +131 -94
- package/skills/yad-discovery/references/discovery-schema.md +22 -6
- package/skills/yad-discovery/references/foundation-schema.md +374 -0
- package/skills/yad-docs/SKILL.md +13 -8
- package/skills/yad-docs/references/data-mapping.md +9 -7
- package/skills/yad-docs/templates/app/package-lock.json +3 -3
- package/skills/yad-docs-overview/SKILL.md +30 -15
- package/skills/yad-docs-overview/references/pipeline-model.md +33 -20
- package/skills/yad-docs-sync/SKILL.md +10 -5
- package/skills/yad-docs-sync/references/staleness.md +8 -7
- package/skills/yad-engineer-review/SKILL.md +81 -17
- package/skills/yad-engineer-review/references/ship-and-record.md +17 -8
- package/skills/yad-epic/SKILL.md +173 -92
- package/skills/yad-epic/references/state-schema.md +610 -94
- package/skills/yad-hub-bridge/SKILL.md +57 -38
- package/skills/yad-hub-bridge/references/bridge.md +94 -67
- package/skills/yad-hub-bridge/references/login-roster.md +163 -70
- package/skills/yad-hub-bridge/templates/checks/hub-route.sh +22 -19
- package/skills/yad-hub-bridge/templates/github/yad-gate-sync.yml +34 -14
- package/skills/yad-hub-bridge/templates/gitlab/gitlab-ci.include-root.yml +2 -2
- package/skills/yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml +21 -11
- package/skills/yad-implement/SKILL.md +27 -13
- package/skills/yad-implement/references/implement-conventions.md +2 -2
- package/skills/yad-learn/SKILL.md +9 -9
- package/skills/yad-learn/references/learning-state.md +2 -2
- package/skills/yad-open-pr/SKILL.md +61 -26
- package/skills/yad-pair-review/SKILL.md +7 -5
- package/skills/yad-pair-review/references/session-state.md +1 -1
- package/skills/yad-pr-template/SKILL.md +47 -26
- package/skills/yad-pr-template/references/risk-routing.md +97 -24
- package/skills/yad-pr-template/templates/checks/pr-template.sh +34 -11
- package/skills/yad-pr-template/templates/checks/pr-title.sh +32 -9
- package/skills/yad-pr-template/templates/checks/risk-route.sh +107 -14
- package/skills/yad-pr-template/templates/github/pull_request_template.md +7 -5
- package/skills/yad-pr-template/templates/gitlab/merge_request_templates/Default.md +7 -5
- package/skills/yad-pr-template/templates/hub/github/pull_request_template.md +14 -13
- package/skills/yad-pr-template/templates/hub/gitlab/merge_request_templates/Default.md +14 -12
- package/skills/yad-reconcile/SKILL.md +3 -3
- package/skills/yad-report/SKILL.md +5 -5
- package/skills/yad-review-companion/SKILL.md +6 -3
- package/skills/yad-review-gate/SKILL.md +203 -93
- package/skills/yad-review-gate/references/gating.md +232 -54
- package/skills/yad-run/SKILL.md +81 -51
- package/skills/yad-run/references/run-loop.md +61 -39
- package/skills/yad-ship/SKILL.md +15 -11
- package/skills/yad-spec/SKILL.md +21 -6
- package/skills/yad-spec/references/spec-handoff.md +17 -5
- package/skills/yad-status/SKILL.md +115 -50
- package/skills/yad-stories/SKILL.md +37 -21
- package/skills/yad-stories/references/story-schema.md +7 -6
- package/skills/yad-stub/SKILL.md +58 -47
- package/skills/yad-sync-repos/SKILL.md +2 -2
- package/skills/yad-test-cases/SKILL.md +32 -23
- package/skills/yad-test-cases/references/test-cases-schema.md +7 -4
- package/skills/yad-timeline/SKILL.md +8 -7
- package/skills/yad-ui/SKILL.md +41 -18
- package/cli/roster.mjs +0 -164
- 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
|
|
17
|
-
>
|
|
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)
|
|
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
|
|
36
|
-
|
|
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
|
-

|
|
42
42
|
|
|
43
43
|
**Legend:** 🟨 **artifact** (a step writes a file and stops) · 🟧 **gate** (a human review that must
|
|
44
|
-
pass) · 🟦 **
|
|
45
|
-
⬜ **locked** (the engineer review
|
|
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 **
|
|
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 —
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
88
|
-
spec-link, contract-check, verified-commits, build/test/lint, the feature-thread gates,
|
|
89
|
-
|
|
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
|
|
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
|
|
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
|
|
125
|
-
|
|
126
|
-
Shape
|
|
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,
|
|
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
|
|
package/bin/commands.mjs
ADDED
|
@@ -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';
|