@opengsd/gsd-core 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +33 -2
- package/agents/gsd-executor.md +1 -1
- package/agents/gsd-plan-checker.md +1 -1
- package/agents/gsd-planner.md +3 -3
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +265 -161
- package/commands/gsd/autonomous.md +1 -1
- package/commands/gsd/new-milestone.md +2 -2
- package/commands/gsd/new-project.md +2 -2
- package/gsd-core/bin/gsd-tools.cjs +554 -823
- package/gsd-core/bin/lib/capability-activation.cjs +8 -2
- package/gsd-core/bin/lib/capability-command-router.cjs +6 -2
- package/gsd-core/bin/lib/capability-ledger.cjs +1 -1
- package/gsd-core/bin/lib/capability-lock.cjs +19 -27
- package/gsd-core/bin/lib/capability-registry.cjs +74 -71
- package/gsd-core/bin/lib/capability-validator.cjs +1 -0
- package/gsd-core/bin/lib/capability-writer.cjs +7 -4
- package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +142 -62
- package/gsd-core/bin/lib/claude-orchestration.cjs +214 -122
- package/gsd-core/bin/lib/cli-surface.cjs +545 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +356 -103
- package/gsd-core/bin/lib/commands.cjs +99 -2
- package/gsd-core/bin/lib/config-file-read.cjs +85 -0
- package/gsd-core/bin/lib/config-loader.cjs +23 -15
- package/gsd-core/bin/lib/config.cjs +139 -101
- package/gsd-core/bin/lib/configuration.cjs +41 -2
- package/gsd-core/bin/lib/criterion-baseline.cjs +346 -0
- package/gsd-core/bin/lib/criterion-replay.cjs +380 -0
- package/gsd-core/bin/lib/estimate-cli.cjs +5 -1
- package/gsd-core/bin/lib/gap-checker.cjs +12 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +593 -27
- package/gsd-core/bin/lib/gate-phase-context.cjs +16 -4
- package/gsd-core/bin/lib/graphify.cjs +19 -2
- package/gsd-core/bin/lib/gsd-tool-dir.cjs +134 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +5 -1
- package/gsd-core/bin/lib/init.cjs +20 -18
- package/gsd-core/bin/lib/install-effort-resolver.cjs +24 -4
- package/gsd-core/bin/lib/install-engine.cjs +20 -28
- package/gsd-core/bin/lib/install-fs-adapter.cjs +5 -1
- package/gsd-core/bin/lib/install-manifest-record.cjs +86 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -3
- package/gsd-core/bin/lib/install-profiles.cjs +4 -2
- package/gsd-core/bin/lib/io.cjs +6 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +62 -31
- package/gsd-core/bin/lib/markdown-table.cjs +39 -1
- package/gsd-core/bin/lib/milestone.cjs +8 -6
- package/gsd-core/bin/lib/model-resolver.cjs +8 -4
- package/gsd-core/bin/lib/phase-entry-grammar.cjs +14 -0
- package/gsd-core/bin/lib/phase-id.cjs +26 -9
- package/gsd-core/bin/lib/phase-locator.cjs +8 -3
- package/gsd-core/bin/lib/phase.cjs +170 -45
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +46 -23
- package/gsd-core/bin/lib/planning-snapshot.cjs +10 -6
- package/gsd-core/bin/lib/planning-workspace.cjs +20 -10
- package/gsd-core/bin/lib/profile-output.cjs +9 -6
- package/gsd-core/bin/lib/project-context.cjs +439 -0
- package/gsd-core/bin/lib/project-root.cjs +9 -230
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +1 -1
- package/gsd-core/bin/lib/report-parser.cjs +16 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +357 -50
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +24 -5
- package/gsd-core/bin/lib/roadmap.cjs +2 -2
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +317 -134
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +81 -3
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +6 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +279 -8
- package/gsd-core/bin/lib/runtime-slash.cjs +7 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +1010 -10
- package/gsd-core/bin/lib/stale-bake-guard.cjs +4 -1
- package/gsd-core/bin/lib/state-transition.cjs +103 -46
- package/gsd-core/bin/lib/state.cjs +448 -63
- package/gsd-core/bin/lib/surface.cjs +4 -7
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +10 -3
- package/gsd-core/bin/lib/verify-command-router.cjs +6 -1
- package/gsd-core/bin/lib/verify.cjs +49 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +4 -4
- package/gsd-core/bin/lib/worktree-base-ref.cjs +32 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +8 -111
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/references/autonomous-smart-discuss.md +99 -18
- package/gsd-core/references/checkpoints.md +1 -1
- package/gsd-core/references/planner-guidance.md +11 -0
- package/gsd-core/references/planner-human-verify-mode.md +1 -1
- package/gsd-core/references/planner-reversibility.md +2 -0
- package/gsd-core/references/planner-verify-command-grounding.md +22 -6
- package/gsd-core/workflows/autonomous.md +4 -4
- package/gsd-core/workflows/code-review-fix.md +5 -7
- package/gsd-core/workflows/execute-phase.md +21 -7
- package/gsd-core/workflows/plan-phase/steps/plan-pre-dispatch.md +101 -0
- package/gsd-core/workflows/plan-phase.md +18 -19
- package/hooks/dist/gsd-agent-isolation-guard.js +4 -3
- package/hooks/dist/gsd-config-reload.js +2 -2
- package/hooks/dist/gsd-context-monitor.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +9 -6
- package/hooks/dist/gsd-read-injection-scanner.js +2 -2
- package/hooks/dist/gsd-secret-read-guard.js +141 -6
- package/hooks/dist/gsd-statusline.js +3 -2
- package/hooks/dist/gsd-workflow-guard.js +2 -1
- package/hooks/dist/lib/config-read.js +49 -0
- package/hooks/dist/lib/git-cmd.js +3 -1
- package/hooks/dist/lib/git-head-tree.js +474 -0
- package/hooks/dist/lib/isolation-sentinel.js +168 -13
- package/hooks/dist/lib/secret-read-exemptions.js +161 -0
- package/hooks/gsd-agent-isolation-guard.js +4 -3
- package/hooks/gsd-config-reload.js +2 -2
- package/hooks/gsd-context-monitor.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +9 -6
- package/hooks/gsd-read-injection-scanner.js +2 -2
- package/hooks/gsd-secret-read-guard.js +141 -6
- package/hooks/gsd-statusline.js +3 -2
- package/hooks/gsd-workflow-guard.js +2 -1
- package/hooks/lib/config-read.js +49 -0
- package/hooks/lib/git-cmd.js +3 -1
- package/hooks/lib/git-head-tree.js +474 -0
- package/hooks/lib/isolation-sentinel.js +168 -13
- package/hooks/lib/secret-read-exemptions.js +161 -0
- package/package.json +7 -2
- package/pi/package-agents/gsd-executor.md +1 -1
- package/pi/package-agents/gsd-plan-checker.md +1 -1
- package/pi/package-agents/gsd-planner.md +3 -3
- package/pi/package-agents/gsd-verifier.md +2 -2
- package/pi/package-agents/manifest.json +4 -4
- package/pi/package-skills/gsd-autonomous/SKILL.md +1 -1
- package/pi/package-skills/gsd-new-milestone/SKILL.md +1 -1
- package/pi/package-skills/gsd-new-project/SKILL.md +1 -1
- package/scripts/changeset/cli.cjs +2 -2
- package/scripts/changeset/lint.cjs +28 -3
- package/scripts/changeset/serialize.cjs +12 -2
- package/scripts/ci-compact-v8-coverage.cjs +204 -0
- package/scripts/ci-fix-next-rerun.cjs +149 -0
- package/scripts/ci-next-health.cjs +52 -9
- package/scripts/ci-test-scope.cjs +77 -71
- package/scripts/command-contract-helpers.cjs +56 -7
- package/scripts/docs-guard-registry.cjs +3 -0
- package/scripts/gen-cli-surface-manifest.cjs +287 -0
- package/scripts/gen-platform-conformance-tier.cjs +258 -19
- package/scripts/lib/macos-conformance-tier.generated.cjs +59 -47
- package/scripts/lib/platform-conformance-tier.generated.cjs +23 -64
- package/scripts/lib/shellcheck-fetch.cjs +71 -4
- package/scripts/lint-removed-but-needed.cjs +562 -50
- package/scripts/merge-commit-pr.cjs +186 -0
- package/scripts/release-ancestry.cjs +86 -0
- package/scripts/release-notes/changelog-release-notes.cjs +345 -0
- package/scripts/release-notes/discord-release-summary.cjs +82 -1
- package/scripts/release-pipeline-pr.cjs +92 -0
- package/scripts/require-issue-link-policy.cjs +18 -9
- package/scripts/sync-next-version.cjs +11 -2
- package/scripts/timeout-evidence-from-ci.cjs +964 -0
- package/skills/gsd-autonomous/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-new-project/SKILL.md +1 -1
- package/vscode/package.json +1 -1
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
9
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
10
|
};
|
|
11
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
11
|
const node_path_1 = __importDefault(require("node:path"));
|
|
13
12
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
14
13
|
const planningWorkspaceMod = require("./planning-workspace.cjs");
|
|
15
14
|
const { planningDir, planningRoot } = planningWorkspaceMod;
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- config-file-read.cjs is an export= CommonJS module
|
|
16
|
+
const configFileReadMod = require("./config-file-read.cjs");
|
|
17
|
+
const { readConfigFileBounded } = configFileReadMod;
|
|
16
18
|
function _getNestedConfigValue(config, dotKey) {
|
|
17
19
|
const segments = dotKey.split('.');
|
|
18
20
|
let current = config;
|
|
@@ -34,7 +36,11 @@ function _getNestedConfigValue(config, dotKey) {
|
|
|
34
36
|
const _warnedRawConfigPaths = new Set();
|
|
35
37
|
function _readRawConfigKey(filePath, dotKey, quiet = false) {
|
|
36
38
|
try {
|
|
37
|
-
|
|
39
|
+
// Bounded read (#5759): null is an absent file; a FIFO/device/oversized one throws to the
|
|
40
|
+
// catch below, which reports the key as not found.
|
|
41
|
+
const raw = readConfigFileBounded(filePath);
|
|
42
|
+
if (raw === null)
|
|
43
|
+
return { found: false, value: undefined };
|
|
38
44
|
let parsed;
|
|
39
45
|
try {
|
|
40
46
|
parsed = JSON.parse(raw);
|
|
@@ -88,10 +88,14 @@ async function routeCapabilityCommand({ args, cwd, raw }) {
|
|
|
88
88
|
} catch {
|
|
89
89
|
return undefined; // cannot even resolve the project config dir — permissive default
|
|
90
90
|
}
|
|
91
|
-
if (!fs.existsSync(cfgPath)) return undefined; // no project config — permissive default
|
|
92
91
|
let cfg;
|
|
93
92
|
try {
|
|
94
|
-
|
|
93
|
+
// #5759: bounded regular-file read — a FIFO/device/oversized config throws (fails closed
|
|
94
|
+
// below) instead of blocking; null is an absent file.
|
|
95
|
+
const { readConfigFileBounded } = require('./config-file-read.cjs');
|
|
96
|
+
const rawCfg = readConfigFileBounded(cfgPath);
|
|
97
|
+
if (rawCfg === null) return undefined; // no project config — permissive default
|
|
98
|
+
cfg = JSON.parse(rawCfg);
|
|
95
99
|
} catch {
|
|
96
100
|
// Config is PRESENT but unreadable/unparseable: a security policy must not silently
|
|
97
101
|
// downgrade to permissive. Fail CLOSED — lockdown ([]) blocks external installs (local
|
|
@@ -158,7 +158,7 @@ function readSmallRegularFile(filePath, maxBytes) {
|
|
|
158
158
|
*/
|
|
159
159
|
function readSmallRegularFileBuffer(filePath, maxBytes) {
|
|
160
160
|
// O_RDONLY | O_NONBLOCK: never block on opening a FIFO/device — return the fd so fstat can reject it.
|
|
161
|
-
const openFlags = node_fs_1.default.constants.O_RDONLY | node_fs_1.default.constants.O_NONBLOCK;
|
|
161
|
+
const openFlags = node_fs_1.default.constants.O_RDONLY | node_fs_1.default.constants.O_NONBLOCK | (node_fs_1.default.constants.O_NOCTTY || 0);
|
|
162
162
|
let fd;
|
|
163
163
|
try {
|
|
164
164
|
fd = node_fs_1.default.openSync(filePath, openFlags);
|
|
@@ -80,6 +80,16 @@ const LOCK_MAX_BODY_BYTES = 64 * 1024;
|
|
|
80
80
|
*/
|
|
81
81
|
const LOCK_MAX_ATTEMPTS = 8;
|
|
82
82
|
const LOCK_RETRY_BACKOFF_MS = 25;
|
|
83
|
+
/** The exact (dev, ino) of `p`, or nulls when it cannot be statted. */
|
|
84
|
+
function statIdentity(p) {
|
|
85
|
+
try {
|
|
86
|
+
const st = node_fs_1.default.statSync(p, { bigint: true });
|
|
87
|
+
return { dev: typeof st.dev === 'bigint' ? st.dev : null, ino: typeof st.ino === 'bigint' ? st.ino : null };
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return { dev: null, ino: null };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
83
93
|
// ---------------------------------------------------------------------------
|
|
84
94
|
// Tokens + backoff
|
|
85
95
|
// ---------------------------------------------------------------------------
|
|
@@ -308,16 +318,9 @@ function readParsedLockBounded(lockPath) {
|
|
|
308
318
|
* "changed" and retries rather than stealing. Never throws.
|
|
309
319
|
*/
|
|
310
320
|
function lockIdentity(lockPath) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
try {
|
|
314
|
-
const st = node_fs_1.default.statSync(lockPath);
|
|
315
|
-
dev = typeof st.dev === 'number' ? st.dev : null;
|
|
316
|
-
ino = typeof st.ino === 'number' ? st.ino : null;
|
|
317
|
-
}
|
|
318
|
-
catch {
|
|
321
|
+
const { dev, ino } = statIdentity(lockPath);
|
|
322
|
+
if (dev === null || ino === null)
|
|
319
323
|
return { dev: null, ino: null, ts: null }; // vanished/unstatable — treat as changed.
|
|
320
|
-
}
|
|
321
324
|
const ts = readParsedLockBounded(lockPath).ts;
|
|
322
325
|
return { dev, ino, ts };
|
|
323
326
|
}
|
|
@@ -437,14 +440,7 @@ function acquireLock(lockPath, opts) {
|
|
|
437
440
|
}
|
|
438
441
|
// Capture the lock inode's (dev, ino) so releaseLock can confirm, immediately before rmSync, that
|
|
439
442
|
// the path still holds OUR inode. Best-effort: a null dev/ino just falls back to the token check.
|
|
440
|
-
|
|
441
|
-
let ino = null;
|
|
442
|
-
try {
|
|
443
|
-
const lst = node_fs_1.default.statSync(lockPath);
|
|
444
|
-
dev = typeof lst.dev === 'number' ? lst.dev : null;
|
|
445
|
-
ino = typeof lst.ino === 'number' ? lst.ino : null;
|
|
446
|
-
}
|
|
447
|
-
catch { /* best-effort — release falls back to the token check alone */ }
|
|
443
|
+
const { dev, ino } = statIdentity(lockPath); // best-effort — null falls back to the token check alone
|
|
448
444
|
return { path: lockPath, token, dev, ino };
|
|
449
445
|
}
|
|
450
446
|
catch (err) {
|
|
@@ -456,7 +452,7 @@ function acquireLock(lockPath, opts) {
|
|
|
456
452
|
// Held — decide whether to steal.
|
|
457
453
|
let st;
|
|
458
454
|
try {
|
|
459
|
-
st = node_fs_1.default.statSync(lockPath);
|
|
455
|
+
st = node_fs_1.default.statSync(lockPath, { bigint: true });
|
|
460
456
|
}
|
|
461
457
|
catch {
|
|
462
458
|
continue; // lock vanished between open and stat — retry the create immediately.
|
|
@@ -466,7 +462,7 @@ function acquireLock(lockPath, opts) {
|
|
|
466
462
|
// even if the file `mtime` is stale-old. A legacy/garbage/no-`ts` body — and a FUTURE/implausible
|
|
467
463
|
// `ts` — falls back to the file `mtime` age so a planted/clock-skewed future ts can never deadlock.
|
|
468
464
|
const parsed = readParsedLockBounded(lockPath);
|
|
469
|
-
const age = lockAgeMs(parsed.ts, st.mtimeMs);
|
|
465
|
+
const age = lockAgeMs(parsed.ts, Number(st.mtimeMs));
|
|
470
466
|
if (age <= LOCK_STALE_MS) { // genuinely held (fresh) — blocked.
|
|
471
467
|
const b = blocked(attempt);
|
|
472
468
|
if (b === 'retry')
|
|
@@ -474,8 +470,8 @@ function acquireLock(lockPath, opts) {
|
|
|
474
470
|
return b;
|
|
475
471
|
}
|
|
476
472
|
const decisionIdentity = {
|
|
477
|
-
dev: typeof st.dev === '
|
|
478
|
-
ino: typeof st.ino === '
|
|
473
|
+
dev: typeof st.dev === 'bigint' ? st.dev : null,
|
|
474
|
+
ino: typeof st.ino === 'bigint' ? st.ino : null,
|
|
479
475
|
ts: parsed.ts,
|
|
480
476
|
};
|
|
481
477
|
if (isSameHost(parsed) && parsed.pid !== null) {
|
|
@@ -553,13 +549,9 @@ function releaseLock(handle) {
|
|
|
553
549
|
if (lockBodyToken(body) !== handle.token && body !== handle.token)
|
|
554
550
|
return; // not our token (PRIMARY).
|
|
555
551
|
if (handle.dev !== null && handle.ino !== null) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
cur = node_fs_1.default.statSync(handle.path);
|
|
559
|
-
}
|
|
560
|
-
catch {
|
|
552
|
+
const cur = statIdentity(handle.path);
|
|
553
|
+
if (cur.dev === null || cur.ino === null)
|
|
561
554
|
return; // vanished/unstatable between read and rmSync → nothing of ours to release.
|
|
562
|
-
}
|
|
563
555
|
if (cur.dev !== handle.dev || cur.ino !== handle.ino)
|
|
564
556
|
return; // successor inode — not ours.
|
|
565
557
|
}
|