@drafthq/draft 3.5.2 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.cursor-plugin/plugin.json +1 -1
  4. package/cli/src/hosts/cursor.js +3 -0
  5. package/cli/src/installer.js +7 -3
  6. package/cli/src/lib/fsx.js +3 -0
  7. package/cli/src/lib/marker.js +8 -3
  8. package/core/shared/condensation.md +1 -1
  9. package/core/shared/git-report-metadata.md +1 -1
  10. package/core/shared/graph-query.md +24 -24
  11. package/core/shared/tool-resolver.md +20 -15
  12. package/core/templates/okf/index.md +6 -10
  13. package/core/templates/okf/section-index.md +2 -11
  14. package/core/templates/plan.md +1 -1
  15. package/integrations/agents/AGENTS.md +142 -492
  16. package/integrations/copilot/.github/copilot-instructions.md +142 -492
  17. package/package.json +1 -1
  18. package/scripts/fetch-memory-engine.sh +1 -1
  19. package/scripts/lib.sh +79 -2
  20. package/scripts/tools/_graph_queries.sh +12 -5
  21. package/scripts/tools/_lib.sh +56 -8
  22. package/scripts/tools/adr-index.sh +1 -1
  23. package/scripts/tools/check-skill-line-caps.sh +2 -2
  24. package/scripts/tools/check-track-hygiene.sh +41 -21
  25. package/scripts/tools/classify-files.sh +1 -1
  26. package/scripts/tools/cycle-detect.sh +2 -9
  27. package/scripts/tools/detect-test-framework.sh +1 -1
  28. package/scripts/tools/emit-skill-metrics.sh +7 -2
  29. package/scripts/tools/freshness-check.sh +2 -2
  30. package/scripts/tools/git-metadata.sh +6 -6
  31. package/scripts/tools/graph-arch.sh +4 -10
  32. package/scripts/tools/graph-callers.sh +4 -12
  33. package/scripts/tools/graph-deps.sh +3 -10
  34. package/scripts/tools/graph-errors.sh +4 -11
  35. package/scripts/tools/graph-hierarchy.sh +4 -11
  36. package/scripts/tools/graph-impact.sh +17 -17
  37. package/scripts/tools/graph-init.sh +1 -1
  38. package/scripts/tools/graph-preflight.sh +1 -1
  39. package/scripts/tools/graph-query.sh +5 -12
  40. package/scripts/tools/graph-risk.sh +3 -10
  41. package/scripts/tools/graph-search.sh +4 -11
  42. package/scripts/tools/graph-snapshot.sh +9 -4
  43. package/scripts/tools/graph-snippet.sh +3 -10
  44. package/scripts/tools/graph-tests.sh +3 -10
  45. package/scripts/tools/graph-traces.sh +3 -10
  46. package/scripts/tools/hotspot-rank.sh +4 -11
  47. package/scripts/tools/mermaid-from-graph.sh +3 -10
  48. package/scripts/tools/migrate-track-frontmatter.sh +3 -1
  49. package/scripts/tools/okf-coverage-check.sh +24 -6
  50. package/scripts/tools/okf-emit-catalog.sh +256 -0
  51. package/scripts/tools/okf-fix-links.sh +326 -0
  52. package/scripts/tools/okf-plan-concepts.sh +245 -14
  53. package/scripts/tools/okf-render-views.sh +65 -13
  54. package/scripts/tools/okf-validate-all.sh +20 -9
  55. package/scripts/tools/okf-validate-quality.sh +2 -8
  56. package/scripts/tools/okf-validate.sh +20 -10
  57. package/scripts/tools/parse-git-log.sh +4 -4
  58. package/scripts/tools/parse-reports.sh +1 -1
  59. package/scripts/tools/render-track.sh +1 -1
  60. package/scripts/tools/run-coverage.sh +1 -1
  61. package/scripts/tools/scan-markers.sh +4 -4
  62. package/scripts/tools/validate-frontmatter.sh +2 -2
  63. package/scripts/tools/verify-citations.sh +2 -2
  64. package/scripts/tools/verify-doc-anchors.sh +1 -1
  65. package/scripts/tools/verify-graph-binary.sh +2 -2
  66. package/skills/adr/SKILL.md +1 -1
  67. package/skills/bughunt/SKILL.md +1 -1
  68. package/skills/coverage/SKILL.md +2 -2
  69. package/skills/debug/SKILL.md +1 -1
  70. package/skills/decompose/SKILL.md +3 -3
  71. package/skills/deep-review/SKILL.md +2 -2
  72. package/skills/deploy-checklist/SKILL.md +1 -1
  73. package/skills/graph/SKILL.md +1 -1
  74. package/skills/impact/SKILL.md +1 -1
  75. package/skills/implement/SKILL.md +2 -2
  76. package/skills/init/SKILL.md +10 -7
  77. package/skills/init/references/architecture-spec.md +1 -1
  78. package/skills/init/references/okf-emitter.md +51 -76
  79. package/skills/learn/SKILL.md +1 -1
  80. package/skills/quick-review/SKILL.md +1 -1
  81. package/skills/review/SKILL.md +3 -3
  82. package/skills/standup/SKILL.md +1 -1
  83. package/skills/status/SKILL.md +1 -1
  84. package/skills/tech-debt/SKILL.md +2 -2
  85. package/skills/upload/SKILL.md +1 -1
  86. package/core/templates/track-architecture.md +0 -311
@@ -338,13 +338,16 @@ The tier-gated default rests on **maintainability/readability** (one navigable c
338
338
 
339
339
  **OKF Completeness Verification (blocking — tier 3+ `okf` mode).** Completeness is enforced by tooling, not honor system, so the wiki is generated completely for every module/sub-module/component on every run. Before promoting `draft.tmp/` → `draft/`, ALL must hold (see `references/okf-emitter.md` for the pipeline):
340
340
 
341
- 1. `okf-plan-concepts.sh` ran and the expected/required/deferred counts were logged **before** any page was written (the concept boundary is a tool output, not an in-context guess).
342
- 2. Every `required` entry in `concept-plan.json` has a non-stub page.
343
- 3. `okf-validate-all.sh --plan … --strict` exits 0 (structure + per-type quality + coverage all pass).
344
- 4. `systems/coverage.md` was generated by tooling (verify the `<!-- okf:coverage-generated -->` marker) — **every** package/module the graph found is required by default (the fan-in floor only types Subsystem-vs-Module, it does not exempt), so none may be **MISSING**. Section `index.md` tables are regenerated by `okf-render-views.sh --section-indexes`, never hand-authored, so their links cannot dangle.
345
- 5. On any failure: **do not** atomic-rename; surface `.state/validation-report.json`.
341
+ 1. `okf-plan-concepts.sh` ran and counts were logged **before** any page was written. Plan discovery is language-aware: **Cargo workspace members / npm workspaces / Go modules first**, then graph packages (noise-filtered), then heuristic dirs. Log `discovery[]` (e.g. `cargo+graph`).
342
+ 2. `okf-emit-catalog.sh` ran so every REQUIRED plan entry has at least a minimum non-stub catalog page (LLM deep-dives may enrich top hotspots afterward).
343
+ 3. Every `required` entry in `concept-plan.json` has a non-stub page.
344
+ 4. `okf-render-views.sh` + `okf-fix-links.sh --fix` produced `architecture.md` with resolving `wiki/…` links and GFM TOC anchors.
345
+ 5. `okf-validate-all.sh --plan --strict` exits 0 (**quality coverage → structure**; structure runs last so coverage.md rewrites are checked).
346
+ 6. `okf-fix-links.sh --draft draft.tmp --check` exits 0 (zero dead links in architecture / wiki views).
347
+ 7. `systems/coverage.md` has the `<!-- okf:coverage-generated -->` marker; section indexes were regenerated by `okf-render-views.sh --section-indexes`.
348
+ 8. On any failure: **do not** atomic-rename; surface `.state/validation-report.json`.
346
349
 
347
- > **Red flag:** writing concept pages without first running `okf-plan-concepts.sh`, or finishing generation while any `required` plan entry is unwritten, is a **completeness failure** — not a stylistic one.
350
+ > **Red flag:** writing concept pages without first running `okf-plan-concepts.sh` + `okf-emit-catalog.sh`, or finishing while any `required` plan entry is unwritten, is a **completeness failure** — not a stylistic one.
348
351
 
349
352
  ### Route Explicit Modes Before Initialization
350
353
 
@@ -644,7 +647,7 @@ One command resolves ROOT, ensures the engine, builds the whole-repo spine, and
644
647
  ```bash
645
648
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
646
649
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
647
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
650
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
648
651
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
649
652
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
650
653
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -2284,7 +2287,7 @@ First resolve the bundled helpers:
2284
2287
  ```bash
2285
2288
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
2286
2289
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
2287
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
2290
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
2288
2291
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
2289
2292
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
2290
2293
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -3353,7 +3356,8 @@ Templates for each bundle page live in `core/templates/okf/` (`index.md`,
3353
3356
  ## Frozen `type` vocabulary
3354
3357
 
3355
3358
  Every concept carries a `type` from this frozen set (changing it churns every
3356
- file; versioned via `index.md` frontmatter `okf_types_version`):
3359
+ file; versioned via the `okf-types-version` comment in the wiki root `index.md`
3360
+ body — OKF §6/§11 permit only `okf_version` in an index file's frontmatter):
3357
3361
 
3358
3362
  | type | Maps to | Home |
3359
3363
  |------|---------|------|
@@ -3379,6 +3383,16 @@ the task at hand?"), never a summary. Draft extensions are namespaced `x-` and
3379
3383
  ignored by generic OKF consumers: `x-grounded-paths`, `x-hotspot-score`,
3380
3384
  `x-callers`.
3381
3385
 
3386
+ **Meta pages are not concepts.** Index files (`wiki/index.md` and every
3387
+ `<section>/index.md`) carry **no concept frontmatter**: per OKF §6 an index file
3388
+ has no frontmatter, and per §11 the root `index.md` may declare **only**
3389
+ `okf_version`. The tool-generated `systems/coverage.md` is a non-reserved file, so
3390
+ OKF §9.1/§9.2 require it to carry a typed frontmatter block; it uses a descriptive
3391
+ `type: Report` and is exempt from the frozen vocabulary via `is_meta_page`
3392
+ (basename + the `<!-- okf:coverage-generated -->` marker). `okf-validate.sh`
3393
+ short-circuits all meta pages before the concept checks, so they are never
3394
+ vocab-checked or counted as concepts.
3395
+
3382
3396
  ## Concept granularity (resolves open decision 1)
3383
3397
 
3384
3398
  Derive concepts from the graph, not by hand:
@@ -3398,75 +3412,40 @@ Derive concepts from the graph, not by hand:
3398
3412
  ```
3399
3413
  1. Survey → existing draft init 5-phase + graph snapshot (graph-snapshot.sh)
3400
3414
  2. Plan → DETERMINISTIC. okf-plan-concepts.sh derives the expected-concept
3401
- set from the graph. EVERY package the graph knows about is
3402
- required (fan_in floor Subsystem; below floor Module — the
3403
- floor only types/orders, it never exempts); entrypoints required;
3404
- only --allow-defer matches are deferred (with a reason). Writes
3405
- draft.tmp/.state/concept-plan.json.
3415
+ set. Discovery order (exclusive of --manifest):
3416
+ a) Cargo workspace members / npm workspaces / Go modules
3417
+ b) graph packages (noise-filtered when a language inventory exists)
3418
+ c) heuristic top-level source dirs
3419
+ Coarse graph parents (e.g. crates/codegen) become Subsystems;
3420
+ crate/package names become Modules. Tokenizer noise (str, int, …)
3421
+ is dropped when unmapped. Writes draft.tmp/.state/concept-plan.json.
3406
3422
  okf-plan-concepts.sh --repo . [--scope PATH] \
3407
3423
  [--manifest FILE] [--min-fan-in 2] [--allow-defer GLOB]... \
3408
3424
  --out draft.tmp/.state/concept-plan.json
3409
- This replaces the old in-context concept enumeration — the boundary
3410
- of the work is now a tool output, not an LLM judgment, so modules
3411
- and sub-modules cannot be silently dropped. (Legacy fan-in
3412
- exemption is opt-in via --defer-below-floor.) LOG the counts
3413
- (expected/required/deferred) BEFORE writing any page.
3414
- `generated_order` is topo-ish (required + high-fan-in first) so
3415
- forward cross-links resolve.
3416
- 3. Generate → iterate concept-plan.generated_order; write ONE page per REQUIRED
3417
- entry, grounding each from the graph:
3418
- x-callers ← graph-callers.sh --symbol <c>
3419
- x-grounded-paths ← graph-impact.sh --symbol <c> (blast radius)
3420
- x-hotspot-score ← hotspot-rank.sh
3421
- overview diagrams mermaid-from-graph.sh
3422
- Record each source path → page in .state/path-to-concept.json.
3423
- Loop post-condition: every required concept_id has an output file.
3424
- Writing pages via shell heredoc without reading x-grounded-paths
3425
- sources, or finishing while any required entry is unwritten, is a
3426
- completeness failure not a stylistic one.
3427
- 4. Render views → ai-context.md (synopsis + Concept Map), architecture.md
3428
- (concatenated view + coverage banner), wiki/log.md (see M4).
3429
- 5. Validate → the promotion gate. Run all layers via the orchestrator:
3430
- 5a. okf-validate-all.sh draft.tmp/wiki \
3431
- --repo . \
3432
- --plan draft.tmp/.state/concept-plan.json \
3433
- --path-index draft.tmp/.state/path-to-concept.json \
3434
- --strict --report draft.tmp/.state/validation-report.json
3435
- It runs, in order: okf-validate.sh (structure + reverse index +
3436
- empty/untyped-page + leftover-template-token + dangling-link checks),
3437
- okf-validate-quality.sh (per-type anti-stub / depth / per-section
3438
- content / mermaid lint), okf-coverage-check.sh (every required plan
3439
- entry → real page).
3440
- ANY layer failing ⇒ exit non-zero ⇒ DO NOT atomic-rename.
3441
- coverage.md (systems/coverage.md) is regenerated by the coverage
3442
- layer; it is tool-owned (marker <!-- okf:coverage-generated -->) —
3443
- never hand-author it except deferral reasons in the manifest.
3444
- 6. Emit → mv draft.tmp/ draft/ ONLY IF step 5 exit 0 ; update .state/.
3445
- On failure keep draft.tmp/ and surface validation-report.json.
3446
- ```
3447
-
3448
- ### Validation report schema (`.state/validation-report.json`)
3449
-
3450
- ```json
3451
- { "valid": false, "bundle": "draft.tmp/wiki",
3452
- "layers": { "structure": "pass", "quality": "pass", "coverage": "fail" } }
3425
+ LOG counts (expected/required/deferred + discovery[]) BEFORE pages.
3426
+ 3. Catalog floor okf-emit-catalog.sh writes a quality-passing MINIMUM page for
3427
+ every REQUIRED plan entry that is still missing (so XL monorepos
3428
+ do not depend on the LLM for completeness):
3429
+ okf-emit-catalog.sh --plan draft.tmp/.state/concept-plan.json \
3430
+ --bundle draft.tmp/wiki --repo .
3431
+ 4. Generate/enrich → iterate concept-plan.generated_order; enrich top hotspots
3432
+ (LLM) beyond the catalog floor. Record path-to-concept.json.
3433
+ Post-condition: every required concept_id has a non-stub page.
3434
+ 5. Render views → okf-render-views.sh (architecture.md + Concept Map + section
3435
+ indexes). Uses GFM slugs for TOC; rewrites sibling links to
3436
+ wiki/<section>/…. Then okf-fix-links.sh --draft draft.tmp --fix.
3437
+ 6. Validate → promotion gate (order is intentional):
3438
+ okf-validate-all.sh draft.tmp/wiki \
3439
+ --plan draft.tmp/.state/concept-plan.json \
3440
+ --path-index draft.tmp/.state/path-to-concept.json \
3441
+ --strict --report draft.tmp/.state/validation-report.json
3442
+ Runs: quality coverage (rewrites coverage.md) → structure LAST
3443
+ so coverage relative links are checked. Also run:
3444
+ okf-fix-links.sh --draft draft.tmp --check
3445
+ ANY failure DO NOT atomic-rename.
3446
+ 7. Emit → mv draft.tmp/ draft/ ONLY IF step 6 exit 0 ; update .state/.
3453
3447
  ```
3454
3448
 
3455
- ### Component manifest (optional — `--manifest FILE`)
3456
-
3457
- When the graph engine is unavailable (or a repo wants an authoritative list), pass
3458
- a plain-text manifest: one component name per line, `#` comments and blanks ignored.
3459
- Every listed component becomes a REQUIRED concept; `--allow-defer GLOB` still moves
3460
- matches to deferred. Without a manifest the plan comes from the graph, and only if
3461
- both are unavailable does it fall back to a heuristic top-level-dir scan (which it
3462
- marks `degraded: true`).
3463
-
3464
- Page bodies are LLM-narrated for readability **but** the graph-derived
3465
- frontmatter and the `Blast radius`/`Used by` sections are deterministic. To keep
3466
- incremental carry-forward byte-identical (open decision 2), cache the narrated
3467
- prose keyed by the source hash of `x-grounded-paths` — unchanged sources reuse
3468
- the cached narration verbatim.
3469
-
3470
3449
  ## Render views (M4)
3471
3450
 
3472
3451
  Both are produced by the deterministic helper `okf-render-views.sh` (no LLM) —
@@ -3520,17 +3499,16 @@ section `index.md` tables are the injection slots for the routing tables.
3520
3499
  `draft init refresh` under `okf` mode:
3521
3500
 
3522
3501
  ```
3523
- 1. Re-derive the plan: okf-plan-concepts.sh (modules added since last run become
3524
- REQUIRED — a new package can't slip through a refresh either)
3525
- 2. Diff hashes.json vs working tree changed source paths
3526
- 3. path-to-concept.json affected concept pages
3527
- 4. Regenerate ONLY affected concepts; carry the rest verbatim (cached narration)
3528
- 5. Re-render ai-context.md / architecture.md / log.md (cheap; always regenerated)
3529
- 6. Re-validate (full gate): okf-validate-all.sh on the bundle with --plan and
3530
- --path-index. Refresh re-runs structure + quality + coverage — a changed
3531
- concept must still clear the quality bar, and a newly-required module must
3532
- still be present.
3533
- 7. Append log.md; update hashes.json + path-to-concept.json
3502
+ 1. Re-derive the plan: okf-plan-concepts.sh (cargo/npm/go + graph). Modules added
3503
+ since last run become REQUIRED — a new crate cannot slip through a refresh.
3504
+ 2. Diff plan vs previous concept-plan.json NEW required concept_ids
3505
+ 3. Diff hashes.json vs working tree changed source paths
3506
+ 4. path-to-concept.json → affected concept pages
3507
+ 5. okf-emit-catalog.sh for any NEW missing required pages (completeness floor)
3508
+ 6. Regenerate/enrich changed + new concepts; carry the rest verbatim
3509
+ 7. Re-render ai-context.md / architecture.md / log.md + okf-fix-links --fix
3510
+ 8. Re-validate: okf-validate-all + okf-fix-links --check
3511
+ 9. Append log.md; update hashes.json + path-to-concept.json + concept-plan.json
3534
3512
  ```
3535
3513
 
3536
3514
  A 1-file change regenerates only the concept(s) that file grounds. Unchanged
@@ -3595,7 +3573,7 @@ echo "Target repo: $REPO_ABS"
3595
3573
  # Locate Draft's bundled helpers. Skills run with cwd = the user's project and
3596
3574
  # ${CLAUDE_PLUGIN_ROOT} is not exported into skill Bash, so resolve DRAFT_TOOLS here
3597
3575
  # and call helpers as "$DRAFT_TOOLS/<tool>.sh". See core/shared/tool-resolver.md.
3598
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
3576
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
3599
3577
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
3600
3578
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
3601
3579
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -4529,7 +4507,7 @@ First resolve the bundled helpers:
4529
4507
  ```bash
4530
4508
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
4531
4509
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
4532
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
4510
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
4533
4511
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
4534
4512
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
4535
4513
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -4932,7 +4910,7 @@ Resolve the script via the canonical tool resolver (see [core/shared/tool-resolv
4932
4910
  ```bash
4933
4911
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
4934
4912
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
4935
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
4913
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
4936
4914
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
4937
4915
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
4938
4916
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -5179,7 +5157,7 @@ As the last step after the completion announcement, emit a metrics record. Best-
5179
5157
  ```bash
5180
5158
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
5181
5159
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
5182
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
5160
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
5183
5161
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
5184
5162
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
5185
5163
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -5327,7 +5305,7 @@ If one of these applies, route directly to the specialist workflow and stop this
5327
5305
  ```bash
5328
5306
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
5329
5307
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
5330
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
5308
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
5331
5309
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
5332
5310
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
5333
5311
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -5827,7 +5805,7 @@ After a phase passes review, refresh `metadata.json.impact` so future tracks can
5827
5805
 
5828
5806
  2. **Compute downstream blast radius (graph-aware, optional):** If `draft/graph/schema.yaml` exists, for each file in `files_touched` query (this runs in its own Bash session — re-resolve the helpers):
5829
5807
  ```bash
5830
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
5808
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
5831
5809
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
5832
5810
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
5833
5811
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -6031,7 +6009,7 @@ If no active track and no argument provided:
6031
6009
  **Preferred:** use the deterministic `detect-test-framework.sh` wrapper — it emits JSON `{languages:[{language,framework,runner_command,test_globs,config_file}]}`. Resolve via the canonical tool resolver (see [core/shared/tool-resolver.md](../../core/shared/tool-resolver.md)):
6032
6010
 
6033
6011
  ```bash
6034
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
6012
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
6035
6013
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
6036
6014
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
6037
6015
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -6073,7 +6051,7 @@ Build the coverage command with the appropriate scope/filter flags.
6073
6051
 
6074
6052
  ```bash
6075
6053
  # Re-resolve helpers (this is a separate Bash session from Step 2).
6076
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
6054
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
6077
6055
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
6078
6056
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
6079
6057
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -6406,7 +6384,7 @@ by validator.
6406
6384
  ```bash
6407
6385
  TRACK_DIR="$1" # absolute path to track-under-deploy, or .
6408
6386
 
6409
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
6387
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
6410
6388
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
6411
6389
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
6412
6390
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -6666,7 +6644,7 @@ Read and follow the base procedure in `core/shared/draft-context-loading.md`.
6666
6644
  ```bash
6667
6645
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
6668
6646
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
6669
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
6647
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
6670
6648
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
6671
6649
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
6672
6650
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -7699,7 +7677,7 @@ First resolve the bundled helpers:
7699
7677
  ```bash
7700
7678
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
7701
7679
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
7702
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
7680
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
7703
7681
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
7704
7682
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
7705
7683
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -8068,7 +8046,7 @@ For the files changed in the diff, perform static checks using `grep` or similar
8068
8046
  ```bash
8069
8047
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
8070
8048
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
8071
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
8049
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
8072
8050
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
8073
8051
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
8074
8052
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -8813,7 +8791,7 @@ As the last step after saving the review report, emit a metrics record. Best-eff
8813
8791
  ```bash
8814
8792
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
8815
8793
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
8816
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
8794
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
8817
8795
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
8818
8796
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
8819
8797
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -8874,7 +8852,7 @@ Run the WS-9 chain from [verification-gates.md](../../core/shared/verification-g
8874
8852
 
8875
8853
  ```bash
8876
8854
  TRACK_DIR="draft/tracks/<id>"
8877
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
8855
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
8878
8856
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
8879
8857
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
8880
8858
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -11131,7 +11109,7 @@ First resolve the bundled helpers:
11131
11109
  ```bash
11132
11110
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
11133
11111
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
11134
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
11112
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
11135
11113
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
11136
11114
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
11137
11115
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -11357,7 +11335,7 @@ First resolve the bundled helpers:
11357
11335
  ```bash
11358
11336
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
11359
11337
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
11360
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
11338
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
11361
11339
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
11362
11340
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
11363
11341
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -11672,7 +11650,7 @@ As the last step after saving the deep-review report, emit a metrics record. Bes
11672
11650
  ```bash
11673
11651
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
11674
11652
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
11675
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
11653
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
11676
11654
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
11677
11655
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
11678
11656
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -11890,7 +11868,7 @@ First resolve the bundled helpers:
11890
11868
  ```bash
11891
11869
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
11892
11870
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
11893
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
11871
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
11894
11872
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
11895
11873
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
11896
11874
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -12419,7 +12397,7 @@ Check for arguments:
12419
12397
  If argument is `list`:
12420
12398
  1. Prefer the deterministic `adr-index.sh` wrapper for the listing — it returns a structured JSON `{adrs:[{id,title,date,status,path,related_tracks}]}` derived from each ADR's frontmatter. Resolve via the canonical tool resolver (see [core/shared/tool-resolver.md](../../core/shared/tool-resolver.md)):
12421
12399
  ```bash
12422
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
12400
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
12423
12401
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
12424
12402
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
12425
12403
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -12754,7 +12732,7 @@ First resolve the bundled helpers:
12754
12732
  ```bash
12755
12733
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
12756
12734
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
12757
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
12735
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
12758
12736
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
12759
12737
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
12760
12738
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -13006,7 +12984,7 @@ Check for arguments:
13006
12984
  **Preferred:** invoke `parse-git-log.sh` — it parses conventional commits into structured JSONL `{sha,type,scope,track_id,subject,author,timestamp,files_changed}`, eliminating ambiguity in `type(track-id): subject` parsing. Resolve via the canonical tool resolver (see [core/shared/tool-resolver.md](../../core/shared/tool-resolver.md)):
13007
12985
 
13008
12986
  ```bash
13009
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
12987
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
13010
12988
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
13011
12989
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
13012
12990
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -13150,7 +13128,7 @@ First resolve the bundled helpers:
13150
13128
  ```bash
13151
13129
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
13152
13130
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
13153
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
13131
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
13154
13132
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
13155
13133
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
13156
13134
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -13231,7 +13209,7 @@ For TODO/FIXME/HACK/XXX/DEPRECATED markers, prefer the deterministic `scan-marke
13231
13209
  ```bash
13232
13210
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
13233
13211
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
13234
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
13212
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
13235
13213
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
13236
13214
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
13237
13215
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -13954,7 +13932,7 @@ Display a comprehensive overview of project progress.
13954
13932
  If `parse-reports.sh` and `freshness-check.sh` are available, gather structured signals to enrich the status output (severity counts per track, stale `draft/` docs). Resolve via the canonical tool resolver (see [core/shared/tool-resolver.md](../../core/shared/tool-resolver.md)):
13955
13933
 
13956
13934
  ```bash
13957
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
13935
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
13958
13936
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
13959
13937
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
13960
13938
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -14598,7 +14576,7 @@ First resolve the bundled helpers:
14598
14576
  ```bash
14599
14577
  # Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
14600
14578
  # is not exported into skill Bash). See core/shared/tool-resolver.md.
14601
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
14579
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
14602
14580
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
14603
14581
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
14604
14582
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -16540,7 +16518,7 @@ Referenced by: All skills that generate Draft reports — including `draft bughu
16540
16518
  Use `git-metadata.sh` from the plugin install, resolved via the canonical tool resolver (see [tool-resolver.md](tool-resolver.md)):
16541
16519
 
16542
16520
  ```bash
16543
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
16521
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
16544
16522
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
16545
16523
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
16546
16524
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -16975,7 +16953,7 @@ Write the completed content to `draft/.ai-context.md`.
16975
16953
  After writing both output files, strip trailing whitespace and blank lines at EOF to prevent GitHub upload failures. Resolve the script via the canonical tool resolver (see [tool-resolver.md](tool-resolver.md)):
16976
16954
 
16977
16955
  ```bash
16978
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
16956
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
16979
16957
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
16980
16958
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
16981
16959
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -17436,10 +17414,10 @@ These fields are appended to `~/.draft/metrics.jsonl` along with the existing sk
17436
17414
 
17437
17415
  ## Tooling Wrappers
17438
17416
 
17439
- For common query modes, prefer the deterministic wrappers that ship with the plugin. Resolve their location via the canonical tool resolver (see [tool-resolver.md](tool-resolver.md)) before invoking. Skills run with cwd = the user's project and `${CLAUDE_PLUGIN_ROOT}` is **not** exported into skill Bash, so a bare `scripts/tools/foo.sh` fails — establish `DRAFT_TOOLS` once before the first helper call, in the same Bash session as your tool calls (re-establish it if you split helper calls into a separate, later Bash block):
17417
+ For common query modes, prefer the deterministic wrappers that ship with the plugin. Resolve their location via the canonical tool resolver (see [tool-resolver.md](tool-resolver.md)) before invoking. Skills run with cwd = the user's project and `${CLAUDE_PLUGIN_ROOT}` is **not** exported into skill Bash, so a bare `scripts/tools/git-metadata.sh` fails — establish `DRAFT_TOOLS` once before the first helper call, in the same Bash session as your tool calls (re-establish it if you split helper calls into a separate, later Bash block):
17440
17418
 
17441
17419
  ```bash
17442
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
17420
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
17443
17421
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
17444
17422
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
17445
17423
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -17555,7 +17533,7 @@ Live queries go through the shell tools under `scripts/tools/`, which drive the
17555
17533
  ### Callers — who calls this function?
17556
17534
 
17557
17535
  ```bash
17558
- scripts/tools/graph-callers.sh --repo . --symbol <name>
17536
+ "$DRAFT_TOOLS/graph-callers.sh" --repo . --symbol <name>
17559
17537
  ```
17560
17538
 
17561
17539
  Output: `{symbol, callers[{name, file}], source}`. Use when enumerating call sites before claiming "no other usages" or judging breaking-change severity.
@@ -17563,8 +17541,8 @@ Output: `{symbol, callers[{name, file}], source}`. Use when enumerating call sit
17563
17541
  ### Impact — blast radius of a file or symbol
17564
17542
 
17565
17543
  ```bash
17566
- scripts/tools/graph-impact.sh --repo . --file <path> # changed-file impact (working-tree diff)
17567
- scripts/tools/graph-impact.sh --repo . --symbol <name> # transitive callers of a function
17544
+ "$DRAFT_TOOLS/graph-impact.sh" --repo . --file <path> # changed-file impact (working-tree diff)
17545
+ "$DRAFT_TOOLS/graph-impact.sh" --repo . --symbol <name> # transitive callers of a function
17568
17546
  ```
17569
17547
 
17570
17548
  Output: `{target, kind, impacted[{name, file, hop}], source}`. Use when sizing risk before modifying a file or symbol, especially high-fan-in hotspots.
@@ -17572,7 +17550,7 @@ Output: `{target, kind, impacted[{name, file, hop}], source}`. Use when sizing r
17572
17550
  ### Hotspots — fan-in ranking
17573
17551
 
17574
17552
  ```bash
17575
- scripts/tools/hotspot-rank.sh --repo . [--top N]
17553
+ "$DRAFT_TOOLS/hotspot-rank.sh" --repo . [--top N]
17576
17554
  ```
17577
17555
 
17578
17556
  Output: `{hotspots[{id, name, fanIn}], source}` (server-computed by the engine).
@@ -17580,7 +17558,7 @@ Output: `{hotspots[{id, name, fanIn}], source}` (server-computed by the engine).
17580
17558
  ### Cycles — call-cycle detection
17581
17559
 
17582
17560
  ```bash
17583
- scripts/tools/cycle-detect.sh --repo .
17561
+ "$DRAFT_TOOLS/cycle-detect.sh" --repo .
17584
17562
  ```
17585
17563
 
17586
17564
  Output: `{cycles[[a,b],[a,b,c]], source}` — fixed-length 2- and 3-node `CALLS` cycles (mutual recursion / tight coupling).
@@ -17590,7 +17568,7 @@ Output: `{cycles[[a,b],[a,b,c]], source}` — fixed-length 2- and 3-node `CALLS`
17590
17568
  Query the engine's architecture view live with the `graph-arch.sh` wrapper (it resolves the engine, indexes on demand, and auto-resolves the project):
17591
17569
 
17592
17570
  ```bash
17593
- scripts/tools/graph-arch.sh --repo . \
17571
+ "$DRAFT_TOOLS/graph-arch.sh" --repo . \
17594
17572
  | jq '{packages, node_labels, edge_types, routes, layers, boundaries}'
17595
17573
  ```
17596
17574
 
@@ -17599,8 +17577,8 @@ scripts/tools/graph-arch.sh --repo . \
17599
17577
  ### Mermaid — diagram text
17600
17578
 
17601
17579
  ```bash
17602
- scripts/tools/mermaid-from-graph.sh --repo . --diagram module-deps # co-change coupling
17603
- scripts/tools/mermaid-from-graph.sh --repo . --diagram proto-map # detected routes
17580
+ "$DRAFT_TOOLS/mermaid-from-graph.sh" --repo . --diagram module-deps # co-change coupling
17581
+ "$DRAFT_TOOLS/mermaid-from-graph.sh" --repo . --diagram proto-map # detected routes
17604
17582
  ```
17605
17583
 
17606
17584
  Emits a ready-to-inject ` ```mermaid ``` ` block on the fly (computed live by the engine), or an empty stub (exit 2) when the engine is unavailable. Diagrams are generated at the moment of use — they are never committed.
@@ -17608,7 +17586,7 @@ Emits a ready-to-inject ` ```mermaid ``` ` block on the fly (computed live by th
17608
17586
  ### Snippet — verified source + caller/callee counts
17609
17587
 
17610
17588
  ```bash
17611
- scripts/tools/graph-snippet.sh --repo . --qualified <pkg.Mod.Class.method>
17589
+ "$DRAFT_TOOLS/graph-snippet.sh" --repo . --qualified <pkg.Mod.Class.method>
17612
17590
  ```
17613
17591
 
17614
17592
  Output: `{qualified_name, file, start_line, end_line, callers, callees, transitive_loop_depth, complexity, code, status, source}`. Prefer this over grep+Read when you have a qualified name — it returns the engine's attributed source plus pre-computed counts.
@@ -17616,7 +17594,7 @@ Output: `{qualified_name, file, start_line, end_line, callers, callees, transiti
17616
17594
  ### Search — semantic / ranked symbol lookup
17617
17595
 
17618
17596
  ```bash
17619
- scripts/tools/graph-search.sh --repo . --query "auth token refresh" [--limit N]
17597
+ "$DRAFT_TOOLS/graph-search.sh" --repo . --query "auth token refresh" [--limit N]
17620
17598
  ```
17621
17599
 
17622
17600
  Output: `{query, results[{name, qualified_name, label, file, rank}], total, source}`. Use when the user names an **intent/concept** rather than an exact symbol — this is the first move in the Concept-to-Files recipe.
@@ -17624,8 +17602,8 @@ Output: `{query, results[{name, qualified_name, label, file, rank}], total, sour
17624
17602
  ### Tests — coverage edges and untested surface
17625
17603
 
17626
17604
  ```bash
17627
- scripts/tools/graph-tests.sh --repo . --symbol <name> # tests covering a symbol
17628
- scripts/tools/graph-tests.sh --repo . --untested # exported symbols with no TESTS edge
17605
+ "$DRAFT_TOOLS/graph-tests.sh" --repo . --symbol <name> # tests covering a symbol
17606
+ "$DRAFT_TOOLS/graph-tests.sh" --repo . --untested # exported symbols with no TESTS edge
17629
17607
  ```
17630
17608
 
17631
17609
  Output: `{symbol, tests[{test,file}], status, source}` or `{untested[{symbol,file}], total, truncated, source}`. Feeds coverage gaps for `init`/`testing-strategy`/`coverage`.
@@ -17633,7 +17611,7 @@ Output: `{symbol, tests[{test,file}], status, source}` or `{untested[{symbol,fil
17633
17611
  ### Deps — real module/file import graph
17634
17612
 
17635
17613
  ```bash
17636
- scripts/tools/graph-deps.sh --repo . [--file PATH]
17614
+ "$DRAFT_TOOLS/graph-deps.sh" --repo . [--file PATH]
17637
17615
  ```
17638
17616
 
17639
17617
  Output: `{imports[{src,dst}], total, truncated, source}` from actual `IMPORTS` edges (self-imports filtered). This is the auto-derived dependency graph behind `mermaid-from-graph.sh --diagram module-deps` and `architecture.md §9`.
@@ -17641,7 +17619,7 @@ Output: `{imports[{src,dst}], total, truncated, source}` from actual `IMPORTS` e
17641
17619
  ### Hierarchy — class inheritance
17642
17620
 
17643
17621
  ```bash
17644
- scripts/tools/graph-hierarchy.sh --repo . [--symbol <Class> | --derived <Base>]
17622
+ "$DRAFT_TOOLS/graph-hierarchy.sh" --repo . [--symbol <Class> | --derived <Base>]
17645
17623
  ```
17646
17624
 
17647
17625
  Output: `{edges[{child,parent}], status, source}`. `--derived` gives the blast radius of changing a base class.
@@ -17649,8 +17627,8 @@ Output: `{edges[{child,parent}], status, source}`. `--derived` gives the blast r
17649
17627
  ### Errors — error-propagation paths
17650
17628
 
17651
17629
  ```bash
17652
- scripts/tools/graph-errors.sh --repo . --symbol <name> # what it raises/throws
17653
- scripts/tools/graph-errors.sh --repo . --type <ErrType> # who raises/throws that type
17630
+ "$DRAFT_TOOLS/graph-errors.sh" --repo . --symbol <name> # what it raises/throws
17631
+ "$DRAFT_TOOLS/graph-errors.sh" --repo . --type <ErrType> # who raises/throws that type
17654
17632
  ```
17655
17633
 
17656
17634
  Output: `{symbol, raises[...], status, source}` or `{type, raisers[...], status, source}`. `--type` drives fail-closed audits.
@@ -17658,7 +17636,7 @@ Output: `{symbol, raises[...], status, source}` or `{type, raisers[...], status,
17658
17636
  ### Risk — pre-computed risk hotspots
17659
17637
 
17660
17638
  ```bash
17661
- scripts/tools/graph-risk.sh --repo . [--min-complexity N]
17639
+ "$DRAFT_TOOLS/graph-risk.sh" --repo . [--min-complexity N]
17662
17640
  ```
17663
17641
 
17664
17642
  Output: `{risky[{symbol, file, complexity, flags}], total, truncated, source}` from the engine's pre-computed flags (`unguarded_recursion`, `recursion_in_loop`, `alloc_in_loop`, `linear_scan_in_loop`). High-signal input for `bughunt`/`deep-review` — the engine already found these.
@@ -17666,8 +17644,8 @@ Output: `{risky[{symbol, file, complexity, flags}], total, truncated, source}` f
17666
17644
  ### Generic — read-only escape hatch (all 20 edges / ~30 properties)
17667
17645
 
17668
17646
  ```bash
17669
- scripts/tools/graph-query.sh --repo . --cypher 'MATCH (f)-[:WRITES]->(v) RETURN f.name, v.name LIMIT 50'
17670
- scripts/tools/graph-query.sh --repo . --tool get_graph_schema --json '{}'
17647
+ "$DRAFT_TOOLS/graph-query.sh" --repo . --cypher 'MATCH (f)-[:WRITES]->(v) RETURN f.name, v.name LIMIT 50'
17648
+ "$DRAFT_TOOLS/graph-query.sh" --repo . --tool get_graph_schema --json '{}'
17671
17649
  ```
17672
17650
 
17673
17651
  Unlocks any edge type or node property without a purpose-built wrapper. Write verbs are rejected; stay inside the SAFE dialect set (above). Emits raw engine JSON.
@@ -17675,7 +17653,7 @@ Unlocks any edge type or node property without a purpose-built wrapper. Write ve
17675
17653
  ### Indexing / refreshing the gate marker
17676
17654
 
17677
17655
  ```bash
17678
- scripts/tools/graph-snapshot.sh --repo .
17656
+ "$DRAFT_TOOLS/graph-snapshot.sh" --repo .
17679
17657
  ```
17680
17658
 
17681
17659
  Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker (now including the `detect_changes` delta: `changed_files`/`impacted_symbols`). It writes **no** graph data. Run during `draft init` and `draft graph`, or whenever the index should be refreshed.
@@ -17694,7 +17672,7 @@ The engine is the `codebase-memory-mcp` binary. Resolution order (implemented by
17694
17672
  The canonical verifier is `scripts/tools/verify-graph-binary.sh` (`--json --verbose --strict`). It resolves and liveness-checks the engine and, in a `draft/` context, writes the usage-report side-effect:
17695
17673
 
17696
17674
  ```bash
17697
- ENGINE_INFO="$(scripts/tools/verify-graph-binary.sh --repo . --json 2>/dev/null || true)"
17675
+ ENGINE_INFO="$("$DRAFT_TOOLS/verify-graph-binary.sh" --repo . --json 2>/dev/null || true)"
17698
17676
  # {"status":"ok","engine_bin":"...","source":"managed|path|bundled:<arch>|override","arch":"..."}
17699
17677
  ```
17700
17678
 
@@ -17707,7 +17685,7 @@ After successful detection, `draft/.graph-binary-report.json` contains: `detecte
17707
17685
  Run during `draft:init` / `draft:graph`, or manually:
17708
17686
 
17709
17687
  ```bash
17710
- scripts/tools/graph-snapshot.sh --repo .
17688
+ "$DRAFT_TOOLS/graph-snapshot.sh" --repo .
17711
17689
  ```
17712
17690
 
17713
17691
  The engine indexes C/C++, Go, Python, TypeScript/JS, and more (tree-sitter, 159 languages) plus LSP-assisted resolution for the major ones, and detects HTTP/gRPC/GraphQL routes. Indexing is incremental in the engine (content-based, git-aware). This refreshes the engine index and rewrites the `schema.yaml` gate marker; it produces no committed graph data.
@@ -18546,7 +18524,7 @@ project**, not the plugin. The helpers live inside the plugin install directory,
18546
18524
  which on a marketplace/npm install is `~/.claude/plugins/cache/<marketplace>/draft/<version>/`
18547
18525
  — never the cwd. `${CLAUDE_PLUGIN_ROOT}` is **not** exported into skill-driven Bash
18548
18526
  (it is only set for hooks, MCP/LSP servers, and monitor commands), so a bare
18549
- `scripts/tools/foo.sh` or `${CLAUDE_PLUGIN_ROOT}/...` invocation silently fails.
18527
+ `scripts/tools/git-metadata.sh` or `${CLAUDE_PLUGIN_ROOT}/...` invocation silently fails.
18550
18528
 
18551
18529
  Every skill MUST resolve `DRAFT_TOOLS` and invoke helpers as `"$DRAFT_TOOLS/<tool>.sh"`.
18552
18530
 
@@ -18555,16 +18533,20 @@ Every skill MUST resolve `DRAFT_TOOLS` and invoke helpers as `"$DRAFT_TOOLS/<too
18555
18533
  `DRAFT_TOOLS` resolves to the first directory that exists, in this order:
18556
18534
 
18557
18535
  1. `${DRAFT_PLUGIN_ROOT}/scripts/tools` — explicit override (testing / pinned installs)
18558
- 2. `$(cat ~/.cache/draft/plugin-root)/scripts/tools` — install marker written by `draft install` (authoritative)
18559
- 3. `${CLAUDE_PLUGIN_ROOT}/scripts/tools` set in hook/MCP contexts; harmless to probe
18560
- 4. `installed_plugins.json installPath` for `draft@*` Claude Code's own registry (needs `jq`)
18561
- 5. `~/.claude/plugins/cache/*/draft/*/scripts/tools` — newest cache install (glob, `sort -V`)
18562
- 6. `~/.claude/plugins/marketplaces/*draft*/scripts/tools` — marketplace clone
18563
- 7. `~/.cursor/plugins/local/draft/scripts/tools` — Cursor local install
18564
- 8. `$PWD/scripts/tools` — dev / dogfooding (running inside the draft repo itself)
18565
-
18566
- The marker (step 2) is the fast, authoritative path; steps 5–6 are the glob fallback
18567
- that keeps resolution working on installs predating the marker (no reinstall required).
18536
+ 2. `$PWD/scripts/tools` — dev / dogfooding when cwd IS the draft repo (guarded by
18537
+ `resolve-tools.sh`'s own presence, so it can never misfire in a user project;
18538
+ deliberately beats the install marker so a repo checkout always wins)
18539
+ 3. `$(cat ~/.cache/draft/plugin-root)/scripts/tools` — install marker written by `draft install` (authoritative for installs)
18540
+ 4. `${CLAUDE_PLUGIN_ROOT}/scripts/tools` — set in hook/MCP contexts; harmless to probe
18541
+ 5. `installed_plugins.json → installPath` for `draft@*` Claude Code's own registry (needs `jq`)
18542
+ 6. `~/.claude/plugins/cache/*/draft/*/scripts/tools` — newest cache install (glob, `sort -V`)
18543
+ 7. `~/.claude/plugins/marketplaces/*draft*/scripts/tools` — marketplace clone
18544
+ 8. `~/.cursor/plugins/local/draft/scripts/tools` Cursor local install
18545
+ 9. `$PWD/scripts/tools` last-resort cwd fallback (unguarded)
18546
+
18547
+ The marker (step 3) is the fast, authoritative path for installs; steps 6–7 are the
18548
+ glob fallback that keeps resolution working on installs predating the marker (no
18549
+ reinstall required).
18568
18550
 
18569
18551
  ## Skill preamble (copy verbatim)
18570
18552
 
@@ -18575,7 +18557,7 @@ invocations (only the cwd does), so if you split helper calls into a later, sepa
18575
18557
  Bash block, re-establish `DRAFT_TOOLS` there too:
18576
18558
 
18577
18559
  ```bash
18578
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
18560
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
18579
18561
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
18580
18562
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
18581
18563
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -18589,9 +18571,10 @@ Then invoke helpers through the variable:
18589
18571
  ```
18590
18572
 
18591
18573
  The four-line inline preamble is self-contained and is the recommended form for
18592
- skills — it needs no marker file and no prior `source`. The full 8-step resolver
18593
- (adding the `${DRAFT_PLUGIN_ROOT}` override, `${CLAUDE_PLUGIN_ROOT}`, the jq-registry
18594
- lookup, and the Cursor path) is shipped as `scripts/tools/resolve-tools.sh` for tests
18574
+ skills — it needs no marker file and no prior `source`. The full resolver
18575
+ (adding the `${DRAFT_PLUGIN_ROOT}` override, the guarded dogfood short-circuit,
18576
+ `${CLAUDE_PLUGIN_ROOT}`, the jq-registry lookup, and the Cursor path) is shipped
18577
+ as `scripts/tools/resolve-tools.sh` for tests
18595
18578
  and for callers that prefer a single source of truth:
18596
18579
 
18597
18580
  ```bash
@@ -19775,326 +19758,6 @@ This is the single forward-looking source of truth. Legacy 28-section volume-ori
19775
19758
 
19776
19759
  ---
19777
19760
 
19778
- ## core/templates/track-architecture.md
19779
-
19780
- <core-file path="core/templates/track-architecture.md">
19781
-
19782
- ---
19783
- project: "{PROJECT_NAME}"
19784
- module: "root"
19785
- track_id: "{TRACK_ID}"
19786
- generated_by: "draft:decompose"
19787
- generated_at: "{ISO_TIMESTAMP}"
19788
- git:
19789
- branch: "{LOCAL_BRANCH}"
19790
- remote: "{REMOTE/BRANCH}"
19791
- commit: "{FULL_SHA}"
19792
- commit_short: "{SHORT_SHA}"
19793
- commit_date: "{COMMIT_DATE}"
19794
- commit_message: "{COMMIT_MESSAGE}"
19795
- dirty: false
19796
- synced_to_commit: "{FULL_SHA}"
19797
- ---
19798
-
19799
- # Track Architecture: {TRACK_TITLE}
19800
-
19801
- > Track-scoped HLD/LLD for a single feature, bug fix, or refactor.
19802
- > Source of truth for implementation — `draft implement` consumes this to guide build order, contracts, and story generation.
19803
- > For project-wide architecture, see `draft/architecture.md`.
19804
-
19805
- | Field | Value |
19806
- |-------|-------|
19807
- | **Track ID** | `{TRACK_ID}` |
19808
- | **Spec** | `./spec.md` |
19809
- | **Plan** | `./plan.md` |
19810
- | **Branch** | `{LOCAL_BRANCH}` → `{REMOTE/BRANCH}` |
19811
- | **Commit** | `{SHORT_SHA}` — {COMMIT_MESSAGE} |
19812
- | **Generated** | {ISO_TIMESTAMP} |
19813
- | **LLD Included** | {true | false} |
19814
-
19815
- ---
19816
-
19817
- ## Table of Contents
19818
-
19819
- 1. [Overview](#1-overview)
19820
- 2. [Module Breakdown](#2-module-breakdown)
19821
- 3. [High-Level Design (HLD)](#3-high-level-design-hld)
19822
- - 3.1 Component Diagram
19823
- - 3.2 Data Flow
19824
- - 3.3 Sequence Diagrams (Critical Flows)
19825
- - 3.4 State Machine(s)
19826
- 4. [Dependency Analysis](#4-dependency-analysis)
19827
- 5. [Implementation Order](#5-implementation-order)
19828
- 6. [Low-Level Design (LLD)](#6-low-level-design-lld)
19829
- - 6.1 Per-Module API Contracts
19830
- - 6.2 Data Models & Schemas
19831
- - 6.3 Error Handling & Retry Semantics
19832
- - 6.4 Algorithm Pseudocode (where non-trivial)
19833
- 7. [Notes & Decisions](#7-notes--decisions)
19834
-
19835
- ---
19836
-
19837
- ## 1. Overview
19838
-
19839
- **What this track delivers:** {one paragraph from spec.md — the feature, bug fix, or refactor being scoped}
19840
-
19841
- **Inputs:** {what triggers or feeds into this feature}
19842
- **Outputs:** {what this feature produces — data, side effects, API responses}
19843
- **Constraints:** {latency, throughput, compatibility, security — anything from spec.md Non-Functional Requirements}
19844
-
19845
- **Integration points:** {which existing modules from `draft/.ai-context.md` this track touches}
19846
-
19847
- ---
19848
-
19849
- ## 2. Module Breakdown
19850
-
19851
- ### Modules Introduced or Modified
19852
-
19853
- For each module in scope, fill out one block:
19854
-
19855
- #### Module: `{module-name}`
19856
-
19857
- - **Status:** `[ ] New` | `[ ] Modified` | `[x] Existing (unchanged)`
19858
- - **Responsibility:** {one sentence — what this module owns}
19859
- - **Files:** `{path/to/file1}`, `{path/to/file2}`
19860
- - **API Surface:** {public functions, classes, or interfaces — names only, contracts in §6.1}
19861
- - **Dependencies:** {other modules this imports from}
19862
- - **Complexity:** `Low` | `Medium` | `High`
19863
- - **Story placeholder:** _populated by `draft implement`_
19864
-
19865
- {Repeat for each module.}
19866
-
19867
- ---
19868
-
19869
- ## 3. High-Level Design (HLD)
19870
-
19871
- ### 3.1 Component Diagram
19872
-
19873
- Shows modules in scope + the external collaborators they talk to.
19874
-
19875
- ```mermaid
19876
- flowchart TD
19877
- subgraph Track["Track: {TRACK_ID}"]
19878
- M1["{module-1}"]
19879
- M2["{module-2}"]
19880
- M3["{module-3}"]
19881
- end
19882
- subgraph Existing["Existing System"]
19883
- E1["{existing-module-A}"]
19884
- E2["{existing-module-B}"]
19885
- end
19886
- subgraph External["External"]
19887
- X1["{DB / queue / API}"]
19888
- end
19889
-
19890
- M1 --> M2
19891
- M2 --> M3
19892
- M1 --> E1
19893
- M3 --> X1
19894
- ```
19895
-
19896
- > Draw one node per module in scope. Include existing modules only when this track calls into them. Label edges with the transport (HTTP, RPC, queue, direct call) when non-obvious.
19897
-
19898
- ### 3.2 Data Flow
19899
-
19900
- End-to-end flow of data through the track's modules.
19901
-
19902
- ```mermaid
19903
- flowchart LR
19904
- In["{input — request / event}"] --> V["{validation}"]
19905
- V --> L["{business logic}"]
19906
- L --> P["{persistence}"]
19907
- P --> Out["{output — response / emitted event}"]
19908
- ```
19909
-
19910
- > Replace with the actual transforms. If the track has distinct read and write paths, draw them separately.
19911
-
19912
- ### 3.3 Sequence Diagrams — Critical Flows
19913
-
19914
- One sequence per acceptance criterion that involves more than a single module call. Skip for trivial single-module tracks.
19915
-
19916
- #### Flow: {name — e.g., "Happy path: user submits X"}
19917
-
19918
- ```mermaid
19919
- sequenceDiagram
19920
- participant U as {Caller}
19921
- participant A as {module-1}
19922
- participant B as {module-2}
19923
- participant D as {DB / external}
19924
-
19925
- U->>A: {request payload}
19926
- A->>B: {internal call}
19927
- B->>D: {query / write}
19928
- D-->>B: {result}
19929
- B-->>A: {response}
19930
- A-->>U: {final response}
19931
-
19932
- Note over A,B: {invariant / gate — e.g., "tx must be open here"}
19933
- ```
19934
-
19935
- #### Flow: {error path — e.g., "Dependency timeout"}
19936
-
19937
- ```mermaid
19938
- sequenceDiagram
19939
- participant U as {Caller}
19940
- participant A as {module-1}
19941
- participant D as {External}
19942
-
19943
- U->>A: {request}
19944
- A->>D: {call with timeout={N}ms}
19945
- D--xA: {timeout}
19946
- A->>A: {fallback / circuit breaker}
19947
- A-->>U: {degraded response or error}
19948
- ```
19949
-
19950
- ### 3.4 State Machine(s)
19951
-
19952
- Include only if the track introduces or modifies stateful entities. Omit otherwise.
19953
-
19954
- ```mermaid
19955
- stateDiagram-v2
19956
- [*] --> Pending
19957
- Pending --> Processing: start
19958
- Processing --> Complete: success
19959
- Processing --> Failed: error
19960
- Failed --> Pending: retry (max {N})
19961
- Failed --> DeadLetter: retries exhausted
19962
- Complete --> [*]
19963
- ```
19964
-
19965
- ---
19966
-
19967
- ## 4. Dependency Analysis
19968
-
19969
- ### ASCII Dependency Graph
19970
-
19971
- ```
19972
- [module-1] ──> [module-2]
19973
- │ │
19974
- └──> [module-3] <──┘
19975
- ```
19976
-
19977
- ### Dependency Table
19978
-
19979
- | Module | Depends On | Depended By | Cycle? |
19980
- |--------|------------|-------------|--------|
19981
- | `{mod}` | `{list}` | `{list}` | no |
19982
-
19983
- ### Cycle Mitigation
19984
-
19985
- _If any cycles detected, describe how they are broken (shared interface extraction, dependency inversion, etc.). Otherwise: "No cycles detected."_
19986
-
19987
- ---
19988
-
19989
- ## 5. Implementation Order
19990
-
19991
- Topological sort — leaves first.
19992
-
19993
- 1. `{module-A}` (no internal deps) — foundational
19994
- 2. `{module-B}` (depends on: A)
19995
- 3. `{module-C}` (depends on: A, B)
19996
-
19997
- **Parallel opportunities:** {which modules can be built concurrently}
19998
-
19999
- ---
20000
-
20001
- ## 6. Low-Level Design (LLD)
20002
-
20003
- > Present when `--lld` flag was passed to `draft decompose` OR any module in §2 has `Complexity: High`. Otherwise this section reads: _"LLD not generated. Run `draft decompose --lld` to expand."_
20004
-
20005
- ### 6.1 Per-Module API Contracts
20006
-
20007
- For each module in §2 marked `New` or `Modified`:
20008
-
20009
- #### `{module-name}` — Public API
20010
-
20011
- | Function / Method | Signature | Params | Returns | Errors / Exceptions |
20012
- |-------------------|-----------|--------|---------|---------------------|
20013
- | `{name}` | `{lang-appropriate signature}` | `{param: type — constraint}` | `{type — shape}` | `{error types / codes}` |
20014
-
20015
- **Preconditions:** {what must be true before call — caller responsibilities}
20016
- **Postconditions:** {what is guaranteed after successful call}
20017
- **Invariants:** {properties preserved across calls — thread safety, idempotency, ordering}
20018
-
20019
- {Repeat per module.}
20020
-
20021
- ### 6.2 Data Models & Schemas
20022
-
20023
- Concrete shapes for every new or modified entity this track introduces.
20024
-
20025
- #### `{ModelName}`
20026
-
20027
- ```{language}
20028
- {actual type definition — struct, class, interface, proto message, TypedDict, etc.}
20029
- ```
20030
-
20031
- | Field | Type | Nullable | Default | Validation / Constraint |
20032
- |-------|------|----------|---------|-------------------------|
20033
- | `{field}` | `{type}` | yes/no | `{default or —}` | `{rule}` |
20034
-
20035
- **Storage:** {where persisted — table, collection, key prefix}
20036
- **Indexes / Keys:** {primary key, unique constraints, indexed fields}
20037
- **Migration:** {if this is a schema change — migration path and rollback}
20038
-
20039
- {Repeat per model.}
20040
-
20041
- ### 6.3 Error Handling & Retry Semantics
20042
-
20043
- Per-operation policy. One row per operation that has non-trivial error handling.
20044
-
20045
- | Operation | Error Class | Classification | Retry? | Backoff | Max Attempts | Fallback |
20046
- |-----------|-------------|----------------|--------|---------|--------------|----------|
20047
- | `{op}` | `{ErrorType}` | transient / permanent / timeout | yes/no | `{policy}` | `{N}` | `{behavior}` |
20048
-
20049
- **Propagation model:** {how errors surface — Result type, exceptions, error codes}
20050
- **Circuit breaker:** {thresholds, half-open policy, reset} — omit if N/A
20051
- **Idempotency:** {which operations are idempotent and how — dedup key, tx id}
20052
-
20053
- ### 6.4 Algorithm Pseudocode
20054
-
20055
- Include only for non-trivial logic. Skip for straightforward CRUD.
20056
-
20057
- #### {Algorithm name}
20058
-
20059
- **Inputs:** `{...}`
20060
- **Outputs:** `{...}`
20061
- **Complexity:** `O({...})` time, `O({...})` space
20062
-
20063
- ```
20064
- {numbered or indented pseudocode — language-agnostic}
20065
- 1. validate inputs
20066
- 2. ...
20067
- 3. return result
20068
- ```
20069
-
20070
- **Edge cases handled:**
20071
- - {case 1 — what happens}
20072
- - {case 2 — what happens}
20073
-
20074
- ---
20075
-
20076
- ## 7. Notes & Decisions
20077
-
20078
- ### Architecture Decisions
20079
-
20080
- - {decision 1 — rationale, alternatives considered}
20081
- - {decision 2 — rationale, alternatives considered}
20082
-
20083
- ### Open Questions
20084
-
20085
- - {question tracked during decomposition — to resolve before or during implementation}
20086
-
20087
- ### Links
20088
-
20089
- - Spec: `./spec.md`
20090
- - Plan: `./plan.md`
20091
- - Related ADRs: `{paths if any, created via draft adr}`
20092
- - Project architecture: `draft/.ai-context.md` → `draft/architecture.md`
20093
-
20094
- </core-file>
20095
-
20096
- ---
20097
-
20098
19761
  ## core/templates/jira.md
20099
19762
 
20100
19763
  <core-file path="core/templates/jira.md">
@@ -21011,7 +20674,7 @@ validator chain via the canonical resolver pattern (see
21011
20674
  [core/shared/verification-gates.md](../../core/shared/verification-gates.md)):
21012
20675
 
21013
20676
  ```bash
21014
- DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
20677
+ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}/scripts/tools"
21015
20678
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
21016
20679
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
21017
20680
  [ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
@@ -22653,19 +22316,15 @@ List down alerting thresholds on those metrics:
22653
22316
  <core-file path="core/templates/okf/index.md">
22654
22317
 
22655
22318
  ---
22656
- type: Subsystem
22657
- title: "{PROJECT_NAME} — Wiki"
22658
- description: >
22659
- Root index of the project wiki. Start here, then route into
22660
- overview/, systems/, features/, reference/, or entrypoints/ via the
22661
- Concept Map. Open a concept only when its description matches the task.
22662
- resource: .
22663
- tags: [index]
22664
- timestamp: "{ISO_TIMESTAMP}"
22665
22319
  okf_version: "0.1"
22666
- okf_types_version: "0.1"
22667
22320
  ---
22668
22321
 
22322
+ <!-- OKF §6/§11: an index file carries NO concept frontmatter; the root index.md
22323
+ may declare ONLY `okf_version`. The frozen concept-`type` vocabulary version
22324
+ is tracked here in the body (not in frontmatter) so bumping it stays visible
22325
+ without violating the index-frontmatter rule.
22326
+ okf-types-version: 0.1 -->
22327
+
22669
22328
  # {PROJECT_NAME} — Wiki
22670
22329
 
22671
22330
  > Project wiki. One concept per file; cross-links form the graph. The
@@ -22773,17 +22432,8 @@ Entrypoint) require ≥1 valid Mermaid block and ≥2 x-grounded-paths.
22773
22432
 
22774
22433
  <core-file path="core/templates/okf/section-index.md">
22775
22434
 
22776
- ---
22777
- type: Subsystem
22778
- title: "{SECTION_TITLE}"
22779
- description: >
22780
- Section index. Lists every concept in this section with its one-line
22781
- routing description so an agent can pick the right page without opening
22782
- each one. {SECTION_PURPOSE}
22783
- resource: .
22784
- tags: [index]
22785
- timestamp: "{ISO_TIMESTAMP}"
22786
- ---
22435
+ <!-- OKF §6: an index file contains NO frontmatter. This page is a reserved
22436
+ navigation index, not a concept — its Concepts table is tool-generated. -->
22787
22437
 
22788
22438
  # {SECTION_TITLE}
22789
22439