* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9,9 +9,9 @@ We decided to centralize model-selection data in one Model Catalog Module so the
|
||||
|
||||
Before this ADR there were four drifting sources:
|
||||
|
||||
1. `get-shit-done/bin/lib/model-profiles.cjs` — agent → profile alias map, phase-type map, dynamic-routing default tiers
|
||||
1. `gsd-core/bin/lib/model-profiles.cjs` — agent → profile alias map, phase-type map, dynamic-routing default tiers
|
||||
2. `sdk/src/query/config-query.ts` — stale 18-agent copy of `MODEL_PROFILES`
|
||||
3. `get-shit-done/workflows/settings-advanced.md` — runtime → built-in model-id table
|
||||
3. `gsd-core/workflows/settings-advanced.md` — runtime → built-in model-id table
|
||||
4. `sdk/src/session-runner.ts` — hardcoded Claude-only profile → model-id map
|
||||
|
||||
This caused issue #3229: the SDK knew only 18 agents while 33 agent files existed on disk, so ~15 agents silently fell back to Sonnet with `unknown_agent: true`.
|
||||
|
||||
@@ -7,7 +7,7 @@ We propose introducing a Shell Command Projection Module that owns projection fr
|
||||
|
||||
## Decision
|
||||
|
||||
- Add a **Shell Command Projection Module** under `get-shit-done/bin/lib/` as the single owner for runtime-aware command-text rendering.
|
||||
- Add a **Shell Command Projection Module** under `gsd-core/bin/lib/` as the single owner for runtime-aware command-text rendering.
|
||||
- Feed the module typed inputs (`platform`, `shell`, `runtime`, executable token, args, path policy) instead of prebuilt shell strings.
|
||||
- Keep callers as thin Adapters that request projected text for:
|
||||
- managed hook commands in `settings.json`
|
||||
@@ -125,7 +125,7 @@ The seam grew beyond the original "rendering only" scope. The "does not become a
|
||||
|
||||
**Open question resolutions:**
|
||||
|
||||
- Q4 (installer-only vs shared seam): **resolved — shared.** The seam lives in `get-shit-done/bin/lib/`, consumed by installer, planning workflow, and every fs/subprocess call site across the tool.
|
||||
- Q4 (installer-only vs shared seam): **resolved — shared.** The seam lives in `gsd-core/bin/lib/`, consumed by installer, planning workflow, and every fs/subprocess call site across the tool.
|
||||
- Q1, Q2, Q3 (`hooks.shell_preference`, Windows Git Bash modeling, shim/script builder migration timing): unresolved, carried forward as projection-design concerns independent of the I/O expansion.
|
||||
|
||||
See CONTEXT.md "Shell Command Projection Module" entry for the canonical current-state description.
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
---
|
||||
|
||||
We propose introducing a File Operation Engine Module that owns policy for managed file reads, writes, deletes, locks, backups, and rollbacks across installer, migration, and planning surfaces. Today, file mutation behavior is duplicated across `bin/install.js`, `get-shit-done/bin/lib/installer-migrations.cjs`, and multiple planning modules, with drift in atomic-write guarantees, path safety checks, and ownership classification.
|
||||
We propose introducing a File Operation Engine Module that owns policy for managed file reads, writes, deletes, locks, backups, and rollbacks across installer, migration, and planning surfaces. Today, file mutation behavior is duplicated across `bin/install.js`, `gsd-core/bin/lib/installer-migrations.cjs`, and multiple planning modules, with drift in atomic-write guarantees, path safety checks, and ownership classification.
|
||||
|
||||
This ADR also captures where Shell Command Projection Module policy should be consumed or expanded for hook-command-specific file mutations, so shell command drift and file mutation drift do not evolve as separate bug classes.
|
||||
|
||||
## Decision
|
||||
|
||||
- Add a **File Operation Engine Module** under `get-shit-done/bin/lib/` as the single seam for file mutation safety policy.
|
||||
- Add a **File Operation Engine Module** under `gsd-core/bin/lib/` as the single seam for file mutation safety policy.
|
||||
- Keep command-text projection in the Shell Command Projection Module (ADR-0009), but route projection-adjacent hook file mutations through shared managed-hook ownership policy.
|
||||
- Move file operation adapters to the new seam in two tracks:
|
||||
- **Track A (projection-adjacent):** runtime config hook-command detection/rewrite/delete paths consume shared managed-hook policy from the projection seam.
|
||||
@@ -36,9 +36,9 @@ This ADR also captures where Shell Command Projection Module policy should be co
|
||||
- hook cleanup command detection (`isGsdHookCommand`)
|
||||
- stale Codex hook strip basenames (`STALE_HOOK_BASENAMES`)
|
||||
- settings/config hook entry prune/rewrite paths
|
||||
- `get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs`
|
||||
- `gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs`
|
||||
- `isManagedCodexHookCommand` regex/path detection duplicated from installer-owned hook policy
|
||||
- `get-shit-done/bin/lib/shell-command-projection.cjs`
|
||||
- `gsd-core/bin/lib/shell-command-projection.cjs`
|
||||
- `isManagedHookBasename` already owns part of this policy and should become the canonical owner
|
||||
|
||||
### Solution-wide file operation drift (Track B)
|
||||
@@ -46,13 +46,13 @@ This ADR also captures where Shell Command Projection Module policy should be co
|
||||
- `bin/install.js`
|
||||
- local `atomicWriteFileSync` and temp cleanup registry
|
||||
- large inlined read/modify/write + backup/rollback logic for runtime config and hooks
|
||||
- `get-shit-done/bin/lib/core.cjs`
|
||||
- `gsd-core/bin/lib/core.cjs`
|
||||
- `atomicWriteFileSync` helper diverges in fallback behavior from installer/migration variants
|
||||
- `get-shit-done/bin/lib/installer-migrations.cjs`
|
||||
- `gsd-core/bin/lib/installer-migrations.cjs`
|
||||
- separate `writeFileAtomicSync`, rollback journaling, lock handling, and containment checks
|
||||
- `get-shit-done/bin/lib/planning-workspace.cjs` and `get-shit-done/bin/lib/state.cjs`
|
||||
- `gsd-core/bin/lib/planning-workspace.cjs` and `gsd-core/bin/lib/state.cjs`
|
||||
- duplicated lock-file create/release/remove patterns and best-effort cleanup semantics
|
||||
- `get-shit-done/bin/lib/roadmap.cjs`, `phase.cjs`, `milestone.cjs`, `frontmatter.cjs`, `drift.cjs`
|
||||
- `gsd-core/bin/lib/roadmap.cjs`, `phase.cjs`, `milestone.cjs`, `frontmatter.cjs`, `drift.cjs`
|
||||
- direct read/modify/write flows with inconsistent atomicity and normalization policy application
|
||||
|
||||
## Interface sketch
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
- **Status:** Proposed
|
||||
- **Date:** 2026-05-12
|
||||
|
||||
We propose extending the existing install profile seam (`get-shit-done/bin/lib/install-profiles.cjs`) into a **Skill Surface Budget Module** that owns which subset of GSD's 66 skills is written to the runtime config dirs, and that owns the per-skill `requires:` dependency manifest used to keep that subset closed under cross-skill references. GSD currently ships a binary `--minimal` / full toggle; runtimes that enumerate skills (Claude Code, OpenCode, etc.) cap the `<available_skills>` system-prompt block at `skillListingBudgetFraction` of the context window (default 1% = ~2k tokens at 200k), and GSD alone consumes ~60% of that cap (#3408). Further description shrinkage is unavailable — `scripts/lint-descriptions.cjs` already enforces a hard 100-char ceiling and the mean is 72.5 chars. The remaining lever is surfacing fewer skills, which requires a typed profile model plus a dependency manifest, not more ad-hoc allowlists.
|
||||
We propose extending the existing install profile seam (`gsd-core/bin/lib/install-profiles.cjs`) into a **Skill Surface Budget Module** that owns which subset of GSD's 66 skills is written to the runtime config dirs, and that owns the per-skill `requires:` dependency manifest used to keep that subset closed under cross-skill references. GSD currently ships a binary `--minimal` / full toggle; runtimes that enumerate skills (Claude Code, OpenCode, etc.) cap the `<available_skills>` system-prompt block at `skillListingBudgetFraction` of the context window (default 1% = ~2k tokens at 200k), and GSD alone consumes ~60% of that cap (#3408). Further description shrinkage is unavailable — `scripts/lint-descriptions.cjs` already enforces a hard 100-char ceiling and the mean is 72.5 chars. The remaining lever is surfacing fewer skills, which requires a typed profile model plus a dependency manifest, not more ad-hoc allowlists.
|
||||
|
||||
## Decision
|
||||
|
||||
- Add a **Skill Surface Budget Module** by extending `get-shit-done/bin/lib/install-profiles.cjs` as the single owner for which `commands/gsd/*.md` and `agents/gsd-*.md` files are staged into the per-runtime copy pipeline.
|
||||
- Add a **Skill Surface Budget Module** by extending `gsd-core/bin/lib/install-profiles.cjs` as the single owner for which `commands/gsd/*.md` and `agents/gsd-*.md` files are staged into the per-runtime copy pipeline.
|
||||
- Replace the single `MINIMAL_SKILL_ALLOWLIST` constant with a typed `PROFILES` map keyed by profile name. Each profile is a *base set* of skills; the module computes the **transitive closure** over each skill's declared `requires:` set before staging.
|
||||
- Add a `requires:` frontmatter field to every skill whose body references another GSD skill. The dependency graph in the research memo (`docs/research/2026-05-12-skill-surface-budget.md` §3.1) is the migration spec for this pass.
|
||||
- Extend `bin/install.js` argument parsing to accept `--profile=<name>` and `--profile=<name1>,<name2>` (composable). Preserve `--minimal` / `--core-only` as aliases for `--profile=core`. Default install (no flag) remains `full` for back-compat.
|
||||
@@ -35,7 +35,7 @@ It should **not** in the first pass:
|
||||
|
||||
## Migration Inventory
|
||||
|
||||
### `get-shit-done/bin/lib/install-profiles.cjs`
|
||||
### `gsd-core/bin/lib/install-profiles.cjs`
|
||||
|
||||
- Replace `MINIMAL_SKILL_ALLOWLIST` Object.freeze constant with `PROFILES` Object.freeze map of profile-name → base skill set.
|
||||
- Replace `isMinimalMode(mode)` with `resolveProfile(mode)` returning a typed `{name, skills: Set, agents: Set}` after transitive-closure computation.
|
||||
@@ -141,7 +141,7 @@ requires: [phase, discuss-phase] # GSD skills only; not Claude Code primitives
|
||||
|
||||
- Feature issue: `#3408`
|
||||
- Research input: `docs/research/2026-05-12-skill-surface-budget.md`
|
||||
- Existing seam being extended: `get-shit-done/bin/lib/install-profiles.cjs`
|
||||
- Existing seam being extended: `gsd-core/bin/lib/install-profiles.cjs`
|
||||
- Description budget enforcement: `scripts/lint-descriptions.cjs`
|
||||
- Installer dispatch site: `bin/install.js:123-124`, `:8167-8207`
|
||||
- See `0008-installer-migration-module.md` (the migration that records the profile marker lives here)
|
||||
|
||||
@@ -11,7 +11,7 @@ The root problem is an absence of a profile/surface seam: the installer wrote ev
|
||||
|
||||
## Decision
|
||||
|
||||
- Add a **Skill Surface Budget Module** under `get-shit-done/bin/lib/install-profiles.cjs` as the single owner for which skills and agents are written to runtime config directories.
|
||||
- Add a **Skill Surface Budget Module** under `gsd-core/bin/lib/install-profiles.cjs` as the single owner for which skills and agents are written to runtime config directories.
|
||||
- Define three named profiles: `core` (six skills covering the main loop), `standard` (core + phase management and workspace skills), and `full` (all skills — the previous default).
|
||||
- Compute each profile's effective skill set as the transitive closure over the `requires:` dependency graph extracted from skill frontmatter, so partial installs never break cross-skill dependencies.
|
||||
- Persist the chosen profile in a `.gsd-profile` marker file in each runtime config directory; `gsd update` reads the marker to honor the profile on re-install.
|
||||
@@ -33,9 +33,9 @@ The Phase 2 decision, previously listed as an open question, is recorded here as
|
||||
- `disable <cluster>` — mark a cluster disabled; re-stage to remove its skills from the runtime config dir
|
||||
- `enable <cluster>` — mark a cluster enabled; re-stage to add its skills back
|
||||
- `reset` — clear surface state and re-apply the active profile from `.gsd-profile`
|
||||
- Implement the runtime surface engine in `get-shit-done/bin/lib/surface.cjs`, consuming `stageSkillsForProfile` and `stageAgentsForProfile` from the Phase 1 module without duplicating staging logic.
|
||||
- Implement the runtime surface engine in `gsd-core/bin/lib/surface.cjs`, consuming `stageSkillsForProfile` and `stageAgentsForProfile` from the Phase 1 module without duplicating staging logic.
|
||||
- Persist per-runtime surface state in `<runtimeConfigDir>/.gsd-surface.json`, independent from `.gsd-profile`. The profile marker owns install-time identity; the surface JSON owns session-scope cluster toggles.
|
||||
- Source cluster taxonomy from the research memo §3.2 (2026-05-12-skill-surface-budget.md). Define clusters in `get-shit-done/bin/lib/clusters.cjs` — a separate module so the surface engine and future SDK callers can import cluster definitions without loading the full profile module.
|
||||
- Source cluster taxonomy from the research memo §3.2 (2026-05-12-skill-surface-budget.md). Define clusters in `gsd-core/bin/lib/clusters.cjs` — a separate module so the surface engine and future SDK callers can import cluster definitions without loading the full profile module.
|
||||
- Cluster taxonomy: `core_loop`, `audit_review`, `milestone`, `research_ideate`, `workspace_state`, `docs`, `ui`, `ai_eval`, `ns_meta`, `utility`. Membership may overlap; every installed skill stem must appear in at least one cluster (enforced by `tests/surface-clusters.test.cjs`).
|
||||
- Relationship to Anthropic platform asks: Asks D (native per-skill toggle API) and E (budget-fraction negotiation) remain filed separately. The `/gsd:surface` command is a unilateral GSD-side workaround that does not depend on those platform changes.
|
||||
|
||||
@@ -43,7 +43,7 @@ The Phase 2 decision, previously listed as an open question, is recorded here as
|
||||
|
||||
Phase 1 artifacts landed on `feat/3408-skills-description-dropped-due-to-size`:
|
||||
|
||||
- `get-shit-done/bin/lib/install-profiles.cjs` — `PROFILES` map, `resolveProfile`, `loadSkillsManifest`, `stageSkillsForProfile`, `stageAgentsForProfile`, `readActiveProfile`, `writeActiveProfile`, `mostRestrictiveProfile`, `resolveEffectiveProfile`
|
||||
- `gsd-core/bin/lib/install-profiles.cjs` — `PROFILES` map, `resolveProfile`, `loadSkillsManifest`, `stageSkillsForProfile`, `stageAgentsForProfile`, `readActiveProfile`, `writeActiveProfile`, `mostRestrictiveProfile`, `resolveEffectiveProfile`
|
||||
- `requires:` frontmatter added to 64 skills in `commands/gsd/*.md`
|
||||
- `scripts/lint-skill-deps.cjs` — CI gate for `requires:` integrity, wired into `pretest`
|
||||
- `bin/install.js` — `--profile=<name>` flag (composable); `--minimal`/`--core-only` as aliases; `.gsd-profile` marker write on install; `gsd update` re-reads marker
|
||||
@@ -52,8 +52,8 @@ Phase 1 artifacts landed on `feat/3408-skills-description-dropped-due-to-size`:
|
||||
Phase 2 shipped on the same branch:
|
||||
|
||||
- `commands/gsd/surface.md` — `/gsd:surface` slash command runbook (sub-commands: `list`, `status`, `profile <name>`, `disable <cluster>`, `enable <cluster>`, `reset`)
|
||||
- `get-shit-done/bin/lib/surface.cjs` — runtime engine (`readSurface`, `writeSurface`, `resolveSurface`, `applySurface`, `listSurface`); reuses `stageSkillsForProfile` / `stageAgentsForProfile` from Phase 1
|
||||
- `get-shit-done/bin/lib/clusters.cjs` — 10-cluster taxonomy covering all installed skill stems
|
||||
- `gsd-core/bin/lib/surface.cjs` — runtime engine (`readSurface`, `writeSurface`, `resolveSurface`, `applySurface`, `listSurface`); reuses `stageSkillsForProfile` / `stageAgentsForProfile` from Phase 1
|
||||
- `gsd-core/bin/lib/clusters.cjs` — 10-cluster taxonomy covering all installed skill stems
|
||||
- Tests: `tests/surface-state.test.cjs`, `tests/surface-clusters.test.cjs`, `tests/surface-resolve.test.cjs`, `tests/surface-apply.test.cjs`, `tests/surface-list.test.cjs`
|
||||
- Persistent surface state: `<runtimeConfigDir>/.gsd-surface.json` (independent from `.gsd-profile`)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Seven `*-command-router.cjs` files (`phase`, `phases`, `roadmap`, `state`, `veri
|
||||
|
||||
## Decision
|
||||
|
||||
Introduce `CommandRoutingHub` (`get-shit-done/bin/lib/command-routing-hub.cjs`) as the single dispatch seam for all CJS command family routers. The hub contract:
|
||||
Introduce `CommandRoutingHub` (`gsd-core/bin/lib/command-routing-hub.cjs`) as the single dispatch seam for all CJS command family routers. The hub contract:
|
||||
|
||||
```
|
||||
createHub({ mode: 'sdk' | 'cjs', sdkLoader, cjsRegistry, manifest }) -> hub
|
||||
|
||||
@@ -164,12 +164,12 @@ Root architectural gap: orchestration flows lack a plan strategy seam (`local` v
|
||||
|
||||
- Issue: #15
|
||||
- `commands/gsd/progress.md`
|
||||
- `get-shit-done/workflows/progress.md`
|
||||
- `get-shit-done/workflows/next.md`
|
||||
- `gsd-core/workflows/progress.md`
|
||||
- `gsd-core/workflows/next.md`
|
||||
- `commands/gsd/autonomous.md`
|
||||
- `get-shit-done/workflows/autonomous.md`
|
||||
- `gsd-core/workflows/autonomous.md`
|
||||
- `commands/gsd/plan-review-convergence.md`
|
||||
- `get-shit-done/workflows/plan-review-convergence.md`
|
||||
- `gsd-core/workflows/plan-review-convergence.md`
|
||||
- `commands/gsd/review.md`
|
||||
- `docs/COMMANDS.md` (`/gsd-plan-review-convergence`, `/gsd-review`)
|
||||
- `docs/CONFIGURATION.md` (`workflow.plan_review_convergence`, `review.default_reviewers`, `review.models.*`)
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
- **Extends:** ADR-0005 (seam map) — adds the **Shared-Module Source Policy** to the seam family
|
||||
- **Defers to:** ADR-0001 (Dispatch Policy Module), ADR-0003 (Model Catalog Module), ADR-0004 (Planning Workspace Module), ADR-0006 (Planning Path Projection Module), ADR-0009 (Shell Command Projection Module — post-Phase 3–4, also subsuming superseded ADR-0010)
|
||||
|
||||
We decided to harden the boundary between the CJS tooling layer (`get-shit-done/bin/lib/*.cjs`) and the SDK (`sdk/src/**/*.ts`) by making every Module that is conceptually shared between the two runtimes have exactly one hand-authored source of truth and at most one generated artifact per runtime. The trigger is the recurring drift bug class — #1535, #1542, #2047/#2052, #2638/#2655, #2653/#2670, #2687/#2706, #2798/#2816, #3055/#3116, #3523 — each of which was a fix landing on one side without the other.
|
||||
We decided to harden the boundary between the CJS tooling layer (`gsd-core/bin/lib/*.cjs`) and the SDK (`sdk/src/**/*.ts`) by making every Module that is conceptually shared between the two runtimes have exactly one hand-authored source of truth and at most one generated artifact per runtime. The trigger is the recurring drift bug class — #1535, #1542, #2047/#2052, #2638/#2655, #2653/#2670, #2687/#2706, #2798/#2816, #3055/#3116, #3523 — each of which was a fix landing on one side without the other.
|
||||
|
||||
The precedent shape is already in the repo. `sdk/scripts/gen-command-aliases.ts` emits `sdk/src/query/command-aliases.generated.ts` **and** `get-shit-done/bin/lib/command-aliases.generated.cjs` from one TypeScript source. `sdk/scripts/check-command-aliases-fresh.mjs` is the CI freshness gate. The two consuming sides are pure Adapters over the generated artifact. This ADR generalizes that pattern to the other Shared Modules and forbids the hand-synced-pair anti-pattern that produced #3523.
|
||||
The precedent shape is already in the repo. `sdk/scripts/gen-command-aliases.ts` emits `sdk/src/query/command-aliases.generated.ts` **and** `gsd-core/bin/lib/command-aliases.generated.cjs` from one TypeScript source. `sdk/scripts/check-command-aliases-fresh.mjs` is the CI freshness gate. The two consuming sides are pure Adapters over the generated artifact. This ADR generalizes that pattern to the other Shared Modules and forbids the hand-synced-pair anti-pattern that produced #3523.
|
||||
|
||||
## Decision
|
||||
|
||||
@@ -20,10 +20,10 @@ A **Shared Module** is any Module whose Interface is consumed identically by bot
|
||||
For every Shared Module:
|
||||
|
||||
1. **Exactly one hand-authored source of truth.** Lives at `sdk/src/<module-name>/` as TypeScript when the Module has behavior, or `sdk/shared/<module-name>.manifest.json` when the Module is pure data.
|
||||
2. **Generated artifacts only.** The CJS-side file is `get-shit-done/bin/lib/<module-name>.generated.cjs` and is emitted mechanically. It is never hand-edited.
|
||||
2. **Generated artifacts only.** The CJS-side file is `gsd-core/bin/lib/<module-name>.generated.cjs` and is emitted mechanically. It is never hand-edited.
|
||||
3. **Per-Module freshness check.** A CI script `sdk/scripts/check-<module>-fresh.mjs` re-runs the generator and fails if the emitted artifact differs from the committed one. Precedent: `check-command-aliases-fresh.mjs`.
|
||||
4. **Per-Module drift lint** (when the source is data, not a generator output). Precedent: `scripts/lint-shell-command-projection-drift.cjs`. The lint asserts the canonical-owner invariants that aren't captured by file-equality.
|
||||
5. **Hand-synced pairs are forbidden.** A pre-merge `lint-shared-module-handsync.cjs` greps `get-shit-done/bin/lib/` for non-`.generated.*` files whose basename matches a `sdk/src/query/<same-name>.ts` source and fails the build unless the pair is explicitly allow-listed.
|
||||
5. **Hand-synced pairs are forbidden.** A pre-merge `lint-shared-module-handsync.cjs` greps `gsd-core/bin/lib/` for non-`.generated.*` files whose basename matches a `sdk/src/query/<same-name>.ts` source and fails the build unless the pair is explicitly allow-listed.
|
||||
|
||||
### 2. Module-indexed canonical-owner table
|
||||
|
||||
@@ -31,13 +31,13 @@ The table below indexes by Module, not by physical layer. Each row names the sou
|
||||
|
||||
| Module | Status | Source of truth | Generated artifacts | Adapters |
|
||||
|---|---|---|---|---|
|
||||
| **STATE.md Document Module** | New under this ADR (Phase 1) — see CONTEXT.md "STATE.md Document Module" | `sdk/src/state/index.ts` (promoted from `sdk/src/query/state-document.ts`) | `sdk/src/query/state-document.generated.ts`, `get-shit-done/bin/lib/state-document.generated.cjs` | `bin/lib/state.cjs` and `sdk/src/query/state*.ts` import the generated form |
|
||||
| **Configuration Module** | New under this ADR (Phase 2) — definition added to CONTEXT.md as part of Phase 2 | `sdk/src/config/index.ts` plus data manifests `sdk/shared/config-schema.manifest.json` and `sdk/shared/config-defaults.manifest.json` | `sdk/src/query/config-schema.generated.ts`, `get-shit-done/bin/lib/config-schema.generated.cjs`, `get-shit-done/bin/lib/configuration.generated.cjs` | `bin/lib/config.cjs`, `bin/lib/core.cjs:loadConfig`, `sdk/src/config.ts` |
|
||||
| **Workstream Inventory Module** (Builder) | Amended under this ADR (Phase 3) — Builder split documented in CONTEXT.md update | `sdk/src/workstream/builder.ts` (pure projection from directory entries + STATE.md text + plan scan results → typed inventory) | `sdk/src/query/workstream-inventory-builder.generated.ts`, `get-shit-done/bin/lib/workstream-inventory-builder.generated.cjs` | Per-side fs Readers (`workstream-inventory.cjs` sync, `workstream-inventory.ts` async) call the Builder. Readers stay hand-authored because the fs idiom legitimately differs. |
|
||||
| **Project-Root Resolution Module** | New under this ADR (Phase 4) — short CONTEXT.md entry, behavior already de-facto shared | `sdk/src/project-root/index.ts` | `get-shit-done/bin/lib/project-root.generated.cjs` | `bin/lib/core.cjs` (`findProjectRoot`, `findEffectiveRoot`), `sdk/src/helpers.ts` |
|
||||
| **Frontmatter Module** | Conditional (Phase 3, only if drift catalogue confirms pair duplication) | `sdk/src/frontmatter/index.ts` | `get-shit-done/bin/lib/frontmatter.generated.cjs` | Existing handler call sites |
|
||||
| **Plan Scan Module** | Conditional (Phase 3 or later) | `sdk/src/plan-scan/index.ts` | `get-shit-done/bin/lib/plan-scan.generated.cjs` | Phase/roadmap routers |
|
||||
| **CJS Command Router Adapter Module** | Amended under this ADR (Phase 5). Existing Module (per CONTEXT.md) is extended so the per-family `handlers` map delegates to the SDK runtime bridge in-process instead of to parallel CJS handler implementations. | `sdk/src/query-runtime-bridge.ts` (already exists) + per-family delegate emitter | `get-shit-done/bin/lib/cjs-command-router-adapter.cjs` (existing, ~40 lines) plus per-family `handlers` maps that `require('../../sdk/dist/query-runtime-bridge.cjs')` and call `QueryRuntimeBridge.execute()` | `bin/gsd-tools.cjs` and the seven `bin/lib/*-command-router.cjs` files are the consumers. Per-family CJS handler files (`state.cjs`, `verify.cjs`, `init.cjs`, etc.) shrink to delegates or are deleted once the SDK handler is the only implementation. |
|
||||
| **STATE.md Document Module** | New under this ADR (Phase 1) — see CONTEXT.md "STATE.md Document Module" | `sdk/src/state/index.ts` (promoted from `sdk/src/query/state-document.ts`) | `sdk/src/query/state-document.generated.ts`, `gsd-core/bin/lib/state-document.generated.cjs` | `bin/lib/state.cjs` and `sdk/src/query/state*.ts` import the generated form |
|
||||
| **Configuration Module** | New under this ADR (Phase 2) — definition added to CONTEXT.md as part of Phase 2 | `sdk/src/config/index.ts` plus data manifests `sdk/shared/config-schema.manifest.json` and `sdk/shared/config-defaults.manifest.json` | `sdk/src/query/config-schema.generated.ts`, `gsd-core/bin/lib/config-schema.generated.cjs`, `gsd-core/bin/lib/configuration.generated.cjs` | `bin/lib/config.cjs`, `bin/lib/core.cjs:loadConfig`, `sdk/src/config.ts` |
|
||||
| **Workstream Inventory Module** (Builder) | Amended under this ADR (Phase 3) — Builder split documented in CONTEXT.md update | `sdk/src/workstream/builder.ts` (pure projection from directory entries + STATE.md text + plan scan results → typed inventory) | `sdk/src/query/workstream-inventory-builder.generated.ts`, `gsd-core/bin/lib/workstream-inventory-builder.generated.cjs` | Per-side fs Readers (`workstream-inventory.cjs` sync, `workstream-inventory.ts` async) call the Builder. Readers stay hand-authored because the fs idiom legitimately differs. |
|
||||
| **Project-Root Resolution Module** | New under this ADR (Phase 4) — short CONTEXT.md entry, behavior already de-facto shared | `sdk/src/project-root/index.ts` | `gsd-core/bin/lib/project-root.generated.cjs` | `bin/lib/core.cjs` (`findProjectRoot`, `findEffectiveRoot`), `sdk/src/helpers.ts` |
|
||||
| **Frontmatter Module** | Conditional (Phase 3, only if drift catalogue confirms pair duplication) | `sdk/src/frontmatter/index.ts` | `gsd-core/bin/lib/frontmatter.generated.cjs` | Existing handler call sites |
|
||||
| **Plan Scan Module** | Conditional (Phase 3 or later) | `sdk/src/plan-scan/index.ts` | `gsd-core/bin/lib/plan-scan.generated.cjs` | Phase/roadmap routers |
|
||||
| **CJS Command Router Adapter Module** | Amended under this ADR (Phase 5). Existing Module (per CONTEXT.md) is extended so the per-family `handlers` map delegates to the SDK runtime bridge in-process instead of to parallel CJS handler implementations. | `sdk/src/query-runtime-bridge.ts` (already exists) + per-family delegate emitter | `gsd-core/bin/lib/cjs-command-router-adapter.cjs` (existing, ~40 lines) plus per-family `handlers` maps that `require('../../sdk/dist/query-runtime-bridge.cjs')` and call `QueryRuntimeBridge.execute()` | `bin/gsd-tools.cjs` and the seven `bin/lib/*-command-router.cjs` files are the consumers. Per-family CJS handler files (`state.cjs`, `verify.cjs`, `init.cjs`, etc.) shrink to delegates or are deleted once the SDK handler is the only implementation. |
|
||||
| Command-Alias Module | **Already sealed** by this pattern's precedent — `sdk/scripts/gen-command-aliases.ts` + `check-command-aliases-fresh.mjs` | No change | No change | No change |
|
||||
| Dispatch Policy Module | **Defer — see ADR-0001** (and its 2026-05-05 SDK Runtime Bridge amendment) | n/a | n/a | n/a |
|
||||
| Model Catalog Module | **Defer — see ADR-0003**; the `sdk/shared/model-catalog.json` manifest already follows the source-of-truth policy | n/a | n/a | n/a |
|
||||
@@ -68,7 +68,7 @@ Drift is blocked at three layers, each modeled on an existing in-repo script:
|
||||
|
||||
1. **Per-Module freshness check** — `sdk/scripts/check-<module>-fresh.mjs`, one per Shared Module in the table. Precedent: `check-command-aliases-fresh.mjs`.
|
||||
2. **Per-Module drift lint** (when invariants are not pure file-equality) — `scripts/lint-<module>-drift.cjs`, one per data-manifest-backed Module. Precedent: `lint-shell-command-projection-drift.cjs`.
|
||||
3. **Hand-sync pair lint** — `scripts/lint-shared-module-handsync.cjs` rejects any pair of files at `get-shit-done/bin/lib/<name>.cjs` and `sdk/src/query/<name>.ts` (or `sdk/src/<name>.ts`) that are neither generated artifacts nor on an explicit allow-list. This blocks the #3523 anti-pattern at PR time.
|
||||
3. **Hand-sync pair lint** — `scripts/lint-shared-module-handsync.cjs` rejects any pair of files at `gsd-core/bin/lib/<name>.cjs` and `sdk/src/query/<name>.ts` (or `sdk/src/<name>.ts`) that are neither generated artifacts nor on an explicit allow-list. This blocks the #3523 anti-pattern at PR time.
|
||||
|
||||
CODEOWNERS extends to `sdk/src/<module>/` for each Shared Module. Architecture-team review is required for changes to a source of truth.
|
||||
|
||||
@@ -105,11 +105,11 @@ _(Append-only. Use a dated header when the decision evolves.)_
|
||||
### 2026-05-23 — validate.ts → verify.cjs generator pattern (issue #6)
|
||||
|
||||
Three pure helpers from `sdk/src/query/validate.ts` Check 8 are now generated into
|
||||
`get-shit-done/bin/lib/validate.generated.cjs` via `sdk/scripts/gen-validate.mjs`,
|
||||
`gsd-core/bin/lib/validate.generated.cjs` via `sdk/scripts/gen-validate.mjs`,
|
||||
following the same I/O adapter pattern established by PR #154 (issue #4):
|
||||
|
||||
**Generator:** `sdk/scripts/gen-validate.mjs`
|
||||
**Artifact:** `get-shit-done/bin/lib/validate.generated.cjs`
|
||||
**Artifact:** `gsd-core/bin/lib/validate.generated.cjs`
|
||||
**Freshness check:** `sdk/scripts/check-validate-fresh.mjs`
|
||||
**CI:** `.github/workflows/test.yml` — "SDK generated validate artifact drift check"
|
||||
|
||||
@@ -150,7 +150,7 @@ is still a full implementation; only Check 8 helpers are generated).
|
||||
#### Extension — issue #26: W005/W006-archived/I001 generator migration
|
||||
|
||||
PR #3479 fixed three false-positive classes in `sdk/src/query/validate.ts`. PR #3806 hand-ported
|
||||
the three fixes to `get-shit-done/bin/lib/verify.cjs` but did not route them through the generator
|
||||
the three fixes to `gsd-core/bin/lib/verify.cjs` but did not route them through the generator
|
||||
— meaning they could drift again. Issue #26 closes this gap by extending `gen-validate.mjs`
|
||||
(introduced in this amendment above) to also extract and export the W005/W006-archived/I001 items.
|
||||
|
||||
@@ -211,11 +211,11 @@ verify.cjs migration scope for generator-pattern coverage.
|
||||
**Decision:** Apply the I/O adapter pattern (Section 4) to the pure-computation kernel inside `phase-lifecycle.ts`:
|
||||
|
||||
1. **Three new generator scripts** extract pure helpers from the phase family:
|
||||
- `sdk/scripts/gen-phase.mjs` → `get-shit-done/bin/lib/phase.generated.cjs`
|
||||
- `sdk/scripts/gen-phase.mjs` → `gsd-core/bin/lib/phase.generated.cjs`
|
||||
(pure helpers: `isCanonicalPlanFile`, `describeNonCanonicalPlans`)
|
||||
- `sdk/scripts/gen-phase-lifecycle.mjs` → `get-shit-done/bin/lib/phase-lifecycle.generated.cjs`
|
||||
- `sdk/scripts/gen-phase-lifecycle.mjs` → `gsd-core/bin/lib/phase-lifecycle.generated.cjs`
|
||||
(pure helpers: `deriveProgressFromRoadmap`, `clampPercent`)
|
||||
- `sdk/scripts/gen-phase-lifecycle-policy.mjs` → `get-shit-done/bin/lib/phase-lifecycle-policy.generated.cjs`
|
||||
- `sdk/scripts/gen-phase-lifecycle-policy.mjs` → `gsd-core/bin/lib/phase-lifecycle-policy.generated.cjs`
|
||||
(14 pure policy helpers: `generatePhaseSlug`, `computePhaseDirectory`, `buildPhaseRoadmapEntry`, etc.)
|
||||
|
||||
2. **`phase.cjs:cmdPhaseComplete`** is migrated to use `deriveProgressFromRoadmap` + `clampPercent` from the generated artifact. It reads the freshly-updated ROADMAP synchronously, derives the completed-phase count from Complete-row matching (idempotent), and passes it through `clampPercent` to prevent >100% Progress.
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
- **Issue:** #3660
|
||||
- **Implementation:** #3663 (Phase 1), feat/3663-runtime-artifact-layout-module-phase-1-m
|
||||
|
||||
The **Runtime Surface Module** (`get-shit-done/bin/lib/surface.cjs`, introduced by ADR-0011 Phase 2) re-materializes a resolved Skill Surface profile to disk via `applySurface`. It currently hardcodes two artifact kinds (`commands`, `agents`) and re-derives their source directories via `_findInstallSource` / `_findAgentsSource` walk-up heuristics. The install and uninstall pipelines in `bin/install.js` each encode the same per-runtime artifact layout independently across ~14 install sites and ~6 uninstall sites. Bug #3659 surfaced the resulting drift: `applySurface` omits the `skills` kind for runtimes whose canonical layout is `skills/gsd-<stem>/SKILL.md`, so `gsd-surface profile <name>` leaves ~67 skill directories on disk under the install-time profile's footprint when the resolved profile should have pruned them — roughly 2.7k tokens per session on a measured workstation.
|
||||
The **Runtime Surface Module** (`gsd-core/bin/lib/surface.cjs`, introduced by ADR-0011 Phase 2) re-materializes a resolved Skill Surface profile to disk via `applySurface`. It currently hardcodes two artifact kinds (`commands`, `agents`) and re-derives their source directories via `_findInstallSource` / `_findAgentsSource` walk-up heuristics. The install and uninstall pipelines in `bin/install.js` each encode the same per-runtime artifact layout independently across ~14 install sites and ~6 uninstall sites. Bug #3659 surfaced the resulting drift: `applySurface` omits the `skills` kind for runtimes whose canonical layout is `skills/gsd-<stem>/SKILL.md`, so `gsd-surface profile <name>` leaves ~67 skill directories on disk under the install-time profile's footprint when the resolved profile should have pruned them — roughly 2.7k tokens per session on a measured workstation.
|
||||
|
||||
The root problem is the absence of a typed seam for "where does runtime R put artifact kind K." Three lifecycle sites (install, uninstall, surface) each independently encode this knowledge and drift independently.
|
||||
|
||||
## Decision
|
||||
|
||||
- Add a **Runtime Artifact Layout Module** at `get-shit-done/bin/lib/runtime-artifact-layout.cjs` as the single owner of the per-runtime artifact-placement table.
|
||||
- Add a **Runtime Artifact Layout Module** at `gsd-core/bin/lib/runtime-artifact-layout.cjs` as the single owner of the per-runtime artifact-placement table.
|
||||
- The module requires `runtime-homes.cjs` for the canonical runtime enum and global config-dir resolution. It adds the artifact-kind axis on top.
|
||||
- Expose `resolveRuntimeArtifactLayout(runtime, configDir) → Layout`. The returned `Layout` is a plain typed object — `{ runtime, configDir, kinds: ArtifactKind[] }` — with no I/O on resolution.
|
||||
- Each `ArtifactKind` is `{ kind: 'commands'|'agents'|'skills', destSubpath, prefix, stage }`. `stage` is a function `(resolvedProfile) → stagedDir` that closes over the per-runtime converter where one is needed (e.g. `convertClaudeCommandToClaudeSkill` for the `skills` kind on Claude global).
|
||||
@@ -29,7 +29,7 @@ The root problem is the absence of a typed seam for "where does runtime R put ar
|
||||
|
||||
Phase 1 should land the module and one consumer (the bug-#3659 fix):
|
||||
|
||||
1. New `get-shit-done/bin/lib/runtime-artifact-layout.cjs` — `resolveRuntimeArtifactLayout`, the typed `Layout`/`ArtifactKind` shapes, and the runtime table covering every runtime currently enumerated in `runtime-homes.cjs`.
|
||||
1. New `gsd-core/bin/lib/runtime-artifact-layout.cjs` — `resolveRuntimeArtifactLayout`, the typed `Layout`/`ArtifactKind` shapes, and the runtime table covering every runtime currently enumerated in `runtime-homes.cjs`.
|
||||
2. `surface.cjs:applySurface` migrates to layout-driven iteration. `_findInstallSource` and `_findAgentsSource` deleted. The `skills` kind is now iterated alongside `commands` and `agents` — bug #3659 closed.
|
||||
3. `commands/gsd/surface.md` and `tests/surface-apply.test.cjs` updated to construct + pass `Layout` values.
|
||||
4. New `tests/runtime-artifact-layout-*.test.cjs` covering:
|
||||
@@ -47,10 +47,10 @@ Phase 1 should **not**:
|
||||
## Migration Inventory
|
||||
|
||||
### New file
|
||||
- `get-shit-done/bin/lib/runtime-artifact-layout.cjs` — module body + runtime layout table.
|
||||
- `gsd-core/bin/lib/runtime-artifact-layout.cjs` — module body + runtime layout table.
|
||||
|
||||
### Files modified (Phase 1)
|
||||
- `get-shit-done/bin/lib/surface.cjs` — `applySurface` signature change; `_findInstallSource` + `_findAgentsSource` removal.
|
||||
- `gsd-core/bin/lib/surface.cjs` — `applySurface` signature change; `_findInstallSource` + `_findAgentsSource` removal.
|
||||
- `commands/gsd/surface.md` — runbook updates the 3 sites that call `applySurface` to first call `resolveRuntimeArtifactLayout`.
|
||||
- `tests/surface-apply.test.cjs` — 5 call sites pass `layout` instead of `commandsDir, agentsDir`.
|
||||
|
||||
@@ -132,17 +132,17 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap) {
|
||||
- See `0011-skill-surface-budget-module.md` — the Runtime Surface Module this seam serves
|
||||
- See `0008-installer-migration-module.md` — legacy-layout migrations stay there
|
||||
- See `0005-sdk-architecture-seam-map.md` — the seam map this module joins
|
||||
- Existing canonical sibling: `get-shit-done/bin/lib/runtime-homes.cjs`
|
||||
- Existing canonical sibling: `gsd-core/bin/lib/runtime-homes.cjs`
|
||||
- Per-runtime skill converters this module references: `bin/install.js:1622` (Copilot), `:1681` (Claude), `:1792` (Antigravity), `:2534` (Codex)
|
||||
- Hermes nested-skills layout rationale: `#2841`
|
||||
|
||||
## Implementation status
|
||||
|
||||
Phase 1 implementation landed on `feat/3663-runtime-artifact-layout-module-phase-1-m`:
|
||||
- `get-shit-done/bin/lib/runtime-artifact-layout.cjs` — 15-runtime layout table (grok intentionally excluded), `resolveRuntimeArtifactLayout(runtime, configDir, scope) → Layout`, walk-up `findInstallSourceRoot` helper.
|
||||
- `gsd-core/bin/lib/runtime-artifact-layout.cjs` — 15-runtime layout table (grok intentionally excluded), `resolveRuntimeArtifactLayout(runtime, configDir, scope) → Layout`, walk-up `findInstallSourceRoot` helper.
|
||||
- Clarification: in this Phase 1 implementation, **Cline resolves to zero kinds** (`kinds: []`), so it carries no `commands` kind in the layout table.
|
||||
- `get-shit-done/bin/lib/install-profiles.cjs` — new `stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converter, prefix) → stagedDir` helper.
|
||||
- `get-shit-done/bin/lib/surface.cjs` — `applySurface(runtimeConfigDir, layout, manifest, clusterMap)` signature migration; `_findInstallSource` + `_findAgentsSource` deleted; `_syncGsdDir` extended to handle the `skills` kind via directory iteration.
|
||||
- `gsd-core/bin/lib/install-profiles.cjs` — new `stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converter, prefix) → stagedDir` helper.
|
||||
- `gsd-core/bin/lib/surface.cjs` — `applySurface(runtimeConfigDir, layout, manifest, clusterMap)` signature migration; `_findInstallSource` + `_findAgentsSource` deleted; `_syncGsdDir` extended to handle the `skills` kind via directory iteration.
|
||||
- Tests: `runtime-artifact-layout-resolve.test.cjs` (16), `runtime-artifact-layout-edge-cases.test.cjs` (10), `runtime-artifact-layout-stage.test.cjs` (5), `install-profiles-stage.test.cjs` (+7 new), `surface-apply.test.cjs` (updated 5 call sites + new skills-kind test).
|
||||
|
||||
Phase 2 (separate issue #3664 — `bin/install.js` install/uninstall pipeline migration) is blocked on Phase 1 merge.
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
### The `$GSD_SDK` → `gsd_run` rename (#373/#379)
|
||||
|
||||
PRs #373 and #379 renamed the runtime resolver from the unquoted `$GSD_SDK` shell variable to a single-line, space-safe `gsd_run` launcher. The launcher is defined in `get-shit-done/workflows/_runtime-launcher.snippet.sh`, propagated to all workflow `.md` files by `scripts/sync-runtime-launcher.cjs`, and enforced by `tests/runtime-launcher-parity.test.cjs` (which forbids any `$GSD_SDK` token in workflow markdown).
|
||||
PRs #373 and #379 renamed the runtime resolver from the unquoted `$GSD_SDK` shell variable to a single-line, space-safe `gsd_run` launcher. The launcher is defined in `gsd-core/workflows/_runtime-launcher.snippet.sh`, propagated to all workflow `.md` files by `scripts/sync-runtime-launcher.cjs`, and enforced by `tests/runtime-launcher-parity.test.cjs` (which forbids any `$GSD_SDK` token in workflow markdown).
|
||||
|
||||
### The silent regression (#406)
|
||||
|
||||
During a multi-PR merge sweep, PR #406 (`fix(#160)`) — branched **before** #379 — re-introduced 5 `$GSD_SDK` occurrences into `get-shit-done/workflows/next.md`. Because it edited a **different** region of the file than #379, the merge produced no textual conflict and Git accepted it silently.
|
||||
During a multi-PR merge sweep, PR #406 (`fix(#160)`) — branched **before** #379 — re-introduced 5 `$GSD_SDK` occurrences into `gsd-core/workflows/next.md`. Because it edited a **different** region of the file than #379, the merge produced no textual conflict and Git accepted it silently.
|
||||
|
||||
#406's own CI was green because its base predated the parity test, and nothing re-checked the merge result against current `next`. #406 also carried a stale companion assertion (`tests/policy-160-route0-resume.test.cjs`) that **required** `$GSD_SDK` to be present.
|
||||
|
||||
@@ -64,5 +64,5 @@ A green PR on a stale base can still regress the integration branch via a **sema
|
||||
- Rename PRs: #373, #379 (`gsd_run`)
|
||||
- Propagator: `scripts/sync-runtime-launcher.cjs`
|
||||
- Parity test: `tests/runtime-launcher-parity.test.cjs`
|
||||
- Launcher snippet: `get-shit-done/workflows/_runtime-launcher.snippet.sh`
|
||||
- Launcher snippet: `gsd-core/workflows/_runtime-launcher.snippet.sh`
|
||||
- Tracking issue: #415
|
||||
|
||||
@@ -23,7 +23,7 @@ This codebase adopts ESLint flat config (eslint ≥ 9) with `typescript-eslint`,
|
||||
|
||||
### Generated vs hand-written split
|
||||
|
||||
Approximately 59 hand-written and 13 generated `.cjs` files currently coexist in `get-shit-done/bin/lib/`. The hand-written files are not checked by `typescript-eslint` type-aware rules because `tsconfig.lint.json` is not wired into an ESLint project. ADR 457 (`457-generated-cjs-single-source.md`) proposes collapsing this split; the present ADR is a prerequisite: the ESLint harness must exist before the collapse can surface type errors.
|
||||
Approximately 59 hand-written and 13 generated `.cjs` files currently coexist in `gsd-core/bin/lib/`. The hand-written files are not checked by `typescript-eslint` type-aware rules because `tsconfig.lint.json` is not wired into an ESLint project. ADR 457 (`457-generated-cjs-single-source.md`) proposes collapsing this split; the present ADR is a prerequisite: the ESLint harness must exist before the collapse can surface type errors.
|
||||
|
||||
## Decision
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
>
|
||||
> **Provenance note.** An earlier draft of this ADR (and issue #457) was authored
|
||||
> by an agent and asserted a codebase state that did not exist — "~13 files
|
||||
> generated from `.ts` via `tsc`", `get-shit-done/src/` / `sdk/src/` source trees,
|
||||
> generated from `.ts` via `tsc`", `gsd-core/src/` / `sdk/src/` source trees,
|
||||
> and a `tests/cjs-ts-parity.test.cjs`. None of those existed. This rewrite
|
||||
> grounds the decision in verified ground truth. Do not restore the earlier
|
||||
> "natural completion of the 13 generated files" framing; it was fiction.
|
||||
@@ -18,12 +18,12 @@
|
||||
|
||||
### What actually exists today (verified 2026-05-31)
|
||||
|
||||
- `get-shit-done/bin/lib/` holds **84** `.cjs` files. **Exactly one** carries a
|
||||
- `gsd-core/bin/lib/` holds **84** `.cjs` files. **Exactly one** carries a
|
||||
`// @generated` header: `package-identity.cjs`.
|
||||
- That one generated file is **not** `tsc` output. It is produced by
|
||||
`scripts/generate-package-identity.cjs` — a plain Node script that reads
|
||||
`package.json` and **bakes literal coordinate values** into a CJS module.
|
||||
- There is **no** `get-shit-done/src/` or `sdk/src/` TypeScript tree. There is
|
||||
- There is **no** `gsd-core/src/` or `sdk/src/` TypeScript tree. There is
|
||||
**no** TS→CJS transpilation pipeline. There is **no**
|
||||
`tests/cjs-ts-parity.test.cjs`. The only parity test is
|
||||
`tests/issue-498-package-identity.test.cjs`, scoped to the one baked file: it
|
||||
@@ -88,7 +88,7 @@ build artifact?** Three models:
|
||||
|
||||
2. **Build at publish (recommended).** `bin/lib/*.cjs` becomes a gitignored
|
||||
build artifact emitted from a TS `src/` tree by `tsc`; npm publishes the
|
||||
built output. **Feasible today:** `package.json` already ships `get-shit-done`
|
||||
built output. **Feasible today:** `package.json` already ships `gsd-core`
|
||||
and `scripts` via its `files` array, and already runs a pre-publish build
|
||||
step (`"prepublishOnly": "npm run build:hooks"`) — the `.cjs` emit hooks into
|
||||
the same step, and `npm pack` includes on-disk artifacts regardless of
|
||||
|
||||
Reference in New Issue
Block a user