@opengsd/gsd-core 1.9.0 → 1.10.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 +2 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +131 -34
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-executor.md +7 -5
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-plan-checker.md +9 -0
- package/agents/gsd-planner.md +5 -8
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-verifier.md +14 -70
- package/bin/install.js +503 -341
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +607 -63
- package/gsd-core/bin/lib/active-workstream-store.cjs +25 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +38 -6
- package/gsd-core/bin/lib/api-coverage.cjs +120 -0
- package/gsd-core/bin/lib/audit.cjs +89 -1
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- package/gsd-core/bin/lib/capability-registry.cjs +96 -110
- package/gsd-core/bin/lib/capability-validator.cjs +12 -2
- package/gsd-core/bin/lib/check-command-router.cjs +43 -1
- package/gsd-core/bin/lib/command-aliases.cjs +72 -0
- package/gsd-core/bin/lib/commands.cjs +26 -25
- package/gsd-core/bin/lib/commonjs-marker.cjs +136 -0
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +12 -1
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +91 -12
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/frontmatter.cjs +84 -12
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +58 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +27 -4
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1021 -57
- package/gsd-core/bin/lib/install-engine.cjs +64 -10
- package/gsd-core/bin/lib/install-profiles.cjs +27 -1
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +87 -1
- package/gsd-core/bin/lib/io.cjs +28 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +6 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone.cjs +106 -51
- package/gsd-core/bin/lib/phase-id.cjs +63 -0
- package/gsd-core/bin/lib/phase-locator.cjs +138 -45
- package/gsd-core/bin/lib/phase.cjs +260 -25
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +232 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +4 -0
- package/gsd-core/bin/lib/project-root.cjs +48 -0
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +80 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +99 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +30 -6
- package/gsd-core/bin/lib/roadmap-command-router.cjs +42 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +100 -18
- package/gsd-core/bin/lib/roadmap.cjs +37 -7
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +195 -62
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +15 -3
- package/gsd-core/bin/lib/runtime-homes.cjs +154 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +105 -41
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +113 -27
- package/gsd-core/bin/lib/smart-entry.cjs +12 -0
- package/gsd-core/bin/lib/state-transition.cjs +73 -8
- package/gsd-core/bin/lib/state.cjs +151 -62
- package/gsd-core/bin/lib/surface.cjs +12 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +11 -1
- package/gsd-core/bin/lib/uat.cjs +320 -21
- package/gsd-core/bin/lib/unusable-input.cjs +9 -0
- package/gsd-core/bin/lib/verification.cjs +29 -12
- package/gsd-core/bin/lib/verify.cjs +29 -5
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +181 -18
- package/gsd-core/bin/lib/workstream-inventory.cjs +519 -27
- package/gsd-core/bin/lib/workstream.cjs +6 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +276 -118
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/specless-probe-fallback.md +7 -6
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +32 -69
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +83 -0
- package/gsd-core/workflows/code-review.md +42 -145
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +23 -81
- package/gsd-core/workflows/debug.md +9 -12
- package/gsd-core/workflows/diagnose-issues.md +22 -0
- package/gsd-core/workflows/discovery-phase.md +4 -4
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +5 -16
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +34 -2
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +19 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +65 -137
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/ingest-docs.md +2 -1
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +21 -38
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +13 -226
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +49 -193
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +11 -153
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +46 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +20 -390
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +15 -8
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +17 -14
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +49 -11
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +8 -21
- package/gsd-core/workflows/ui-phase.md +8 -7
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +18 -7
- package/gsd-core/workflows/verify-phase.md +4 -7
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +8 -58
- package/hooks/dist/gsd-agent-isolation-guard.js +428 -0
- package/hooks/dist/gsd-check-update-worker.js +14 -5
- package/hooks/dist/gsd-cursor-subagent-start.js +532 -26
- package/hooks/dist/gsd-read-injection-scanner.js +7 -0
- package/hooks/dist/gsd-statusline.js +72 -6
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/isolation-sentinel.js +268 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +428 -0
- package/hooks/gsd-check-update-worker.js +14 -5
- package/hooks/gsd-cursor-subagent-start.js +532 -26
- package/hooks/gsd-read-injection-scanner.js +7 -0
- package/hooks/gsd-statusline.js +72 -6
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/isolation-sentinel.js +268 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +14 -5
- package/pi/gsd.cjs +57 -12
- package/scripts/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +9 -2
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-context-index.cjs +448 -0
- package/scripts/gen-inventory-manifest.cjs +101 -1
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +39 -15
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lint-allow-test-rule-refs.allowlist.json +17 -31
- package/scripts/lint-compiled-artifact-sync.cjs +6 -1
- package/scripts/lint-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-test-file-count.allowlist.json +27 -1
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/prompt-injection-scan.sh +27 -6
- package/scripts/registry-schema.cjs +323 -94
- package/scripts/run-tests.cjs +3 -2
- package/scripts/validate-registry.cjs +10 -6
- package/skills/gsd-autonomous/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +2 -2
- package/vscode/package.json +1 -1
- package/scripts/gen-emitted-baseline.cjs +0 -145
|
@@ -707,7 +707,6 @@ const VALID_CONVERTER_NAMES = new Set([
|
|
|
707
707
|
'convertClaudeCommandToCodebuddySkill',
|
|
708
708
|
'convertClaudeCommandToCodexSkill',
|
|
709
709
|
'convertClaudeCommandToCopilotSkill',
|
|
710
|
-
'convertClaudeCommandToCursorCommand',
|
|
711
710
|
'convertClaudeCommandToCursorSkill',
|
|
712
711
|
'convertClaudeCommandToKiloSkill',
|
|
713
712
|
'convertClaudeCommandToKimiSkill',
|
|
@@ -1075,7 +1074,18 @@ function validateArtifactLayout(capId, layout) {
|
|
|
1075
1074
|
errors.push(ctx + '.' + scope + ' must be an array');
|
|
1076
1075
|
} else {
|
|
1077
1076
|
for (let i = 0; i < arr.length; i++) {
|
|
1078
|
-
|
|
1077
|
+
const entry = arr[i];
|
|
1078
|
+
errors.push(...validateArtifactKindEntry(capId, entry, 'artifactLayout.' + scope + '[' + i + ']'));
|
|
1079
|
+
if (
|
|
1080
|
+
scope === 'local' &&
|
|
1081
|
+
typeof entry === 'object' && entry !== null && !Array.isArray(entry) &&
|
|
1082
|
+
Object.prototype.hasOwnProperty.call(entry, 'home')
|
|
1083
|
+
) {
|
|
1084
|
+
errors.push(
|
|
1085
|
+
ctx + '.local[' + i + '].home is not allowed; ' +
|
|
1086
|
+
'local artifact layout entries must remain project-scoped',
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1079
1089
|
}
|
|
1080
1090
|
}
|
|
1081
1091
|
}
|
|
@@ -22,7 +22,11 @@ const { planningDir } = planningWorkspaceMod;
|
|
|
22
22
|
const phaseLocatorMod = require("./phase-locator.cjs");
|
|
23
23
|
const { findPhaseInternal } = phaseLocatorMod;
|
|
24
24
|
const decisions_cjs_1 = require("./decisions.cjs");
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
|
+
const frontmatterMod = require("./frontmatter.cjs");
|
|
27
|
+
const { extractFrontmatter } = frontmatterMod;
|
|
25
28
|
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
29
|
+
const security_cjs_1 = require("./security.cjs");
|
|
26
30
|
const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
|
|
27
31
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
32
|
const verifyModule = require("./verify.cjs");
|
|
@@ -849,9 +853,47 @@ function buildPredicateDeps() {
|
|
|
849
853
|
stdout: r.stdout,
|
|
850
854
|
stderr: r.stderr,
|
|
851
855
|
signal: r.signal,
|
|
852
|
-
timedOut: r.
|
|
856
|
+
timedOut: r.timedOut,
|
|
853
857
|
};
|
|
854
858
|
},
|
|
859
|
+
findPhaseArtifact(phaseDir, artifactSuffix) {
|
|
860
|
+
if (!node_fs_1.default.existsSync(phaseDir))
|
|
861
|
+
return null;
|
|
862
|
+
if (artifactSuffix === '.' ||
|
|
863
|
+
artifactSuffix === '..' ||
|
|
864
|
+
artifactSuffix.includes('\0') ||
|
|
865
|
+
node_path_1.default.basename(artifactSuffix) !== artifactSuffix ||
|
|
866
|
+
node_path_1.default.win32.basename(artifactSuffix) !== artifactSuffix) {
|
|
867
|
+
return null;
|
|
868
|
+
}
|
|
869
|
+
const directPath = (0, security_cjs_1.validatePath)(artifactSuffix, phaseDir);
|
|
870
|
+
if (directPath.safe && node_fs_1.default.existsSync(directPath.resolved) && node_fs_1.default.statSync(directPath.resolved).isFile()) {
|
|
871
|
+
return directPath.resolved;
|
|
872
|
+
}
|
|
873
|
+
const planningPath = (0, security_cjs_1.validatePath)(node_path_1.default.join('.planning', artifactSuffix), phaseDir);
|
|
874
|
+
if (planningPath.safe && node_fs_1.default.existsSync(planningPath.resolved) && node_fs_1.default.statSync(planningPath.resolved).isFile()) {
|
|
875
|
+
return planningPath.resolved;
|
|
876
|
+
}
|
|
877
|
+
try {
|
|
878
|
+
const files = node_fs_1.default.readdirSync(phaseDir);
|
|
879
|
+
for (const f of files) {
|
|
880
|
+
if (f.endsWith('-' + artifactSuffix) || f === artifactSuffix) {
|
|
881
|
+
const candidate = (0, security_cjs_1.validatePath)(f, phaseDir);
|
|
882
|
+
if (candidate.safe && node_fs_1.default.statSync(candidate.resolved).isFile())
|
|
883
|
+
return candidate.resolved;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
catch { /* ignore */ }
|
|
888
|
+
return null;
|
|
889
|
+
},
|
|
890
|
+
readFrontmatter(filePath) {
|
|
891
|
+
const content = (0, shell_command_projection_cjs_1.platformReadSync)(filePath);
|
|
892
|
+
if (content === null)
|
|
893
|
+
throw new Error(`predicate artifact disappeared before it could be read: ${filePath}`);
|
|
894
|
+
const parsed = extractFrontmatter(content, filePath);
|
|
895
|
+
return parsed;
|
|
896
|
+
}
|
|
855
897
|
};
|
|
856
898
|
}
|
|
857
899
|
/** Parse `--flag value` pairs from an args array into a map (last write wins). */
|
|
@@ -331,6 +331,30 @@ exports.INIT_COMMAND_ALIASES = [
|
|
|
331
331
|
"subcommand": "phase-op",
|
|
332
332
|
"mutation": false
|
|
333
333
|
},
|
|
334
|
+
{
|
|
335
|
+
"canonical": "init.code-review",
|
|
336
|
+
"aliases": [
|
|
337
|
+
"init code-review"
|
|
338
|
+
],
|
|
339
|
+
"subcommand": "code-review",
|
|
340
|
+
"mutation": false
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"canonical": "init.review",
|
|
344
|
+
"aliases": [
|
|
345
|
+
"init review"
|
|
346
|
+
],
|
|
347
|
+
"subcommand": "review",
|
|
348
|
+
"mutation": false
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"canonical": "init.discuss-phase-assumptions",
|
|
352
|
+
"aliases": [
|
|
353
|
+
"init discuss-phase-assumptions"
|
|
354
|
+
],
|
|
355
|
+
"subcommand": "discuss-phase-assumptions",
|
|
356
|
+
"mutation": false
|
|
357
|
+
},
|
|
334
358
|
{
|
|
335
359
|
"canonical": "init.todos",
|
|
336
360
|
"aliases": [
|
|
@@ -371,6 +395,54 @@ exports.INIT_COMMAND_ALIASES = [
|
|
|
371
395
|
"subcommand": "manager",
|
|
372
396
|
"mutation": false
|
|
373
397
|
},
|
|
398
|
+
{
|
|
399
|
+
"canonical": "init.complete-milestone",
|
|
400
|
+
"aliases": [
|
|
401
|
+
"init complete-milestone"
|
|
402
|
+
],
|
|
403
|
+
"subcommand": "complete-milestone",
|
|
404
|
+
"mutation": false
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"canonical": "init.autonomous",
|
|
408
|
+
"aliases": [
|
|
409
|
+
"init autonomous"
|
|
410
|
+
],
|
|
411
|
+
"subcommand": "autonomous",
|
|
412
|
+
"mutation": false
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"canonical": "init.docs-update",
|
|
416
|
+
"aliases": [
|
|
417
|
+
"init docs-update"
|
|
418
|
+
],
|
|
419
|
+
"subcommand": "docs-update",
|
|
420
|
+
"mutation": false
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"canonical": "init.update",
|
|
424
|
+
"aliases": [
|
|
425
|
+
"init update"
|
|
426
|
+
],
|
|
427
|
+
"subcommand": "update",
|
|
428
|
+
"mutation": false
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"canonical": "init.transition",
|
|
432
|
+
"aliases": [
|
|
433
|
+
"init transition"
|
|
434
|
+
],
|
|
435
|
+
"subcommand": "transition",
|
|
436
|
+
"mutation": false
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
"canonical": "init.debug",
|
|
440
|
+
"aliases": [
|
|
441
|
+
"init debug"
|
|
442
|
+
],
|
|
443
|
+
"subcommand": "debug",
|
|
444
|
+
"mutation": false
|
|
445
|
+
},
|
|
374
446
|
{
|
|
375
447
|
"canonical": "init.new-workspace",
|
|
376
448
|
"aliases": [
|
|
@@ -762,21 +762,28 @@ function cmdCommit(cwd, message, files, raw, amend, noVerify) {
|
|
|
762
762
|
if (branchName) {
|
|
763
763
|
const currentBranch = (0, shell_command_projection_cjs_1.execGit)(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd });
|
|
764
764
|
if (currentBranch.exitCode === 0 && currentBranch.stdout.trim() !== branchName) {
|
|
765
|
-
// #2539: the #1278 intent is to CREATE the phase/milestone branch
|
|
765
|
+
// #2539/#3079: the #1278 intent is to CREATE the phase/milestone branch
|
|
766
766
|
// before the FIRST commit on it — not to force-switch an already-
|
|
767
767
|
// checked-out working branch onto a DIFFERENT existing branch. The
|
|
768
|
-
// prior
|
|
769
|
-
//
|
|
770
|
-
//
|
|
771
|
-
//
|
|
772
|
-
//
|
|
773
|
-
//
|
|
774
|
-
//
|
|
775
|
-
//
|
|
776
|
-
const
|
|
777
|
-
if (
|
|
778
|
-
//
|
|
779
|
-
|
|
768
|
+
// prior `git checkout -b` both created AND switched (silently moving
|
|
769
|
+
// HEAD), which resurrected merged-and-deleted phase branches (#3079).
|
|
770
|
+
// Now: create-if-absent WITHOUT switching, using `git branch` instead
|
|
771
|
+
// of `git checkout -b`. The commit always lands on the current branch.
|
|
772
|
+
// If the resolved branch already exists, log the resolution so the
|
|
773
|
+
// operator sees that the phase branch was resolved and deliberately
|
|
774
|
+
// not switched to (#2539 AC2: an auto-checkout mid-commit must never
|
|
775
|
+
// happen silently).
|
|
776
|
+
const verify = (0, shell_command_projection_cjs_1.execGit)(['rev-parse', '--verify', `refs/heads/${branchName}`], { cwd });
|
|
777
|
+
if (verify.exitCode !== 0) {
|
|
778
|
+
// Branch does not exist — create it WITHOUT switching.
|
|
779
|
+
const create = (0, shell_command_projection_cjs_1.execGit)(['branch', branchName], { cwd });
|
|
780
|
+
if (create.exitCode !== 0) {
|
|
781
|
+
process.stderr.write(`Warning: could not create ${branchingStrategy} branch "${branchName}" ` +
|
|
782
|
+
`(${create.stderr.trim()}); committing on the current branch "${currentBranch.stdout.trim()}".\n`);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
// Branch already exists — do NOT switch, commit on current branch.
|
|
780
787
|
process.stderr.write(`Warning: resolved ${branchingStrategy} branch "${branchName}" already exists; ` +
|
|
781
788
|
`committing on the current branch "${currentBranch.stdout.trim()}" instead of switching.\n`);
|
|
782
789
|
}
|
|
@@ -817,11 +824,10 @@ function cmdCommit(cwd, message, files, raw, amend, noVerify) {
|
|
|
817
824
|
// exit is a real I/O failure, not a missing file.
|
|
818
825
|
const rmResult = (0, shell_command_projection_cjs_1.execGit)(['rm', '--cached', '--ignore-unmatch', file], { cwd });
|
|
819
826
|
if (rmResult.exitCode !== 0) {
|
|
820
|
-
const rmErr = rmResult.error;
|
|
821
827
|
stagingFailures.push({
|
|
822
828
|
file,
|
|
823
829
|
error: rmResult.stderr || rmResult.stdout,
|
|
824
|
-
timed_out: rmResult
|
|
830
|
+
timed_out: (0, shell_command_projection_cjs_1.isSpawnTimeout)(rmResult),
|
|
825
831
|
});
|
|
826
832
|
}
|
|
827
833
|
}
|
|
@@ -834,17 +840,13 @@ function cmdCommit(cwd, message, files, raw, amend, noVerify) {
|
|
|
834
840
|
stagedPaths.push(file);
|
|
835
841
|
}
|
|
836
842
|
else {
|
|
837
|
-
// `SpawnResultOutput.error` is typed `Error | null`; widen to the errno
|
|
838
|
-
// shape by ANNOTATION rather than assertion — `Error` is assignable to
|
|
839
|
-
// `NodeJS.ErrnoException` (its extra fields are optional), so an `as`
|
|
840
|
-
// cast here trips no-unnecessary-type-assertion.
|
|
841
|
-
const addErr = addResult.error;
|
|
842
843
|
stagingFailures.push({
|
|
843
844
|
file,
|
|
844
845
|
error: addResult.stderr || addResult.stdout,
|
|
845
|
-
// The projection exposes a timeout distinctly (#2608 AC5); this
|
|
846
|
-
//
|
|
847
|
-
|
|
846
|
+
// The projection exposes a timeout distinctly (#2608 AC5); this uses
|
|
847
|
+
// the shared isSpawnTimeout predicate (shell-command-projection.cts)
|
|
848
|
+
// also used by worktree-safety.cts and worktree-base-ref.cts (#3050).
|
|
849
|
+
timed_out: (0, shell_command_projection_cjs_1.isSpawnTimeout)(addResult),
|
|
848
850
|
});
|
|
849
851
|
}
|
|
850
852
|
}
|
|
@@ -1015,11 +1017,10 @@ function cmdCommitToSubrepo(cwd, message, files, raw) {
|
|
|
1015
1017
|
stagedRelPaths.push(relativePath);
|
|
1016
1018
|
}
|
|
1017
1019
|
else {
|
|
1018
|
-
const addErr = addResult.error;
|
|
1019
1020
|
subStagingFailures.push({
|
|
1020
1021
|
file,
|
|
1021
1022
|
error: addResult.stderr || addResult.stdout,
|
|
1022
|
-
timed_out: addResult
|
|
1023
|
+
timed_out: (0, shell_command_projection_cjs_1.isSpawnTimeout)(addResult),
|
|
1023
1024
|
});
|
|
1024
1025
|
}
|
|
1025
1026
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.COMMONJS_MARKER_CONTENT = exports.COMMONJS_MARKER = void 0;
|
|
7
|
+
exports.markerPathFor = markerPathFor;
|
|
8
|
+
exports.classifyMarker = classifyMarker;
|
|
9
|
+
exports.ensureCommonJsMarker = ensureCommonJsMarker;
|
|
10
|
+
exports.removeCommonJsMarker = removeCommonJsMarker;
|
|
11
|
+
/**
|
|
12
|
+
* CommonJS module-type marker — single source of truth (#2544).
|
|
13
|
+
*
|
|
14
|
+
* GSD stages its own hook scripts and native plugin adapters as `.js` files.
|
|
15
|
+
* Node resolves a `.js` file's module type by walking up for the nearest
|
|
16
|
+
* `package.json`, so an ambient `"type": "module"` above the install location
|
|
17
|
+
* makes every one of those scripts fail with `require is not defined`. GSD
|
|
18
|
+
* pins them to CommonJS by writing a minimal `{"type":"commonjs"}` marker.
|
|
19
|
+
*
|
|
20
|
+
* Two rules govern that marker, and this module exists so both are enforced in
|
|
21
|
+
* exactly one place:
|
|
22
|
+
*
|
|
23
|
+
* 1. **Write only where GSD owns the contents.** The marker belongs in the
|
|
24
|
+
* directories GSD fills with its own `.js` files (`hooks/`, and the
|
|
25
|
+
* `nativePlugin.dir` for the runtimes that declare one) — never at the
|
|
26
|
+
* runtime's shared config root, which on OpenCode and Kilo is documented,
|
|
27
|
+
* user-writable territory for declaring local-plugin npm dependencies.
|
|
28
|
+
*
|
|
29
|
+
* 2. **Never overwrite a file GSD did not write.** Before #2544 the install
|
|
30
|
+
* path wrote the marker unconditionally while the uninstall path already
|
|
31
|
+
* compared content before unlinking. That asymmetry is the defect: the
|
|
32
|
+
* discipline existed in the codebase, it was simply not applied on the
|
|
33
|
+
* write side. `classifyMarker` is now the shared predicate behind both
|
|
34
|
+
* `ensureCommonJsMarker` and `removeCommonJsMarker`, so install and
|
|
35
|
+
* uninstall cannot drift apart again.
|
|
36
|
+
*
|
|
37
|
+
* Ownership is decided by exact content match against the marker GSD itself
|
|
38
|
+
* writes — the same test the uninstall path has always used.
|
|
39
|
+
*/
|
|
40
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
41
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
42
|
+
/** The exact marker content GSD writes (and the only content it will remove). */
|
|
43
|
+
exports.COMMONJS_MARKER = '{"type":"commonjs"}';
|
|
44
|
+
/** File bytes written to disk — the marker plus a trailing newline. */
|
|
45
|
+
exports.COMMONJS_MARKER_CONTENT = `${exports.COMMONJS_MARKER}\n`;
|
|
46
|
+
/** The marker path for a directory. */
|
|
47
|
+
function markerPathFor(dir) {
|
|
48
|
+
return node_path_1.default.join(dir, 'package.json');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Classify the package.json in `dir` by ownership.
|
|
52
|
+
*
|
|
53
|
+
* Fails CLOSED: a file that exists but cannot be read is reported `foreign`,
|
|
54
|
+
* never `absent`. Reporting it absent would license the overwrite this module
|
|
55
|
+
* exists to prevent. (Same posture as the unreadable-config branch in
|
|
56
|
+
* capability-command-router.cjs: present-but-unreadable never downgrades to
|
|
57
|
+
* the permissive answer.)
|
|
58
|
+
*/
|
|
59
|
+
function classifyMarker(dir) {
|
|
60
|
+
const markerPath = markerPathFor(dir);
|
|
61
|
+
let stat;
|
|
62
|
+
try {
|
|
63
|
+
// lstat, not existsSync: existsSync follows symlinks and reports `false`
|
|
64
|
+
// for a DANGLING one, which would classify the path `absent` and let the
|
|
65
|
+
// write below follow the link and land outside the directory GSD owns.
|
|
66
|
+
stat = node_fs_1.default.lstatSync(markerPath);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
if (err.code === 'ENOENT')
|
|
70
|
+
return 'absent';
|
|
71
|
+
return 'foreign';
|
|
72
|
+
}
|
|
73
|
+
// Anything that is not a regular file (symlink, directory, socket) is not
|
|
74
|
+
// something GSD wrote, so it is never ours to overwrite or remove.
|
|
75
|
+
if (!stat.isFile())
|
|
76
|
+
return 'foreign';
|
|
77
|
+
try {
|
|
78
|
+
const content = node_fs_1.default.readFileSync(markerPath, 'utf8');
|
|
79
|
+
return content.trim() === exports.COMMONJS_MARKER ? 'gsd-owned' : 'foreign';
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return 'foreign';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Write the CommonJS marker into `dir`, unless a file GSD does not own is
|
|
87
|
+
* already there.
|
|
88
|
+
*
|
|
89
|
+
* Creates `dir` when needed. Returns what happened so the caller can report
|
|
90
|
+
* it; a `preserved-foreign` result is not an error — it is the guard working.
|
|
91
|
+
*
|
|
92
|
+
* NEVER THROWS. Every other marker interaction in this module is best-effort —
|
|
93
|
+
* `removeCommonJsMarker` swallows unlink failures, `classifyMarker` swallows
|
|
94
|
+
* read failures — and the write path is the one most likely to fail on a
|
|
95
|
+
* locked-down config dir (`EACCES` on a read-only `hooks/`, `EROFS`, `ENOSPC`).
|
|
96
|
+
* Letting it throw made an unwritable marker abort the entire install with a
|
|
97
|
+
* raw stack trace, which is a strictly worse outcome than hooks that resolve as
|
|
98
|
+
* ESM: the caller can warn and continue, and does. Both the `mkdir` and the
|
|
99
|
+
* write are inside the guard — creating the directory is the same environmental
|
|
100
|
+
* hazard as writing into it.
|
|
101
|
+
*/
|
|
102
|
+
function ensureCommonJsMarker(dir) {
|
|
103
|
+
const ownership = classifyMarker(dir);
|
|
104
|
+
if (ownership === 'foreign')
|
|
105
|
+
return 'preserved-foreign';
|
|
106
|
+
if (ownership === 'gsd-owned')
|
|
107
|
+
return 'unchanged';
|
|
108
|
+
try {
|
|
109
|
+
node_fs_1.default.mkdirSync(dir, { recursive: true });
|
|
110
|
+
// Exclusive create closes the gap between classifying and writing: if
|
|
111
|
+
// anything at all appeared at the path in between — including a symlink —
|
|
112
|
+
// this fails with EEXIST instead of following or overwriting it.
|
|
113
|
+
node_fs_1.default.writeFileSync(markerPathFor(dir), exports.COMMONJS_MARKER_CONTENT, { flag: 'wx' });
|
|
114
|
+
return 'written';
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
if (err.code === 'EEXIST')
|
|
118
|
+
return 'preserved-foreign';
|
|
119
|
+
return 'failed';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Remove the CommonJS marker from `dir` — only when the content is exactly
|
|
124
|
+
* the marker GSD writes. Returns true when a file was removed.
|
|
125
|
+
*/
|
|
126
|
+
function removeCommonJsMarker(dir) {
|
|
127
|
+
if (classifyMarker(dir) !== 'gsd-owned')
|
|
128
|
+
return false;
|
|
129
|
+
try {
|
|
130
|
+
node_fs_1.default.unlinkSync(markerPathFor(dir));
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -755,6 +755,7 @@ function loadConfigResolved(cwd, options = {}) {
|
|
|
755
755
|
response_language: get('response_language') || null,
|
|
756
756
|
claude_md_path: get('claude_md_path') || null,
|
|
757
757
|
claude_md_assembly: (parsed['claude_md_assembly']) || null,
|
|
758
|
+
phase_id_convention: get('phase_id_convention') ?? null,
|
|
758
759
|
};
|
|
759
760
|
// ADR-857 phase 3b: federated config overlay
|
|
760
761
|
try {
|
|
@@ -65,6 +65,8 @@ const SCHEMA_DEFAULTS = {
|
|
|
65
65
|
'context_window': 200000,
|
|
66
66
|
'executor.stall_detect_interval_minutes': 5,
|
|
67
67
|
'executor.stall_threshold_minutes': 10,
|
|
68
|
+
'planner.stall_detect_interval_minutes': 5,
|
|
69
|
+
'planner.stall_threshold_minutes': 10,
|
|
68
70
|
'git.create_tag': true,
|
|
69
71
|
// Derived from the defaults manifest rather than restated, so the manifest
|
|
70
72
|
// stays the single source of truth for the smart-zone budget (#2630).
|
|
@@ -289,10 +291,19 @@ function buildNewProjectConfig(userChoices) {
|
|
|
289
291
|
const ud = userDefaults;
|
|
290
292
|
const ch = choices;
|
|
291
293
|
const hd = hardcoded;
|
|
294
|
+
// #2840: `runtime` is host-specific (written by the installer for whichever
|
|
295
|
+
// runtime's install ran last). On a machine with 2+ runtimes, it poisons every
|
|
296
|
+
// new project config — e.g. a Codex install's `runtime:"codex"` leaks into
|
|
297
|
+
// Claude Code projects, resolving agents to wrong model IDs. `resolve_model_ids`
|
|
298
|
+
// already has a per-install guard (#2297); `runtime` gets the same treatment
|
|
299
|
+
// by excluding it from the defaults spread. Projects detect the runtime from
|
|
300
|
+
// the install path / .gsd-runtime marker, not from a copied config key.
|
|
301
|
+
const safeDefaults = { ...userDefaults };
|
|
302
|
+
delete safeDefaults['runtime'];
|
|
292
303
|
// Three-level deep merge: hardcoded <- userDefaults <- choices
|
|
293
304
|
const config = {
|
|
294
305
|
...hardcoded,
|
|
295
|
-
...
|
|
306
|
+
...safeDefaults,
|
|
296
307
|
...choices,
|
|
297
308
|
git: {
|
|
298
309
|
...hd['git'],
|