fix(#1920): resolve host version from gsd-core/VERSION + ship capability generators (#1938)

The flattened install layout broke the third-party capability ecosystem in two
ways. Both are fixed at the host-version / installer boundary.

Gap 1 — host version read as 0.0.0. The running GSD version was resolved via
require('../../../package.json') (loader/source) and require('../../package.json')
(the gsd-tools CLI), which in the installed layout is the versionless CommonJS
marker → the fail-closed fallback reported 0.0.0, so `capability install` rejected
any manifest with a real engines.gsd range as "incompatible with GSD 0.0.0". For
runtimes that get no marker, and for local installs, that walked-up package.json
could even be the USER's own project, reporting a wrong version. Fix:
readHostVersion() (capability-loader.cts, capability-source.cts) and capHostVersion()
(gsd-tools.cjs) now prefer the authoritative gsd-core/VERSION the installer already
writes for EVERY runtime (mirrors resolveVersionFrom(), #1383), falling back to the
runtime-root package.json for the dev/source tree, then fail-closing. This fixes
every runtime and the actual `capability install` CLI path without touching the
marker package.json, so uninstall is unchanged (no data-loss surface).

Gap 2 — scripts/gen-capability-registry.cjs (+ its sibling
gen-loop-host-contract.cjs) were never copied by the installer, so the loader's
never-crash invariant discarded every overlay and fell back to the frozen
first-party registry (installed capabilities silently inert). Now copied,
uninstalled, and manifest-tracked exactly like fix-slash-commands.cjs (#1223).

Regenerates the 16 golden-install-parity fixtures to capture the two newly shipped
generator scripts and the gsd-tools.cjs change.

Regression tests (RED→GREEN): readHostVersion VERSION-first / fallback / fail-closed
resolution; an end-to-end `capability install` against a REAL installed layout
proving the engines gate sees the real host version, not 0.0.0; and a real-install
check that both generators are shipped and manifest-tracked.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-02 20:34:30 -04:00
committed by GitHub
parent 69fef7c00e
commit d3d689a5e9
22 changed files with 356 additions and 37 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 1938
---
**Third-party capabilities now work on installed layouts.** `capability install` no longer rejects capabilities with a real `engines.gsd` range as "incompatible with GSD 0.0.0" — the host version is now read from the authoritative `gsd-core/VERSION` file across every runtime and the `capability install` CLI. The installer also now ships the registry generator scripts (`gen-capability-registry.cjs`, `gen-loop-host-contract.cjs`), so installed third-party capabilities actually compose into the loop instead of being silently discarded.

View File

@@ -7377,6 +7377,11 @@ function uninstall(isGlobal, runtime = 'claude') {
const fixSlashUninstallPath = path.join(targetDir, 'scripts', 'fix-slash-commands.cjs');
try { fs.unlinkSync(fixSlashUninstallPath); } catch (_) { /* best-effort */ }
// Remove the capability registry generator scripts (#1920) — before the scripts/ rmdir
for (const gen of ['gen-capability-registry.cjs', 'gen-loop-host-contract.cjs']) {
try { fs.unlinkSync(path.join(targetDir, 'scripts', gen)); } catch (_) { /* best-effort */ }
}
// If scripts/ dir is now empty, remove it too
const scriptsUninstallDir = path.join(targetDir, 'scripts');
if (fs.existsSync(scriptsUninstallDir)) {
@@ -8100,6 +8105,15 @@ function writeManifest(configDir, runtime = 'claude', options = {}) {
manifest.files['scripts/fix-slash-commands.cjs'] = fileHash(fixSlashInstallPath);
}
// Track the capability registry generator scripts (#1920) — top-level scripts/ files
// not covered by the changeset/lib loops.
for (const gen of ['gen-capability-registry.cjs', 'gen-loop-host-contract.cjs']) {
const genInstallPath = path.join(configDir, 'scripts', gen);
if (fs.existsSync(genInstallPath)) {
manifest.files['scripts/' + gen] = fileHash(genInstallPath);
}
}
// Track the OpenCode native plugin adapter (#1914) so update/drift detection
// and uninstall can account for it.
if (isOpencode) {
@@ -9629,6 +9643,31 @@ function install(isGlobal, runtime = 'claude', options = {}) {
}
}
// Copy scripts/gen-capability-registry.cjs + scripts/gen-loop-host-contract.cjs —
// required by gsd-core/bin/lib/capability-loader.cjs at overlay-composition time via
// require('../../../scripts/gen-capability-registry.cjs') (which itself requires
// gen-loop-host-contract.cjs). Without these, the loader's never-crash invariant
// discards EVERY third-party capability overlay and silently falls back to the frozen
// first-party registry, so installed capabilities are inert (#1920). Same class of
// gap as #1223 (fix-slash-commands.cjs) and copied unconditionally for the same reason:
// any runtime that installs gsd-core/ needs the capability system to compose.
{
const capGenDestDir = path.join(targetDir, 'scripts');
fs.mkdirSync(capGenDestDir, { recursive: true });
for (const gen of ['gen-capability-registry.cjs', 'gen-loop-host-contract.cjs']) {
const genSrc = path.join(src, 'scripts', gen);
const genDest = path.join(capGenDestDir, gen);
if (!fs.existsSync(genSrc)) {
failures.push(`scripts/${gen} (source missing from package — reinstall from npm)`);
} else {
fs.copyFileSync(genSrc, genDest);
if (!verifyFileInstalled(genDest, `scripts/${gen}`)) {
failures.push(`scripts/${gen}`);
}
}
}
}
// Remove legacy get-shit-done-cc artifacts and stale update caches (#607).
// cleanupLegacyGsdCc handles both the legacy shared cache and the per-package
// cache (formerly an inline unlinkSync here). A cleanup failure must never

View File

@@ -1667,13 +1667,22 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
return undefined;
};
// Running GSD version (hard gate for engines.gsd at install/load); fail-closed to 0.0.0.
// #1920: prefer the authoritative gsd-core/VERSION the installer writes for EVERY runtime
// (gsd-core/bin/ -> ../VERSION), so installed layouts report the true version even when the
// walked-up ../../package.json is the versionless CommonJS marker or the user's own project.
// Fall back to the runtime-root package.json (dev/source tree), then fail-closed. Mirrors
// readHostVersion() in capability-loader.cts.
const capHostVersion = () => {
const SEMVER_PREFIX = /^\d+\.\d+\.\d+/;
try {
const pkg = require('../../package.json'); // gsd-core/bin/ -> repo root is two up
return typeof pkg.version === 'string' && pkg.version ? pkg.version : '0.0.0';
} catch {
return '0.0.0';
}
const v = fs.readFileSync(path.join(__dirname, '..', 'VERSION'), 'utf8').trim();
if (SEMVER_PREFIX.test(v)) return v;
} catch { /* not an installed tree (no gsd-core/VERSION) */ }
try {
const pkg = require(path.join(__dirname, '..', '..', 'package.json')); // gsd-core/bin/ -> repo root is two up
if (pkg && typeof pkg.version === 'string' && SEMVER_PREFIX.test(pkg.version)) return pkg.version;
} catch { /* runtime root has no package.json */ }
return '0.0.0';
};
// #1459: the USER-OWNED consent home (GSD_HOME||homedir()) where project-scope consent records
// live — OUTSIDE any repo. SAME rule as the loader/consent-store path resolution so a record

View File

@@ -198,16 +198,29 @@ function _setGeneratorForTest(g: GeneratorModule | null): void {
_generatorOverride = g;
}
/** Resolve the running GSD version; fail-closed to '0.0.0' if it cannot be read. */
function readHostVersion(): string {
/**
* Resolve the running GSD version; fail-closed to '0.0.0' if it cannot be read.
*
* Prefer the authoritative `gsd-core/VERSION` the installer writes for EVERY runtime
* (libDir = gsd-core/bin/lib/, so `../../VERSION` = gsd-core/VERSION). This is reliable
* across all installed layouts — including runtimes that get no marker package.json, and
* local installs where the walked-up `../../../package.json` would resolve to the USER's
* own project and report a wrong version (#1920). Fall back to the runtime-root
* package.json for the dev/source tree, then fail-closed. Mirrors resolveVersionFrom()
* (#1383). `libDir` is injectable for tests; it defaults to this module's directory.
*/
export function readHostVersion(libDir: string = __dirname): string {
const SEMVER_PREFIX = /^\d+\.\d+\.\d+/;
try {
const v = fs.readFileSync(path.join(libDir, '..', '..', 'VERSION'), 'utf8').trim();
if (SEMVER_PREFIX.test(v)) return v;
} catch { /* not an installed tree (no gsd-core/VERSION) */ }
try {
// gsd-core/bin/lib/ -> repo/package root is three levels up.
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment
const pkg: { version?: string } = require('../../../package.json');
return typeof pkg.version === 'string' && pkg.version ? pkg.version : '0.0.0';
} catch {
return '0.0.0';
}
const pkg: { version?: string } = require(path.join(libDir, '..', '..', '..', 'package.json'));
if (pkg && typeof pkg.version === 'string' && SEMVER_PREFIX.test(pkg.version)) return pkg.version;
} catch { /* runtime root has no package.json */ }
return '0.0.0';
}
/**
@@ -848,4 +861,5 @@ export function loadRegistry(options: LoadRegistryOptions = {}): Registry {
}
}
module.exports = { loadRegistry, _setValidatorForTest, _setGeneratorForTest };
// readHostVersion is exported for the #1920 regression (VERSION-first host-version resolution).
module.exports = { loadRegistry, readHostVersion, _setValidatorForTest, _setGeneratorForTest };

View File

@@ -279,15 +279,27 @@ function _setCapabilitySourceHttpGet(fn: HttpGetFn | null): void {
// Helpers
// ---------------------------------------------------------------------------
/** Resolve the running GSD version; fail-closed to '0.0.0'. */
function readHostVersion(): string {
/**
* Resolve the running GSD version; fail-closed to '0.0.0'.
*
* Prefer the authoritative `gsd-core/VERSION` the installer writes for EVERY runtime
* (libDir = gsd-core/bin/lib/, so `../../VERSION` = gsd-core/VERSION), so installed
* layouts report the true version even when the walked-up `../../../package.json` is
* absent or belongs to the user's own project (#1920). Fall back to the runtime-root
* package.json (dev/source tree), then fail-closed. Mirrors resolveVersionFrom() (#1383).
*/
function readHostVersion(libDir: string = __dirname): string {
const SEMVER_PREFIX = /^\d+\.\d+\.\d+/;
try {
const v = fs.readFileSync(path.join(libDir, '..', '..', 'VERSION'), 'utf8').trim();
if (SEMVER_PREFIX.test(v)) return v;
} catch { /* not an installed tree (no gsd-core/VERSION) */ }
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const pkg = require('../../../package.json') as { version?: string };
return typeof pkg.version === 'string' && pkg.version ? pkg.version : '0.0.0';
} catch {
return '0.0.0';
}
const pkg = require(path.join(libDir, '..', '..', '..', 'package.json')) as { version?: string };
if (pkg && typeof pkg.version === 'string' && SEMVER_PREFIX.test(pkg.version)) return pkg.version;
} catch { /* runtime root has no package.json */ }
return '0.0.0';
}
/** Compute sha512-<base64> integrity over a buffer. */

View File

@@ -0,0 +1,208 @@
'use strict';
/**
* Regression tests for #1920: the installer must produce a capability-ecosystem-
* complete flattened layout, and the capability loader must resolve the real host
* version in that layout.
*
* Two gaps broke third-party capabilities on installed (flattened) layouts:
*
* Gap 1 — host version read as 0.0.0. `readHostVersion()` resolved the running GSD
* version via require('../../../package.json'), which in the installed layout is the
* marker package.json ({"type":"commonjs"}, no version) → the fail-closed fallback
* reported 0.0.0, so `capability install` rejected any manifest with a real
* engines.gsd range as "incompatible with GSD 0.0.0". Worse, for runtimes that get
* no marker and for local installs, that walked-up package.json could be the USER's
* own project, reporting a wrong version. Fix: readHostVersion() prefers the
* authoritative gsd-core/VERSION the installer writes for EVERY runtime.
*
* Gap 2 — the registry generator was never shipped. The loader composes overlays via
* require('../../../scripts/gen-capability-registry.cjs'); the installer never copied
* it (nor its sibling gen-loop-host-contract.cjs), so the never-crash invariant
* discarded EVERY overlay and fell back to the frozen first-party registry —
* installed third-party capabilities were silently inert. Same class of gap as #1223
* (scripts/fix-slash-commands.cjs).
*
* These tests are RED before the fix (loader/install.js) and GREEN after.
*/
process.env.GSD_TEST_MODE = '1';
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const { cleanup } = require('./helpers.cjs');
const ROOT = path.join(__dirname, '..');
const INSTALL = path.join(ROOT, 'bin', 'install.js');
const MANIFEST_NAME = 'gsd-file-manifest.json';
// The generator scripts the capability loader requires by relative path.
const GENERATORS = ['gen-capability-registry.cjs', 'gen-loop-host-contract.cjs'];
// ---------------------------------------------------------------------------
// Gap 1 — readHostVersion() prefers gsd-core/VERSION (the installer-written,
// all-runtime authoritative source) over an ambient/absent package.json.
// ---------------------------------------------------------------------------
describe('Gap 1: readHostVersion resolves the real host version in an installed layout (#1920)', () => {
const { readHostVersion } = require('../gsd-core/bin/lib/capability-loader.cjs');
/** Build a fake installed tree and return its gsd-core/bin/lib dir (the module libDir). */
function fakeTree({ version, pkg }) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1920-ver-'));
const libDir = path.join(root, 'gsd-core', 'bin', 'lib');
fs.mkdirSync(libDir, { recursive: true });
if (version !== undefined) fs.writeFileSync(path.join(root, 'gsd-core', 'VERSION'), version);
if (pkg !== undefined) fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(pkg));
return { root, libDir };
}
test('prefers gsd-core/VERSION over a wrong ambient package.json version', () => {
// The walked-up package.json belongs to the user's project (wrong version) — must be ignored.
const { root, libDir } = fakeTree({ version: '9.9.9\n', pkg: { name: 'user-app', version: '1.2.3', type: 'commonjs' } });
try {
assert.strictEqual(readHostVersion(libDir), '9.9.9');
} finally {
cleanup(root);
}
});
test('falls back to the runtime-root package.json when no VERSION file (dev/source tree)', () => {
const { root, libDir } = fakeTree({ pkg: { version: '2.3.4' } });
try {
assert.strictEqual(readHostVersion(libDir), '2.3.4');
} finally {
cleanup(root);
}
});
test('fail-closes to 0.0.0 when neither VERSION nor a package.json version resolves', () => {
const { root, libDir } = fakeTree({});
try {
assert.strictEqual(readHostVersion(libDir), '0.0.0');
} finally {
cleanup(root);
}
});
test('a real global install writes gsd-core/VERSION carrying the host version', () => {
const dir = realInstall();
try {
const vfile = path.join(dir, 'gsd-core', 'VERSION');
assert.ok(fs.existsSync(vfile), 'installer must write gsd-core/VERSION');
assert.strictEqual(
fs.readFileSync(vfile, 'utf8').trim(),
require('../package.json').version,
'gsd-core/VERSION must carry the real host version readHostVersion() reads',
);
} finally {
cleanup(dir);
}
});
});
// ---------------------------------------------------------------------------
// Gap 2 — the installer ships (and uninstalls / manifest-tracks) the capability
// registry generator scripts.
// ---------------------------------------------------------------------------
/** Run a real global install into a fresh temp config dir; return that dir. */
function realInstall() {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1920-'));
// The module-level GSD_TEST_MODE=1 gates the installer's main() off entirely —
// strip it from the child env for the spawned REAL install.
const childEnv = { ...process.env };
delete childEnv.GSD_TEST_MODE;
const res = spawnSync(
process.execPath,
[INSTALL, '--claude', '--global', '--config-dir', dir],
{ encoding: 'utf8', timeout: 120000, env: childEnv },
);
assert.strictEqual(res.status, 0, `install --claude failed: ${res.stderr || res.stdout}`);
return dir;
}
// ---------------------------------------------------------------------------
// Gap 1 (end-to-end CLI) — the actual repro: `gsd-tools capability install` on an
// INSTALLED layout must resolve the real host version for the engines.gsd gate, not
// 0.0.0. The dev tree always has a versioned package.json two levels up, so this only
// reproduces against a real install (where ../../package.json is the versionless marker
// and gsd-core/VERSION carries the truth). The CLI computes hostVersion itself, so this
// covers capHostVersion() in gsd-tools.cjs — a path the loader unit test does not touch.
// ---------------------------------------------------------------------------
describe('Gap 1 (end-to-end CLI): installed capability install uses the real host version (#1920)', () => {
const HOST_MAJOR = require('../package.json').version.split('.')[0];
function writeProbeCapability(engines) {
const src = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1920-cap-'));
const cap = {
id: 'p1920-probe', role: 'feature', version: '1.0.0', title: 'probe',
description: 'test capability', tier: 'standard', requires: [],
runtimeCompat: { supported: ['*'], unsupported: [] },
skills: [], agents: [], hooks: [], config: {}, steps: [],
contributions: [], gates: [], engines,
};
fs.writeFileSync(path.join(src, 'capability.json'), JSON.stringify(cap, null, 2));
return src;
}
test('a capability requiring engines.gsd ">=<host major>.0.0" is not rejected as GSD 0.0.0', () => {
const dir = realInstall();
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1920-home-'));
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1920-cwd-'));
fs.mkdirSync(path.join(cwd, '.planning'), { recursive: true });
fs.writeFileSync(path.join(cwd, '.planning', 'config.json'), '{}');
const src = writeProbeCapability({ gsd: `>=${HOST_MAJOR}.0.0` });
try {
const installedTools = path.join(dir, 'gsd-core', 'bin', 'gsd-tools.cjs');
const env = { ...process.env, GSD_HOME: home, GSD_WORKSTREAM: '', GSD_PROJECT: '', GSD_SESSION_KEY: '', CLAUDE_SESSION_ID: '' };
delete env.GSD_TEST_MODE;
const res = spawnSync(
process.execPath,
[installedTools, 'capability', 'install', src, '--scope', 'global', '--yes', '--json'],
{ cwd, env, encoding: 'utf8', timeout: 60000 },
);
const combined = `${res.stdout || ''}\n${res.stderr || ''}`;
assert.doesNotMatch(
combined,
/incompatible with GSD 0\.0\.0/,
`installed CLI saw host version 0.0.0 — the engines gate read the versionless marker: ${combined}`,
);
assert.strictEqual(res.status, 0, `capability install failed on the installed layout: ${combined}`);
} finally {
cleanup(dir); cleanup(home); cleanup(cwd); cleanup(src);
}
});
});
describe('Gap 2: installer ships the capability registry generator scripts (#1920)', () => {
test('the generator scripts are copied into scripts/', () => {
const dir = realInstall();
try {
for (const gen of GENERATORS) {
const dest = path.join(dir, 'scripts', gen);
assert.ok(fs.existsSync(dest), `installer must ship scripts/${gen}`);
assert.ok(fs.statSync(dest).size > 0, `scripts/${gen} must not be empty`);
}
} finally {
cleanup(dir);
}
});
test('the shipped generator scripts are tracked in the file manifest', () => {
const dir = realInstall();
try {
const manifest = JSON.parse(fs.readFileSync(path.join(dir, MANIFEST_NAME), 'utf8'));
for (const gen of GENERATORS) {
assert.ok(
manifest.files[`scripts/${gen}`],
`manifest must track scripts/${gen} for drift/uninstall accounting`,
);
}
} finally {
cleanup(dir);
}
});
});

View File

@@ -37,7 +37,7 @@
"agents/gsd-verifier.md": "d2bd23b62f95a64f",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "775a6f3d86f8e5e3",
"gsd-core/bin/gsd-tools.cjs": "815b92a0e7b7693e",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -331,6 +331,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "95cd3eb1698fc79b",

View File

@@ -106,7 +106,7 @@
"commands/gsd-workstreams.md": "52ab9c585d3a00f3",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -400,6 +400,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-ns-context/SKILL.md": "90ff2716402f8f61",

View File

@@ -36,7 +36,7 @@
"agents/gsd-verifier.md": "d62ffb1f520520c0",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -330,6 +330,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "6661195a66f25ae8",

View File

@@ -40,7 +40,7 @@
"agents/gsd-verifier.md": "5645dfb20b787f01",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -312,6 +312,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-ns-context/SKILL.md": "e278a50f3ecb8f56",

View File

@@ -106,7 +106,7 @@
"commands/gsd-workstreams.md": "884b6c8d648422c7",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -400,6 +400,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "60dd7f9779d5f493",

View File

@@ -72,7 +72,7 @@
"config.toml": "a34316b9ac61a620",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -346,6 +346,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "f3c1594a059de3ee",

View File

@@ -38,7 +38,7 @@
"copilot-instructions.md": "1fb04111759f1645",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "775a6f3d86f8e5e3",
"gsd-core/bin/gsd-tools.cjs": "815b92a0e7b7693e",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -311,6 +311,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "dfe3f8a07f34c438",

View File

@@ -106,7 +106,7 @@
"commands/gsd-workstreams.md": "112660ceb663c750",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "775a6f3d86f8e5e3",
"gsd-core/bin/gsd-tools.cjs": "815b92a0e7b7693e",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -380,6 +380,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "2cfc1922a2c0f308",

View File

@@ -106,7 +106,7 @@
"commands/gsd/workstreams.toml": "95f0c349b808a84c",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -400,6 +400,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7"
}

View File

@@ -37,7 +37,7 @@
"agents/gsd-verifier.md": "c5916e463df6306e",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -331,6 +331,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd/DESCRIPTION.md": "d93e29a1a09cfd11",

View File

@@ -106,7 +106,7 @@
"command/gsd-workstreams.md": "5e57eed1881c3891",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -401,6 +401,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "addc3a220961a9c7",

View File

@@ -73,7 +73,7 @@
"agents/subagents/gsd-verifier.yaml": "2d2bd6b37626f382",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -345,6 +345,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "217fc2587d3e7ec2",

View File

@@ -106,7 +106,7 @@
"command/gsd-workstreams.md": "5e57eed1881c3891",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -402,6 +402,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-add-tests/SKILL.md": "f60794b90b48cbac",

View File

@@ -37,7 +37,7 @@
"agents/gsd-verifier.md": "7286d42f73e54be1",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "43e6c5810defe512",
"gsd-core/bin/gsd-tools.cjs": "4456f5432471af00",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -331,6 +331,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-ns-context/SKILL.md": "654c71262d91650c",

View File

@@ -37,7 +37,7 @@
"agents/gsd-verifier.md": "2fef6afe676b0e34",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "775a6f3d86f8e5e3",
"gsd-core/bin/gsd-tools.cjs": "815b92a0e7b7693e",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -309,6 +309,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7",
"skills/gsd-ns-context/SKILL.md": "e278a50f3ecb8f56",

View File

@@ -37,7 +37,7 @@
"agents/gsd-verifier.md": "b16b34a580941124",
"gsd-core/VERSION": "ef0deccd81a6723c",
"gsd-core/bin/check-latest-version.cjs": "e4a224058c8f4d74",
"gsd-core/bin/gsd-tools.cjs": "775a6f3d86f8e5e3",
"gsd-core/bin/gsd-tools.cjs": "815b92a0e7b7693e",
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
@@ -309,6 +309,8 @@
"scripts/changeset/render.cjs": "e47bc3e1587c3cae",
"scripts/changeset/serialize.cjs": "ac0b8fe6f87cdb0e",
"scripts/fix-slash-commands.cjs": "0519742531ff3529",
"scripts/gen-capability-registry.cjs": "c52201ff4d1c2cd7",
"scripts/gen-loop-host-contract.cjs": "c7f15237234811a0",
"scripts/lib/allowlist-ratchet.cjs": "ffaceaac3efc2660",
"scripts/lib/cli-exit.cjs": "612d0c372c75b7e7"
}