@hegemonart/get-design-done 1.41.5 → 1.42.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 (120) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +49 -0
  4. package/README.md +2 -0
  5. package/dist/claude-code/.claude/skills/add-backlog/SKILL.md +48 -0
  6. package/dist/claude-code/.claude/skills/analyze-dependencies/SKILL.md +95 -0
  7. package/dist/claude-code/.claude/skills/apply-reflections/SKILL.md +92 -0
  8. package/dist/claude-code/.claude/skills/apply-reflections/apply-reflections-procedure.md +170 -0
  9. package/dist/claude-code/.claude/skills/audit/SKILL.md +79 -0
  10. package/dist/claude-code/.claude/skills/bandit-status/SKILL.md +94 -0
  11. package/dist/claude-code/.claude/skills/benchmark/SKILL.md +65 -0
  12. package/dist/claude-code/.claude/skills/bootstrap-ds/SKILL.md +43 -0
  13. package/dist/claude-code/.claude/skills/brief/SKILL.md +128 -0
  14. package/dist/claude-code/.claude/skills/budget/SKILL.md +45 -0
  15. package/dist/claude-code/.claude/skills/cache-manager/SKILL.md +66 -0
  16. package/dist/claude-code/.claude/skills/cache-manager/cache-policy.md +126 -0
  17. package/dist/claude-code/.claude/skills/check-update/SKILL.md +98 -0
  18. package/dist/claude-code/.claude/skills/compare/SKILL.md +82 -0
  19. package/dist/claude-code/.claude/skills/compare/compare-rubric.md +171 -0
  20. package/dist/claude-code/.claude/skills/complete-cycle/SKILL.md +81 -0
  21. package/dist/claude-code/.claude/skills/connections/SKILL.md +71 -0
  22. package/dist/claude-code/.claude/skills/connections/connections-onboarding.md +608 -0
  23. package/dist/claude-code/.claude/skills/continue/SKILL.md +24 -0
  24. package/dist/claude-code/.claude/skills/darkmode/SKILL.md +76 -0
  25. package/dist/claude-code/.claude/skills/darkmode/darkmode-audit-procedure.md +258 -0
  26. package/dist/claude-code/.claude/skills/debug/SKILL.md +41 -0
  27. package/dist/claude-code/.claude/skills/debug/debug-feedback-loops.md +119 -0
  28. package/dist/claude-code/.claude/skills/design/SKILL.md +99 -0
  29. package/dist/claude-code/.claude/skills/design/design-procedure.md +304 -0
  30. package/dist/claude-code/.claude/skills/discover/SKILL.md +72 -0
  31. package/dist/claude-code/.claude/skills/discover/discover-procedure.md +222 -0
  32. package/dist/claude-code/.claude/skills/discuss/SKILL.md +96 -0
  33. package/dist/claude-code/.claude/skills/do/SKILL.md +45 -0
  34. package/dist/claude-code/.claude/skills/explore/SKILL.md +105 -0
  35. package/dist/claude-code/.claude/skills/explore/explore-procedure.md +267 -0
  36. package/dist/claude-code/.claude/skills/export/SKILL.md +30 -0
  37. package/dist/claude-code/.claude/skills/extract-learnings/SKILL.md +98 -0
  38. package/dist/claude-code/.claude/skills/fast/SKILL.md +91 -0
  39. package/dist/claude-code/.claude/skills/figma-extract/SKILL.md +64 -0
  40. package/dist/claude-code/.claude/skills/figma-write/SKILL.md +39 -0
  41. package/dist/claude-code/.claude/skills/graphify/SKILL.md +49 -0
  42. package/dist/claude-code/.claude/skills/health/SKILL.md +99 -0
  43. package/dist/claude-code/.claude/skills/health/health-mcp-detection.md +44 -0
  44. package/dist/claude-code/.claude/skills/health/health-skill-length-report.md +69 -0
  45. package/dist/claude-code/.claude/skills/help/SKILL.md +87 -0
  46. package/dist/claude-code/.claude/skills/list-assumptions/SKILL.md +61 -0
  47. package/dist/claude-code/.claude/skills/locale/SKILL.md +51 -0
  48. package/dist/claude-code/.claude/skills/map/SKILL.md +89 -0
  49. package/dist/claude-code/.claude/skills/migrate/SKILL.md +70 -0
  50. package/dist/claude-code/.claude/skills/new-cycle/SKILL.md +37 -0
  51. package/dist/claude-code/.claude/skills/new-cycle/milestone-completeness-rubric.md +87 -0
  52. package/dist/claude-code/.claude/skills/new-project/SKILL.md +53 -0
  53. package/dist/claude-code/.claude/skills/next/SKILL.md +68 -0
  54. package/dist/claude-code/.claude/skills/note/SKILL.md +48 -0
  55. package/dist/claude-code/.claude/skills/openrouter-status/SKILL.md +86 -0
  56. package/dist/claude-code/.claude/skills/optimize/SKILL.md +97 -0
  57. package/dist/claude-code/.claude/skills/pause/SKILL.md +77 -0
  58. package/dist/claude-code/.claude/skills/peer-cli-add/SKILL.md +88 -0
  59. package/dist/claude-code/.claude/skills/peer-cli-add/peer-cli-protocol.md +161 -0
  60. package/dist/claude-code/.claude/skills/peer-cli-customize/SKILL.md +90 -0
  61. package/dist/claude-code/.claude/skills/peers/SKILL.md +96 -0
  62. package/dist/claude-code/.claude/skills/plan/SKILL.md +105 -0
  63. package/dist/claude-code/.claude/skills/plan/plan-procedure.md +278 -0
  64. package/dist/claude-code/.claude/skills/plant-seed/SKILL.md +48 -0
  65. package/dist/claude-code/.claude/skills/pr-branch/SKILL.md +32 -0
  66. package/dist/claude-code/.claude/skills/progress/SKILL.md +95 -0
  67. package/dist/claude-code/.claude/skills/quality-gate/SKILL.md +90 -0
  68. package/dist/claude-code/.claude/skills/quality-gate/threat-modeling.md +101 -0
  69. package/dist/claude-code/.claude/skills/quick/SKILL.md +44 -0
  70. package/dist/claude-code/.claude/skills/reapply-patches/SKILL.md +32 -0
  71. package/dist/claude-code/.claude/skills/recall/SKILL.md +75 -0
  72. package/dist/claude-code/.claude/skills/reflect/SKILL.md +85 -0
  73. package/dist/claude-code/.claude/skills/reflect/procedures/capability-gap-scan.md +120 -0
  74. package/dist/claude-code/.claude/skills/report-issue/SKILL.md +53 -0
  75. package/dist/claude-code/.claude/skills/report-issue/report-issue-procedure.md +120 -0
  76. package/dist/claude-code/.claude/skills/resume/SKILL.md +93 -0
  77. package/dist/claude-code/.claude/skills/review-backlog/SKILL.md +46 -0
  78. package/dist/claude-code/.claude/skills/review-decisions/SKILL.md +42 -0
  79. package/dist/claude-code/.claude/skills/roi/SKILL.md +54 -0
  80. package/dist/claude-code/.claude/skills/rollout-status/SKILL.md +35 -0
  81. package/dist/claude-code/.claude/skills/router/SKILL.md +89 -0
  82. package/dist/claude-code/.claude/skills/router/capability-gap-emitter.md +65 -0
  83. package/dist/claude-code/.claude/skills/router/router-pick-emitter.md +78 -0
  84. package/dist/claude-code/.claude/skills/router/router-rules.md +84 -0
  85. package/dist/claude-code/.claude/skills/scan/SKILL.md +92 -0
  86. package/dist/claude-code/.claude/skills/scan/scan-procedure.md +732 -0
  87. package/dist/claude-code/.claude/skills/settings/SKILL.md +87 -0
  88. package/dist/claude-code/.claude/skills/ship/SKILL.md +48 -0
  89. package/dist/claude-code/.claude/skills/sketch/SKILL.md +78 -0
  90. package/dist/claude-code/.claude/skills/sketch-wrap-up/SKILL.md +92 -0
  91. package/dist/claude-code/.claude/skills/skill-manifest/SKILL.md +79 -0
  92. package/dist/claude-code/.claude/skills/spike/SKILL.md +67 -0
  93. package/dist/claude-code/.claude/skills/spike-wrap-up/SKILL.md +86 -0
  94. package/dist/claude-code/.claude/skills/start/SKILL.md +67 -0
  95. package/dist/claude-code/.claude/skills/start/start-procedure.md +115 -0
  96. package/dist/claude-code/.claude/skills/stats/SKILL.md +51 -0
  97. package/dist/claude-code/.claude/skills/style/SKILL.md +71 -0
  98. package/dist/claude-code/.claude/skills/style/style-doc-procedure.md +150 -0
  99. package/dist/claude-code/.claude/skills/synthesize/SKILL.md +94 -0
  100. package/dist/claude-code/.claude/skills/timeline/SKILL.md +66 -0
  101. package/dist/claude-code/.claude/skills/todo/SKILL.md +64 -0
  102. package/dist/claude-code/.claude/skills/turn-closeout/SKILL.md +95 -0
  103. package/dist/claude-code/.claude/skills/undo/SKILL.md +31 -0
  104. package/dist/claude-code/.claude/skills/unlock-decision/SKILL.md +54 -0
  105. package/dist/claude-code/.claude/skills/update/SKILL.md +56 -0
  106. package/dist/claude-code/.claude/skills/using-gdd/SKILL.md +78 -0
  107. package/dist/claude-code/.claude/skills/verify/SKILL.md +113 -0
  108. package/dist/claude-code/.claude/skills/verify/verify-procedure.md +512 -0
  109. package/dist/claude-code/.claude/skills/warm-cache/SKILL.md +81 -0
  110. package/dist/claude-code/.claude/skills/watch-authorities/SKILL.md +82 -0
  111. package/dist/claude-code/.claude/skills/zoom-out/SKILL.md +26 -0
  112. package/package.json +4 -1
  113. package/reference/DEPRECATIONS.md +14 -0
  114. package/reference/registry.json +7 -0
  115. package/reference/skill-placeholders.md +71 -0
  116. package/scripts/lib/build/factory.cjs +62 -0
  117. package/scripts/lib/build/harness-configs.cjs +64 -0
  118. package/sdk/cli/commands/build.ts +106 -0
  119. package/sdk/cli/index.js +84 -2
  120. package/sdk/cli/index.ts +7 -0
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: gdd-watch-authorities
3
+ description: "Fetches the design-authority feed whitelist, diffs against .design/authority-snapshot.json, and writes .design/authority-report.md (consumed by /gdd:reflect). Authority monitoring only — no trend-watching."
4
+ argument-hint: "[--refresh] [--since <date>] [--feed <name>] [--schedule <weekly|daily|monthly>]"
5
+ tools: Read, Write, Task, Bash
6
+ ---
7
+
8
+ # /gdd:watch-authorities
9
+
10
+ Runs `design-authority-watcher` on demand. Fetches the curated design-authority feed whitelist, diffs against the prior snapshot, classifies new entries into five buckets, and writes `.design/authority-report.md`. Phase 11's reflector picks up the report automatically when you next run `/gdd:reflect`.
11
+
12
+ Authority-monitoring only. Not trend-watching. See `reference/authority-feeds.md` §"Rejected kinds" for what this skill will never fetch.
13
+
14
+ ## Steps
15
+
16
+ 1. **Parse args.** Extract optional flags: `--refresh`, `--since <date>`, `--feed <name>`, `--schedule <cadence>`. Anything that doesn't match one of these is an error — print `Unknown flag: <arg>. Valid flags: --refresh --since <date> --feed <name> --schedule <weekly|daily|monthly>.` and STOP.
17
+
18
+ Mutual exclusion rules:
19
+ - `--schedule` is handled entirely by this skill — it does not combine with the other three. If `--schedule` is present alongside any of `--refresh | --since | --feed`, print `--schedule cannot combine with other flags. Schedule registration runs this skill with no flags at the configured cadence.` and STOP.
20
+ - `--refresh` and `--since` are mutually exclusive — print `--refresh and --since are mutually exclusive. --refresh re-seeds the snapshot silently; --since surfaces a backlog from a boundary date. Pick one.` and STOP.
21
+
22
+ 2. **Handle `--schedule <cadence>` branch** (early-return).
23
+
24
+ If `--schedule` is set:
25
+ - Validate cadence ∈ {`weekly`, `daily`, `monthly`}; else print `Unknown cadence: <value>. Use one of: weekly, daily, monthly.` and STOP.
26
+ - Probe for the scheduled-tasks MCP via ToolSearch:
27
+
28
+ ```
29
+ ToolSearch({ query: "scheduled-tasks", max_results: 3 })
30
+ ```
31
+
32
+ - If the probe returns an empty result set: print `scheduled-tasks MCP not connected. Install it with: claude mcp add scheduled-tasks ... then retry with --schedule.` — this is a documented fallback (not an error). Terminate with `## WATCH COMPLETE` and exit 0.
33
+ - If the probe returns one or more `scheduled-tasks` tools: register the cron. Discover the MCP's registration tool name at runtime from the ToolSearch result and follow its schema. Target command: `/gdd:watch-authorities` with NO flags (the cron invokes the default diff-and-report behavior). Cadence → cron expression mapping:
34
+ - `weekly` → `0 9 * * 1` (Mondays 09:00 local)
35
+ - `daily` → `0 9 * * *` (every day 09:00 local)
36
+ - `monthly` → `0 9 1 * *` (1st of each month 09:00 local)
37
+ - After registration: print `Scheduled /gdd:watch-authorities to run <cadence>.` and terminate with `## WATCH COMPLETE`.
38
+
39
+ 3. **Validate `--since <date>`** (if present).
40
+
41
+ Accept ISO8601 (`YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SSZ`). Sanity-check via Bash `date -d "<value>" +%s` (GNU) or the POSIX equivalent `python3 -c "from datetime import datetime; datetime.fromisoformat('<value>'.replace('Z','+00:00'))"`. On parse failure: print `Invalid --since value: <value>. Use ISO8601 (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ).` and STOP.
42
+
43
+ If the parsed date is earlier than `2020-01-01`, ask: `Very old --since value: <value>. Did you mean something more recent? Proceed? [y/N]`. On anything other than `y`/`Y`, STOP.
44
+
45
+ 4. **Spawn the watcher.**
46
+
47
+ Build the `Task(subagent_type="design-authority-watcher", ...)` prompt. The prompt supplies the agent's required-reading block (watcher step 0), echoes the invocation flags verbatim (watcher Flags section), and instructs the agent to follow its own fetch/diff/classify/write loop:
48
+
49
+ ```
50
+ Task("design-authority-watcher", """
51
+ <required_reading>
52
+ @reference/authority-feeds.md
53
+ @.design/authority-snapshot.json
54
+ @.design/STATE.md
55
+ </required_reading>
56
+
57
+ Invocation flags: <joined flag list or "none">
58
+
59
+ Fetch the feeds listed in reference/authority-feeds.md, diff against .design/authority-snapshot.json,
60
+ classify new entries per the D-17 decision table, write .design/authority-snapshot.json and
61
+ .design/authority-report.md.
62
+
63
+ Terminate with ## WATCH COMPLETE.
64
+ """)
65
+ ```
66
+
67
+ `<joined flag list>` is the subset of `--refresh | --since <date> | --feed <name>` actually passed — e.g., `--refresh`, `--since 2026-03-01`, `--feed wai-aria-apg`, `--refresh --feed radix-ui-releases`, or literally `none` when no flags were supplied.
68
+
69
+ 5. **Print summary.**
70
+
71
+ After the agent returns:
72
+ - If STATE.md gained a `<blocker type="contract-violation">` on this run (snapshot version mismatch, hash-format violation, or over-200 entries per feed), surface the blocker verbatim and stop — do not print the default "review and reflect" line.
73
+ - Otherwise print the agent's one-line stdout summary (normal mode: `Surfaced N entries across M feeds. K skipped. See .design/authority-report.md.`; first-run / refresh mode: `Seeded snapshot for N feeds — next run will surface new entries.`) followed by: `Review and reflect: /gdd:reflect`.
74
+
75
+ 6. **Terminate with `## WATCH COMPLETE`.**
76
+
77
+ ## Do Not
78
+
79
+ - Do not modify `agents/design-authority-watcher.md`.
80
+ - Do not modify `agents/design-reflector.md` — Phase 13.2 does not touch the reflector agent (CONTEXT.md D-25).
81
+ - Do not write to `.design/authority-snapshot.json` or `.design/authority-report.md` directly — those are the agent's writes.
82
+ - Do not fetch URLs outside `reference/authority-feeds.md`. The whitelist is the allow-list.
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: zoom-out
3
+ description: "Asks the agent to go up a layer of abstraction and map the relevant modules and callers using the project's CONTEXT.md vocabulary. Use when the user is working in an unfamiliar area of code and needs orientation before deep work."
4
+ disable-model-invocation: true
5
+ argument-hint: "[scope]"
6
+ ---
7
+
8
+ Source: mattpocock/skills (MIT) — adapted with permission. See `../NOTICE` for the full attribution block.
9
+
10
+ # Zoom Out
11
+
12
+ **Role:** Give the user a map, not a fix.
13
+
14
+ I don't know this area of code well. Go up a layer of abstraction. Give me a map of all the relevant modules and callers, using the project's domain glossary (`CONTEXT.md`) vocabulary.
15
+
16
+ When invoked, produce a one-screen map that names:
17
+
18
+ 1. **Modules in scope** — one-line description of each, using terms from `CONTEXT.md` (see `./../reference/context-md-format.md` for the schema). Do not invent terms.
19
+ 2. **Callers** — who calls these modules from elsewhere, with file paths.
20
+ 3. **Seams** — where data crosses module boundaries, named per `./../reference/architecture-vocabulary.md`.
21
+
22
+ Do not propose fixes. Do not write code. The output is a map.
23
+
24
+ If `CONTEXT.md` is absent, suggest `/gdd:discuss` to start one, but still produce the map using basenames and inferred terms.
25
+
26
+ ## ZOOM-OUT COMPLETE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.41.5",
3
+ "version": "1.42.0",
4
4
  "description": "A design-quality pipeline for AI coding agents: brief, plan, implement, and verify UI work against your design system.",
5
5
  "author": "Hegemon",
6
6
  "homepage": "https://github.com/hegemonart/get-design-done",
@@ -23,6 +23,7 @@
23
23
  "sdk/",
24
24
  "recipes/",
25
25
  "docs/i18n/",
26
+ "dist/claude-code/",
26
27
  "scripts/lib/",
27
28
  "scripts/cli/",
28
29
  "scripts/install.cjs",
@@ -47,6 +48,8 @@
47
48
  },
48
49
  "scripts": {
49
50
  "build:bundles": "node scripts/build-distribution-bundles.cjs",
51
+ "build:skills": "node scripts/build-skills.cjs",
52
+ "build:skills:check": "node scripts/build-skills.cjs --check",
50
53
  "build:sdk": "node scripts/build-sdk-bins.cjs",
51
54
  "prepack": "npm run build:sdk",
52
55
  "postpack": "node scripts/build-sdk-bins.cjs --clean",
@@ -28,6 +28,20 @@ the scanner pattern list in lockstep.
28
28
  - **`scan`** (stage name) → merged/renamed into `explore` in Phase 3. Migration: references to the `scan` stage in shipped skills and agents were replaced with `explore`.
29
29
  - **`discover`** (stage name) → merged/renamed into `explore` in Phase 3. Migration: references to the `discover` stage in shipped skills and agents were replaced with `explore`.
30
30
 
31
+ ## Authoring surfaces
32
+
33
+ - **`skills/` as the authoring source** → **`source/skills/`** — deprecated in Phase 42 (multi-harness
34
+ source compilation). Skills are now authored once in `source/skills/` with placeholders
35
+ (`{{command_prefix}}` et al.; see `reference/skill-placeholders.md`) and compiled per-harness by
36
+ `scripts/build-skills.cjs`. The committed `skills/` tree is now a **generated artifact** (the Claude-Code
37
+ compile target) — CI's `npm run build:skills:check` drift-gates `committed === generated`.
38
+
39
+ Migration for contributors: **edit `source/skills/`, never `skills/` directly**, then run
40
+ `npm run build:skills` (or `gdd-sdk build skills`) and commit the regenerated `skills/` +
41
+ `dist/claude-code/`. `.claude-plugin/plugin.json`'s `"skills": ["./skills/"]` is unchanged — the plugin
42
+ still loads `skills/`, now produced from `source/skills/`. This is a path/authoring move only; no
43
+ stale-ref token is emitted (both paths are live), so the `detect-stale-refs.cjs` list is not extended.
44
+
31
45
  ## Scanner scope
32
46
 
33
47
  `scripts/detect-stale-refs.cjs` flags these tokens (line-granular match):
@@ -1042,6 +1042,13 @@
1042
1042
  "type": "meta-rules",
1043
1043
  "phase": 40.5,
1044
1044
  "description": "Phase 40.5 CLI-localization contract: locale resolution (config.locale > env LANG > en) + fallback chain locale->base->en + flat-JSON message tables via scripts/lib/i18n/index.cjs; tables at scripts/lib/i18n/messages/{en,ru,uk,de,fr,zh,ja}.json (en source-complete, ru full, 5 placeholders with en fallback); the opt-in description_i18n frontmatter (descriptionFor falls back to English); /gdd:locale skill; warn-only completeness; the add-a-locale contribution path (translate table + NOTICE credit + PR). Distinct from reference/i18n.md (which covers USER-design i18n)."
1045
+ },
1046
+ {
1047
+ "name": "skill-placeholders",
1048
+ "path": "reference/skill-placeholders.md",
1049
+ "type": "meta-rules",
1050
+ "phase": 42,
1051
+ "description": "Phase 42 multi-harness skill-placeholder catalogue: the four placeholders ({{command_prefix}}/{{model}}/{{config_file}}/{{ask_instruction}}) + per-harness substitution table + the \\{{...}} escape + the <!-- harness-only: a,b --> block rule. Skills authored once in source/skills/, compiled per-harness by scripts/build-skills.cjs via scripts/lib/build/factory.cjs reading scripts/lib/manifest/harnesses.json."
1045
1052
  }
1046
1053
  ]
1047
1054
  }
@@ -0,0 +1,71 @@
1
+ # Skill Placeholders — Multi-Harness Source Compilation
2
+
3
+ > Phase 42. Skills are authored once in `source/skills/` with placeholders and compiled per-harness into
4
+ > `dist/<bundle>/<config-dir>/skills/...` by `scripts/build-skills.cjs` (the pure transform lives in
5
+ > `scripts/lib/build/factory.cjs`; the per-harness values in `scripts/lib/build/harness-configs.cjs`,
6
+ > which reads the Phase 41.5 manifest root `scripts/lib/manifest/harnesses.json`). The Claude-Code
7
+ > compile target is the committed `skills/` tree; CI asserts `committed === generated` (the drift gate).
8
+
9
+ ## The four placeholders
10
+
11
+ | Placeholder | Meaning | Claude value (round-trip anchor) |
12
+ |-----------------------|------------------------------------------------------|----------------------------------|
13
+ | `{{command_prefix}}` | The slash-command invocation prefix before a verb. | `/gdd:` (so `{{command_prefix}}audit` -> `/gdd:audit`) |
14
+ | `{{model}}` | How the skill refers to the active model. | `your configured Claude model` |
15
+ | `{{config_file}}` | The harness's settings/config file path. | `.claude/settings.json` |
16
+ | `{{ask_instruction}}` | How the skill tells the user to query the agent. | `ask Claude Code` |
17
+
18
+ Only `{{command_prefix}}` is currently woven through the migrated source (every literal `/gdd:` became
19
+ `{{command_prefix}}`); the other three are documented + factory-supported for authors who need them.
20
+ Because Claude's `command_prefix` is exactly `/gdd:`, `compile(source, claude)` reproduces `skills/`
21
+ byte-for-byte — that pure-inverse property is what makes the drift gate safe.
22
+
23
+ ## Per-harness substitution table
24
+
25
+ | Harness id | `{{command_prefix}}` | `{{config_file}}` |
26
+ |---------------|----------------------|-----------------------------|
27
+ | `claude` | `/gdd:` | `.claude/settings.json` |
28
+ | `codex` | `/gdd-` | `.codex/config.toml` |
29
+ | `gemini` | `/gdd:` | `.gemini/settings.json` |
30
+ | `qwen` | `/gdd:` | `.qwen/settings.json` |
31
+ | `kilo` | `/gdd:` | `.kilo/config.json` |
32
+ | `copilot` | `/gdd:` | `.copilot/config.json` |
33
+ | `cursor` | `/gdd:` | `.cursor/settings.json` |
34
+ | `windsurf` | `/gdd:` | `.windsurf/settings.json` |
35
+ | `antigravity` | `/gdd:` | `.antigravity/config.json` |
36
+ | `augment` | `/gdd:` | `.augment/config.json` |
37
+ | `trae` | `/gdd:` | `.trae/config.json` |
38
+ | `codebuddy` | `/gdd:` | `.codebuddy/config.json` |
39
+ | `cline` | `/gdd:` | `.cline/config.json` |
40
+ | `opencode` | `/gdd:` | `.opencode/config.json` |
41
+
42
+ `codex` is the deliberate outlier: its custom-prompt grammar is flat (`/gdd-audit`), not the namespaced
43
+ `/gdd:audit`. `{{model}}` and `{{ask_instruction}}` follow the pattern `your configured <Name> model` and
44
+ `ask <Name>` respectively (see `harness-configs.cjs` for exact strings). Adding a 15th harness is one new
45
+ entry in `scripts/lib/manifest/harnesses.json` plus an optional row in `harness-configs.cjs`.
46
+
47
+ ## Escaping a literal placeholder
48
+
49
+ To emit a literal `{{command_prefix}}` (or any `{{...}}`) without substitution, backslash-escape the
50
+ opening braces: write `\{{command_prefix}}`. The factory strips the backslash and leaves the braces
51
+ untouched. Use this only when documenting the placeholder syntax itself.
52
+
53
+ ## Harness-only blocks
54
+
55
+ To include a span of content for specific harnesses only, wrap it in an HTML-comment fence (it survives
56
+ Markdown and is easy to grep):
57
+
58
+ ```
59
+ <!-- harness-only: cursor,codex -->
60
+ This sentence ships only in the Cursor and Codex bundles.
61
+ <!-- /harness-only -->
62
+ ```
63
+
64
+ The block body is kept iff the compiling harness's `id` appears in the comma list; otherwise it is removed
65
+ entirely. Full per-harness content forking beyond placeholders and these blocks is intentionally out of
66
+ scope (a maintenance trap) — see the Phase 42 CONTEXT.
67
+
68
+ ## Validation
69
+
70
+ `test/suite/phase-42-placeholders.test.cjs` asserts that every placeholder actually used across
71
+ `source/skills/` is documented in this file, and that `source/skills/` mirrors the `skills/` skill count.
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+ // Phase 42 — pure transformer factory (impeccable-style). compile(text, config) => string.
3
+ // Pure: no filesystem, no I/O, no module imports. The orchestrator (scripts/build-skills.cjs)
4
+ // does all reading/writing; this layer only transforms a single skill body for one harness config.
5
+ //
6
+ // Transform order (deterministic):
7
+ // 1. harness-only blocks <!-- harness-only: a,b -->BODY<!-- /harness-only --> kept iff config.id in {a,b}
8
+ // 2. protect escapes \{{ x }} -> sentinel (emit literal {{ x }}, never substituted)
9
+ // 3. substitute {{command_prefix}} {{model}} {{config_file}} {{ask_instruction}}
10
+ // 4. restore escapes sentinel -> {{ x }}
11
+ //
12
+ // D-01: for the Claude config (command_prefix === '/gdd:') this is the exact inverse of the migration
13
+ // (/gdd: -> {{command_prefix}}), so compile(source, claude) reproduces skills/ byte-for-byte.
14
+
15
+ const PLACEHOLDERS = ['command_prefix', 'model', 'config_file', 'ask_instruction'];
16
+ const ESCAPE_OPEN = '@@GDD_ESC_';
17
+ const ESCAPE_CLOSE = '@@';
18
+
19
+ function stripHarnessOnly(text, id) {
20
+ const re = /<!--\s*harness-only:\s*([^>]*?)\s*-->([\s\S]*?)<!--\s*\/harness-only\s*-->/g;
21
+ return text.replace(re, (_m, list, body) => {
22
+ const ids = String(list).split(',').map((s) => s.trim()).filter(Boolean);
23
+ return ids.includes(id) ? body : '';
24
+ });
25
+ }
26
+
27
+ function compile(text, config) {
28
+ if (typeof text !== 'string') throw new TypeError('compile: text must be a string');
29
+ if (!config || typeof config !== 'object') throw new TypeError('compile: config object is required');
30
+
31
+ let out = stripHarnessOnly(text, config.id);
32
+
33
+ // 2. protect \{{ ... }} escapes
34
+ const escapes = [];
35
+ out = out.replace(/\\\{\{([\s\S]*?)\}\}/g, (_m, inner) => {
36
+ escapes.push('{{' + inner + '}}');
37
+ return ESCAPE_OPEN + (escapes.length - 1) + ESCAPE_CLOSE;
38
+ });
39
+
40
+ // 3. substitute placeholders
41
+ for (const key of PLACEHOLDERS) {
42
+ if (config[key] == null) continue;
43
+ out = out.split('{{' + key + '}}').join(String(config[key]));
44
+ }
45
+
46
+ // 4. restore escapes as literal {{ ... }}
47
+ out = out.replace(/@@GDD_ESC_(\d+)@@/g, (_m, i) => escapes[Number(i)]);
48
+ return out;
49
+ }
50
+
51
+ /** Placeholders genuinely substituted (escaped \{{...}} excluded) — used by the catalogue test. */
52
+ function placeholdersUsed(text) {
53
+ if (typeof text !== 'string') return new Set();
54
+ const scrubbed = String(text).replace(/\\\{\{[\s\S]*?\}\}/g, '');
55
+ const used = new Set();
56
+ const re = /\{\{([a-z_]+)\}\}/g;
57
+ let m;
58
+ while ((m = re.exec(scrubbed)) !== null) used.add(m[1]);
59
+ return used;
60
+ }
61
+
62
+ module.exports = { compile, placeholdersUsed, stripHarnessOnly, PLACEHOLDERS };
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+ // Phase 42 — per-harness build/compile config. The base record (id / name / configDir) comes from the
3
+ // Phase 41.5 manifest SoT (scripts/lib/manifest/harnesses.json); this layer adds the four placeholder
4
+ // substitutions + frontmatter-strip rules + the dist bundle slug. Adding a 15th harness = one manifest
5
+ // entry (+ an optional OVERRIDES row); everything else falls back to DEFAULTS.
6
+ //
7
+ // command_prefix is the ONLY field that affects the byte-identical Claude round-trip: it MUST be '/gdd:'
8
+ // for claude (the migration replaced literal '/gdd:' with {{command_prefix}}; the Claude compile reverses it).
9
+
10
+ const { readHarnesses } = require('../manifest/index.cjs');
11
+
12
+ const DEFAULTS = {
13
+ command_prefix: '/gdd:',
14
+ config_file: 'config.json',
15
+ model: 'your configured model',
16
+ ask_instruction: 'ask your agent',
17
+ stripFrontmatter: [],
18
+ };
19
+
20
+ // Per-harness overrides. Only `codex` diverges on command_prefix (its custom-prompt grammar is flat,
21
+ // `/gdd-audit`, not the namespaced `/gdd:audit`); the rest share Claude's slash-command namespace.
22
+ const OVERRIDES = {
23
+ claude: { bundleSlug: 'claude-code', command_prefix: '/gdd:', config_file: '.claude/settings.json', model: 'your configured Claude model', ask_instruction: 'ask Claude Code' },
24
+ codex: { command_prefix: '/gdd-', config_file: '.codex/config.toml', model: 'your configured Codex model', ask_instruction: 'ask Codex' },
25
+ gemini: { command_prefix: '/gdd:', config_file: '.gemini/settings.json', model: 'your configured Gemini model', ask_instruction: 'ask Gemini' },
26
+ qwen: { command_prefix: '/gdd:', config_file: '.qwen/settings.json', model: 'your configured Qwen model', ask_instruction: 'ask Qwen Code' },
27
+ kilo: { command_prefix: '/gdd:', config_file: '.kilo/config.json', model: 'your configured Kilo model', ask_instruction: 'ask Kilo Code' },
28
+ copilot: { command_prefix: '/gdd:', config_file: '.copilot/config.json', model: 'your configured Copilot model', ask_instruction: 'ask Copilot' },
29
+ cursor: { command_prefix: '/gdd:', config_file: '.cursor/settings.json', model: 'your configured Cursor model', ask_instruction: 'ask Cursor' },
30
+ windsurf: { command_prefix: '/gdd:', config_file: '.windsurf/settings.json', model: 'your configured Windsurf model', ask_instruction: 'ask Cascade' },
31
+ antigravity: { command_prefix: '/gdd:', config_file: '.antigravity/config.json', model: 'your configured Antigravity model', ask_instruction: 'ask Antigravity' },
32
+ augment: { command_prefix: '/gdd:', config_file: '.augment/config.json', model: 'your configured Augment model', ask_instruction: 'ask Augment' },
33
+ trae: { command_prefix: '/gdd:', config_file: '.trae/config.json', model: 'your configured Trae model', ask_instruction: 'ask Trae' },
34
+ codebuddy: { command_prefix: '/gdd:', config_file: '.codebuddy/config.json', model: 'your configured CodeBuddy model', ask_instruction: 'ask CodeBuddy' },
35
+ cline: { command_prefix: '/gdd:', config_file: '.cline/config.json', model: 'your configured Cline model', ask_instruction: 'ask Cline' },
36
+ opencode: { command_prefix: '/gdd:', config_file: '.opencode/config.json', model: 'your configured OpenCode model', ask_instruction: 'ask OpenCode' },
37
+ };
38
+
39
+ function buildConfigs(opts) {
40
+ const { harnesses } = readHarnesses(opts);
41
+ return harnesses.map((h) => {
42
+ const ov = OVERRIDES[h.id] || {};
43
+ return {
44
+ id: h.id,
45
+ name: h.name,
46
+ configDir: h.config_dir,
47
+ bundleSlug: ov.bundleSlug || h.id,
48
+ ...DEFAULTS,
49
+ ...ov,
50
+ };
51
+ });
52
+ }
53
+
54
+ const CONFIGS = buildConfigs();
55
+
56
+ function byId(id) {
57
+ return CONFIGS.find((c) => c.id === id) || null;
58
+ }
59
+
60
+ function claude() {
61
+ return byId('claude');
62
+ }
63
+
64
+ module.exports = { CONFIGS, byId, claude, buildConfigs, DEFAULTS };
@@ -0,0 +1,106 @@
1
+ // sdk/cli/commands/build.ts — Phase 42 (COMPILE-06).
2
+ //
3
+ // `gdd-sdk build skills [--harness <id>] [--zip] [--check]` — compile the per-harness skill bundles
4
+ // from source/skills/ via the orchestrator scripts/build-skills.cjs. The orchestrator is a separate
5
+ // dep-free CJS process (no bundling entanglement with the SDK); we resolve it relative to the package
6
+ // root and spawn it, forwarding stdout/stderr.
7
+ //
8
+ // Exit codes:
9
+ // * 0 — build (or --check) succeeded.
10
+ // * 1 — --check found drift (committed != generated).
11
+ // * 3 — arg / config error (missing/unknown target).
12
+
13
+ import { spawnSync } from 'node:child_process';
14
+ import { existsSync } from 'node:fs';
15
+ import { dirname, join } from 'node:path';
16
+
17
+ import {
18
+ coerceFlags,
19
+ COMMON_FLAGS,
20
+ type FlagSpec,
21
+ type ParsedArgs,
22
+ } from '../parse-args.ts';
23
+
24
+ const BUILD_FLAGS: readonly FlagSpec[] = [
25
+ ...COMMON_FLAGS,
26
+ { name: 'harness', type: 'string' },
27
+ { name: 'zip', type: 'boolean' },
28
+ { name: 'check', type: 'boolean' },
29
+ ];
30
+
31
+ export const BUILD_USAGE = `gdd-sdk build skills [flags]
32
+
33
+ Compile per-harness skill bundles from source/skills/ into dist/<bundle>/ (and regenerate the
34
+ committed Claude-Code surface skills/). One source, N provider bundles.
35
+
36
+ Flags:
37
+ --harness <id> Build only one harness (e.g. claude, codex, gemini). Default: all 14.
38
+ --zip Also package each bundle as dist/<bundle>.tgz (needs tar).
39
+ --check Verify committed skills/ + dist/claude-code/ match source/ (the drift gate); no writes.
40
+ -h, --help Show this help.
41
+
42
+ Exit codes: 0 ok · 1 drift (--check) · 3 arg error
43
+ `;
44
+
45
+ interface CommandCtx {
46
+ readonly stdout: NodeJS.WritableStream;
47
+ readonly stderr: NodeJS.WritableStream;
48
+ }
49
+
50
+ /** Walk up from the CLI entry (argv[1]) to the package root that holds scripts/build-skills.cjs. */
51
+ function findOrchestrator(): string | null {
52
+ let dir = dirname(process.argv[1] ?? process.cwd());
53
+ for (let i = 0; i < 8; i++) {
54
+ const candidate = join(dir, 'scripts', 'build-skills.cjs');
55
+ if (existsSync(candidate)) return candidate;
56
+ const parent = dirname(dir);
57
+ if (parent === dir) break;
58
+ dir = parent;
59
+ }
60
+ const cwdCandidate = join(process.cwd(), 'scripts', 'build-skills.cjs');
61
+ return existsSync(cwdCandidate) ? cwdCandidate : null;
62
+ }
63
+
64
+ export async function buildCommand(parsed: ParsedArgs, ctx: CommandCtx): Promise<number> {
65
+ if (parsed.flags['help'] === true || parsed.flags['h'] === true) {
66
+ ctx.stdout.write(BUILD_USAGE);
67
+ return 0;
68
+ }
69
+
70
+ const target = parsed.positionals[0];
71
+ if (target !== 'skills') {
72
+ ctx.stderr.write(`gdd-sdk build: expected target "skills" (got ${target ? `"${target}"` : 'nothing'})\n${BUILD_USAGE}`);
73
+ return 3;
74
+ }
75
+
76
+ let flags: Record<string, unknown>;
77
+ try {
78
+ flags = coerceFlags(parsed, BUILD_FLAGS);
79
+ } catch {
80
+ ctx.stderr.write(`gdd-sdk build: invalid flags\n${BUILD_USAGE}`);
81
+ return 3;
82
+ }
83
+
84
+ const script = findOrchestrator();
85
+ if (!script) {
86
+ ctx.stderr.write('gdd-sdk build: could not locate scripts/build-skills.cjs\n');
87
+ return 3;
88
+ }
89
+
90
+ const orchestratorArgs: string[] = [];
91
+ if (flags['check'] === true) orchestratorArgs.push('--check');
92
+ if (flags['zip'] === true) orchestratorArgs.push('--zip');
93
+ const harness = flags['harness'];
94
+ if (typeof harness === 'string' && harness.length > 0) {
95
+ orchestratorArgs.push('--harness', harness);
96
+ }
97
+
98
+ const res = spawnSync(process.execPath, [script, ...orchestratorArgs], { encoding: 'utf8' });
99
+ if (res.stdout) ctx.stdout.write(res.stdout);
100
+ if (res.stderr) ctx.stderr.write(res.stderr);
101
+ if (res.error) {
102
+ ctx.stderr.write(`gdd-sdk build: failed to run orchestrator: ${res.error.message}\n`);
103
+ return 3;
104
+ }
105
+ return typeof res.status === 'number' ? res.status : 3;
106
+ }
package/sdk/cli/index.js CHANGED
@@ -8004,6 +8004,83 @@ function errMessage5(err) {
8004
8004
  return String(err);
8005
8005
  }
8006
8006
 
8007
+ // sdk/cli/commands/build.ts
8008
+ var import_node_child_process = require("node:child_process");
8009
+ var import_node_fs22 = require("node:fs");
8010
+ var import_node_path20 = require("node:path");
8011
+ var BUILD_FLAGS = [
8012
+ ...COMMON_FLAGS,
8013
+ { name: "harness", type: "string" },
8014
+ { name: "zip", type: "boolean" },
8015
+ { name: "check", type: "boolean" }
8016
+ ];
8017
+ var BUILD_USAGE = `gdd-sdk build skills [flags]
8018
+
8019
+ Compile per-harness skill bundles from source/skills/ into dist/<bundle>/ (and regenerate the
8020
+ committed Claude-Code surface skills/). One source, N provider bundles.
8021
+
8022
+ Flags:
8023
+ --harness <id> Build only one harness (e.g. claude, codex, gemini). Default: all 14.
8024
+ --zip Also package each bundle as dist/<bundle>.tgz (needs tar).
8025
+ --check Verify committed skills/ + dist/claude-code/ match source/ (the drift gate); no writes.
8026
+ -h, --help Show this help.
8027
+
8028
+ Exit codes: 0 ok \xB7 1 drift (--check) \xB7 3 arg error
8029
+ `;
8030
+ function findOrchestrator() {
8031
+ let dir = (0, import_node_path20.dirname)(process.argv[1] ?? process.cwd());
8032
+ for (let i = 0; i < 8; i++) {
8033
+ const candidate = (0, import_node_path20.join)(dir, "scripts", "build-skills.cjs");
8034
+ if ((0, import_node_fs22.existsSync)(candidate)) return candidate;
8035
+ const parent = (0, import_node_path20.dirname)(dir);
8036
+ if (parent === dir) break;
8037
+ dir = parent;
8038
+ }
8039
+ const cwdCandidate = (0, import_node_path20.join)(process.cwd(), "scripts", "build-skills.cjs");
8040
+ return (0, import_node_fs22.existsSync)(cwdCandidate) ? cwdCandidate : null;
8041
+ }
8042
+ async function buildCommand(parsed, ctx) {
8043
+ if (parsed.flags["help"] === true || parsed.flags["h"] === true) {
8044
+ ctx.stdout.write(BUILD_USAGE);
8045
+ return 0;
8046
+ }
8047
+ const target = parsed.positionals[0];
8048
+ if (target !== "skills") {
8049
+ ctx.stderr.write(`gdd-sdk build: expected target "skills" (got ${target ? `"${target}"` : "nothing"})
8050
+ ${BUILD_USAGE}`);
8051
+ return 3;
8052
+ }
8053
+ let flags;
8054
+ try {
8055
+ flags = coerceFlags(parsed, BUILD_FLAGS);
8056
+ } catch {
8057
+ ctx.stderr.write(`gdd-sdk build: invalid flags
8058
+ ${BUILD_USAGE}`);
8059
+ return 3;
8060
+ }
8061
+ const script = findOrchestrator();
8062
+ if (!script) {
8063
+ ctx.stderr.write("gdd-sdk build: could not locate scripts/build-skills.cjs\n");
8064
+ return 3;
8065
+ }
8066
+ const orchestratorArgs = [];
8067
+ if (flags["check"] === true) orchestratorArgs.push("--check");
8068
+ if (flags["zip"] === true) orchestratorArgs.push("--zip");
8069
+ const harness = flags["harness"];
8070
+ if (typeof harness === "string" && harness.length > 0) {
8071
+ orchestratorArgs.push("--harness", harness);
8072
+ }
8073
+ const res = (0, import_node_child_process.spawnSync)(process.execPath, [script, ...orchestratorArgs], { encoding: "utf8" });
8074
+ if (res.stdout) ctx.stdout.write(res.stdout);
8075
+ if (res.stderr) ctx.stderr.write(res.stderr);
8076
+ if (res.error) {
8077
+ ctx.stderr.write(`gdd-sdk build: failed to run orchestrator: ${res.error.message}
8078
+ `);
8079
+ return 3;
8080
+ }
8081
+ return typeof res.status === "number" ? res.status : 3;
8082
+ }
8083
+
8007
8084
  // sdk/cli/index.ts
8008
8085
  var USAGE6 = `gdd-sdk <command> [flags]
8009
8086
 
@@ -8013,6 +8090,7 @@ Commands:
8013
8090
  query <op> Typed STATE.md read operations.
8014
8091
  audit Probe connections + dry-run verify.
8015
8092
  init Bootstrap a new project.
8093
+ build skills Compile per-harness skill bundles from source/skills/.
8016
8094
 
8017
8095
  Use 'gdd-sdk <command> -h' for command-specific flags.
8018
8096
 
@@ -8030,7 +8108,8 @@ async function dispatch(parsed, deps = {}) {
8030
8108
  stage: deps.commands?.stage ?? stageCommand,
8031
8109
  query: deps.commands?.query ?? queryCommand,
8032
8110
  audit: deps.commands?.audit ?? auditCommand,
8033
- init: deps.commands?.init ?? initCommand
8111
+ init: deps.commands?.init ?? initCommand,
8112
+ build: deps.commands?.build ?? buildCommand
8034
8113
  };
8035
8114
  if (parsed.subcommand === null) {
8036
8115
  stdout.write(USAGE6);
@@ -8054,6 +8133,8 @@ async function dispatch(parsed, deps = {}) {
8054
8133
  return await commands.audit(parsed, { stdout, stderr });
8055
8134
  case "init":
8056
8135
  return await commands.init(parsed, { stdout, stderr });
8136
+ case "build":
8137
+ return await commands.build(parsed, { stdout, stderr });
8057
8138
  default:
8058
8139
  stderr.write(
8059
8140
  `gdd-sdk: unknown subcommand "${parsed.subcommand}"
@@ -8067,7 +8148,8 @@ var KNOWN_SUBCOMMANDS = /* @__PURE__ */ new Set([
8067
8148
  "stage",
8068
8149
  "query",
8069
8150
  "audit",
8070
- "init"
8151
+ "init",
8152
+ "build"
8071
8153
  ]);
8072
8154
  async function main(argv = process.argv.slice(2), deps = {}) {
8073
8155
  const parsed = parseArgs(argv);
package/sdk/cli/index.ts CHANGED
@@ -21,6 +21,7 @@ import { stageCommand } from './commands/stage.ts';
21
21
  import { queryCommand } from './commands/query.ts';
22
22
  import { auditCommand } from './commands/audit.ts';
23
23
  import { initCommand } from './commands/init.ts';
24
+ import { buildCommand } from './commands/build.ts';
24
25
 
25
26
  // ---------------------------------------------------------------------------
26
27
  // Top-level USAGE.
@@ -34,6 +35,7 @@ Commands:
34
35
  query <op> Typed STATE.md read operations.
35
36
  audit Probe connections + dry-run verify.
36
37
  init Bootstrap a new project.
38
+ build skills Compile per-harness skill bundles from source/skills/.
37
39
 
38
40
  Use 'gdd-sdk <command> -h' for command-specific flags.
39
41
 
@@ -57,6 +59,7 @@ export interface DispatcherDeps {
57
59
  readonly query?: typeof queryCommand;
58
60
  readonly audit?: typeof auditCommand;
59
61
  readonly init?: typeof initCommand;
62
+ readonly build?: typeof buildCommand;
60
63
  };
61
64
  }
62
65
 
@@ -81,6 +84,7 @@ export async function dispatch(
81
84
  query: deps.commands?.query ?? queryCommand,
82
85
  audit: deps.commands?.audit ?? auditCommand,
83
86
  init: deps.commands?.init ?? initCommand,
87
+ build: deps.commands?.build ?? buildCommand,
84
88
  };
85
89
 
86
90
  // Bare invocation or top-level help → USAGE.
@@ -111,6 +115,8 @@ export async function dispatch(
111
115
  return await commands.audit(parsed, { stdout, stderr });
112
116
  case 'init':
113
117
  return await commands.init(parsed, { stdout, stderr });
118
+ case 'build':
119
+ return await commands.build(parsed, { stdout, stderr });
114
120
  default:
115
121
  stderr.write(
116
122
  `gdd-sdk: unknown subcommand "${parsed.subcommand}"\n${USAGE}`,
@@ -125,6 +131,7 @@ const KNOWN_SUBCOMMANDS: ReadonlySet<string> = new Set([
125
131
  'query',
126
132
  'audit',
127
133
  'init',
134
+ 'build',
128
135
  ]);
129
136
 
130
137
  // ---------------------------------------------------------------------------