@opengsd/gsd-pi 1.1.1-dev.9f86580 → 1.1.1-dev.b2556262
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/headless-recover.js +56 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/index.js +39 -22
- package/dist/resources/extensions/browser-tools/state.js +12 -0
- package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
- package/dist/resources/extensions/browser-tools/utils.js +3 -3
- package/dist/resources/extensions/gsd/auto/loop.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +43 -10
- package/dist/resources/extensions/gsd/auto/session.js +20 -1
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +72 -12
- package/dist/resources/extensions/gsd/auto-model-selection.js +128 -9
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -19
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -2
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +14 -11
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +172 -65
- package/dist/resources/extensions/gsd/closeout-wizard.js +32 -9
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -9
- package/dist/resources/extensions/gsd/commands-maintenance.js +93 -15
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +2 -2
- package/dist/resources/extensions/gsd/db-writer.js +35 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/dist/resources/extensions/gsd/gsd-db.js +480 -172
- package/dist/resources/extensions/gsd/markdown-renderer.js +37 -53
- package/dist/resources/extensions/gsd/md-importer.js +38 -3
- package/dist/resources/extensions/gsd/migration-auto-check.js +126 -31
- package/dist/resources/extensions/gsd/parsers-legacy.js +23 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +22 -4
- package/dist/resources/extensions/gsd/pre-execution-checks.js +10 -2
- package/dist/resources/extensions/gsd/preferences-models.js +110 -43
- package/dist/resources/extensions/gsd/preferences-types.js +13 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +68 -3
- package/dist/resources/extensions/gsd/preferences.js +4 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -1
- package/dist/resources/extensions/gsd/safety/content-validator.js +6 -4
- package/dist/resources/extensions/gsd/source-observations.js +306 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +15 -8
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +33 -5
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +34 -13
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +39 -14
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +4 -4
- package/dist/resources/extensions/gsd/state.js +7 -3
- package/dist/resources/extensions/gsd/tool-contract.js +14 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +1 -9
- package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -6
- package/dist/resources/extensions/gsd/tools/plan-slice.js +42 -11
- package/dist/resources/extensions/gsd/tools/plan-task.js +7 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +57 -429
- package/dist/resources/extensions/gsd/uat-policy.js +130 -0
- package/dist/resources/extensions/gsd/uat-run.js +414 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +3 -4
- package/dist/resources/extensions/gsd/verdict-parser.js +3 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +132 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +8 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +18 -17
- package/dist/resources/extensions/subagent/agents.js +1 -0
- package/dist/resources/extensions/subagent/index.js +27 -12
- package/dist/resources/extensions/subagent/launch.js +7 -2
- 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/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/8357.js +1 -1
- 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/dist/native.js +22 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +4 -4
- 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/assistant-message.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +66 -12
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +18 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/dist/native.js +22 -0
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +30 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +23 -17
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +25 -24
- 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/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/utils.d.ts +11 -0
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +119 -6
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/themes.js +1 -1
- package/pkg/dist/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +39 -22
- package/src/resources/extensions/browser-tools/state.ts +13 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
- package/src/resources/extensions/browser-tools/utils.ts +3 -3
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +42 -10
- package/src/resources/extensions/gsd/auto/session.ts +22 -1
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +85 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +164 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +20 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +23 -20
- package/src/resources/extensions/gsd/auto-recovery.ts +22 -3
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +13 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +225 -72
- package/src/resources/extensions/gsd/closeout-wizard.ts +47 -13
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -17
- package/src/resources/extensions/gsd/commands-maintenance.ts +124 -13
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +2 -2
- package/src/resources/extensions/gsd/db-writer.ts +38 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/src/resources/extensions/gsd/gsd-db.ts +564 -186
- package/src/resources/extensions/gsd/markdown-renderer.ts +44 -66
- package/src/resources/extensions/gsd/md-importer.ts +49 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +154 -34
- package/src/resources/extensions/gsd/parsers-legacy.ts +20 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +22 -4
- package/src/resources/extensions/gsd/pre-execution-checks.ts +9 -2
- package/src/resources/extensions/gsd/preferences-models.ts +112 -43
- package/src/resources/extensions/gsd/preferences-types.ts +39 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +76 -2
- package/src/resources/extensions/gsd/preferences.ts +5 -0
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +6 -1
- package/src/resources/extensions/gsd/safety/content-validator.ts +8 -5
- package/src/resources/extensions/gsd/source-observations.ts +402 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +20 -8
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +44 -5
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +39 -11
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +45 -15
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +4 -4
- package/src/resources/extensions/gsd/state.ts +7 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +299 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +75 -3
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/closeout-wizard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/content-validator.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +16 -2
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +1 -11
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +62 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +99 -2
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +162 -18
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/source-observations.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -21
- package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +73 -6
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +511 -1
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +44 -0
- package/src/resources/extensions/gsd/tool-contract.ts +28 -0
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +1 -11
- package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -6
- package/src/resources/extensions/gsd/tools/plan-slice.ts +54 -12
- package/src/resources/extensions/gsd/tools/plan-task.ts +8 -1
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +66 -526
- package/src/resources/extensions/gsd/types.ts +1 -0
- package/src/resources/extensions/gsd/uat-policy.ts +191 -0
- package/src/resources/extensions/gsd/uat-run.ts +550 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +3 -4
- package/src/resources/extensions/gsd/verdict-parser.ts +3 -10
- package/src/resources/extensions/gsd/workflow-manifest.ts +193 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +22 -22
- package/src/resources/extensions/shared/tests/format-utils.test.ts +8 -3
- package/src/resources/extensions/subagent/agents.ts +4 -0
- package/src/resources/extensions/subagent/index.ts +28 -3
- package/src/resources/extensions/subagent/launch.ts +8 -0
- package/src/resources/extensions/subagent/tests/model-override.test.ts +31 -0
- /package/dist/web/standalone/.next/static/{zzYMrKpPGfRQRxSFO32Jr → tJOKQbQRO-9MiFDO8DIDS}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{zzYMrKpPGfRQRxSFO32Jr → tJOKQbQRO-9MiFDO8DIDS}/_ssgManifest.js +0 -0
package/dist/headless-recover.js
CHANGED
|
@@ -46,13 +46,20 @@ async function loadExtensionModules() {
|
|
|
46
46
|
const dbModule = await jiti.import(gsdExtensionPath('gsd-db.ts'), {});
|
|
47
47
|
const importerModule = await jiti.import(gsdExtensionPath('md-importer.ts'), {});
|
|
48
48
|
const dynamicToolsModule = await jiti.import(gsdExtensionPath('bootstrap/dynamic-tools.ts'), {});
|
|
49
|
+
const migrationCheckModule = await jiti.import(gsdExtensionPath('migration-auto-check.ts'), {});
|
|
50
|
+
const rendererModule = await jiti.import(gsdExtensionPath('markdown-renderer.ts'), {});
|
|
49
51
|
return {
|
|
50
52
|
ensureDbOpen: dynamicToolsModule.ensureDbOpen,
|
|
51
53
|
isDbAvailable: dbModule.isDbAvailable,
|
|
52
54
|
clearEngineHierarchy: dbModule.clearEngineHierarchy,
|
|
53
55
|
transaction: dbModule.transaction,
|
|
56
|
+
backupDatabaseSnapshot: dbModule.backupDatabaseSnapshot,
|
|
54
57
|
migrateHierarchyToDb: importerModule.migrateHierarchyToDb,
|
|
55
58
|
invalidateStateCache: stateModule.invalidateStateCache,
|
|
59
|
+
countDbHierarchy: migrationCheckModule.countDbHierarchy,
|
|
60
|
+
countMarkdownHierarchy: migrationCheckModule.countMarkdownHierarchy,
|
|
61
|
+
recoverWouldDeleteDbRows: migrationCheckModule.recoverWouldDeleteDbRows,
|
|
62
|
+
renderAllFromDb: rendererModule.renderAllFromDb,
|
|
56
63
|
};
|
|
57
64
|
}
|
|
58
65
|
export async function handleRecover(basePath) {
|
|
@@ -75,6 +82,24 @@ export async function handleRecover(basePath) {
|
|
|
75
82
|
process.stderr.write(`[headless] recover: failed to open or create the GSD database at ${basePath}\n`);
|
|
76
83
|
return { exitCode: 1 };
|
|
77
84
|
}
|
|
85
|
+
// Refuse a destructive recover that would delete authoritative DB rows the
|
|
86
|
+
// markdown lacks, unless explicitly allowed. The DB is the source of truth;
|
|
87
|
+
// re-projecting via rebuild is almost always what's wanted instead. The
|
|
88
|
+
// check is identity-based, so it also catches equal-count divergence (DB S99
|
|
89
|
+
// vs markdown S01) that a cardinality-only comparison would miss.
|
|
90
|
+
const markdown = modules.countMarkdownHierarchy(basePath);
|
|
91
|
+
const beforeDb = modules.countDbHierarchy();
|
|
92
|
+
const dataLoss = modules.recoverWouldDeleteDbRows(basePath);
|
|
93
|
+
const allowDataLoss = process.env.GSD_RECOVER_ALLOW_DATA_LOSS === '1';
|
|
94
|
+
if (dataLoss && !allowDataLoss) {
|
|
95
|
+
process.stderr.write(`[headless] recover refused: the DB (${beforeDb.milestones}M/${beforeDb.slices}S/${beforeDb.tasks}T) ` +
|
|
96
|
+
`holds rows the markdown (${markdown.milestones}M/${markdown.slices}S/${markdown.tasks}T) lacks; ` +
|
|
97
|
+
`recover would delete them. Set GSD_RECOVER_ALLOW_DATA_LOSS=1 to override, ` +
|
|
98
|
+
`or run a DB-to-markdown rebuild instead.\n`);
|
|
99
|
+
return { exitCode: 1 };
|
|
100
|
+
}
|
|
101
|
+
// Snapshot the DB before the destructive clear so recover is reversible.
|
|
102
|
+
const backupPath = modules.backupDatabaseSnapshot('pre-recover');
|
|
78
103
|
let counts;
|
|
79
104
|
try {
|
|
80
105
|
counts = modules.transaction(() => {
|
|
@@ -88,6 +113,36 @@ export async function handleRecover(basePath) {
|
|
|
88
113
|
return { exitCode: 1 };
|
|
89
114
|
}
|
|
90
115
|
modules.invalidateStateCache();
|
|
91
|
-
|
|
116
|
+
// Re-project markdown from the freshly imported DB so disk and DB agree.
|
|
117
|
+
// renderAllFromDb resolves even when individual artifacts fail, so inspect
|
|
118
|
+
// its error list — a silent projection failure must surface, not pass as a
|
|
119
|
+
// clean recover.
|
|
120
|
+
let projectionErrors = 0;
|
|
121
|
+
try {
|
|
122
|
+
const renderResult = await modules.renderAllFromDb(basePath);
|
|
123
|
+
projectionErrors = renderResult.errors.length;
|
|
124
|
+
if (projectionErrors > 0) {
|
|
125
|
+
process.stderr.write(`[headless] recover: ${projectionErrors} markdown projection(s) failed to render — markdown may be stale:\n`);
|
|
126
|
+
for (const e of renderResult.errors.slice(0, 10)) {
|
|
127
|
+
process.stderr.write(` - ${e}\n`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
133
|
+
process.stderr.write(`[headless] recover: re-render after import failed: ${msg}\n`);
|
|
134
|
+
projectionErrors = 1;
|
|
135
|
+
}
|
|
136
|
+
if (counts.milestones < markdown.milestones ||
|
|
137
|
+
counts.slices < markdown.slices ||
|
|
138
|
+
counts.tasks < markdown.tasks) {
|
|
139
|
+
process.stderr.write(`[headless] recover: imported fewer rows than markdown contained ` +
|
|
140
|
+
`(${markdown.milestones}M/${markdown.slices}S/${markdown.tasks}T on disk); some markdown may have failed to parse\n`);
|
|
141
|
+
}
|
|
142
|
+
if (backupPath) {
|
|
143
|
+
process.stderr.write(`[headless] recover: pre-recover snapshot saved to ${backupPath}\n`);
|
|
144
|
+
}
|
|
145
|
+
process.stderr.write(`gsd-recover: recovered ${counts.milestones}M/${counts.slices}S/${counts.tasks}T hierarchy` +
|
|
146
|
+
`${projectionErrors > 0 ? ` (${projectionErrors} projection error(s) — run rebuild markdown)` : ''}\n`);
|
|
92
147
|
return { exitCode: 0 };
|
|
93
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
fc4ebdcd3723ade9
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { importExtensionModule } from "@gsd/pi-coding-agent";
|
|
3
3
|
import { closeManagedGsdBrowser, registerManagedGsdBrowserTools, warmUpManagedGsdBrowser } from "./engine/managed-gsd-browser.js";
|
|
4
4
|
import { resolveBrowserEngineMode } from "./engine/selection.js";
|
|
5
|
+
import { setArtifactRootForCwd } from "./state.js";
|
|
5
6
|
import { detectWebApp } from "./web-app-detect.js";
|
|
6
7
|
let legacyRegistrationPromise = null;
|
|
7
8
|
let managedRegistrationPromise = null;
|
|
@@ -84,28 +85,29 @@ async function registerLegacyBrowserTools(pi) {
|
|
|
84
85
|
sanitizeArtifactName: utils.sanitizeArtifactName,
|
|
85
86
|
formatArtifactTimestamp: utils.formatArtifactTimestamp,
|
|
86
87
|
};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
88
|
+
const cwdScopedPi = withBrowserArtifactCwdScope(pi);
|
|
89
|
+
navigation.registerNavigationTools(cwdScopedPi, deps);
|
|
90
|
+
screenshot.registerScreenshotTools(cwdScopedPi, deps);
|
|
91
|
+
interaction.registerInteractionTools(cwdScopedPi, deps);
|
|
92
|
+
inspection.registerInspectionTools(cwdScopedPi, deps);
|
|
93
|
+
session.registerSessionTools(cwdScopedPi, deps);
|
|
94
|
+
assertions.registerAssertionTools(cwdScopedPi, deps);
|
|
95
|
+
refTools.registerRefTools(cwdScopedPi, deps);
|
|
96
|
+
wait.registerWaitTools(cwdScopedPi, deps);
|
|
97
|
+
pages.registerPageTools(cwdScopedPi, deps);
|
|
98
|
+
forms.registerFormTools(cwdScopedPi, deps);
|
|
99
|
+
intent.registerIntentTools(cwdScopedPi, deps);
|
|
100
|
+
pdf.registerPdfTools(cwdScopedPi, deps);
|
|
101
|
+
statePersistence.registerStatePersistenceTools(cwdScopedPi, deps);
|
|
102
|
+
networkMock.registerNetworkMockTools(cwdScopedPi, deps);
|
|
103
|
+
device.registerDeviceTools(cwdScopedPi, deps);
|
|
104
|
+
extract.registerExtractTools(cwdScopedPi, deps);
|
|
105
|
+
visualDiff.registerVisualDiffTools(cwdScopedPi, deps);
|
|
106
|
+
zoom.registerZoomTools(cwdScopedPi, deps);
|
|
107
|
+
codegen.registerCodegenTools(cwdScopedPi, deps);
|
|
108
|
+
actionCache.registerActionCacheTools(cwdScopedPi, deps);
|
|
109
|
+
injectionDetection.registerInjectionDetectionTools(cwdScopedPi, deps);
|
|
110
|
+
verify.registerVerifyTools(cwdScopedPi, deps);
|
|
109
111
|
})().catch((error) => {
|
|
110
112
|
legacyRegistrationPromise = null;
|
|
111
113
|
throw error;
|
|
@@ -113,6 +115,21 @@ async function registerLegacyBrowserTools(pi) {
|
|
|
113
115
|
}
|
|
114
116
|
return legacyRegistrationPromise;
|
|
115
117
|
}
|
|
118
|
+
function withBrowserArtifactCwdScope(pi) {
|
|
119
|
+
return {
|
|
120
|
+
...pi,
|
|
121
|
+
registerTool(definition) {
|
|
122
|
+
pi.registerTool({
|
|
123
|
+
...definition,
|
|
124
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
125
|
+
if (ctx?.cwd)
|
|
126
|
+
setArtifactRootForCwd(ctx.cwd);
|
|
127
|
+
return definition.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
116
133
|
async function registerBrowserTools(pi) {
|
|
117
134
|
const engine = resolveBrowserEngineMode();
|
|
118
135
|
if (engine === "off")
|
|
@@ -18,6 +18,17 @@ export const HAR_FILENAME = "session.har";
|
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
// Mutable state variables — accessed only via get/set functions
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
|
+
// 0. artifactRoot
|
|
22
|
+
let _artifactRoot = ARTIFACT_ROOT;
|
|
23
|
+
export function getArtifactRoot() { return _artifactRoot; }
|
|
24
|
+
export function setArtifactRootForCwd(cwd) {
|
|
25
|
+
const newRoot = path.resolve(cwd, ".artifacts", "browser");
|
|
26
|
+
if (newRoot !== _artifactRoot) {
|
|
27
|
+
_artifactRoot = newRoot;
|
|
28
|
+
_sessionArtifactDir = null;
|
|
29
|
+
}
|
|
30
|
+
return _artifactRoot;
|
|
31
|
+
}
|
|
21
32
|
// 1. browser
|
|
22
33
|
let _browser = null;
|
|
23
34
|
export function getBrowser() { return _browser; }
|
|
@@ -102,6 +113,7 @@ export function setHarState(h) { _harState = h; }
|
|
|
102
113
|
// resetAllState — mirrors closeBrowser()'s reset logic
|
|
103
114
|
// ---------------------------------------------------------------------------
|
|
104
115
|
export function resetAllState() {
|
|
116
|
+
_artifactRoot = ARTIFACT_ROOT;
|
|
105
117
|
_browser = null;
|
|
106
118
|
_context = null;
|
|
107
119
|
pageRegistry.pages = [];
|
|
@@ -2,7 +2,7 @@ import { Type } from "@sinclair/typebox";
|
|
|
2
2
|
import { stat } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { formatTimelineEntries, buildFailureHypothesis, summarizeBrowserSession, } from "../core.js";
|
|
5
|
-
import {
|
|
5
|
+
import { HAR_FILENAME, getArtifactRoot, getPageRegistry, getConsoleLogs, getNetworkLogs, getDialogLogs, getActionTimeline, getActiveTraceSession, setActiveTraceSession, getHarState, setHarState, getSessionStartedAt, getSessionArtifactDir, } from "../state.js";
|
|
6
6
|
import { getActiveFrameMetadata, ensureDir, } from "../utils.js";
|
|
7
7
|
export function registerSessionTools(pi, deps) {
|
|
8
8
|
// -------------------------------------------------------------------------
|
|
@@ -289,7 +289,8 @@ export function registerSessionTools(pi, deps) {
|
|
|
289
289
|
const { page: p } = await deps.ensureBrowser();
|
|
290
290
|
const startedAt = Date.now();
|
|
291
291
|
const sessionDir = await deps.ensureSessionArtifactDir();
|
|
292
|
-
const
|
|
292
|
+
const bundleName = `${deps.formatArtifactTimestamp(startedAt)}-${deps.sanitizeArtifactName(params.name ?? "debug-bundle", "debug-bundle")}`;
|
|
293
|
+
const bundleDir = path.join(getArtifactRoot(), bundleName);
|
|
293
294
|
await ensureDir(bundleDir);
|
|
294
295
|
const pages = await deps.getLivePagesSnapshot();
|
|
295
296
|
const actionTimeline = getActionTimeline();
|
|
@@ -8,7 +8,7 @@ import { mkdir, stat, writeFile, copyFile } from "node:fs/promises";
|
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, truncateHead, } from "@gsd/pi-coding-agent";
|
|
10
10
|
import { beginAction, finishAction, findAction, toActionParamsSummary, registryListPages, } from "./core.js";
|
|
11
|
-
import {
|
|
11
|
+
import { getActiveFrame, getArtifactRoot, getActiveTraceSession, getConsoleLogs, getDialogLogs, getHarState, getNetworkLogs, getSessionArtifactDir, getSessionStartedAt, setSessionArtifactDir, setSessionStartedAt, pageRegistry, actionTimeline, getPendingCriticalRequestsByPage, } from "./state.js";
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
// Text truncation
|
|
14
14
|
// ---------------------------------------------------------------------------
|
|
@@ -60,7 +60,7 @@ export async function ensureSessionArtifactDir() {
|
|
|
60
60
|
return existing;
|
|
61
61
|
}
|
|
62
62
|
const startedAt = ensureSessionStartedAt();
|
|
63
|
-
const dir = path.join(
|
|
63
|
+
const dir = path.join(getArtifactRoot(), `${formatArtifactTimestamp(startedAt)}-session`);
|
|
64
64
|
setSessionArtifactDir(dir);
|
|
65
65
|
await ensureDir(dir);
|
|
66
66
|
return dir;
|
|
@@ -95,7 +95,7 @@ export function getActiveFrameMetadata() {
|
|
|
95
95
|
}
|
|
96
96
|
export function getSessionArtifactMetadata() {
|
|
97
97
|
return {
|
|
98
|
-
artifactRoot:
|
|
98
|
+
artifactRoot: getArtifactRoot(),
|
|
99
99
|
sessionStartedAt: getSessionStartedAt(),
|
|
100
100
|
sessionArtifactDir: getSessionArtifactDir(),
|
|
101
101
|
activeTraceSession: getActiveTraceSession(),
|
|
@@ -1106,7 +1106,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
1106
1106
|
unitId: iterData.unitId,
|
|
1107
1107
|
});
|
|
1108
1108
|
const finalizeReason = finalizeResult.action === "break" ? finalizeResult.reason : undefined;
|
|
1109
|
-
const finalizeStatus = finalizeReason === "step-wizard"
|
|
1109
|
+
const finalizeStatus = (finalizeReason === "step-wizard" || finalizeReason === "milestone-complete")
|
|
1110
1110
|
? "completed"
|
|
1111
1111
|
: finalizeResult.action === "next"
|
|
1112
1112
|
? "completed"
|
|
@@ -1172,7 +1172,9 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
1172
1172
|
stuckStatePersistedThisIteration = true;
|
|
1173
1173
|
finishTurn("completed");
|
|
1174
1174
|
if (finalizeDecision.action === "complete-and-break") {
|
|
1175
|
-
s.
|
|
1175
|
+
if (!s.completionStopInProgress) {
|
|
1176
|
+
s.preserveStepSurfaceAfterLoopExit = true;
|
|
1177
|
+
}
|
|
1176
1178
|
break;
|
|
1177
1179
|
}
|
|
1178
1180
|
}
|
|
@@ -49,7 +49,7 @@ import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
|
|
|
49
49
|
import { getContextPauseAction } from "../auto-budget.js";
|
|
50
50
|
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, supportsStructuredQuestions, } from "../workflow-mcp.js";
|
|
51
51
|
import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
|
|
52
|
-
import { getToolBaselineSnapshot } from "../auto-model-selection.js";
|
|
52
|
+
import { getToolBaselineSnapshot, applyThinkingLevelForModel, floorThinkingLevelForUnit } from "../auto-model-selection.js";
|
|
53
53
|
import { resolveManifest } from "../unit-context-manifest.js";
|
|
54
54
|
import { createWorktreeSafetyModule } from "../worktree-safety.js";
|
|
55
55
|
import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
|
|
@@ -393,7 +393,7 @@ async function generateMilestoneReport(s, ctx, milestoneId) {
|
|
|
393
393
|
async function closeoutAndStop(ctx, pi, s, deps, reason) {
|
|
394
394
|
if (s.currentUnit) {
|
|
395
395
|
await deps.closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
396
|
-
s.
|
|
396
|
+
s.clearCurrentUnit();
|
|
397
397
|
}
|
|
398
398
|
await deps.stopAuto(ctx, pi, reason);
|
|
399
399
|
}
|
|
@@ -581,7 +581,7 @@ async function failClosedOnFinalizeTimeout(ic, iterData, loopState, stage, start
|
|
|
581
581
|
});
|
|
582
582
|
ctx.ui.notify(`${stage === "pre" ? "postUnitPreVerification" : "postUnitPostVerification"} timed out after ${timeoutMs / 1000}s for ${unitType} ${unitId} (${loopState.consecutiveFinalizeTimeouts}/${MAX_FINALIZE_TIMEOUTS}) — pausing auto-mode for recovery.`, "warning");
|
|
583
583
|
await deps.pauseAuto(ctx, pi);
|
|
584
|
-
s.
|
|
584
|
+
s.clearCurrentUnit();
|
|
585
585
|
clearCurrentPhase();
|
|
586
586
|
drainLogs();
|
|
587
587
|
return { action: "break", reason: progressKind };
|
|
@@ -1029,7 +1029,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
1029
1029
|
deps.logCmuxEvent(prefs, `Milestone ${mid} complete.`, "success");
|
|
1030
1030
|
if (s.currentUnit) {
|
|
1031
1031
|
await deps.closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
|
|
1032
|
-
s.
|
|
1032
|
+
s.clearCurrentUnit();
|
|
1033
1033
|
}
|
|
1034
1034
|
await deps.stopAuto(ctx, pi, `Milestone ${mid} complete`, {
|
|
1035
1035
|
completionWidget: {
|
|
@@ -1712,9 +1712,16 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1712
1712
|
if (match) {
|
|
1713
1713
|
const ok = await pi.setModel(match, { persist: false });
|
|
1714
1714
|
if (ok) {
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1715
|
+
// Apply the per-phase reasoning effort selectAndApplyModel resolved for
|
|
1716
|
+
// this unit — not the auto-start session snapshot — but route it through
|
|
1717
|
+
// the same floor + capability-clamp pipeline against the *hook* model
|
|
1718
|
+
// (ADR-026). The hook override can pick a different model family than the
|
|
1719
|
+
// one selectAndApplyModel clamped against, so re-clamping here prevents
|
|
1720
|
+
// sending an unsupported level; the floor fills in when no phase level
|
|
1721
|
+
// resolved so a hook-overridden execute-task still meets the floor.
|
|
1722
|
+
const hookThinkingBase = modelResult.appliedThinkingLevel
|
|
1723
|
+
?? floorThinkingLevelForUnit(unitType, s.autoModeStartThinkingLevel);
|
|
1724
|
+
applyThinkingLevelForModel(pi, hookThinkingBase, match, ctx);
|
|
1718
1725
|
s.currentUnitModel = match;
|
|
1719
1726
|
ctx.ui.notify(`Hook model override: ${match.provider}/${match.id}`, "info");
|
|
1720
1727
|
}
|
|
@@ -1783,7 +1790,21 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1783
1790
|
_resetLogs();
|
|
1784
1791
|
const unitStartedAt = Date.now();
|
|
1785
1792
|
s.unitDispatchCount.set(dispatchKey, nextDispatchCount);
|
|
1786
|
-
s.
|
|
1793
|
+
s.setCurrentUnit({ type: unitType, id: unitId, startedAt: unitStartedAt, workspaceRoot: s.basePath });
|
|
1794
|
+
if (unitType === "execute-task") {
|
|
1795
|
+
const { milestone, slice, task } = parseUnitId(unitId);
|
|
1796
|
+
if (milestone && slice && task && isDbAvailable()) {
|
|
1797
|
+
try {
|
|
1798
|
+
const taskRow = getTask(milestone, slice, task);
|
|
1799
|
+
if (taskRow)
|
|
1800
|
+
s.sourceObservations.observePlanTask(taskRow);
|
|
1801
|
+
}
|
|
1802
|
+
catch (err) {
|
|
1803
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1804
|
+
logWarning("prompt", `failed to preload source observations for ${unitId}: ${message}`);
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1787
1808
|
s.rootWriteBaseline = isIsolatedWorktreeSession(s)
|
|
1788
1809
|
? captureRootDirtySnapshot(s.originalBasePath)
|
|
1789
1810
|
: null;
|
|
@@ -1869,7 +1890,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1869
1890
|
category: "unknown",
|
|
1870
1891
|
isTransient: true,
|
|
1871
1892
|
});
|
|
1872
|
-
s.
|
|
1893
|
+
s.clearCurrentUnit();
|
|
1873
1894
|
await deps.pauseAuto(ctx, pi);
|
|
1874
1895
|
return { action: "break", reason: "ghost-completion" };
|
|
1875
1896
|
}
|
|
@@ -2204,7 +2225,7 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
|
|
|
2204
2225
|
s.currentUnit?.type === preUnitSnapshot.type &&
|
|
2205
2226
|
s.currentUnit?.id === preUnitSnapshot.id &&
|
|
2206
2227
|
s.currentUnit?.startedAt === preUnitSnapshot.startedAt) {
|
|
2207
|
-
s.
|
|
2228
|
+
s.clearCurrentUnit();
|
|
2208
2229
|
}
|
|
2209
2230
|
s.rootWriteBaseline = null;
|
|
2210
2231
|
};
|
|
@@ -2439,5 +2460,17 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
|
|
|
2439
2460
|
ctx.ui.notify(formatForNotification(logs), severity);
|
|
2440
2461
|
}
|
|
2441
2462
|
}
|
|
2463
|
+
if (preUnitSnapshot?.type === "complete-milestone" && s.currentMilestoneId) {
|
|
2464
|
+
// cleanupAfterLoopExit skips gsd-progress when preserveCompletionSurface is true, so clear stale controls here.
|
|
2465
|
+
ctx.ui.setStatus?.("gsd-step", undefined);
|
|
2466
|
+
ctx.ui.setWidget?.("gsd-progress", undefined);
|
|
2467
|
+
await deps.stopAuto(ctx, pi, `Milestone ${s.currentMilestoneId} complete`, {
|
|
2468
|
+
completionWidget: {
|
|
2469
|
+
milestoneId: s.currentMilestoneId,
|
|
2470
|
+
milestoneTitle: iterData.midTitle,
|
|
2471
|
+
},
|
|
2472
|
+
});
|
|
2473
|
+
return { action: "break", reason: "milestone-complete" };
|
|
2474
|
+
}
|
|
2442
2475
|
return { action: "next", data: undefined };
|
|
2443
2476
|
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* auto-session-encapsulation.test.ts enforce that auto.ts has no module-level
|
|
18
18
|
* `let` or `var` declarations.
|
|
19
19
|
*/
|
|
20
|
+
import { SourceObservationStore, supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
20
21
|
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
21
22
|
import { normalizeRealPath } from "../paths.js";
|
|
22
23
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
@@ -76,6 +77,7 @@ export class AutoSession {
|
|
|
76
77
|
currentTurnId = null;
|
|
77
78
|
currentUnitRouting = null;
|
|
78
79
|
currentMilestoneId = null;
|
|
80
|
+
sourceObservations = new SourceObservationStore();
|
|
79
81
|
// ── Model state ──────────────────────────────────────────────────────────
|
|
80
82
|
autoModeStartModel = null;
|
|
81
83
|
/** Explicit /gsd model pin captured at bootstrap (session-scoped policy override). */
|
|
@@ -196,6 +198,23 @@ export class AutoSession {
|
|
|
196
198
|
this.unitDispatchCount.clear();
|
|
197
199
|
this.unitLifetimeDispatches.clear();
|
|
198
200
|
}
|
|
201
|
+
setCurrentUnit(unit) {
|
|
202
|
+
this.currentUnit = unit;
|
|
203
|
+
if (!supportsSourceObservationsForUnit(unit.type)) {
|
|
204
|
+
this.sourceObservations.clear();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
this.sourceObservations.beginUnit({
|
|
208
|
+
unitType: unit.type,
|
|
209
|
+
unitId: unit.id,
|
|
210
|
+
startedAt: unit.startedAt,
|
|
211
|
+
basePath: unit.workspaceRoot ?? this.basePath,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
clearCurrentUnit() {
|
|
215
|
+
this.currentUnit = null;
|
|
216
|
+
this.sourceObservations.clear();
|
|
217
|
+
}
|
|
199
218
|
get lockBasePath() {
|
|
200
219
|
return resolveWorktreeProjectRoot(this.basePath, this.originalBasePath);
|
|
201
220
|
}
|
|
@@ -246,7 +265,7 @@ export class AutoSession {
|
|
|
246
265
|
this.unitLifetimeDispatches.clear();
|
|
247
266
|
this.unitRecoveryCount.clear();
|
|
248
267
|
// Unit
|
|
249
|
-
this.
|
|
268
|
+
this.clearCurrentUnit();
|
|
250
269
|
this.currentTraceId = null;
|
|
251
270
|
this.currentTurnId = null;
|
|
252
271
|
this.currentUnitRouting = null;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Declarative auto-mode dispatch rules and dispatch resolver.
|
|
3
3
|
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getUatBrowserToolSupportError } from "./uat-policy.js";
|
|
5
|
+
import { isDbAvailable, getMilestoneSlices, getPendingGatesForTurn, markPendingGatesOmittedForTurn, getMilestone, insertArtifact, insertAssessment, setSliceSketchFlag, transaction, getAssessment, } from "./gsd-db.js";
|
|
5
6
|
import { isClosedStatus } from "./status-guards.js";
|
|
6
7
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
7
8
|
import { gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveTaskFile, relTaskFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, gsdProjectionRoot, } from "./paths.js";
|
|
@@ -12,7 +13,7 @@ import { logWarning, logError } from "./workflow-logger.js";
|
|
|
12
13
|
import { dirname, join } from "node:path";
|
|
13
14
|
import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
|
|
14
15
|
import { buildDiscussMilestonePrompt, buildDiscussProjectPrompt, buildDiscussRequirementsPrompt, buildResearchDecisionPrompt, buildResearchProjectPrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
15
|
-
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
16
|
+
import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit } from "./preferences-models.js";
|
|
16
17
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
17
18
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
18
19
|
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
@@ -250,6 +251,43 @@ export function findMissingSummaries(basePath, mid) {
|
|
|
250
251
|
})
|
|
251
252
|
.map(s => s.id);
|
|
252
253
|
}
|
|
254
|
+
function stringField(row, key) {
|
|
255
|
+
const value = row?.[key];
|
|
256
|
+
return typeof value === "string" ? value : null;
|
|
257
|
+
}
|
|
258
|
+
function stripGsdPrefix(path) {
|
|
259
|
+
return path.startsWith(".gsd/") ? path.slice(".gsd/".length) : path;
|
|
260
|
+
}
|
|
261
|
+
function persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content) {
|
|
262
|
+
const artifactPath = stripGsdPrefix(assessmentRelPath);
|
|
263
|
+
const existingAssessment = getAssessment(assessmentRelPath) ??
|
|
264
|
+
getAssessment(artifactPath);
|
|
265
|
+
const scope = stringField(existingAssessment, "scope") ?? "run-uat";
|
|
266
|
+
const status = stringField(existingAssessment, "status") ??
|
|
267
|
+
extractVerdict(content)?.toLowerCase() ??
|
|
268
|
+
"unknown";
|
|
269
|
+
transaction(() => {
|
|
270
|
+
insertArtifact({
|
|
271
|
+
path: artifactPath,
|
|
272
|
+
artifact_type: "ASSESSMENT",
|
|
273
|
+
milestone_id: mid,
|
|
274
|
+
slice_id: sliceId,
|
|
275
|
+
task_id: null,
|
|
276
|
+
full_content: content,
|
|
277
|
+
});
|
|
278
|
+
if (!getAssessment(assessmentRelPath)) {
|
|
279
|
+
insertAssessment({
|
|
280
|
+
path: assessmentRelPath,
|
|
281
|
+
milestoneId: mid,
|
|
282
|
+
sliceId,
|
|
283
|
+
taskId: null,
|
|
284
|
+
status,
|
|
285
|
+
scope,
|
|
286
|
+
fullContent: content,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
253
291
|
function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
254
292
|
const completedSliceIds = new Set();
|
|
255
293
|
if (isDbAvailable()) {
|
|
@@ -281,11 +319,12 @@ function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
|
281
319
|
const slicePath = resolveSlicePath(basePath, mid, sliceId);
|
|
282
320
|
const assessmentPath = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT")
|
|
283
321
|
?? (slicePath ? join(slicePath, buildSliceFileName(sliceId, "ASSESSMENT")) : null);
|
|
284
|
-
if (!assessmentPath
|
|
322
|
+
if (!assessmentPath)
|
|
285
323
|
continue;
|
|
286
|
-
|
|
324
|
+
const assessmentRelPath = relSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
287
325
|
const now = new Date().toISOString();
|
|
288
|
-
const
|
|
326
|
+
const didCreateAssessment = !existsSync(assessmentPath);
|
|
327
|
+
const content = didCreateAssessment ? [
|
|
289
328
|
"---",
|
|
290
329
|
`sliceId: ${sliceId}`,
|
|
291
330
|
"verdict: PASS",
|
|
@@ -297,8 +336,19 @@ function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
|
297
336
|
"Auto-created during milestone validation because this completed slice had a SUMMARY but no ASSESSMENT artifact.",
|
|
298
337
|
"No additional reassessment changes were detected in this backfill step.",
|
|
299
338
|
"",
|
|
300
|
-
].join("\n");
|
|
301
|
-
|
|
339
|
+
].join("\n") : readFileSync(assessmentPath, "utf-8");
|
|
340
|
+
if (isDbAvailable()) {
|
|
341
|
+
try {
|
|
342
|
+
persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content);
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
logWarning("dispatch", `failed to backfill assessment DB rows for ${mid}/${sliceId}: ${err.message}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (didCreateAssessment) {
|
|
349
|
+
mkdirSync(dirname(assessmentPath), { recursive: true });
|
|
350
|
+
writeFileSync(assessmentPath, content, "utf-8");
|
|
351
|
+
}
|
|
302
352
|
}
|
|
303
353
|
}
|
|
304
354
|
// ─── Rewrite Circuit Breaker ──────────────────────────────────────────────
|
|
@@ -480,6 +530,15 @@ export const DISPATCH_RULES = [
|
|
|
480
530
|
if (transportError) {
|
|
481
531
|
return { action: "stop", reason: transportError, level: "warning" };
|
|
482
532
|
}
|
|
533
|
+
const browserToolError = getUatBrowserToolSupportError({
|
|
534
|
+
uatType,
|
|
535
|
+
activeTools,
|
|
536
|
+
milestoneId: mid,
|
|
537
|
+
sliceId,
|
|
538
|
+
});
|
|
539
|
+
if (browserToolError) {
|
|
540
|
+
return { action: "stop", reason: browserToolError, level: "warning" };
|
|
541
|
+
}
|
|
483
542
|
// Cap run-uat dispatch attempts to prevent infinite replay (#3624).
|
|
484
543
|
// Check before incrementing so an exhausted counter cannot create a
|
|
485
544
|
// no-progress skip loop that starves later dispatch rules.
|
|
@@ -885,7 +944,7 @@ export const DISPATCH_RULES = [
|
|
|
885
944
|
action: "dispatch",
|
|
886
945
|
unitType: "research-slice",
|
|
887
946
|
unitId: `${mid}/parallel-research`,
|
|
888
|
-
prompt: await buildParallelResearchSlicesPrompt(mid, midTitle, researchReadySlices, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary),
|
|
947
|
+
prompt: await buildParallelResearchSlicesPrompt(mid, midTitle, researchReadySlices, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary, resolveThinkingLevelForUnit("subagent")),
|
|
889
948
|
};
|
|
890
949
|
},
|
|
891
950
|
},
|
|
@@ -1037,17 +1096,17 @@ export const DISPATCH_RULES = [
|
|
|
1037
1096
|
// Gate evaluation is opt-in via preferences
|
|
1038
1097
|
const gateConfig = prefs?.gate_evaluation;
|
|
1039
1098
|
if (!gateConfig?.enabled) {
|
|
1040
|
-
|
|
1099
|
+
markPendingGatesOmittedForTurn(mid, sid, "gate-evaluate");
|
|
1041
1100
|
return { action: "skip" };
|
|
1042
1101
|
}
|
|
1043
|
-
const pending =
|
|
1102
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
1044
1103
|
if (pending.length === 0)
|
|
1045
1104
|
return { action: "skip" };
|
|
1046
1105
|
return {
|
|
1047
1106
|
action: "dispatch",
|
|
1048
1107
|
unitType: "gate-evaluate",
|
|
1049
1108
|
unitId: `${mid}/${sid}/gates+${pending.map(g => g.gate_id).join(",")}`,
|
|
1050
|
-
prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary),
|
|
1109
|
+
prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary, resolveThinkingLevelForUnit("subagent")),
|
|
1051
1110
|
};
|
|
1052
1111
|
},
|
|
1053
1112
|
},
|
|
@@ -1090,6 +1149,7 @@ export const DISPATCH_RULES = [
|
|
|
1090
1149
|
return null;
|
|
1091
1150
|
const maxParallel = reactiveConfig?.max_parallel ?? 2;
|
|
1092
1151
|
const subagentModel = reactiveConfig?.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
|
|
1152
|
+
const subagentThinking = resolveThinkingLevelForUnit("subagent");
|
|
1093
1153
|
// Default-on safety threshold: only activate reactive dispatch when at
|
|
1094
1154
|
// least N tasks are ready. Users who explicitly enabled reactive_execution
|
|
1095
1155
|
// keep the legacy threshold of 2 (matches the prior "any parallelism is
|
|
@@ -1147,7 +1207,7 @@ export const DISPATCH_RULES = [
|
|
|
1147
1207
|
action: "dispatch",
|
|
1148
1208
|
unitType: "reactive-execute",
|
|
1149
1209
|
unitId: `${mid}/${sid}/reactive+${batchSuffix}`,
|
|
1150
|
-
prompt: await buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, selected, basePath, subagentModel, { sessionContextWindow, modelRegistry, sessionProvider }),
|
|
1210
|
+
prompt: await buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, selected, basePath, subagentModel, { sessionContextWindow, modelRegistry, sessionProvider, subagentThinking }),
|
|
1151
1211
|
};
|
|
1152
1212
|
}
|
|
1153
1213
|
catch (err) {
|