Merge origin/main into feat/3597-split-suites-node-matrix

Resolves conflict in .github/workflows/test.yml: keep the 6 new drift-check
steps from main (plan-scan, secrets, schema-detect, decisions,
workstream-name-policy, Shared Module hand-sync) before the split-lane test
runs from this PR. PR's dedicated `coverage` job replaces main's per-matrix
`Run tests with coverage` step.

Other conflicting files (CONTRIBUTING.md, get-shit-done/bin/lib/init.cjs,
package.json) auto-merged cleanly. Changeset files (.changeset/*) brought in
from main as adds.
This commit is contained in:
Tom Boucher
2026-05-16 13:22:07 -04:00
132 changed files with 9379 additions and 1405 deletions

View File

@@ -264,6 +264,7 @@
"artifacts.cjs",
"audit.cjs",
"cjs-command-router-adapter.cjs",
"cjs-sdk-bridge.cjs",
"clusters.cjs",
"command-aliases.generated.cjs",
"commands.cjs",
@@ -273,6 +274,7 @@
"context-utilization.cjs",
"core.cjs",
"decisions.cjs",
"decisions.generated.cjs",
"docs.cjs",
"drift.cjs",
"fallow-runner.cjs",
@@ -295,6 +297,7 @@
"phase.cjs",
"phases-command-router.cjs",
"plan-scan.cjs",
"plan-scan.generated.cjs",
"planning-workspace.cjs",
"profile-output.cjs",
"profile-pipeline.cjs",
@@ -305,7 +308,9 @@
"runtime-homes.cjs",
"runtime-slash.cjs",
"schema-detect.cjs",
"schema-detect.generated.cjs",
"secrets.cjs",
"secrets.generated.cjs",
"security.cjs",
"shell-command-projection.cjs",
"state-command-router.cjs",
@@ -321,6 +326,7 @@
"workstream-inventory-builder.generated.cjs",
"workstream-inventory.cjs",
"workstream-name-policy.cjs",
"workstream-name-policy.generated.cjs",
"workstream.cjs",
"worktree-safety.cjs"
],

View File

@@ -361,7 +361,7 @@ The `gsd-planner` agent is decomposed into a core agent plus reference modules t
---
## CLI Modules (64 shipped)
## CLI Modules (70 shipped)
Full listing: `get-shit-done/bin/lib/*.cjs`.
@@ -372,6 +372,7 @@ Full listing: `get-shit-done/bin/lib/*.cjs`.
| `artifacts.cjs` | Canonical artifact registry — known `.planning/` root file names; used by `gsd-health` W019 lint |
| `audit.cjs` | Audit dispatch, audit open sessions, audit storage helpers |
| `cjs-command-router-adapter.cjs` | Shared compatibility adapter for manifest-backed CJS command-family routers |
| `cjs-sdk-bridge.cjs` | Shared SDK runtime-bridge loader (`tryLoadSdk`/`getExecuteForCjs`); consumed by every CJS router and `gsd-tools.cjs` to delegate canonical commands to the SDK in-process |
| `clusters.cjs` | Skill cluster definitions for the runtime surface module (ADR-0011 Phase 2) |
| `command-aliases.generated.cjs` | Generated CJS alias/subcommand metadata for manifest-backed family routers |
| `commands.cjs` | Misc CLI commands (slug, timestamp, todos, scaffolding, stats) |
@@ -380,7 +381,8 @@ Full listing: `get-shit-done/bin/lib/*.cjs`.
| `configuration.generated.cjs` | Generated Configuration Module — canonical config loading, legacy-key normalization, defaults merge, and explicit on-disk migration; source of truth for both SDK and CJS consumers |
| `context-utilization.cjs` | Pure classifier for `gsd-health --context` — turns (tokensUsed, contextWindow) into a `{ percent, state }` triage result against the 60%/70% fracture-point thresholds (#2792) |
| `core.cjs` | Error handling, output formatting, shared utilities, runtime fallbacks; compatibility re-exports for planning-workspace helpers |
| `decisions.cjs` | Shared parser for CONTEXT.md `<decisions>` blocks (D-NN entries); used by `gap-checker.cjs` and intended for #2492 plan/verify decision gates |
| `decisions.cjs` | CJS shim adapter — re-exports from `decisions.generated.cjs` (Phase 6/#3575 Shared Module migration) |
| `decisions.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/query/decisions.ts` via `sdk/scripts/gen-decisions.mjs`; parses CONTEXT.md `<decisions>` blocks, accepts numeric (D-42) and alphanumeric (D-INFRA-01) IDs, returns `{id, text, category, tags, trackable}`; do not edit directly |
| `docs.cjs` | Docs-update workflow init, Markdown scanning, monorepo detection |
| `drift.cjs` | Post-execute codebase structural drift detector (#2003): classifies file changes into new-dir/barrel/migration/route categories and round-trips `last_mapped_commit` frontmatter |
| `fallow-runner.cjs` | Fallow audit adapter for `/gsd-code-review`: binary resolution (`PATH` then `node_modules/.bin`), actionable missing-binary errors, and structural findings normalization |
@@ -402,7 +404,8 @@ Full listing: `get-shit-done/bin/lib/*.cjs`.
| `phase-command-router.cjs` | Thin CJS subcommand router adapter for `gsd-tools phase` |
| `phase.cjs` | Phase directory operations, decimal numbering, plan indexing |
| `phases-command-router.cjs` | Thin CJS subcommand router adapter for `gsd-tools phases` |
| `plan-scan.cjs` | Canonical phase-plan scanner — shared helper for detecting plan and summary files in flat and nested layouts (k014); consumed by state, roadmap, init, and workstream inventory paths |
| `plan-scan.cjs` | CJS shim adapter — re-exports from `plan-scan.generated.cjs` (Phase 6/#3575 Shared Module migration) |
| `plan-scan.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/query/plan-scan.ts` via `sdk/scripts/gen-plan-scan.mjs`; canonical phase-plan scanner for detecting plan and summary files in flat and nested layouts (k014); do not edit directly |
| `planning-workspace.cjs` | Planning path/workstream seam (`planningDir`, `planningPaths`, active-workstream routing, `.planning/.lock` orchestration) |
| `project-root.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/project-root/index.ts` via `sdk/scripts/gen-project-root.mjs`; resolves a project root from a starting directory using four heuristics (own `.planning/` guard, `sub_repos` config, `multiRepo` flag, `.git` heuristic); do not edit directly |
| `profile-output.cjs` | Profile rendering, USER-PROFILE.md and dev-preferences.md generation |
@@ -412,8 +415,10 @@ Full listing: `get-shit-done/bin/lib/*.cjs`.
| `roadmap.cjs` | ROADMAP.md parsing, phase extraction, plan progress |
| `runtime-homes.cjs` | Canonical runtime → global config/skills directory mapping; first-class support for all 15 runtimes including Hermes nested layout and Cline rules-based exclusion (#3126) |
| `runtime-slash.cjs` | Runtime-aware slash-command formatter — single source of truth for emitting `/gsd-<cmd>` (skills-based runtimes) and `$gsd-<cmd>` (codex) in user-facing output and persisted artifacts (#3584) |
| `schema-detect.cjs` | Schema-drift detection for ORM patterns (Prisma, Drizzle, etc.) |
| `secrets.cjs` | Secret-config masking convention (`****<last-4>`) for integration keys managed by `/gsd-config --integrations` — keeps plaintext out of `config-set` output |
| `schema-detect.cjs` | CJS shim adapter — re-exports from `schema-detect.generated.cjs` (Phase 6/#3575 Shared Module migration) |
| `schema-detect.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/query/schema-detect.ts` via `sdk/scripts/gen-schema-detect.mjs`; schema-drift detection for ORM patterns (Prisma, Drizzle, Supabase, TypeORM, Payload); exports `detectSchemaFiles`, `detectSchemaOrm`, `checkSchemaDrift`, `SCHEMA_PATTERNS`, `ORM_INFO`; do not edit directly |
| `secrets.cjs` | CJS shim adapter — re-exports from `secrets.generated.cjs` (Phase 6/#3575 Shared Module migration) |
| `secrets.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/query/secrets.ts` via `sdk/scripts/gen-secrets.mjs`; secret-config masking convention (`****<last-4>`) for integration keys; exports `SECRET_CONFIG_KEYS`, `isSecretKey`, `maskSecret`, `maskIfSecret`; do not edit directly |
| `security.cjs` | Path traversal prevention, prompt injection detection, safe JSON/shell helpers |
| `shell-command-projection.cjs` | Runtime-aware shell command projection for managed hook serialization: decides PowerShell call-operator usage by runtime/platform and normalizes Windows script path tokens |
| `state-command-router.cjs` | Thin CJS subcommand router adapter for `gsd-tools state` |
@@ -428,7 +433,8 @@ Full listing: `get-shit-done/bin/lib/*.cjs`.
| `verify.cjs` | Plan structure, phase completeness, reference, commit validation |
| `workstream-inventory-builder.generated.cjs` | GENERATED — pure workstream inventory projection builder; CJS artifact emitted from `sdk/src/workstream-inventory/builder.ts` via `sdk/scripts/gen-workstream-inventory-builder.mjs`; do not edit directly |
| `workstream-inventory.cjs` | Shared workstream inventory projection: state fields, phase/plan/summary counts, roadmap phase count, and active marker — thin orchestrator that delegates pure projection to `workstream-inventory-builder.generated.cjs` |
| `workstream-name-policy.cjs` | Canonical workstream name validation (`isValidActiveWorkstreamName`) and slug normalization (`toWorkstreamSlug`); shared by all workstream callers |
| `workstream-name-policy.cjs` | CJS shim adapter — re-exports from `workstream-name-policy.generated.cjs` (Phase 6/#3575 Shared Module migration) |
| `workstream-name-policy.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/workstream-name-policy.ts` via `sdk/scripts/gen-workstream-name-policy.mjs`; canonical workstream name validation (`isValidActiveWorkstreamName`, `hasInvalidPathSegment`, `validateWorkstreamName`) and slug normalization (`toWorkstreamSlug`); do not edit directly |
| `workstream.cjs` | Workstream CRUD, migration, session-scoped active pointer |
| `worktree-safety.cjs` | Worktree-root resolution and non-destructive prune policy decisions; owns W017 health-check logic |

269
docs/agents/cjs-sdk-seam.md Normal file
View File

@@ -0,0 +1,269 @@
# CJS↔SDK Hard-Seam Migration: Complete Reference
## Issue #3575 (Parent: #3524)
---
## Migration overview
The CJS↔SDK hard-seam migration (#3524) eliminates a class of config-schema drift bugs by introducing single sources of truth at every decision point where CJS and SDK code previously diverged. The migration proceeded in six phases:
| Phase | PR | Summary |
|-------|----|---------|
| Phase 1 | [#3531](https://github.com/gsd-build/get-shit-done/pull/3531) | `state-document` Shared Module — source-of-truth at `sdk/src/state-document/`, generator, freshness check, CJS Adapter (`state-document.generated.cjs`). Worked example for the pattern. |
| Phase 2 | [#3540](https://github.com/gsd-build/get-shit-done/pull/3540) | `configuration` Shared Module — `sdk/shared/config-schema.manifest.json` + `sdk/shared/config-defaults.manifest.json` as data manifests; generator + freshness check + CJS Adapter. |
| Phase 3 | [#3548](https://github.com/gsd-build/get-shit-done/pull/3548) | `workstream-inventory` Shared Module — source-of-truth at `sdk/src/workstream-inventory/`, builder, generator, freshness check, CJS Adapter. |
| Phase 4 | [#3554](https://github.com/gsd-build/get-shit-done/pull/3554) | `project-root` Shared Module — source-of-truth at `sdk/src/project-root/`, generator, freshness check, CJS Adapter. |
| Phase 5.0 | [#3558](https://github.com/gsd-build/get-shit-done/pull/3558) | `runtime-bridge-sync` worker — enables CJS-side execution of SDK native handlers; state.* family initial router delegation via `executeForCjs`. |
| Phase 5.1 | [#3574](https://github.com/gsd-build/get-shit-done/pull/3574) | `state.*` router delegation complete — all known state subcommands delegated via `executeForCjs`; Phase 5.0 worker bug fix. |
| Phase 6 | [#3577](https://github.com/gsd-build/get-shit-done/pull/3577) (closes [#3575](https://github.com/gsd-build/get-shit-done/issues/3575)) | Enforcement hardening + Final completion — hand-sync drift lint, CODEOWNERS, 6 family-router migrations, 5 Shared Module migrations (plan-scan, secrets, schema-detect, decisions, workstream-name-policy), workstream native support, parity fixes. Migration feature-complete: 22 cooperating siblings, 0 backlog pairs. |
---
## Phase 6 Retrospective: 15 config-schema drift bugs
This section captures 15 recurring config-schema drift bugs that motivated the migration. For each, we record what drifted, the surgical fix, and which Phase 6 enforcement layer would have prevented it.
---
### #1535 — Silent failure on unrecognized config.json keys
- **Drifted:** `loadConfig` silently ignored any top-level key in `.planning/config.json` not in `VALID_CONFIG_KEYS`, giving users no feedback when hand-edited or external-tool-added keys had no effect.
- **Fix landed:** PR #1542 — added stderr warning listing unrecognized keys.
- **Would have been blocked by:** **handsync lint** — a seam-aware linter would forbid having parallel hand-authored config validators (CJS `config.cjs` and SDK `config-mutation.ts`) that could silently diverge.
---
### #1542 — fix(config): warn on unrecognized keys in config.json instead of silent drop
- **Drifted:** No drift in this bug itself; it *fixed* #1535's silent-drop behavior by adding the warning.
- **Fix landed:** PR #1542 — merged as the direct fix for #1535.
- **Would have been blocked by:** **per-Module drift lint** (freshness check on config validation) — both CJS and SDK config paths would be regenerated from a single source-of-truth schema module, eliminating the silent-drop risk.
---
### #2047 — bug: config-set rejects intel.enabled despite being a documented config key
- **Drifted:** `intel.enabled` was documented in workflows and gated in runtime code (`intel.cjs:58`), but missing from `VALID_CONFIG_KEYS` in `config.cjs`, so `config-set` rejected it.
- **Fix landed:** PR #2021 — added `intel.enabled` to `VALID_CONFIG_KEYS` in CJS.
- **Would have been blocked by:** **handsync lint** — linter would enforce that every config key gated in runtime code or documented in workflows must appear in the validator allowlist.
---
### #2052 — fix(config): add intel.enabled to VALID_CONFIG_KEYS
- **Drifted:** Same as #2047 (missing from allowlist).
- **Fix landed:** PR #2021 (same PR as #2047 fix).
- **Would have been blocked by:** **handsync lint** — same as #2047.
---
### #2638 — bug: loadConfig writes sub_repos to top-level, then warns it's unknown
- **Drifted:** After #2561 canonicalized `sub_repos` to `planning.sub_repos`, the legacy migration and filesystem auto-sync in `loadConfig` still wrote to top-level `parsed.sub_repos`, which was then flagged as unknown.
- **Fix landed:** PR #2668 — rewrote both paths to target `parsed.planning.sub_repos` and deleted stale top-level copy.
- **Would have been blocked by:** **per-Module drift lint** (freshness check for config shape) — the canonical location for `sub_repos` would be codified in a schema, and any code path writing to it would be verified against that schema at lint time.
---
### #2655 — fix(core): write sub_repos to planning.sub_repos, not top-level
- **Drifted:** Same as #2638.
- **Fix landed:** PR #2668 (same as #2638 fix).
- **Would have been blocked by:** **per-Module drift lint** — same as #2638.
---
### #2653 — bug: SDK config-set rejects documented config keys accepted by CJS config-set
- **Drifted:** SDK's `config-mutation.ts` had a hand-maintained `VALID_CONFIG_KEYS` set that had drifted **28 keys** behind CJS's `config-schema.cjs`, so documented commands like `gsd-sdk query config-set planning.sub_repos` were rejected.
- **Fix landed:** PR #2670 — extracted shared `sdk/src/query/config-schema.ts` module mirroring CJS exactly; added parity test to fail on future drift.
- **Would have been blocked by:** **manifest data isolation** — the config schema would live in one place (e.g., `sdk/shared/config.manifest.json`), and both CJS and SDK would read it, eliminating the possibility of independent drift.
---
### #2670 — fix(#2653): eliminate SDK↔CJS config-schema drift
- **Drifted:** Same as #2653 (28-key drift).
- **Fix landed:** PR #2670 (same as #2653 fix).
- **Would have been blocked by:** **manifest data isolation** — same as #2653.
---
### #2687 — bug: loadConfig warns on valid dynamic-pattern containers in .planning/config.json
- **Drifted:** Keys like `review.models.<cli>` were registered in `config-schema.cjs`'s `DYNAMIC_KEY_PATTERNS` but absent from the hand-maintained `KNOWN_TOP_LEVEL` set in `core.cjs`, causing false-positive "unknown key" warnings.
- **Fix landed:** PR #2706 — added `topLevel` field to `DYNAMIC_KEY_PATTERNS` entries; derived `KNOWN_TOP_LEVEL` from schema instead of maintaining it manually.
- **Would have been blocked by:** **per-Module drift lint** — the validator that builds `KNOWN_TOP_LEVEL` would be regenerated from the schema each run, not hand-maintained.
---
### #2706 — fix(#2687): loadConfig no longer warns on valid dynamic-pattern containers
- **Drifted:** Same as #2687 (false warnings on valid dynamic keys).
- **Fix landed:** PR #2706 (same as #2687 fix).
- **Would have been blocked by:** **per-Module drift lint** — same as #2687.
---
### #2798 — context_window missing from VALID_CONFIG_KEYS
- **Drifted:** `context_window` was documented in workflows and read in SDK runtime (`init.js:190`, `validate.js:575`), but missing from allowlists in both `config-mutation.ts` and `config-schema.cjs`, so writes were rejected.
- **Fix landed:** PR #2816 — added `context_window` to `VALID_CONFIG_KEYS` in both SDK and CJS.
- **Would have been blocked by:** **handsync lint** — linter would enforce that every key read at runtime must be in the allowlist.
---
### #2816 — fix(#2798): add context_window to VALID_CONFIG_KEYS allowlist
- **Drifted:** Same as #2798 (missing from allowlists).
- **Fix landed:** PR #2816 (same as #2798 fix).
- **Would have been blocked by:** **handsync lint** — same as #2798.
---
### #3055 — bug: top-level branching_strategy silently becomes "none"
- **Drifted:** `.planning/config.json` with top-level `branching_strategy: "phase"` was flagged as unknown and dropped by validator, causing `loadConfig` to fall back to the `"none"` default, so phase commits landed on the operator's current branch instead of creating `gsd/phase-{N}` branches.
- **Fix landed:** PR #3116 — SDK-side only; added legacy normalization in `mergeDefaults()` to graft top-level value into canonical `git.branching_strategy` slot before validation.
- **Would have been blocked by:** **per-Module drift lint** — the canonical location for `branching_strategy` would be codified in schema; validator would not strip the value before migrations had a chance to run, or CJS and SDK would share the same migration code.
---
### #3116 — fix: normalize legacy top-level branching_strategy into git config
- **Drifted:** Same as #3055 (legacy top-level shape not normalized before validator strips it).
- **Fix landed:** PR #3116 (SDK-side normalization in `mergeDefaults()`).
- **Would have been blocked by:** **per-Module drift lint** — same as #3055, but SDK-side fix would be shared with CJS via seam layer instead of being ported separately.
---
### #3523 — bug: CJS loadConfig warns top-level branching_strategy 'will be ignored', but actively reads it
- **Drifted:** After PR #3116 fixed the SDK side, the CJS path still emitted false "will be ignored" warnings on the same legacy top-level key, because `KNOWN_TOP_LEVEL` derivation extracted top-level names from `VALID_CONFIG_KEYS` (which contains `'git.branching_strategy'` but not `'branching_strategy'`), and the warning was factually incorrect — `core.cjs:485` does read the legacy value via fallback logic.
- **Fix landed:** PR #3527 — added `'branching_strategy'` to the `KNOWN_TOP_LEVEL` hand-maintained list under the deprecated-keys bucket, suppressing the false warning.
- **Would have been blocked by:** **runtime-bridge delegation** — if CJS and SDK config loading shared a common normalization routine (via `executeForCjs` or a shared seam module), the SDK fix in #3116 would automatically apply to CJS; no separate CJS-side warning would be possible.
---
## Surprises
None. All 15 bugs are genuine CJS↔SDK schema/validation drift, exactly the class the seam migration prevents.
## Phase 6 Enforcement Summary
The seam migration introduces these layers:
1. **handsync lint** (`scripts/lint-shared-module-handsync.cjs`) — Forbids parallel hand-authored validator modules; catches #1535, #2047, #2798.
2. **freshness check** (`sdk/scripts/check-<module>-fresh.mjs`) — Regenerates config validators from schema each run; catches #2687, #3055.
3. **manifest data isolation** (`sdk/shared/*.manifest.json`) — Single source-of-truth for schema; catches #2653.
4. **per-Module drift lint** — Combination of freshness checks and schema-derived allowlists; catches #2638, #2687, #3055.
5. **runtime-bridge delegation** (`executeForCjs` + shared seam modules) — Eliminates parallel CJS/SDK implementations; catches #3523 by preventing separate CJS warning logic.
Together, these layers eliminate the 15-bug class by enforcing single sources of truth at each decision point.
---
## Guide: Adding a new Shared Module
Use this when you want to extract a new piece of data or logic that both CJS and SDK currently duplicate hand-by-hand. Phase 1's `state-document` migration is the worked example.
**Step 1 — Create the source-of-truth file**
```text
sdk/src/<module>/index.ts
```
This is the canonical definition. It may export a schema, a set of keys, a type, or a data object. It must not import from CJS or from generated files.
**Step 2 — Write the generator script**
```text
sdk/scripts/gen-<module>.mjs
```
The generator reads `sdk/src/<module>/index.ts` (or `sdk/shared/<module>.manifest.json` for pure-data manifests), produces a generated output file (either `sdk/src/<module>.generated.ts` or `get-shit-done/bin/lib/<module>.generated.cjs`), and exits 0. It must be idempotent: running it twice produces the same output.
**Step 3 — Write the freshness check**
```text
sdk/scripts/check-<module>-fresh.mjs
```
The freshness check re-runs the generator into a temp location, diffs against the committed file, and exits 1 with a clear message if they diverge. This is what CI runs.
**Step 4 — Write the parity test** (optional but recommended)
```text
tests/<module>-parity.test.cjs
```
Assert that the CJS Adapter and the SDK source-of-truth agree on every field that matters (key sets, defaults, schema shape). This test catches generator bugs that the freshness check cannot.
**Step 5 — Wire CI**
Add a step in `.github/workflows/test.yml` after the existing freshness-check block (before "Run tests with coverage"), gated on `matrix.os == 'ubuntu-latest' && matrix.node-version == 24`:
```yaml
- name: SDK generated <module> artifact drift check
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24
shell: bash
run: node sdk/scripts/check-<module>-fresh.mjs
```
**Step 6 — Run inventory regen**
If the module affects `CONTEXT.md`'s module inventory, update that section. Also update `scripts/shared-module-handsync-allowlist.json`: move any matching entry from `migrateMeBacklog` to `cooperatingSiblings` (or remove it entirely if the CJS hand-copy is now deleted).
**Step 7 — Update CODEOWNERS**
Add the new source-of-truth path to `.github/CODEOWNERS` under the Phase 6 block to make the architectural ownership explicit.
**Reference:** Phase 1 PR [#3531](https://github.com/gsd-build/get-shit-done/pull/3531) — `state-document` migration.
---
## Guide: Adding a new canonical command
Use this when adding a new `gsd-sdk query <family>.<subcommand>` that should be handled natively in the SDK (not delegated to CJS). Phase 5.1's `state.update` migration (PR [#3574](https://github.com/gsd-build/get-shit-done/pull/3574)) is the worked example.
**Step 1 — Declare in the command manifest**
Add the command definition to `sdk/src/query/command-manifest.<family>.ts`. Include the full argument schema and a `handler` reference.
**Step 2 — Implement the SDK handler**
Write the handler in `sdk/src/query/<subcommand>.ts` (or inline in the manifest file for simple cases). The handler receives validated args and the runtime context; it must not shell out to CJS.
**Step 3 — Add CJS router delegate (Phase 5.1+ pattern)**
In the family's CJS command router (e.g. `get-shit-done/bin/lib/state-command-router.cjs`), add a delegate case that calls `executeForCjs(subcommand, args)` from `cjs-command-router-adapter.cjs`. This ensures the CJS binary dispatches to the SDK native handler rather than re-implementing the logic.
**Step 4 — Add a golden parity test**
Add a test in `tests/<family>-command-router.test.cjs` (or a new file if the family has no test yet) that:
1. Invokes the command via the SDK query path.
2. Invokes the command via the CJS router path.
3. Asserts both produce identical output.
This test enforces that the delegate and the native handler stay aligned.
**Reference:** Phase 5.1 PR [#3574](https://github.com/gsd-build/get-shit-done/pull/3574) — `state.update` delegation.
---
## Phase 6 Final Completion Summary
Phase 6 (issue #3575, PR #3577) is feature-complete. The migration is done.
**What shipped in Phase 6:**
- **Shared Modules migrated (5 total in Phase 6):** `plan-scan`, `secrets`, `schema-detect`, `decisions`, `workstream-name-policy`. Each follows the full pattern: SDK source-of-truth, generator (`gen-<name>.mjs`), freshness check (`check-<name>-fresh.mjs`), generated CJS artifact (`<name>.generated.cjs`), CJS shim re-export, parity test, CI step, pre-commit hook, CODEOWNERS entry.
- **Workstream native support:** The sync bridge worker now correctly threads `workstream` through to `registry.dispatch()`. `GSDTransport` no longer forces subprocess for workstream-scoped requests. Workstream-scoped state commands execute natively.
- **State parity divergences resolved:** `state.record-metric` and `state.prune` SDK handlers now match CJS semantics exactly.
- **MIGRATE_ME pairs resolved:** `decisions` and `workstream-name-policy` migrated from `migrateMeBacklog` to `cooperatingSiblings` as ADAPTER-OVER-MODULE.
- **Lint final state:** 22 cooperating siblings, 0 backlog pairs.
**Decisions migration specifics (B1):**
- SDK `decisions.ts` regex aligned to CJS: `D-([A-Za-z0-9_-]+)` (alphanumeric IDs like `D-INFRA-01` accepted).
- SDK returns richer `{id, text, category, tags, trackable}`; CJS callers using only `{id, text}` safely ignore extras.
- Parity test: `tests/decisions-generator.test.cjs` (15 tests covering numeric IDs, alphanumeric IDs, richer schema fields).
**Workstream-name-policy migration specifics (B2):**
- Added `hasInvalidPathSegment` and `isValidActiveWorkstreamName` to SDK `workstream-name-policy.ts`.
- `validateWorkstreamName` is now an alias for `isValidActiveWorkstreamName` (consistent with CJS semantics).
- Parity test: `tests/workstream-name-policy-generator.test.cjs` (19 tests covering all four exports).
---
## Open follow-ups
No migration items remain. The following are future quality candidates, not defects:
- **`config.cjs` / `sdk/src/config.ts`** — These files are CJS-CLI-ONLY (per allowlist classification). The `config.cjs` file contains only CLI command handlers that use sync CJS APIs; `sdk/src/config.ts` provides the async SDK layer. They serve disjoint surfaces. A future migration would require converting the CLI handlers to async + SDK patterns, which is a larger refactor out of scope for this migration cycle.
- **`intel.cjs` / `sdk/src/query/intel.ts`** — Intentional architectural divergence (different file naming conventions between CJS and SDK; documented in allowlist). A future migration would require reconciling INTEL_FILES naming, which is a breaking change for existing consumers.
- **`model-catalog.cjs` / `sdk/src/model-catalog.ts`** — Both sides read from `sdk/shared/model-catalog.json` independently (ADAPTER-OVER-MODULE pattern). This is intentional; the shared JSON is the source-of-truth. No duplication of logic between CJS and SDK consumers.

View File

@@ -0,0 +1,244 @@
# Grok Build + GSD Compatibility & Local Multi-Runtime Sync (May 2026)
**Date:** 2026-05-16
**Status:** Discussion active on closed issue. Awaiting maintainer response.
**Purpose of this document:** Serve as the primary context file for future Grok (or other) agent sessions started inside this repository (`/home/cristian/bum/get-shit-done`) so they can work on local Grok Build support and improved synchronization across multiple AI coding harnesses.
---
## 1. Executive Summary & Goals
**Goal:** Achieve reliable, first-class GSD support when using **Grok Build**, while maintaining excellent compatibility and low-friction synchronization across the four runtimes the author uses daily:
- Grok Build (current primary TUI)
- Claude Code
- Gemini CLI
- Codex
Currently, Grok Build is only supported via its Claude compatibility layer. This creates daily friction in paths, skill discovery, command surfaces, hooks, `grok inspect` output, and mental models.
**Long-term vision:**
- Run GSD natively and cleanly inside Grok Build.
- Maintain a single source of truth in this repository.
- Have a robust, automated (or semi-automated) sync mechanism that deploys adapted skills/agents/hooks to all four runtime environments (`~/.agents/`, `~/.claude/`, `~/.grok/`, Gemini location, Codex location).
- Keep the work clean enough that high-quality pieces can eventually be contributed upstream.
---
## 2. Current Multi-Runtime Setup (as of May 2026)
### Development Source (Single Source of Truth)
- **Path:** `/home/cristian/bum/get-shit-done` (this repo — your working fork of `gsd-build/get-shit-done`)
### Installed Locations
- `~/.agents/get-shit-done/` — Core workflows, references, templates, `gsd-tools.cjs`, `bin/`
- `~/.agents/skills/gsd-*` — ~125 skills (heavily GSD + many large reference skills like `userinterface-wiki`, `react-best-practices`, etc.)
- `~/.agents/agents/` — 22 GSD sub-agents (with `.md` + `.toml`)
- `~/.claude/skills/gsd-*` + `~/.claude/get-shit-done/` + `~/.claude/agents/` — Parallel Claude Code install (~208 skills total)
- `~/.grok/skills/` — Mostly empty (only the 7 official bundled Grok skills)
- `~/.grok/` — Not yet properly used by GSD
### Existing Sync Tooling
- `gsd-sync-skills` skill exists in `~/.agents/skills/gsd-sync-skills/`
- Its stated purpose: "Sync managed GSD skills across runtime roots so multi-runtime users stay aligned after an update"
- Currently uses a combination of manual processes + this skill.
### Codex-Style Adaptations Already in Use
- Many `gsd-*` skills in `~/.agents/skills/` contain a `<codex_skill_adapter>` section at the top.
- This adapter translates Claude Code patterns (`AskUserQuestion`, `Task()`) into Codex/Grok-compatible ones (`request_user_input`, `spawn_agent`).
- This pattern was developed because Grok Build / Codex use a different skill invocation and subagent model than Claude Code.
---
## 3. History & Prior Art
### Previous Upstream Attempt (May 2026)
- **Issue #3603**: "Add Grok Build (`--grok`) as a first-class runtime"
- **PR #3604** (by `lordgraysith`): Very large, high-quality implementation attempt.
The PR included:
- Full `--grok` installer support
- Conversion functions (`convertClaudeToGrokMarkdown`, `convertClaudeCommandToGrokSkill`, `convertClaudeAgentToGrokAgent`)
- JSON hook manifest generation for Grok
- Model catalog entries for Grok models
- `GROK_CONFIG_DIR` support
- Extensive tests and documentation
- A complete planning folder: `docs/grok-build-support/` containing 7 detailed documents:
- 01-runtime-detection-and-config.md
- 02-installer-logic.md
- 03-model-catalog-and-profiles.md
- 04-skills-agents-hooks-conversion.md
- 05-documentation-and-user-experience.md
- 06-testing-strategy.md
- 07-phased-implementation-and-rollout.md
**Outcome:** Both issue and PR were closed the next day by `trek-e` as `not_planned`.
### Maintainer’s Position (Critical Context)
From `trek-e`’s detailed closing comment on #3603:
- **Biggest blockers right now:**
- Grok Build is extremely new (launched May 14, 2026) and still in early beta. Hook events and config surface are unstable.
- Strong desire to protect GSD’s reputation for stability ("vibe coded piece of junk" reputation risk).
- Recent painful experience with Codex making breaking changes shortly after GSD stabilized something.
- **Price was clarified as low priority** ("honestly price is probably the lowest of the factors").
- **Claude-compat already works**, so native support is seen as polish rather than a must-have.
- **Process concern:** Implementation was done before the issue was properly approved.
- **Recommendation:** Revisit once Grok Build has stabilized (versioned config surface held for at least one minor release) **and** is reachable on a more realistic solo-dev price tier.
**Important:** The 7 planning documents in `docs/grok-build-support/` remain excellent reference material even if the code from that PR is not merged.
---
## 4. Recommended Work Plan for Future Grok Sessions in This Repo
When a new Grok session is started inside `/home/cristian/bum/get-shit-done`, it should follow something like this phased approach:
### Phase 0 — Orientation (Current Session Context)
- Read this document fully.
- Read the 7 files in `docs/grok-build-support/`.
- Explore the current local multi-runtime setup (see Section 2 above).
- Understand the existing `gsd-sync-skills` skill and any Codex adapters already present.
### Phase 1 — Audit Current State
- Map exactly what is installed where across `~/.agents/`, `~/.claude/`, `~/.grok/`, and Gemini/Codex locations.
- Identify duplication, drift, and friction points when using GSD in Grok Build today.
- Run `grok inspect` and analyze what it shows for GSD skills.
- Document gaps specific to Grok Build (command surface, hooks, `grok inspect` cleanliness, agent spawning, etc.).
### Phase 2 — Study Prior Art
- Deeply study the conversion specifications in `docs/grok-build-support/04-skills-agents-hooks-conversion.md`.
- Understand what a proper Grok `SKILL.md` should look like (frontmatter, description style, runtime hints).
- Understand Grok hook JSON manifest requirements.
- Review how the previous PR handled model catalog and runtime homes.
- Look for any existing local experiments or partial adapters in this fork.
### Phase 3 — Design Local Grok Adapter (MVP)
Design a practical local solution that works for **this user’s four-runtime reality**, not necessarily a full upstream `--grok` installer yet.
Possible components:
- A local Grok conversion layer (or extension of existing Codex adapters).
- Proper `gsd-*` skills under `~/.grok/skills/` with correct Grok frontmatter + `codex_skill_adapter` sections where needed.
- Grok-compatible agent definitions (`.md` + any required TOML/config).
- JSON hook manifests in `~/.grok/hooks/`.
- Updates to the sync mechanism (`gsd-sync-skills` or a new `gsd-multi-runtime-sync` tool) so one source can deploy cleanly to all four targets.
**Key principle:** Prefer extending/improving the existing sync tooling rather than creating yet another parallel install path.
### Phase 4 — Implementation & Testing
- Implement the MVP Grok adapter in this local fork.
- Create or enhance sync logic.
- Test end-to-end inside an actual Grok Build session:
- `grok inspect` cleanliness
- Command discovery (`/gsd-*` or Grok-native form)
- Agent spawning
- Hook firing
- Full `gsd-new-project` → `gsd-progress` → `gsd-execute-phase` flow
- Verify no regression in Claude / Gemini / Codex usage.
### Phase 5 — Documentation & Future Upstream Path
- Update this discussion note and any relevant docs in the repo.
- Document the local sync architecture clearly.
- Identify which pieces of the local solution would be good candidates for upstream contribution later (when Grok Build is more mature).
---
## 5. Key Files & Areas to Study
**In this repo:**
- `docs/grok-build-support/` (all 7 documents — highest priority)
- `bin/install.js` (installer logic, especially runtime handling and conversion functions)
- `get-shit-done/bin/lib/runtime-homes.cjs`
- `get-shit-done/bin/lib/shell-command-projection.cjs` (hook projection)
- `sdk/shared/model-catalog.json`
- Existing `gsd-sync-skills` skill (in `~/.agents/skills/gsd-sync-skills/`)
- Any skills that already contain `<codex_skill_adapter>` sections (study the pattern)
**External / Prior Art:**
- The original PR #3604 (study the actual conversion code if accessible via the author’s fork)
- Grok Build documentation on skill format, agent format, and hook JSON manifests (as of the session date)
---
## 6. How to Test Grok Build Compatibility Locally
Useful commands and checks when working on this:
- `grok inspect` (and `grok inspect --json`) — check skill discovery, sources, and token counts.
- `grok` TUI inside a real project that uses GSD.
- Full workflow test: `/gsd-progress`, `/gsd-discuss-phase`, `/gsd-plan-phase`, `/gsd-execute-phase`, etc.
- Verify hooks fire correctly via Grok’s JSON hook system.
- Check that subagents (the 22 GSD agents in `~/.agents/agents/`) can be spawned from Grok.
---
## 7. Sync Strategy Principles (for Multi-Runtime)
When designing improvements to sync:
- Single source of truth = this repository (`/home/cristian/bum/get-shit-done`).
- Runtime-specific transformations should be as declarative and maintainable as possible.
- The `<codex_skill_adapter>` pattern is already proven for Grok/Codex — extend it rather than reinvent.
- Prefer generating the runtime-specific artifacts during sync rather than maintaining four separate copies.
- Make it easy to add a fifth runtime later if needed.
---
## 8. Open Questions & Decisions to Make (for Future Sessions)
- Should we aim for a full local `--grok` installer equivalent, or just excellent skill/agent/hook generation + sync?
- How much of the previous PR’s conversion logic can/should be reused locally?
- What is the right balance between “make Grok work great for me now” vs “keep it clean for potential upstream contribution”?
- Should the sync tool become a first-class GSD skill (`gsd-multi-runtime-sync` or similar)?
- How do we handle model profiles and agent routing differences for Grok models?
---
## 9. How to Resume This Work
When starting a new Grok session in this repository, begin by reading:
1. This file: `docs/discussions/grok-build-support-2026-05.md`
2. All files in `docs/grok-build-support/`
3. The existing `gsd-sync-skills` skill
Then follow the phased plan in Section 4.
---
**Last updated:** 2026-05-16 (by Grok, in this session)
---
## 10. Progress — May 2026 Session (Current)
### Audit Findings (Phase 1)
- **Version drift confirmed**: `~/.agents/get-shit-done/` (Grok Build primary) was on 1.38.4; `~/.claude/` on 1.42.2; `~/.codex/` and `~/.gemini/` on 1.41.2.
- `~/.agents/hooks/` was empty (no hooks active for Grok Build sessions).
- `grok inspect` successfully discovers 80+ `gsd-*` skills via the `~/.agents/skills/` layout + the existing `<codex_skill_adapter>` blocks.
- No `grok` or `agents` runtime existed in installer or sync logic.
- `~/.grok/` itself contains only the 7 official bundled skills; GSD lives entirely in the shared `~/.agents/` layout.
### Immediate Actions Taken
- **Engine drift fixed ASAP**: Backed up old `~/.agents/get-shit-done/` to `.backup-1.38.4/`, then rsynced the current source `get-shit-done/` tree into `~/.agents/get-shit-done/`. Now running the latest from this repo (v1.50.0-canary.0). New modules (active-workstream-store, adr-parser, etc.) and updated workflows are live for Grok Build sessions.
- **First-class 'grok' runtime added** (pragmatic choice: maps to `~/.agents/`):
- [get-shit-done/bin/lib/runtime-homes.cjs](/home/cristian/bum/get-shit-done/get-shit-done/bin/lib/runtime-homes.cjs): Added `grok` case (honors `GROK_AGENTS_HOME` env, defaults to `~/.agents`).
- [bin/install.js](/home/cristian/bum/get-shit-done/bin/install.js): Added `--grok` flag, `hasGrok`, `getDirName('grok') → '.agents'`, `getGlobalDir('grok')`, `getConfigDirFromHome`, inclusion in `--all` and help text. Reuses existing Codex conversion logic (skill adapters + agent .toml generation) because Grok Build uses the same invocation model.
- [get-shit-done/workflows/sync-skills.md](/home/cristian/bum/get-shit-done/get-shit-done/workflows/sync-skills.md): Added `grok` to supported runtimes and the `--to all` list.
- Verified: `node bin/install.js --skills-root grok` correctly returns `~/.agents/skills`.
### Next Steps (for follow-up sessions)
- Full `gsd install --grok --global` end-to-end (hook projection, agent .toml generation with correct sandbox, skill wrapping with adapters, statusline, etc.). Currently the flag is recognized but some codex-specific install branches may need `|| runtime === 'grok'`.
- Run `gsd update --sync --from claude --to grok --apply` (or `--from grok --to claude`) once the runtime is fully wired, to keep the 4 harnesses in sync without manual rsync.
- Slim the `<codex_skill_adapter>` blocks (currently ~60 lines inlined in every gsd-* SKILL.md). Options: extract detailed mapping to a shared `@reference/codex-skill-adapter.md` that skills include, or make the adapter header shorter/optional for lower `grok inspect` token cost.
- Investigate Grok Build native hook support (JSON manifests under `~/.grok/hooks/` vs the shell hooks in `~/.agents/hooks/`).
- Update `grok inspect` output cleanliness (remove "unknown tool prefix: Skill(gsd:*)" warnings if possible via settings or skill manifest).
- Consider whether to also populate a native `~/.grok/skills/gsd-*` tree in addition to the working `.agents` layout.
This session delivered working `grok` runtime resolution + immediate version parity for the user's primary Grok Build harness.
---
**Last updated:** 2026-05-16 (by Grok, in this session)
This document is intended to be living. Update it as the local Grok Build work progresses.