yadflow 4.2.0 → 4.4.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.
package/cli/workspace.mjs CHANGED
@@ -32,6 +32,7 @@ import { productConfigPath, PROJECT_FILES } from './manifest.mjs';
32
32
  import { runSetup, insideWorkspace, throughGitDir, selectIdeTargets } from './setup.mjs';
33
33
  import { moduleActions, gitHookActions } from './plan.mjs';
34
34
  import { writeWorkspaceFile, WORKSPACE_FILE } from './find-product.mjs';
35
+ import { offerToolbox } from './toolbox.mjs';
35
36
 
36
37
  // E80: the file that lets yad find the Product from inside the repos it registers. Written by all three.
37
38
  function noteWorkspaceFile(product) {
@@ -483,13 +484,20 @@ export async function runJoin(cwd, url, folder, opts = {}) {
483
484
  const hook = gitHookActions(product);
484
485
  for (const a of hook) a.apply();
485
486
  if (hook.length) ok('installed the git pre-commit hook in this clone');
487
+ // E85: the tools the team chose (the Product's toolbox.json, just cloned) that this machine lacks. A
488
+ // new teammate is the person most likely to miss one. Offered, never installed.
489
+ log('');
490
+ log(c.bold('Toolbox'));
491
+ const toolbox = offerToolbox(product, product, { canRemove: false });
486
492
 
493
+ // Under a heading of its own, so these lines do not read as part of the toolbox list above.
487
494
  log('');
495
+ log(c.bold('Next'));
488
496
  if (repos.failed.length) hand(`${repos.failed.length} repo(s) not cloned — fix what is named above and re-run \`yad join ${shown(url)}\`; it keeps what is already there`);
489
497
  hand(`start with: cd ${fromShell(product)} && yad next`);
490
498
  return {
491
499
  workspace, product,
492
500
  repos, skills: { installed: skills.installed, stale: skills.stale.length, shared: skills.shared.length },
493
- hook: hook.length ? 'installed' : 'unchanged',
501
+ hook: hook.length ? 'installed' : 'unchanged', toolbox,
494
502
  };
495
503
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yadflow",
3
- "version": "4.2.0",
3
+ "version": "4.4.0",
4
4
  "description": "Shared project memory and workflows for teams building with AI: a versioned record of plans, decisions, contracts and reviews across repos, human-approved review gates, and a zero-dependency `yad` CLI plus 38 skills for your AI assistant.",
5
5
  "type": "module",
6
6
  "author": "AbdelRahman Nasr",
@@ -217,7 +217,7 @@ build:
217
217
  story_build_states: [in-build, shipped] # in-build = some tasks shipped; shipped = all tasks in tasks.md shipped
218
218
  # Backfill (yad-backfill) — specs for already-built features in an existing repo.
219
219
  backfill:
220
- tool: repomix # the one true CLI subprocess: `npx repomix@latest` (Phase 0 / RESEARCH-NOTES §3)
220
+ tool: repomix # the one true CLI subprocess: `npx repomix@1.18.1` (Phase 0 / RESEARCH-NOTES §3)
221
221
  pack_flags: "--compress --include <globs> --include-logs --style markdown" # one feature at a time; Secretlint by default
222
222
  spec_location: "specs/backfill/<feature>/spec.md" # draft (verified: false) until a human approves
223
223
  gate_scope: touched-features # block a change only until the features it touches have approved specs
@@ -24,7 +24,7 @@ SDLC Workflow,yad-open-pr,Open PR/MR,OP,"Build helper: open a code-repo task PR/
24
24
  SDLC Workflow,yad-ship,Commit + Open PR/MR,SP2,"Build helper: commit AND open the task PR/MR in one step — a thin orchestration over yad-commit then yad-open-pr. Commits the staged atomic change by the conventions, then pushes the branch and opens the PR/MR from the committed template, assigned to the logged-in gh/glab login with no reviewers requested. The PR step runs ONLY if the commit lands (a failed commit, tripped guard, or --dry-run stops before pushing). Drives the yad ship CLI. Never merges; never auto-advances.",,{type: feat|fix|...} {message: subject} {ai: <tool|none>} {repo: <name>} {risk: low|medium|high} {contract-change: true|false} {base: <branch>},3-build,yad-pr-template,,false,<repo>/,one commit + one PR/MR
25
25
  SDLC Workflow,yad-product-bridge,Product Review Bridge,PB,"The templated PR/MR bridge for the Shape review gate: when the Product has a platform (.sdlc/product.json), open a review PR/MR on the Product for an authored artifact, apply the touched-domain labels (no reviewers are requested), and provide the read-only gh/glab recipes yad-review-gate's sync uses to pull platform comments + approvals into the file ledger. Local-user auth, no stored tokens; file ledger stays the source of truth; degrades to local when no platform/CLI. Never auto-advances.",,{epic: EP-<slug>} {artifact: epic.md|architecture.md|ui-design.md|stories/} {action: open|route},1-front,yad-review-gate,yad-review-gate,false,epics/EP-<slug>/.sdlc/,product-prs.json
26
26
  SDLC Workflow,yad-engineer-review,Engineer Review & Merge,ER,"Build Step E: wire an advisory AI first-pass (CodeRabbit) on the PR, record the human engineer review with the same advance-human discipline as the Shape gates (1 approval from someone other than the author; high risk / contract / auth / payments add an advisory risk step), and on merge record the ship in epics/<epic>/.sdlc/build-log.json and update the story state. AI review is advisory, never the authority; the human owns the merge. Never auto-advances.",,{epic: EP-<slug>} {story: EP-<slug>-S0N} {task: T0N} {repo: <repo>} {action: ai-review|approve|ship},3-build,yad-ship,,false,epics/EP-<slug>/.sdlc/,build-log.json story-status
27
- SDLC Workflow,yad-backfill,Backfill Specs,BF,"Build Step G: generate specs for already-built features in an existing repo. Confirm Repomix (npx repomix CLI), pack ONE feature (compress + git logs, secret-scan), feed to AI with a 'describe what exists, do not invent' prompt, write a DRAFT spec marked verified: false. Human approval (reuse yad-review-gate) makes it real. Boundary auto-proposed and human-confirmed. A change is blocked only until the features it touches have approved specs. The promote action flips a brownfield stub epic (yad-stub) to a real, verified feature epic once its backfill spec is approved. Never auto-advances.",,{repo: <repo>} {feature: <name + globs>} {action: pack|draft|approve|gate|promote} {epic: EP-<slug> (promote)},3-build,,,false,demo-repos/<repo>/specs/backfill/<feature>/,spec.md backfill-check.sh
27
+ SDLC Workflow,yad-backfill,Backfill Specs,BF,"Build Step G: generate specs for already-built features in an existing repo. Confirm Repomix (npx repomix@1.18.1 CLI), pack ONE feature (compress + git logs, secret-scan), feed to AI with a 'describe what exists, do not invent' prompt, write a DRAFT spec marked verified: false. Human approval (reuse yad-review-gate) makes it real. Boundary auto-proposed and human-confirmed. A change is blocked only until the features it touches have approved specs. The promote action flips a brownfield stub epic (yad-stub) to a real, verified feature epic once its backfill spec is approved. Never auto-advances.",,{repo: <repo>} {feature: <name + globs>} {action: pack|draft|approve|gate|promote} {epic: EP-<slug> (promote)},3-build,,,false,demo-repos/<repo>/specs/backfill/<feature>/,spec.md backfill-check.sh
28
28
  SDLC Workflow,yad-run,Run (Automation),RN,"Phase 4 orchestrator: drive a story's Build loop (spec→tasks→implement→checks) in one code repo, reading each step's advance dial through the engine (yad dial --json) — on auto it advances on its own, on human it stops for a human. Records every run in the trust log, the run record yad dial shows as advice. A clean checks pass on auto advances to the engineer review; any FAIL / scope overrun / contract touch HALTS. set-dial runs yad dial (no trust threshold since E34; a gate is refused); kill/unkill run yad kill / yad unkill, recorded in .sdlc/automation.json. Never drives a Shape step; the human merge gate never auto-advances.",,{epic: EP-<slug>} {story: EP-<slug>-S0N} {repo: <repo>} {action: run|set-dial|kill|unkill} {step: <back-step>} {to: human|auto},4-automate,yad-spec,yad-engineer-review,false,epics/EP-<slug>/.sdlc/,build-state/<story-id>.json trust-log.json
29
29
  SDLC Workflow,yad-status,SDLC Status,SS,"Read-only: print the full Shape step chain, per-step dials, contract lock, story repo tags, and pending approvals at the active gate. For stories in Build, also print each Build step's automation dial and status, the run record (runs / % approved-unchanged, as advice), the Shape author dials and the kill switch from .sdlc/automation.json.",,{epic: EP-<slug>},anytime,,,false,,
30
30
  SDLC Workflow,yad-report,Report Issue,RP,"Self issue reporter: when a yad flow breaks, file a well-formed bug in the upstream yadflow repo with AUTO-SCRUBBED diagnostics (yadflow/node/os version, tool present+authenticated booleans, Product platform enum, the YadError code/hint, a path-scrubbed message, and the failing command + flag NAMES only) — never absolute paths, hostnames, git URLs, repo names, logins/emails, epic/story IDs, branch names, or flag values. Searches open issues first to avoid duplicates, previews the exact payload, and asks before posting to the public repo; files via an authenticated gh (the upstream repo is on GitHub) or a prefilled issues/new URL fallback. Also offered automatically after an unexpected failure (interactive only; YAD_NO_REPORT=1 disables). Never a gate, never touches epic state.",,{message: one-line summary},,,,false,,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yad-backfill
3
- description: 'Build Step G of the gated SDLC — backfill: generate specs for already-built features in an existing repo so new work does not break them. Confirm Repomix (the one true CLI subprocess: npx repomix), pack ONE feature at a time (compress + git logs, secret-scan), feed it to AI with a "describe what exists, do not invent" prompt, and write a DRAFT spec marked unverified. Require human approval (reuse yad-review-gate) before the spec counts as real. Boundary is auto-proposed from the project convention and human-confirmed. A change is blocked only until the features IT touches have approved specs. The `promote` action flips a brownfield stub epic (minted by yad-stub, so defects could thread off it) to a real, verified feature epic once its backfill spec is approved. Use when the user says "backfill specs", "document an existing feature", "spec the legacy code", or "promote the stub epic".'
3
+ description: 'Build Step G of the gated SDLC — backfill: generate specs for already-built features in an existing repo so new work does not break them. Confirm Repomix (the one true CLI subprocess: npx repomix@1.18.1), pack ONE feature at a time (compress + git logs, secret-scan), feed it to AI with a "describe what exists, do not invent" prompt, and write a DRAFT spec marked unverified. Require human approval (reuse yad-review-gate) before the spec counts as real. Boundary is auto-proposed from the project convention and human-confirmed. A change is blocked only until the features IT touches have approved specs. The `promote` action flips a brownfield stub epic (minted by yad-stub, so defects could thread off it) to a real, verified feature epic once its backfill spec is approved. Use when the user says "backfill specs", "document an existing feature", "spec the legacy code", or "promote the stub epic".'
4
4
  ---
5
5
 
6
6
  # SDLC — Backfill (existing-code specs)
@@ -11,12 +11,41 @@ generating a spec for what is **already built** — so future changes have a con
11
11
  it count. Gating is **per touched feature**: a new change is blocked only until the features it touches
12
12
  have approved specs — never the whole repo at once.
13
13
 
14
+ ## When a tool is missing
15
+
16
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
17
+
18
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
19
+ beside it.
20
+
21
+ For Repomix, decide from yad's answer, not from a guess:
22
+ run `yad toolbox list --json` and read, in its `tools` list, the entry with the tool's `id`. Run it
23
+ where the tool will run: for work inside a code repo, add `--dir <that repo>`, so the tools installed
24
+ there are found.
25
+
26
+ - **The team's choices.** They come from the Product. If the answer's `product` is null, yad found no
27
+ Product, so a tool the team chose not to use still shows `used: true`. Tell the person that.
28
+ - **When yad cannot see the tool.** yad does not read every way a tool can be set up (an older install
29
+ may be missed). If the entry says `missing` but the check in the steps below finds the tool, use
30
+ it — but never when the entry says `used: false`.
31
+ - **When yad cannot answer** (yad is not installed here, or the command fails), use the check in the
32
+ steps below.
33
+
34
+ Tell the person which tools you used and which fallbacks, and why.
35
+
36
+ - **Repomix** (`repomix`). Use it when its entry has `used: true` and `status.state` is `installed` or `available`. Otherwise — not found, its plugin turned off in Claude Code, or the team chose not to use it (`yad toolbox remove repomix`) — use the fallback.
37
+ - Fallback — no Repomix pack. yad-connect-repos and yad-backfill put the same context together by hand, from the source tree and the recent git log, and the Shape steps read the code map.
38
+ - Record `source: repomix-unavailable`. It means the tool was not used, whatever the reason.
39
+
40
+ <!-- end: When a tool is missing -->
41
+
14
42
  ## Conventions
15
43
 
16
44
  - `{project-root}` resolves from the project working directory; code repos are separate git repos under
17
45
  `{project-root}/demo-repos/<repo>/`.
18
- - **Repomix is a true CLI subprocess** (Phase 0 / RESEARCH-NOTES §3): `npx repomix@latest [flags]` —
19
- NOT a slash-command. It secret-scans by default (Secretlint).
46
+ - **Repomix is a true CLI subprocess** (Phase 0 / RESEARCH-NOTES §3): `npx repomix@1.18.1 [flags]` —
47
+ NOT a slash-command. Run exactly that version: it is the one yadflow vetted, and `@latest` would
48
+ take a release nobody checked. It secret-scans by default (Secretlint).
20
49
  - Backfilled specs live in the code repo at `specs/backfill/<feature>/spec.md`.
21
50
  - A **feature** is the project's natural unit from the constitution (e.g. a module / a `src/<feature>/`
22
51
  directory). Auto-propose the boundary from the convention; **a human confirms** it where the code
@@ -40,12 +69,13 @@ guess silently where the code breaks the convention.
40
69
  ### Step 2 — `pack` (Repomix, one feature)
41
70
  Run, from inside the repo, over **only this feature's files**:
42
71
  ```
43
- npx repomix@latest --compress --include "<feature globs>" --include-logs --style markdown -o <out>.md
72
+ npx repomix@1.18.1 --compress --include "<feature globs>" --include-logs --style markdown -o <out>.md
44
73
  ```
45
74
  `--compress` (Tree-sitter structural compression) keeps it small; `--include-logs` adds the relevant
46
75
  git history (default 50; `--include-logs-count N` to change); Secretlint secret-scans by default. If a
47
- secret is reported, STOP and have it removed/redacted before continuing. (If `npx repomix` is
48
- unavailable, degrade: hand-assemble the same feature context and record `repomix: unavailable`.)
76
+ secret is reported, STOP and have it removed/redacted before continuing. (If Repomix is not
77
+ used — see **When a tool is missing** — degrade: hand-assemble the same feature context and record
78
+ `source: repomix-unavailable`.)
49
79
 
50
80
  ### Step 3 — `draft` (describe what exists — do NOT invent)
51
81
  Feed the packed context to the AI with the **"describe what exists, do not invent"** instruction
@@ -58,10 +88,13 @@ repo: <repo>
58
88
  artifact: backfill-spec
59
89
  status: draft
60
90
  verified: false
61
- source: repomix # or "repomix: unavailable" when degraded
91
+ source: repomix
62
92
  generated: <YYYY-MM-DD>
63
93
  ---
64
94
  ```
95
+
96
+ When Repomix was not used, write `source: repomix-unavailable` instead.
97
+
65
98
  `verified: false` means the spec is not real until a human approves it. Keep that line free of a `#`
66
99
  comment: the gate reads the whole line, so `verified: true # approved` would not count. Mark every
67
100
  uncertain item explicitly (`<!-- unverified: ... -->`); do not fill gaps with invented behaviour.
@@ -6,10 +6,10 @@ the whole repo.
6
6
 
7
7
  ## Repomix (the one true CLI subprocess)
8
8
 
9
- `npx repomix@latest [flags]` (Phase 0 / RESEARCH-NOTES §3). For a single feature:
9
+ `npx repomix@1.18.1 [flags]` (Phase 0 / RESEARCH-NOTES §3). For a single feature:
10
10
 
11
11
  ```
12
- npx repomix@latest --compress --include "src/<feature>/**" --include-logs --style markdown -o <out>.md
12
+ npx repomix@1.18.1 --compress --include "src/<feature>/**" --include-logs --style markdown -o <out>.md
13
13
  ```
14
14
 
15
15
  - `--compress` — Tree-sitter structural compression (keeps the pack small and signal-dense).
@@ -18,8 +18,9 @@ npx repomix@latest --compress --include "src/<feature>/**" --include-logs --styl
18
18
  - `--style markdown` — human/AI-readable; default output is `repomix-output.xml`.
19
19
  - **Secretlint runs by default** — if a secret is reported, STOP and redact before any AI sees the code.
20
20
 
21
- If `npx repomix` is unavailable, degrade: hand-assemble the same feature context (the feature's files +
22
- recent git log for those paths) and record `repomix: unavailable` in the spec frontmatter.
21
+ If Repomix is not used (the skill's "When a tool is missing" section says how to tell), degrade:
22
+ hand-assemble the same feature context (the feature's files + recent git log for those paths) and record
23
+ `source: repomix-unavailable` in the spec frontmatter.
23
24
 
24
25
  ## The "describe what exists, do not invent" prompt
25
26
 
@@ -249,7 +249,7 @@ is paid (Shape artifacts updated **and** a regression test added, then `status:
249
249
  Report: the new `EP-<slug>`, its thread + parent, the re-author-vs-inherit split, the seeded
250
250
  `currentStep`, and the next skill — run `yad next EP-<slug>` and name what it names, followed by
251
251
  `yad-review-gate`. Do NOT name a skill from memory: which skill runs a step is the project's setting
252
- (`.sdlc/skills.json`), so a team that bound its own would be sent to one this epic will never use
252
+ (`.sdlc/skills.json`, for every epic or for this epic's route), so a team that bound its own would be sent to one this epic will never use
253
253
  again. Unbound, that command names `yad-architecture` for a contract-surface change and `yad-stories`
254
254
  / `yad-test-cases` otherwise, which is what this step used to say. Shape steps do not auto-advance. Suggest
255
255
  `yad thread <thread>` to see the evolution and `yad-timeline` / `yad-defects` to render it.
@@ -16,6 +16,22 @@ connected and its MCP is available, the `ux-designer` lens **generates** screens
16
16
  **links** an existing human-made design and reads it back); when nothing is connected, `yad-ui` runs
17
17
  markdown-only exactly as before.
18
18
 
19
+ ## When a tool is missing
20
+
21
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
22
+
23
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
24
+ beside it.
25
+
26
+ Tell the person which tools you used and which fallbacks, and why.
27
+
28
+ - **Figma** (`figma`, a connector). This skill connects it, by writing `.sdlc/design.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
29
+ - Fallback — markdown-only: yad-ui writes ui-design.md and DESIGN.md only.
30
+ - **Pencil (pen.dev)** (`pencil`, a connector). This skill connects it, by writing `.sdlc/design.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
31
+ - Fallback — markdown-only: yad-ui writes ui-design.md and DESIGN.md only.
32
+
33
+ <!-- end: When a tool is missing -->
34
+
19
35
  ## Conventions
20
36
 
21
37
  - `{project-root}` resolves from the project working directory (the **Product**).
@@ -17,6 +17,20 @@ available it drives the CLI (grounded in the knowledge base); when nothing is co
17
17
  degrades to **harness-native** tutoring — the harness model reads the project artifacts directly and
18
18
  explains the concept. The learning layer is **purely opt-in and never blocks a gate**.
19
19
 
20
+ ## When a tool is missing
21
+
22
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
23
+
24
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
25
+ beside it.
26
+
27
+ Tell the person which tools you used and which fallbacks, and why.
28
+
29
+ - **DeepTutor** (`deeptutor`, a connector). This skill connects it, by writing `.sdlc/learning.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
30
+ - Fallback — harness-native tutoring: yad-learn has your agent read the project files directly.
31
+
32
+ <!-- end: When a tool is missing -->
33
+
20
34
  ## Conventions
21
35
 
22
36
  - `{project-root}` resolves from the project working directory (the **Product**).
@@ -14,6 +14,34 @@ This is **setup/maintenance**, not a gated Shape step — it never touches `.sdl
14
14
  epic's approvals. It writes the project-wide registry, the per-repo context cache, and — in the code
15
15
  repo itself — a draft of that repo's risk map (Step 3b), which the team commits there through a PR.
16
16
 
17
+ ## When a tool is missing
18
+
19
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
20
+
21
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
22
+ beside it.
23
+
24
+ For Repomix, decide from yad's answer, not from a guess:
25
+ run `yad toolbox list --json` and read, in its `tools` list, the entry with the tool's `id`. Run it
26
+ where the tool will run: for work inside a code repo, add `--dir <that repo>`, so the tools installed
27
+ there are found.
28
+
29
+ - **The team's choices.** They come from the Product. If the answer's `product` is null, yad found no
30
+ Product, so a tool the team chose not to use still shows `used: true`. Tell the person that.
31
+ - **When yad cannot see the tool.** yad does not read every way a tool can be set up (an older install
32
+ may be missed). If the entry says `missing` but the check in the steps below finds the tool, use
33
+ it — but never when the entry says `used: false`.
34
+ - **When yad cannot answer** (yad is not installed here, or the command fails), use the check in the
35
+ steps below.
36
+
37
+ Tell the person which tools you used and which fallbacks, and why.
38
+
39
+ - **Repomix** (`repomix`). Use it when its entry has `used: true` and `status.state` is `installed` or `available`. Otherwise — not found, its plugin turned off in Claude Code, or the team chose not to use it (`yad toolbox remove repomix`) — use the fallback.
40
+ - Fallback — no Repomix pack. yad-connect-repos and yad-backfill put the same context together by hand, from the source tree and the recent git log, and the Shape steps read the code map.
41
+ - Record `source: repomix-unavailable`. It means the tool was not used, whatever the reason.
42
+
43
+ <!-- end: When a tool is missing -->
44
+
17
45
  ## Conventions
18
46
 
19
47
  - `{project-root}` resolves from the project working directory (the **Product**).
@@ -21,8 +49,9 @@ repo itself — a draft of that repo's risk map (Step 3b), which the team commit
21
49
  Impeccable, later) are installed/run **here** and target the connected code repos **by path**. The
22
50
  code repos themselves need no install for this. (The Build CI gates are the exception — they
23
51
  live inside each code repo; see `yad-checks`.)
24
- - **Repomix is a true CLI subprocess** (Phase 0 / RESEARCH-NOTES §3): `npx repomix@latest [flags]` —
25
- NOT a slash-command. It secret-scans by default (Secretlint).
52
+ - **Repomix is a true CLI subprocess** (Phase 0 / RESEARCH-NOTES §3): `npx repomix@1.18.1 [flags]` —
53
+ NOT a slash-command. Run exactly that version: it is the one yadflow vetted, and `@latest` would
54
+ take a release nobody checked. It secret-scans by default (Secretlint).
26
55
  - Registry: `{project-root}/.sdlc/repos.json` (project-wide, shared across all epics — NOT per-epic).
27
56
  - Per-repo cache: `{project-root}/.sdlc/code-context/<repo>/` holds `pack.md` + `code-map.md`.
28
57
 
@@ -84,12 +113,12 @@ Determine where the code is:
84
113
  ### Step 2 — Pack the repo (Repomix, the full cached context layer)
85
114
  From the code repo, run (flags from `config.yaml` `code_context.pack_flags`):
86
115
  ```
87
- npx repomix@latest --compress --include-logs --style markdown -o {project-root}/.sdlc/code-context/<repo>/pack.md
116
+ npx repomix@1.18.1 --compress --include-logs --style markdown -o {project-root}/.sdlc/code-context/<repo>/pack.md
88
117
  ```
89
118
  `--compress` (Tree-sitter structural compression) keeps it small and signal-dense; `--include-logs`
90
119
  adds recent git history; Secretlint secret-scans by default. **If a secret is reported, STOP and have
91
120
  it redacted before any AI reads the pack.** Pack the whole repo, or the source boundary from the
92
- project's constitution if one is defined. (If `npx repomix` is unavailable, degrade: hand-assemble the
121
+ project's constitution if one is defined. (If Repomix is not used — see **When a tool is missing** — degrade: hand-assemble the
93
122
  same context — the repo's source tree + recent git log — and record `source: repomix-unavailable`.)
94
123
 
95
124
  ### Step 3 — Build the code-map (the lightweight index layer)
@@ -231,7 +260,7 @@ the repo's default branch.
231
260
  The cached pack + map are the default. When a Shape phase needs an **area** not in the map, it may
232
261
  re-run Repomix **live**, scoped to that area:
233
262
  ```bash
234
- npx repomix@latest --compress --include "<area globs>" --style markdown -o -
263
+ npx repomix@1.18.1 --compress --include "<area globs>" --style markdown -o -
235
264
  ```
236
265
  Same CLI, invoked ad hoc — no registry write. A **stale repo** (HEAD ≠ `syncedHead`) is different: the
237
266
  phase **flags it and stops**, pointing the human at `yad repo refresh <repo>` (or `yad check --fix`) —
@@ -10,7 +10,7 @@ Run from the Product, targeting the connected repo (flags from `config.yaml`
10
10
  `code_context.pack_flags`):
11
11
 
12
12
  ```
13
- npx repomix@latest --compress --include-logs --style markdown \
13
+ npx repomix@1.18.1 --compress --include-logs --style markdown \
14
14
  -o {project-root}/.sdlc/code-context/<repo>/pack.md
15
15
  ```
16
16
 
@@ -20,8 +20,8 @@ npx repomix@latest --compress --include-logs --style markdown \
20
20
  - **Secretlint runs by default** — if a secret is reported, **STOP and redact** before any AI reads the
21
21
  pack. Never let a secret reach the model or the cache.
22
22
 
23
- Pack the whole repo, or the source boundary defined in the project's constitution. If `npx repomix` is
24
- unavailable, degrade: hand-assemble the same context (the repo's source tree + recent git log) and
23
+ Pack the whole repo, or the source boundary defined in the project's constitution. If Repomix is not
24
+ used (the skill's "When a tool is missing" section says how to tell), degrade: hand-assemble the same context (the repo's source tree + recent git log) and
25
25
  record `source: repomix-unavailable` in the registry entry.
26
26
 
27
27
  ## Layer 2 — the code-map (lightweight index, the default the brain reads)
@@ -73,7 +73,7 @@ When a Shape phase needs an area not captured in the code-map, it may re-pack th
73
73
  scoped to the area, without writing the cache:
74
74
 
75
75
  ```bash
76
- npx repomix@latest --compress --include "<area globs>" --style markdown -o -
76
+ npx repomix@1.18.1 --compress --include "<area globs>" --style markdown -o -
77
77
  ```
78
78
 
79
79
  This is for a one-off look at a specific area. **Staleness is a human decision, not an automatic
@@ -93,7 +93,7 @@ lands the removal + the managed `.gitignore` line in the same audit commit. The
93
93
  ## Why this stays DRY with backfill
94
94
 
95
95
  `yad-backfill` already documents the exact Repomix command, the Secretlint discipline, the
96
- `repomix: unavailable` degrade, and the "describe what exists, do not invent" prompt
96
+ `source: repomix-unavailable` degrade, and the "describe what exists, do not invent" prompt
97
97
  (`../yad-backfill/references/backfill.md`). This skill reuses all of it; the only differences are
98
98
  **scope** (repo-wide index vs one feature) and **output** (a lightweight code-map for the brain vs a
99
99
  human-approved feature spec). Backfill produces a *verified* spec that gates changes; connect produces a
@@ -16,6 +16,26 @@ tool is connected and its MCP is available, the `test architect` lens **generate
16
16
  into the connected repo(s) (or **links** an existing suite and reads it back); when nothing is
17
17
  connected, `yad-test-cases` runs artifacts-only exactly as before.
18
18
 
19
+ ## When a tool is missing
20
+
21
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
22
+
23
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
24
+ beside it.
25
+
26
+ Tell the person which tools you used and which fallbacks, and why.
27
+
28
+ - **Playwright MCP** (`playwright`, a connector). This skill connects it, by writing `.sdlc/testing.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
29
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
30
+ - **Cypress** (`cypress`, a connector). This skill connects it, by writing `.sdlc/testing.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
31
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
32
+ - **pytest** (`pytest`, a connector). This skill connects it, by writing `.sdlc/testing.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
33
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
34
+ - **Maestro** (`maestro`, a connector). This skill connects it, by writing `.sdlc/testing.json` as the steps below say. The other skills follow that file, not yad's toolbox answer.
35
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
36
+
37
+ <!-- end: When a tool is missing -->
38
+
19
39
  ## Conventions
20
40
 
21
41
  - `{project-root}` resolves from the project working directory (the **Product**).
@@ -120,7 +120,7 @@ Optionally record a `docs:` line in a `DOCS.md` index under the epic.
120
120
  - `action: generate` (default) — generate the source + manifest; stop. The CLI may npm-build to verify,
121
121
  but no publish.
122
122
  - `action: deploy` — drive **`yad docs deploy --epic <id>`**: it npm-builds the site (`npm ci && npm run
123
- build` as a subprocess, like `yad-spec` shelling `npx repomix`), ensures the Pages CI workflow is
123
+ build` as a subprocess, like `yad-spec` shelling out to Repomix), ensures the Pages CI workflow is
124
124
  present, and reports the deploy URL (publish happens via CI). **Degrades** to the local `dist/` path
125
125
  when no platform CLI / `target: "none"` (build-only). **A failed build exits 1**: if `npm ci` (or
126
126
  `npm install`, when the site has no lockfile) or `npm run build` fails, or the site was never generated, the command names the site and exits 1 —
@@ -119,6 +119,14 @@ binding that will never run: a value that is not a skill name (`YAD-CFG-006`), a
119
119
  does not know (`skills:unknown-step`) and a review gate, which `yad gate` drives (`skills:review-step`).
120
120
  It never rewrites the file.
121
121
 
122
+ A line can also apply to **one route only** (E51): `"profiles": { "spike": { "steps": { "epic":
123
+ "spike-skill" } } }`, written with `yad skill bind <step> <skill> --profile <route>`. The most specific
124
+ line wins — the epic's route (the `profile` its `state.json` records, as written; an epic that records
125
+ none uses the project-wide line, never a route guessed from its chain), then the project-wide `steps`,
126
+ then the catalogue. `yad skill list --epic <id>` shows one
127
+ epic's view; `yad doctor` also reports a route this release does not have (`skills:unknown-profile`)
128
+ and a step the route never walks (`skills:off-route`).
129
+
122
130
  **The kill switch and the Shape dials live in `.sdlc/automation.json` (E34)**, also a Product-level file,
123
131
  also absent by default:
124
132
 
@@ -762,8 +770,8 @@ no `steps`, just the state and its record:
762
770
  `yad next` reads these files too: once an epic is `ready-for-build`, `yad next <epic>` resolves each
763
771
  story/repo's `currentStep` into the next build sub-step and prints it with the remaining chain and the
764
772
  step's advance dial — so Build is guided, not just hinted at. The skill it names comes from
765
- `.sdlc/skills.json` when the project bound one (see "The one column a project overrides is the skill"
766
- above); unbound, the defaults are `spec`/`tasks` → `yad-spec`, `implement` → `yad-implement`,
773
+ `.sdlc/skills.json` when the project bound one — for the epic's route first, then project-wide (see
774
+ "The one column a project overrides is the skill" above); unbound, the defaults are `spec`/`tasks` → `yad-spec`, `implement` → `yad-implement`,
767
775
  `checks` → `yad-checks`, `engineer-review` → `yad-engineer-review`.
768
776
 
769
777
  ## `trust-log.json` (shard-then-fold)
@@ -22,6 +22,20 @@ This is a **cross-cutting, opt-in** skill (like `yad-status`, it runs any time).
22
22
  it does not move `currentStep`, never records an approval, and never touches `.sdlc/state.json`, the
23
23
  approvals ledger, or the contract lock. It writes only the local learning ledger + tutorial artifacts.
24
24
 
25
+ ## When a tool is missing
26
+
27
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
28
+
29
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
30
+ beside it.
31
+
32
+ Tell the person which tools you used and which fallbacks, and why.
33
+
34
+ - **DeepTutor** (`deeptutor`, a connector). Used when `.sdlc/learning.json` connects it. yad-connect-learning writes that file; follow it, not yad's toolbox answer.
35
+ - Fallback — harness-native tutoring: yad-learn has your agent read the project files directly.
36
+
37
+ <!-- end: When a tool is missing -->
38
+
25
39
  ## Conventions
26
40
 
27
41
  - `{project-root}` resolves from the project working directory (the **Product**).
@@ -72,15 +72,18 @@ it**: stop, report the recorded `record.reason`, and point at `yad unskip <epic>
72
72
  the lane is owed after all. **Never write a Build step as `skipped` or `deferred`**: a lane is skipped
73
73
  whole or not at all, and `yad doctor` reports a single step set aside.
74
74
 
75
- Also read **which skill runs each step** — `yad skill list --json`, whose `steps[]` gives each step id
76
- its `skills` array. That is the project's choice (`.sdlc/skills.json`, E6) and the engine's default
77
- when it has made none. Read it once here; it does not change during a run.
75
+ Also read **which skill runs each step** — `yad skill list --epic <epic> --json`, whose `steps[]` gives
76
+ each step id its `skills` array. Always pass `--epic`: a project may bind a step for one route only
77
+ (`profiles.<route>` in `.sdlc/skills.json`, E51), and that line wins for an epic on the route — the
78
+ plain `yad skill list` shows the project-wide answer, which may be the wrong skill for this epic. That
79
+ is the project's choice (`.sdlc/skills.json`, E6) and the engine's default when it has made none. Read
80
+ it once here; it does not change during a run.
78
81
 
79
82
  ### `action: run` — drive the loop
80
83
  Walk the steps for `repo` starting at `from`/`currentStep`. For each step:
81
84
 
82
85
  1. **Run the step's skill — use the list from Step 0, never a name written here.** Look the step id
83
- up in `yad skill list --json` and run every entry of its `skills` **in order**, each one seeing what
86
+ up in `yad skill list --epic <epic> --json` and run every entry of its `skills` **in order**, each one seeing what
84
87
  the one before it produced; the last output is the result. (`yad next <epic> --json` gives the same
85
88
  answer per lane once `build-state/<story>.json` is on disk, if you already have it open.) Which
86
89
  skill runs a step is the project's setting, so a hardcoded name here would make this loop do one
@@ -14,7 +14,8 @@ spec → tasks → implement → checks → engineer-review(locked)
14
14
  ```
15
15
 
16
16
  **These names are the engine's DEFAULTS, not a fixed wiring.** Which skill runs a step is the
17
- project's setting in `.sdlc/skills.json`, so the loop reads `yad skill list --json` once at Step 0 and
17
+ project's setting in `.sdlc/skills.json` — for every epic, or for one route only — so the loop reads
18
+ `yad skill list --epic <epic> --json` (that epic's route, E51) once at Step 0 and
18
19
  runs every entry of that step's `skills`, in order, when it is bound to more than one. Unbound: `spec` and `tasks` are the two legs of `yad-spec` (the heavy ceremony, then the atomic
19
20
  `tasks.md`), `implement` is one atomic task via `yad-implement`, and `checks` is
20
21
  `yad-checks (action: run)`. `engineer-review` is the human gate at `yad-engineer-review` — always a
@@ -14,10 +14,39 @@ when driven by the orchestrator (`yad-run`, Phase 4) it records a `spec`/`tasks`
14
14
  (Step 8) — but it never auto-advances a contract change or a Shape step.
15
15
 
16
16
  Spec Kit is driven as **harness slash-commands** (`/speckit.*`), not a subprocess CLI (Phase 0
17
- Deviation 3). When Spec Kit is not installed, the same files are hand-authored in Spec Kit's exact
18
- layout and the spec is marked `speckit: not-installed` — the workflow does not block on the tool. This
17
+ Deviation 3). When Spec Kit is not used (**When a tool is missing** below), the same files are
18
+ hand-authored in Spec Kit's exact layout and the spec is marked `speckit: not-installed` — the workflow
19
+ does not block on the tool. This
19
20
  is the same graceful-degradation pattern `yad-ui` uses for Impeccable.
20
21
 
22
+ ## When a tool is missing
23
+
24
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
25
+
26
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
27
+ beside it.
28
+
29
+ For Spec Kit, decide from yad's answer, not from a guess:
30
+ run `yad toolbox list --json` and read, in its `tools` list, the entry with the tool's `id`. Run it
31
+ where the tool will run: for work inside a code repo, add `--dir <that repo>`, so the tools installed
32
+ there are found.
33
+
34
+ - **The team's choices.** They come from the Product. If the answer's `product` is null, yad found no
35
+ Product, so a tool the team chose not to use still shows `used: true`. Tell the person that.
36
+ - **When yad cannot see the tool.** yad does not read every way a tool can be set up (an older install
37
+ may be missed). If the entry says `missing` but the check in the steps below finds the tool, use
38
+ it — but never when the entry says `used: false`.
39
+ - **When yad cannot answer** (yad is not installed here, or the command fails), use the check in the
40
+ steps below.
41
+
42
+ Tell the person which tools you used and which fallbacks, and why.
43
+
44
+ - **Spec Kit** (`spec-kit`). Use it when its entry has `used: true` and `status.state` is `installed` or `available`. Otherwise — not found, its plugin turned off in Claude Code, or the team chose not to use it (`yad toolbox remove spec-kit`) — use the fallback.
45
+ - Fallback — yad-spec writes the same spec files by hand, in Spec Kit's layout.
46
+ - Record `speckit: not-installed`. It means the tool was not used, whatever the reason.
47
+
48
+ <!-- end: When a tool is missing -->
49
+
21
50
  ## Conventions
22
51
 
23
52
  - `{project-root}` resolves from the project working directory — the **product** repo (epic
@@ -75,17 +104,19 @@ contract here. (On a route that HAS one; the short lanes do not — see below.)
75
104
  already exists, a commit that only DELETES it is allowed through, which is the way back out.)
76
105
 
77
106
  ### Step 4 — Detect Spec Kit
78
- Check for `/speckit.*` slash-commands and/or `demo-repos/<repo>/.specify/`. Record the result for
79
- Step 6's frontmatter (`speckit: installed | not-installed`).
107
+ Read Spec Kit's entry in `yad toolbox list --json --dir demo-repos/<repo>`, as **When a tool is
108
+ missing** says. If yad cannot answer, check for `/speckit.*` slash-commands and/or
109
+ `demo-repos/<repo>/.specify/`. Record the result for Step 6's
110
+ frontmatter (`speckit: installed | not-installed`).
80
111
 
81
112
  ### Step 5 — Run the heavy ceremony ONCE (or degrade)
82
- **Installed** — from inside `demo-repos/<repo>/`, drive, in order:
113
+ **Used** — from inside `demo-repos/<repo>/`, drive, in order:
83
114
  `/speckit.specify` → `/speckit.clarify` → `/speckit.plan` → `/speckit.analyze` →
84
115
  `/speckit.checklist` → `/speckit.tasks`. **Pin the feature to `<story>`** (do not accept an
85
116
  auto-slug). Seed `specify` from the story's acceptance criteria and the contract elements from Step 3.
86
117
  `/speckit.constitution` and `/speckit.implement` are **out of scope for Step A** (implement is Step B).
87
118
 
88
- **Not installed (degrade)** — hand-author the identical files in Spec Kit's layout under
119
+ **Not used (degrade)** — hand-author the identical files in Spec Kit's layout under
89
120
  `demo-repos/<repo>/specs/<story>/`: `spec.md`, `research.md`, `data-model.md`, `contracts/`,
90
121
  `plan.md`, `tasks.md`. The content is what a real Spec Kit run would produce, traceable to the story's
91
122
  acceptance criteria and the locked contract surface. `tasks.md` MUST be numbered atomic tasks (`T01…`),
@@ -2,7 +2,7 @@
2
2
 
3
3
  Step A (`yad-spec`) runs the **heavy Spec Kit ceremony once per story per repo** and writes the
4
4
  result into the story's code repo. This reference pins the exact commands, the files they produce, and
5
- how to hand-author the same files faithfully when Spec Kit is not installed — so Step B
5
+ how to hand-author the same files faithfully when Spec Kit is not used — so Step B
6
6
  (`yad-implement`, not built yet) can read them unchanged.
7
7
 
8
8
  ## The ceremony (run once, in order)
@@ -39,7 +39,7 @@ demo-repos/<repo>/specs/<story-id>/
39
39
  link.md # back-pointer to the story in the product repo (Step A adds this; not a Spec Kit file)
40
40
  ```
41
41
 
42
- ## Degradation rules (when Spec Kit is not installed)
42
+ ## Degradation rules (when Spec Kit is not used)
43
43
 
44
44
  Author each file by hand so it is **indistinguishable in shape** from a real Spec Kit run. The content
45
45
  comes from the story's acceptance criteria and the **locked contract surface** — never invented.
@@ -23,6 +23,26 @@ automation is materialized in the **testing tool connected via `yad-connect-test
23
23
  into it (or **links** an existing suite and reads it back); when none is connected, the step degrades to
24
24
  the Markdown artifact only — the testing tool is additive, exactly like the design tool.
25
25
 
26
+ ## When a tool is missing
27
+
28
+ <!-- Written from yadflow's cli/toolbox.mjs (E87). Change the words there: a test holds this section to it. -->
29
+
30
+ No tool below is required. When one is missing, this skill still finishes, using the fallback written
31
+ beside it.
32
+
33
+ Tell the person which tools you used and which fallbacks, and why.
34
+
35
+ - **Playwright MCP** (`playwright`, a connector). Used when `.sdlc/testing.json` connects it. yad-connect-testing writes that file; follow it, not yad's toolbox answer.
36
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
37
+ - **Cypress** (`cypress`, a connector). Used when `.sdlc/testing.json` connects it. yad-connect-testing writes that file; follow it, not yad's toolbox answer.
38
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
39
+ - **pytest** (`pytest`, a connector). Used when `.sdlc/testing.json` connects it. yad-connect-testing writes that file; follow it, not yad's toolbox answer.
40
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
41
+ - **Maestro** (`maestro`, a connector). Used when `.sdlc/testing.json` connects it. yad-connect-testing writes that file; follow it, not yad's toolbox answer.
42
+ - Fallback — artifacts-only: yad-test-cases writes test-cases.md only.
43
+
44
+ <!-- end: When a tool is missing -->
45
+
26
46
  ## Conventions
27
47
 
28
48
  - `{project-root}` resolves from the project working directory.