@opengsd/gsd-pi 1.1.1-dev.b2556262 → 1.2.0-dev.844675c9
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/dist/project-sessions.js +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -9
- package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +659 -57
- package/dist/resources/extensions/gsd/auto-prompts.js +110 -1
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +5 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +29 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +24 -17
- package/dist/resources/extensions/gsd/auto.js +62 -464
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -1
- package/dist/resources/extensions/gsd/debug-logger.js +10 -0
- package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
- package/dist/resources/extensions/gsd/guided-flow.js +2 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +31 -32
- package/dist/resources/extensions/gsd/mcp-filter.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +45 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +6 -7
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -5
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
- package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +169 -20
- package/dist/resources/extensions/gsd/user-input-boundary.js +42 -4
- package/dist/tsconfig.extensions.tsbuildinfo +1 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/5047.js +2 -0
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/package.json +16 -11
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +0 -34
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +12 -46
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +11 -3
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/deps.js +10 -0
- package/scripts/link-workspace-packages.cjs +7 -40
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -8
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +2 -2
- package/src/resources/extensions/gsd/auto/contracts.ts +8 -119
- package/src/resources/extensions/gsd/auto/orchestrator.ts +794 -58
- package/src/resources/extensions/gsd/auto-prompts.ts +114 -1
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +5 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +33 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +24 -16
- package/src/resources/extensions/gsd/auto.ts +81 -500
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -0
- package/src/resources/extensions/gsd/debug-logger.ts +11 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
- package/src/resources/extensions/gsd/guided-flow.ts +2 -2
- package/src/resources/extensions/gsd/markdown-renderer.ts +38 -19
- package/src/resources/extensions/gsd/mcp-filter.ts +7 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +48 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +6 -7
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -5
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
- package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
- package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +590 -855
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +38 -10
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/native-merge-regular.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -2
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +19 -5
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +183 -21
- package/src/resources/extensions/gsd/user-input-boundary.ts +37 -5
- package/dist/web/standalone/.next/server/chunks/678.js +0 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
- package/scripts/ensure-workspace-builds.cjs +0 -129
- /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → Qbr81pQ-pbQXP4bq2VXLv}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → Qbr81pQ-pbQXP4bq2VXLv}/_ssgManifest.js +0 -0
|
@@ -22,6 +22,7 @@ import { assertGateCoverage, getGatesForTurn, } from "./gate-registry.js";
|
|
|
22
22
|
import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
|
|
23
23
|
import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
|
|
24
24
|
import { composeContextModeInstructions, composeInlinedContext, composeUnitContext } from "./unit-context-composer.js";
|
|
25
|
+
import { resolveManifest } from "./unit-context-manifest.js";
|
|
25
26
|
import { readCompactionSnapshot } from "./compaction-snapshot.js";
|
|
26
27
|
import { logWarning } from "./workflow-logger.js";
|
|
27
28
|
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
@@ -1451,6 +1452,75 @@ export async function buildDiscussRequirementsPrompt(base, structuredQuestionsAv
|
|
|
1451
1452
|
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1452
1453
|
}));
|
|
1453
1454
|
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Bounded codebase snapshot for research-milestone grounding (ADR-029).
|
|
1457
|
+
*
|
|
1458
|
+
* Reuses the in-process, ~millisecond `analyzeCodebase` / `formatCodebaseBrief`
|
|
1459
|
+
* machinery that powers the guided-discuss Preparation Snapshot, so research
|
|
1460
|
+
* grounds on current code reality instead of running an open-ended `rg`/`find`/
|
|
1461
|
+
* `scout` survey on every dispatch (the auto-mode counterpart to ADR-028).
|
|
1462
|
+
*
|
|
1463
|
+
* Gated on the manifest's `codebaseMap` flag (previously a dead policy flag)
|
|
1464
|
+
* and the `discuss_preparation` opt-out. Failures degrade silently — research
|
|
1465
|
+
* still runs, it just falls back to on-demand reads.
|
|
1466
|
+
*/
|
|
1467
|
+
async function buildResearchCodebaseSnapshot(base) {
|
|
1468
|
+
const manifest = resolveManifest("research-milestone");
|
|
1469
|
+
if (!manifest?.codebaseMap)
|
|
1470
|
+
return null;
|
|
1471
|
+
const prefs = loadEffectiveGSDPreferences(base)?.preferences;
|
|
1472
|
+
if (prefs?.discuss_preparation === false)
|
|
1473
|
+
return null;
|
|
1474
|
+
try {
|
|
1475
|
+
const { analyzeCodebase, formatCodebaseBrief } = await import("./preparation.js");
|
|
1476
|
+
const brief = await analyzeCodebase(base);
|
|
1477
|
+
const formatted = formatCodebaseBrief(brief).trim();
|
|
1478
|
+
if (!formatted)
|
|
1479
|
+
return null;
|
|
1480
|
+
return [
|
|
1481
|
+
"### Codebase Snapshot (current code reality)",
|
|
1482
|
+
"Source: in-process bounded scan of the working tree.",
|
|
1483
|
+
"",
|
|
1484
|
+
"This snapshot describes what already exists. Treat it as authoritative for current code reality and do NOT re-survey the tree to rediscover it. Read a specific file only when a research question hinges on its exact contents.",
|
|
1485
|
+
"",
|
|
1486
|
+
formatted,
|
|
1487
|
+
].join("\n");
|
|
1488
|
+
}
|
|
1489
|
+
catch (err) {
|
|
1490
|
+
logWarning("prompt", `buildResearchCodebaseSnapshot failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1491
|
+
return null;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Lightweight research resume block (ADR-029).
|
|
1496
|
+
*
|
|
1497
|
+
* When a prior attempt for this milestone left durable output — a partial
|
|
1498
|
+
* RESEARCH artifact and/or a research phase anchor — inline it under a
|
|
1499
|
+
* "continue, do not redo" banner so a re-dispatched research unit extends
|
|
1500
|
+
* prior work instead of re-running every command from scratch (the
|
|
1501
|
+
* restart-from-scratch pattern observed in the 789 run trace). No new state
|
|
1502
|
+
* machine: the partial RESEARCH file and the existing phase anchor are the
|
|
1503
|
+
* durable signals. Returns null when there is nothing to resume.
|
|
1504
|
+
*/
|
|
1505
|
+
async function buildResearchResumeBlock(base, mid) {
|
|
1506
|
+
const researchPath = resolveMilestoneFile(base, mid, "RESEARCH");
|
|
1507
|
+
const researchRel = relMilestoneFile(base, mid, "RESEARCH");
|
|
1508
|
+
const partial = await inlineFileOptional(researchPath, researchRel, "Prior Partial Research");
|
|
1509
|
+
const anchor = readPhaseAnchor(base, mid, "research-milestone");
|
|
1510
|
+
if (!partial && !anchor)
|
|
1511
|
+
return null;
|
|
1512
|
+
const lines = [
|
|
1513
|
+
"### Resume — Prior Partial Research (continue, do not redo)",
|
|
1514
|
+
"",
|
|
1515
|
+
"A previous research attempt for this milestone left the durable output below. **Build on it — do not restart from scratch.** Re-run a command only when its prior result is missing or stale, and persist progress incrementally with `gsd_summary_save` so any interruption keeps your findings.",
|
|
1516
|
+
"",
|
|
1517
|
+
];
|
|
1518
|
+
if (anchor)
|
|
1519
|
+
lines.push(formatAnchorForPrompt(anchor), "");
|
|
1520
|
+
if (partial)
|
|
1521
|
+
lines.push(partial);
|
|
1522
|
+
return lines.join("\n").trimEnd();
|
|
1523
|
+
}
|
|
1454
1524
|
export async function buildResearchMilestonePrompt(mid, midTitle, base) {
|
|
1455
1525
|
const contextTelemetry = [];
|
|
1456
1526
|
// Keep research milestone prompts focused on the milestone brief and
|
|
@@ -1490,6 +1560,32 @@ export async function buildResearchMilestonePrompt(mid, midTitle, base) {
|
|
|
1490
1560
|
const parts = [];
|
|
1491
1561
|
if (composed.prepend)
|
|
1492
1562
|
parts.push(composed.prepend);
|
|
1563
|
+
// Resume grounding (ADR-029): if a prior attempt left partial research or a
|
|
1564
|
+
// phase anchor, inline it prominently so a re-dispatched unit continues
|
|
1565
|
+
// rather than re-running every command from scratch.
|
|
1566
|
+
const resumeBlock = await buildResearchResumeBlock(base, mid);
|
|
1567
|
+
if (resumeBlock) {
|
|
1568
|
+
parts.push(resumeBlock);
|
|
1569
|
+
trackPromptContext(contextTelemetry, "research-resume", "inline", resumeBlock);
|
|
1570
|
+
}
|
|
1571
|
+
else {
|
|
1572
|
+
trackPromptContext(contextTelemetry, "research-resume", "skipped", null, "no prior partial research");
|
|
1573
|
+
}
|
|
1574
|
+
// Project-size signal (ADR-029): same classification plan-milestone gets, so
|
|
1575
|
+
// research right-sizes effort on tiny projects instead of over-researching.
|
|
1576
|
+
const classificationBlock = formatProjectClassificationForPlanning(classifyProject(base));
|
|
1577
|
+
parts.push(classificationBlock);
|
|
1578
|
+
trackPromptContext(contextTelemetry, "project-classification", "inline", classificationBlock);
|
|
1579
|
+
// Codebase snapshot (ADR-029): bounded, in-process code-reality grounding so
|
|
1580
|
+
// research does not open-endedly survey the tree (auto-mode ADR-028).
|
|
1581
|
+
const codebaseSnapshot = await buildResearchCodebaseSnapshot(base);
|
|
1582
|
+
if (codebaseSnapshot) {
|
|
1583
|
+
parts.push(codebaseSnapshot);
|
|
1584
|
+
trackPromptContext(contextTelemetry, "codebase-snapshot", "inline", codebaseSnapshot);
|
|
1585
|
+
}
|
|
1586
|
+
else {
|
|
1587
|
+
trackPromptContext(contextTelemetry, "codebase-snapshot", "skipped", null, "disabled, empty, or scan failed");
|
|
1588
|
+
}
|
|
1493
1589
|
if (knowledgeInlineRM && composed.inline) {
|
|
1494
1590
|
const idx = composed.inline.lastIndexOf("### Output Template:");
|
|
1495
1591
|
if (idx > 0) {
|
|
@@ -3190,6 +3286,17 @@ opts) {
|
|
|
3190
3286
|
// gate-registry.ts so that prompt builders, dispatch rules, state
|
|
3191
3287
|
// derivation, and tool handlers all consult the same source of truth.
|
|
3192
3288
|
// See gate-registry.ts for the full ownership map.
|
|
3289
|
+
/**
|
|
3290
|
+
* Adapt gate-registry guidance for section-close phases.
|
|
3291
|
+
*
|
|
3292
|
+
* Gate-registry text is shared with the gate-evaluate subagent, where
|
|
3293
|
+
* "Return verdict ..." is literal. Section-close units write artifact sections
|
|
3294
|
+
* instead, so translate that wording at render time without mutating the
|
|
3295
|
+
* canonical guidance.
|
|
3296
|
+
*/
|
|
3297
|
+
function sectionModeGuidance(guidance) {
|
|
3298
|
+
return guidance.replace(/Return verdict '([^']+)'/g, (_match, verdict) => verdict === "omitted" ? "Leave the section empty" : `Record a \`${verdict}\``);
|
|
3299
|
+
}
|
|
3193
3300
|
/**
|
|
3194
3301
|
* Render a "Gates to Close" block for turns like `complete-slice` and
|
|
3195
3302
|
* `validate-milestone` that own gates which are closed as a side-effect
|
|
@@ -3208,12 +3315,14 @@ function renderGatesToCloseBlock(gates, opts) {
|
|
|
3208
3315
|
lines.push("");
|
|
3209
3316
|
lines.push("These quality gates are still pending for this unit. You MUST address every one before calling the closing tool — the handler closes the DB row based on whether the corresponding artifact section is present.");
|
|
3210
3317
|
lines.push("");
|
|
3318
|
+
lines.push("**Do NOT call `gsd_save_gate_result` (or any gate-result tool) for these gates** — that tool belongs to a different phase and the call will be blocked. You close each gate purely by writing its named section: a populated section records `pass`, an empty section records `omitted`, and the completion handler persists the verdict for you. Treat any \"return verdict\" wording in the guidance below as describing that section outcome, not as an instruction to call a tool.");
|
|
3319
|
+
lines.push("");
|
|
3211
3320
|
for (const def of applicable) {
|
|
3212
3321
|
lines.push(`### ${def.id} — ${def.promptSection}`);
|
|
3213
3322
|
lines.push("");
|
|
3214
3323
|
lines.push(`**Question:** ${def.question}`);
|
|
3215
3324
|
lines.push("");
|
|
3216
|
-
lines.push(def.guidance);
|
|
3325
|
+
lines.push(sectionModeGuidance(def.guidance));
|
|
3217
3326
|
if (opts.allowOmit) {
|
|
3218
3327
|
lines.push("");
|
|
3219
3328
|
lines.push(`If this gate genuinely does not apply to this unit, leave the **${def.promptSection}** section empty and the handler will record it as \`omitted\`. Otherwise, fill the section with concrete evidence.`);
|
|
@@ -23,6 +23,9 @@ export function isAutoPaused() {
|
|
|
23
23
|
export function isAutoCompletionStopInProgress() {
|
|
24
24
|
return autoSession.completionStopInProgress;
|
|
25
25
|
}
|
|
26
|
+
export function clearAutoCompletionStopInProgress() {
|
|
27
|
+
autoSession.completionStopInProgress = false;
|
|
28
|
+
}
|
|
26
29
|
export function markToolStart(toolCallId, toolName) {
|
|
27
30
|
markTrackedToolStart(toolCallId, autoSession.active, toolName);
|
|
28
31
|
}
|
|
@@ -123,6 +123,11 @@ export const DETERMINISTIC_POLICY_ERROR_STRINGS = [
|
|
|
123
123
|
// "Cannot write to milestone CONTEXT.md without depth verification." for direct
|
|
124
124
|
// write tool calls to *-CONTEXT.md paths (different code path than gsd_summary_save).
|
|
125
125
|
"CONTEXT.md without depth verification",
|
|
126
|
+
// Section-close gate units (execute-task, complete-slice, validate-milestone) that
|
|
127
|
+
// reach for gsd_save_gate_result get the calm redirect from softGateToolRedirect
|
|
128
|
+
// (auto-unit-tool-scope.ts) instead of a HARD BLOCK. Still deterministic — those
|
|
129
|
+
// phases never own that tool, so a retry hits the same redirect every time.
|
|
130
|
+
"closes its quality gates by writing summary sections",
|
|
126
131
|
];
|
|
127
132
|
/**
|
|
128
133
|
* Returns true if the error message indicates a deterministic policy gate
|
|
@@ -25,6 +25,16 @@ const EXECUTE_TASK_UNIT_TYPES = new Set([
|
|
|
25
25
|
"execute-task-simple",
|
|
26
26
|
"reactive-execute",
|
|
27
27
|
]);
|
|
28
|
+
// These units own quality gates, but their completion handlers persist verdicts
|
|
29
|
+
// from artifact sections. gsd_save_gate_result belongs to gate-evaluate, so keep
|
|
30
|
+
// blocking it here with a calm redirect to the section-write path.
|
|
31
|
+
const SECTION_CLOSE_GATE_UNIT_TYPES = new Set([
|
|
32
|
+
"execute-task",
|
|
33
|
+
"execute-task-simple",
|
|
34
|
+
"reactive-execute",
|
|
35
|
+
"complete-slice",
|
|
36
|
+
"validate-milestone",
|
|
37
|
+
]);
|
|
28
38
|
const EXTRA_SCOPED_GSD_LIFECYCLE_TOOLS = [
|
|
29
39
|
"gsd_skip_slice",
|
|
30
40
|
"gsd_slice_reopen",
|
|
@@ -38,6 +48,7 @@ const SCOPED_GSD_LIFECYCLE_TOOLS = new Set([
|
|
|
38
48
|
.filter((tool) => tool.startsWith("gsd_"))
|
|
39
49
|
.map(canonicalWorkflowToolName));
|
|
40
50
|
export const GSD_PHASE_SCOPE_DISPLAY_REASON = "This GSD phase only allows its scoped workflow tools.";
|
|
51
|
+
export const GSD_SECTION_CLOSE_GATE_DISPLAY_REASON = "Gates here close by writing summary sections — gsd_save_gate_result isn't needed.";
|
|
41
52
|
function stripMcpToolPrefix(toolName) {
|
|
42
53
|
if (!toolName.startsWith("mcp__"))
|
|
43
54
|
return toolName;
|
|
@@ -65,6 +76,21 @@ function hardBlock(unitType, what) {
|
|
|
65
76
|
displayReason: GSD_PHASE_SCOPE_DISPLAY_REASON,
|
|
66
77
|
};
|
|
67
78
|
}
|
|
79
|
+
// This stable marker is registered in auto-tool-tracking.ts so auto-mode treats
|
|
80
|
+
// the redirect as deterministic policy, not a retryable execution failure.
|
|
81
|
+
function softGateToolRedirect(unitType) {
|
|
82
|
+
return {
|
|
83
|
+
block: true,
|
|
84
|
+
reason: [
|
|
85
|
+
`Skip this call — the "${unitType}" phase closes its quality gates by writing summary sections,`,
|
|
86
|
+
"not by calling gsd_save_gate_result (that tool belongs to the gate-evaluate phase).",
|
|
87
|
+
"Record each gate by filling its named section in your summary: a populated section records `pass`,",
|
|
88
|
+
"an empty one records `omitted`. Then call your completion tool and the handler persists every verdict.",
|
|
89
|
+
"This is expected, not an error — continue without gsd_save_gate_result.",
|
|
90
|
+
].join(" "),
|
|
91
|
+
displayReason: GSD_SECTION_CLOSE_GATE_DISPLAY_REASON,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
68
94
|
function allowedGsdToolsForUnit(unitType) {
|
|
69
95
|
return [...new Set((AUTO_UNIT_SCOPED_TOOLS[unitType] ?? [])
|
|
70
96
|
.filter((tool) => tool.startsWith("gsd_"))
|
|
@@ -122,5 +148,8 @@ export function shouldBlockAutoUnitToolCall(unitType, toolName, input, unitId) {
|
|
|
122
148
|
if (forbiddenReason) {
|
|
123
149
|
return hardBlock(unitType, `GSD lifecycle tool "${canonicalTool}" is not permitted; ${forbiddenReason} Fix unit-tool-contracts.ts or the ${unitType} prompt.`);
|
|
124
150
|
}
|
|
151
|
+
if (canonicalTool === "gsd_save_gate_result" && SECTION_CLOSE_GATE_UNIT_TYPES.has(unitType)) {
|
|
152
|
+
return softGateToolRedirect(unitType);
|
|
153
|
+
}
|
|
125
154
|
return hardBlock(unitType, `GSD lifecycle tool "${canonicalTool}" is not permitted; allowed GSD tools: ${allowedTools.length > 0 ? allowedTools.join(", ") : "(none)"}`);
|
|
126
155
|
}
|
|
@@ -25,7 +25,7 @@ import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
|
25
25
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
26
26
|
import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
27
27
|
import { classifyProject } from "./detection.js";
|
|
28
|
-
import { nativeGetCurrentBranch, nativeDetectMainBranch, nativeWorkingTreeStatus, nativeAddAllWithExclusions, nativeCommit, nativeCheckoutBranch, nativeMergeSquash, nativeConflictFiles, nativeAddPaths, nativeRmForce, nativeBranchDelete, nativeBranchForceReset, nativeBranchExists, nativeDiffNumstat, nativeUpdateRef, nativeIsAncestor, nativeMergeAbort, nativeWorktreeList, nativeLsFiles, } from "./native-git-bridge.js";
|
|
28
|
+
import { nativeGetCurrentBranch, nativeDetectMainBranch, nativeWorkingTreeStatus, nativeAddAllWithExclusions, nativeCommit, nativeCheckoutBranch, nativeMergeSquash, nativeMergeRegular, nativeConflictFiles, nativeAddPaths, nativeRmForce, nativeBranchDelete, nativeBranchForceReset, nativeBranchExists, nativeDiffNumstat, nativeUpdateRef, nativeIsAncestor, nativeMergeAbort, nativeWorktreeList, nativeLsFiles, } from "./native-git-bridge.js";
|
|
29
29
|
import { CLOSEOUT_CONSISTENCY_BLOCKED_REASON, checkCloseoutConsistencyGate, formatCloseoutConsistencyBlock, } from "./closeout-consistency-gate.js";
|
|
30
30
|
import { gsdHome } from "./gsd-home.js";
|
|
31
31
|
import { createWorkspace } from "./workspace.js";
|
|
@@ -438,16 +438,17 @@ function removeMergeStateFiles(basePath, contextLabel) {
|
|
|
438
438
|
logError("worktree", `${contextLabel} merge state cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
|
-
function
|
|
442
|
-
//
|
|
443
|
-
//
|
|
444
|
-
// remove merge message files that native/libgit2 paths may have
|
|
441
|
+
function cleanupConflictState(basePath) {
|
|
442
|
+
// Merge conflicts can leave unmerged index entries; merge-abort alone is not
|
|
443
|
+
// enough for squash merges (MERGE_HEAD is never written). Reset the merge
|
|
444
|
+
// index, then remove merge message files that native/libgit2 paths may have
|
|
445
|
+
// created.
|
|
445
446
|
try {
|
|
446
447
|
nativeMergeAbort(basePath);
|
|
447
448
|
}
|
|
448
449
|
catch (err) {
|
|
449
|
-
//
|
|
450
|
-
debugLog("
|
|
450
|
+
// MERGE_HEAD absent (squash merge path) — abort is a no-op, which is fine.
|
|
451
|
+
debugLog("conflict-cleanup:merge-abort-skipped", {
|
|
451
452
|
error: err instanceof Error ? err.message : String(err),
|
|
452
453
|
});
|
|
453
454
|
}
|
|
@@ -459,9 +460,9 @@ function cleanupSquashConflictState(basePath) {
|
|
|
459
460
|
});
|
|
460
461
|
}
|
|
461
462
|
catch (err) {
|
|
462
|
-
logError("worktree", `git reset --merge failed after
|
|
463
|
+
logError("worktree", `git reset --merge failed after merge conflict: ${err instanceof Error ? err.message : String(err)}`);
|
|
463
464
|
}
|
|
464
|
-
removeMergeStateFiles(basePath, "
|
|
465
|
+
removeMergeStateFiles(basePath, "conflict");
|
|
465
466
|
}
|
|
466
467
|
// ─── Dispatch-Level Sync (project root ↔ worktree) ──────────────────────────
|
|
467
468
|
/**
|
|
@@ -1871,14 +1872,20 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
|
|
|
1871
1872
|
// report the dirty tree if it fails.
|
|
1872
1873
|
logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1873
1874
|
}
|
|
1874
|
-
// 7b. Clean up stale merge state before attempting
|
|
1875
|
+
// 7b. Clean up stale merge state before attempting the merge (#2912).
|
|
1875
1876
|
// A leftover MERGE_HEAD (from a previous failed merge, libgit2 native path,
|
|
1876
|
-
// or interrupted operation) causes
|
|
1877
|
+
// or interrupted operation) causes git merge to refuse with
|
|
1877
1878
|
// "fatal: You have not concluded your merge (MERGE_HEAD exists)".
|
|
1878
1879
|
// Defensively remove merge artifacts before starting.
|
|
1879
1880
|
removeMergeStateFiles(originalBasePath_, "pre-merge");
|
|
1880
|
-
// 8.
|
|
1881
|
-
|
|
1881
|
+
// 8. Merge — respect merge_strategy preference (#549).
|
|
1882
|
+
// "squash" (default): stages changes without a merge commit; caller commits.
|
|
1883
|
+
// "merge": --no-ff --no-commit so caller can supply the commit message while
|
|
1884
|
+
// git records a real merge commit (MERGE_HEAD present when nativeCommit runs).
|
|
1885
|
+
const effectiveStrategy = prefs.merge_strategy === "merge" ? "merge" : "squash";
|
|
1886
|
+
const mergeResult = effectiveStrategy === "merge"
|
|
1887
|
+
? nativeMergeRegular(originalBasePath_, milestoneBranch)
|
|
1888
|
+
: nativeMergeSquash(originalBasePath_, milestoneBranch);
|
|
1882
1889
|
if (needsDbCycle && dbPathToReopen) {
|
|
1883
1890
|
try {
|
|
1884
1891
|
openDatabase(dbPathToReopen);
|
|
@@ -1912,7 +1919,7 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
|
|
|
1912
1919
|
const fileList = mergeResult.dirtyFiles?.length
|
|
1913
1920
|
? `Dirty files:\n${mergeResult.dirtyFiles.map((f) => ` ${f}`).join("\n")}`
|
|
1914
1921
|
: `Check \`git status\` in the project root for details.`;
|
|
1915
|
-
throw new GSDError(GSD_GIT_ERROR,
|
|
1922
|
+
throw new GSDError(GSD_GIT_ERROR, `${effectiveStrategy === "merge" ? "Merge" : "Squash merge"} of ${milestoneBranch} rejected: working tree has dirty or untracked files ` +
|
|
1916
1923
|
`that conflict with the merge. ${fileList}`);
|
|
1917
1924
|
}
|
|
1918
1925
|
// Check for conflicts — use merge result first, fall back to nativeConflictFiles
|
|
@@ -1930,7 +1937,7 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
|
|
|
1930
1937
|
}
|
|
1931
1938
|
// If there are still real code conflicts, escalate
|
|
1932
1939
|
if (codeConflicts.length > 0) {
|
|
1933
|
-
|
|
1940
|
+
cleanupConflictState(originalBasePath_);
|
|
1934
1941
|
// Pop stash before throwing so local work is not lost (#2151).
|
|
1935
1942
|
if (stashed) {
|
|
1936
1943
|
try {
|
|
@@ -1947,7 +1954,7 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
|
|
|
1947
1954
|
// causing autoCommitDirtyState to commit unrelated milestone files to
|
|
1948
1955
|
// the integration branch (#2929).
|
|
1949
1956
|
process.chdir(previousCwd);
|
|
1950
|
-
throw new MergeConflictError(codeConflicts,
|
|
1957
|
+
throw new MergeConflictError(codeConflicts, effectiveStrategy, milestoneBranch, mainBranch);
|
|
1951
1958
|
}
|
|
1952
1959
|
}
|
|
1953
1960
|
// No conflicts detected — possibly "already up to date", fall through to commit
|
|
@@ -2096,7 +2103,7 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
|
|
|
2096
2103
|
if (codeChanges.length > 0) {
|
|
2097
2104
|
// Milestone has unanchored code changes — abort teardown.
|
|
2098
2105
|
process.chdir(previousCwd);
|
|
2099
|
-
throw new GSDError(GSD_GIT_ERROR,
|
|
2106
|
+
throw new GSDError(GSD_GIT_ERROR, `${effectiveStrategy === "merge" ? "Merge" : "Squash merge"} produced nothing to commit but milestone branch "${milestoneBranch}" ` +
|
|
2100
2107
|
`has ${codeChanges.length} code file(s) not on "${mainBranch}". ` +
|
|
2101
2108
|
`Aborting worktree teardown to prevent data loss.`);
|
|
2102
2109
|
}
|