@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
|
@@ -14,15 +14,16 @@
|
|
|
14
14
|
|
|
15
15
|
import type { GSDState } from "./types.js";
|
|
16
16
|
import type { GSDPreferences } from "./preferences.js";
|
|
17
|
-
import type { UatType } from "./files.js";
|
|
18
17
|
import type { MinimalModelRegistry } from "./context-budget.js";
|
|
19
18
|
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
19
|
+
import { getUatBrowserToolSupportError, type UatType } from "./uat-policy.js";
|
|
20
20
|
import {
|
|
21
21
|
isDbAvailable,
|
|
22
22
|
getMilestoneSlices,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
getPendingGatesForTurn,
|
|
24
|
+
markPendingGatesOmittedForTurn,
|
|
25
25
|
getMilestone,
|
|
26
|
+
insertArtifact,
|
|
26
27
|
insertAssessment,
|
|
27
28
|
setSliceSketchFlag,
|
|
28
29
|
transaction,
|
|
@@ -77,7 +78,7 @@ import {
|
|
|
77
78
|
checkNeedsReassessment,
|
|
78
79
|
checkNeedsRunUat,
|
|
79
80
|
} from "./auto-prompts.js";
|
|
80
|
-
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
81
|
+
import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit } from "./preferences-models.js";
|
|
81
82
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
82
83
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
83
84
|
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
@@ -439,6 +440,53 @@ export function findMissingSummaries(basePath: string, mid: string): string[] {
|
|
|
439
440
|
.map(s => s.id);
|
|
440
441
|
}
|
|
441
442
|
|
|
443
|
+
function stringField(row: Record<string, unknown> | null, key: string): string | null {
|
|
444
|
+
const value = row?.[key];
|
|
445
|
+
return typeof value === "string" ? value : null;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function stripGsdPrefix(path: string): string {
|
|
449
|
+
return path.startsWith(".gsd/") ? path.slice(".gsd/".length) : path;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function persistSliceAssessmentBackfill(
|
|
453
|
+
assessmentRelPath: string,
|
|
454
|
+
mid: string,
|
|
455
|
+
sliceId: string,
|
|
456
|
+
content: string,
|
|
457
|
+
): void {
|
|
458
|
+
const artifactPath = stripGsdPrefix(assessmentRelPath);
|
|
459
|
+
const existingAssessment =
|
|
460
|
+
getAssessment(assessmentRelPath) ??
|
|
461
|
+
getAssessment(artifactPath);
|
|
462
|
+
const scope = stringField(existingAssessment, "scope") ?? "run-uat";
|
|
463
|
+
const status = stringField(existingAssessment, "status") ??
|
|
464
|
+
extractVerdict(content)?.toLowerCase() ??
|
|
465
|
+
"unknown";
|
|
466
|
+
|
|
467
|
+
transaction(() => {
|
|
468
|
+
insertArtifact({
|
|
469
|
+
path: artifactPath,
|
|
470
|
+
artifact_type: "ASSESSMENT",
|
|
471
|
+
milestone_id: mid,
|
|
472
|
+
slice_id: sliceId,
|
|
473
|
+
task_id: null,
|
|
474
|
+
full_content: content,
|
|
475
|
+
});
|
|
476
|
+
if (!getAssessment(assessmentRelPath)) {
|
|
477
|
+
insertAssessment({
|
|
478
|
+
path: assessmentRelPath,
|
|
479
|
+
milestoneId: mid,
|
|
480
|
+
sliceId,
|
|
481
|
+
taskId: null,
|
|
482
|
+
status,
|
|
483
|
+
scope,
|
|
484
|
+
fullContent: content,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
442
490
|
function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string): void {
|
|
443
491
|
const completedSliceIds = new Set<string>();
|
|
444
492
|
if (isDbAvailable()) {
|
|
@@ -467,11 +515,12 @@ function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string):
|
|
|
467
515
|
const slicePath = resolveSlicePath(basePath, mid, sliceId);
|
|
468
516
|
const assessmentPath = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT")
|
|
469
517
|
?? (slicePath ? join(slicePath, buildSliceFileName(sliceId, "ASSESSMENT")) : null);
|
|
470
|
-
if (!assessmentPath
|
|
518
|
+
if (!assessmentPath) continue;
|
|
471
519
|
|
|
472
|
-
|
|
520
|
+
const assessmentRelPath = relSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
473
521
|
const now = new Date().toISOString();
|
|
474
|
-
const
|
|
522
|
+
const didCreateAssessment = !existsSync(assessmentPath);
|
|
523
|
+
const content = didCreateAssessment ? [
|
|
475
524
|
"---",
|
|
476
525
|
`sliceId: ${sliceId}`,
|
|
477
526
|
"verdict: PASS",
|
|
@@ -483,8 +532,20 @@ function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string):
|
|
|
483
532
|
"Auto-created during milestone validation because this completed slice had a SUMMARY but no ASSESSMENT artifact.",
|
|
484
533
|
"No additional reassessment changes were detected in this backfill step.",
|
|
485
534
|
"",
|
|
486
|
-
].join("\n");
|
|
487
|
-
|
|
535
|
+
].join("\n") : readFileSync(assessmentPath, "utf-8");
|
|
536
|
+
|
|
537
|
+
if (isDbAvailable()) {
|
|
538
|
+
try {
|
|
539
|
+
persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content);
|
|
540
|
+
} catch (err) {
|
|
541
|
+
logWarning("dispatch", `failed to backfill assessment DB rows for ${mid}/${sliceId}: ${(err as Error).message}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (didCreateAssessment) {
|
|
546
|
+
mkdirSync(dirname(assessmentPath), { recursive: true });
|
|
547
|
+
writeFileSync(assessmentPath, content, "utf-8");
|
|
548
|
+
}
|
|
488
549
|
}
|
|
489
550
|
}
|
|
490
551
|
|
|
@@ -689,6 +750,15 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
689
750
|
if (transportError) {
|
|
690
751
|
return { action: "stop" as const, reason: transportError, level: "warning" as const };
|
|
691
752
|
}
|
|
753
|
+
const browserToolError = getUatBrowserToolSupportError({
|
|
754
|
+
uatType,
|
|
755
|
+
activeTools,
|
|
756
|
+
milestoneId: mid,
|
|
757
|
+
sliceId,
|
|
758
|
+
});
|
|
759
|
+
if (browserToolError) {
|
|
760
|
+
return { action: "stop" as const, reason: browserToolError, level: "warning" as const };
|
|
761
|
+
}
|
|
692
762
|
|
|
693
763
|
// Cap run-uat dispatch attempts to prevent infinite replay (#3624).
|
|
694
764
|
// Check before incrementing so an exhausted counter cannot create a
|
|
@@ -1095,6 +1165,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1095
1165
|
researchReadySlices,
|
|
1096
1166
|
basePath,
|
|
1097
1167
|
resolveModelWithFallbacksForUnit("subagent")?.primary,
|
|
1168
|
+
resolveThinkingLevelForUnit("subagent"),
|
|
1098
1169
|
),
|
|
1099
1170
|
};
|
|
1100
1171
|
},
|
|
@@ -1264,11 +1335,11 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1264
1335
|
// Gate evaluation is opt-in via preferences
|
|
1265
1336
|
const gateConfig = prefs?.gate_evaluation;
|
|
1266
1337
|
if (!gateConfig?.enabled) {
|
|
1267
|
-
|
|
1338
|
+
markPendingGatesOmittedForTurn(mid, sid, "gate-evaluate");
|
|
1268
1339
|
return { action: "skip" };
|
|
1269
1340
|
}
|
|
1270
1341
|
|
|
1271
|
-
const pending =
|
|
1342
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
1272
1343
|
if (pending.length === 0) return { action: "skip" };
|
|
1273
1344
|
|
|
1274
1345
|
return {
|
|
@@ -1282,6 +1353,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1282
1353
|
sTitle,
|
|
1283
1354
|
basePath,
|
|
1284
1355
|
resolveModelWithFallbacksForUnit("subagent")?.primary,
|
|
1356
|
+
resolveThinkingLevelForUnit("subagent"),
|
|
1285
1357
|
),
|
|
1286
1358
|
};
|
|
1287
1359
|
},
|
|
@@ -1327,6 +1399,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1327
1399
|
if (resolveSliceFile(basePath, mid, sid, "REACTIVE-BLOCKER")) return null;
|
|
1328
1400
|
const maxParallel = reactiveConfig?.max_parallel ?? 2;
|
|
1329
1401
|
const subagentModel = reactiveConfig?.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
|
|
1402
|
+
const subagentThinking = resolveThinkingLevelForUnit("subagent");
|
|
1330
1403
|
// Default-on safety threshold: only activate reactive dispatch when at
|
|
1331
1404
|
// least N tasks are ready. Users who explicitly enabled reactive_execution
|
|
1332
1405
|
// keep the legacy threshold of 2 (matches the prior "any parallelism is
|
|
@@ -1413,7 +1486,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1413
1486
|
selected,
|
|
1414
1487
|
basePath,
|
|
1415
1488
|
subagentModel,
|
|
1416
|
-
{ sessionContextWindow, modelRegistry, sessionProvider },
|
|
1489
|
+
{ sessionContextWindow, modelRegistry, sessionProvider, subagentThinking },
|
|
1417
1490
|
),
|
|
1418
1491
|
};
|
|
1419
1492
|
} catch (err) {
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* and fallback chains.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Api, Model } from "@gsd/pi-ai";
|
|
8
|
-
import { getProviderCapabilities } from "@gsd/pi-ai";
|
|
7
|
+
import type { Api, Model, ModelThinkingLevel } from "@gsd/pi-ai";
|
|
8
|
+
import { getProviderCapabilities, clampThinkingLevel } from "@gsd/pi-ai";
|
|
9
9
|
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
10
10
|
import type { GSDPreferences } from "./preferences.js";
|
|
11
|
-
import { resolveModelWithFallbacksForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
|
|
11
|
+
import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
|
|
12
12
|
import type { ComplexityTier } from "./complexity-classifier.js";
|
|
13
13
|
import { classifyUnitComplexity, extractTaskMetadata, tierLabel } from "./complexity-classifier.js";
|
|
14
14
|
import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides, adjustToolSet, filterToolsForProvider } from "./model-router.js";
|
|
@@ -57,6 +57,12 @@ export interface ModelSelectionResult {
|
|
|
57
57
|
routing: { tier: string; modelDowngraded: boolean } | null;
|
|
58
58
|
/** Concrete model applied before dispatch so it can be restored after a fresh session. */
|
|
59
59
|
appliedModel: Model<Api> | null;
|
|
60
|
+
/**
|
|
61
|
+
* Reasoning effort applied for this dispatch after per-phase resolution,
|
|
62
|
+
* floor, and capability clamping (ADR-026). Null when no level was applied
|
|
63
|
+
* (e.g. no start level captured). Surfaced for metrics/telemetry.
|
|
64
|
+
*/
|
|
65
|
+
appliedThinkingLevel?: ReturnType<ExtensionAPI["getThinkingLevel"]> | null;
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
export interface PreferredModelConfig {
|
|
@@ -278,12 +284,103 @@ function restoreToolBaseline(pi: ExtensionAPI): void {
|
|
|
278
284
|
}
|
|
279
285
|
}
|
|
280
286
|
|
|
281
|
-
|
|
287
|
+
/**
|
|
288
|
+
* Apply the desired reasoning effort for the just-selected model, clamping to
|
|
289
|
+
* what the model actually supports (ADR-026). An unsupported level is never
|
|
290
|
+
* sent to the provider — it is clamped via `clampThinkingLevel` and the
|
|
291
|
+
* mismatch is surfaced once per (model, requested-level). Returns the level
|
|
292
|
+
* actually applied so callers can record it.
|
|
293
|
+
*/
|
|
294
|
+
export function applyThinkingLevelForModel(
|
|
282
295
|
pi: ExtensionAPI,
|
|
296
|
+
desired: ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined,
|
|
297
|
+
model: Model<Api>,
|
|
298
|
+
ctx: ExtensionContext,
|
|
299
|
+
): ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined {
|
|
300
|
+
if (!desired) return desired;
|
|
301
|
+
// Capability-clamp only when we have a bare string level AND the model
|
|
302
|
+
// advertises reasoning capability (`reasoning` is always present on real
|
|
303
|
+
// registry models). Richer host snapshot shapes (e.g. `{ effort: "high" }`)
|
|
304
|
+
// and partial model objects are applied verbatim — we never coerce an unknown
|
|
305
|
+
// shape into a string or guess capability we can't see.
|
|
306
|
+
if (typeof desired === "string" && model != null && typeof model === "object" && "reasoning" in model) {
|
|
307
|
+
const clamped = clampThinkingLevel(model, desired as ModelThinkingLevel) as ReturnType<ExtensionAPI["getThinkingLevel"]>;
|
|
308
|
+
pi.setThinkingLevel(clamped);
|
|
309
|
+
if (clamped !== desired) {
|
|
310
|
+
const key = `${model.provider}/${model.id}:${desired}`;
|
|
311
|
+
if (!_warnedThinkingClamp.has(key)) {
|
|
312
|
+
_warnedThinkingClamp.add(key);
|
|
313
|
+
ctx.ui.notify(
|
|
314
|
+
`Thinking level '${desired}' not supported by ${model.provider}/${model.id}; using '${clamped}'.`,
|
|
315
|
+
"warning",
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return clamped;
|
|
320
|
+
}
|
|
321
|
+
pi.setThinkingLevel(desired);
|
|
322
|
+
return desired;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** Warn-once guard for capability clamps, keyed by `provider/id:requested`. */
|
|
326
|
+
const _warnedThinkingClamp = new Set<string>();
|
|
327
|
+
/** Warn-once guard for the execute-task floor punch-through advisory. */
|
|
328
|
+
let _warnedExecuteTaskFloorBypass = false;
|
|
329
|
+
|
|
330
|
+
type EffectiveThinkingLevel = ReturnType<ExtensionAPI["getThinkingLevel"]>;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Ascending severity order for reasoning levels (matches @gsd/pi-agent-core
|
|
334
|
+
* `ThinkingLevel`). Used only for floor comparisons below.
|
|
335
|
+
*/
|
|
336
|
+
const THINKING_LEVEL_ORDER: readonly EffectiveThinkingLevel[] = [
|
|
337
|
+
"off",
|
|
338
|
+
"minimal",
|
|
339
|
+
"low",
|
|
340
|
+
"medium",
|
|
341
|
+
"high",
|
|
342
|
+
"xhigh",
|
|
343
|
+
] as EffectiveThinkingLevel[];
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Minimum reasoning level for code-writing units.
|
|
347
|
+
*
|
|
348
|
+
* `execute-task` is the only unit that edits source. With a low/minimal
|
|
349
|
+
* thinking level a model does not plan its edits and compensates by re-reading
|
|
350
|
+
* the same files dozens of times per task (measured: index.html read ~49× in a
|
|
351
|
+
* single task on a minimal-thinking model) and shelling out to `nl`/`sed` to
|
|
352
|
+
* re-locate code after every edit invalidates its line numbers. Flooring the
|
|
353
|
+
* level for this unit type removes that read/bash thrash. Planning, research,
|
|
354
|
+
* and lifecycle units are unaffected.
|
|
355
|
+
*/
|
|
356
|
+
const EXECUTE_TASK_MIN_THINKING_LEVEL: EffectiveThinkingLevel = "medium";
|
|
357
|
+
|
|
358
|
+
function thinkingLevelRank(level: EffectiveThinkingLevel): number {
|
|
359
|
+
const idx = THINKING_LEVEL_ORDER.indexOf(level);
|
|
360
|
+
return idx === -1 ? 0 : idx;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Raise (never lower) the thinking level for code-writing units to a sane
|
|
365
|
+
* floor. Returns the input unchanged for non-`execute-task` units, when no
|
|
366
|
+
* level was captured, or when the captured level already meets the floor.
|
|
367
|
+
*/
|
|
368
|
+
export function floorThinkingLevelForUnit(
|
|
369
|
+
unitType: string,
|
|
283
370
|
level: ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined,
|
|
284
|
-
):
|
|
285
|
-
if (
|
|
286
|
-
|
|
371
|
+
): ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined {
|
|
372
|
+
if (unitType !== "execute-task") return level;
|
|
373
|
+
if (!level) return level;
|
|
374
|
+
// Only act on the recognized string levels. Any other shape (e.g. a richer
|
|
375
|
+
// host snapshot object) is passed through untouched so we never coerce an
|
|
376
|
+
// unknown representation into a bare string the host can't apply.
|
|
377
|
+
if (!THINKING_LEVEL_ORDER.includes(level as EffectiveThinkingLevel)) {
|
|
378
|
+
return level;
|
|
379
|
+
}
|
|
380
|
+
if (thinkingLevelRank(level as EffectiveThinkingLevel) >= thinkingLevelRank(EXECUTE_TASK_MIN_THINKING_LEVEL)) {
|
|
381
|
+
return level;
|
|
382
|
+
}
|
|
383
|
+
return EXECUTE_TASK_MIN_THINKING_LEVEL;
|
|
287
384
|
}
|
|
288
385
|
|
|
289
386
|
export function resolvePreferredModelConfig(
|
|
@@ -354,6 +451,42 @@ export async function selectAndApplyModel(
|
|
|
354
451
|
autoModeStartThinkingLevel?: ReturnType<ExtensionAPI["getThinkingLevel"]> | null,
|
|
355
452
|
): Promise<ModelSelectionResult> {
|
|
356
453
|
const uokFlags = resolveUokFlags(prefs);
|
|
454
|
+
// Resolve reasoning effort for this dispatch (ADR-026). An explicit per-phase
|
|
455
|
+
// thinking config (inline `models.<phase>.thinking` or the separate `thinking`
|
|
456
|
+
// block) expresses hard user intent: it bypasses the execute-task floor and is
|
|
457
|
+
// honored verbatim, then capability-clamped per model at apply time below.
|
|
458
|
+
// With no explicit level, fall back to the auto-start session level and raise
|
|
459
|
+
// the code-writing floor — preserving prior behavior exactly. Recomputed per
|
|
460
|
+
// dispatch so neither the floor nor a phase override leaks to other units.
|
|
461
|
+
const explicitThinkingLevel =
|
|
462
|
+
resolveThinkingLevelForUnit(unitType) as ReturnType<ExtensionAPI["getThinkingLevel"]> | undefined;
|
|
463
|
+
const desiredThinkingLevel = explicitThinkingLevel
|
|
464
|
+
?? floorThinkingLevelForUnit(unitType, autoModeStartThinkingLevel);
|
|
465
|
+
if (explicitThinkingLevel) {
|
|
466
|
+
if (
|
|
467
|
+
unitType === "execute-task" &&
|
|
468
|
+
thinkingLevelRank(explicitThinkingLevel) < thinkingLevelRank(EXECUTE_TASK_MIN_THINKING_LEVEL) &&
|
|
469
|
+
!_warnedExecuteTaskFloorBypass
|
|
470
|
+
) {
|
|
471
|
+
_warnedExecuteTaskFloorBypass = true;
|
|
472
|
+
ctx.ui.notify(
|
|
473
|
+
`Explicit execution thinking '${explicitThinkingLevel}' is below the measured execute-task floor ` +
|
|
474
|
+
`(${EXECUTE_TASK_MIN_THINKING_LEVEL}); honoring it as configured. Low reasoning on code edits can ` +
|
|
475
|
+
`cause repeated file re-reads.`,
|
|
476
|
+
"warning",
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
} else if (
|
|
480
|
+
verbose &&
|
|
481
|
+
desiredThinkingLevel &&
|
|
482
|
+
desiredThinkingLevel !== autoModeStartThinkingLevel
|
|
483
|
+
) {
|
|
484
|
+
ctx.ui.notify(
|
|
485
|
+
`Thinking level raised to ${desiredThinkingLevel} for ${unitType} (was ${autoModeStartThinkingLevel ?? "unset"})`,
|
|
486
|
+
"info",
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
let appliedThinkingLevel: ReturnType<ExtensionAPI["getThinkingLevel"]> | null | undefined = null;
|
|
357
490
|
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
358
491
|
? getSessionModelOverride(ctx.sessionManager.getSessionId())
|
|
359
492
|
: (sessionModelOverride ?? undefined);
|
|
@@ -699,7 +832,7 @@ export async function selectAndApplyModel(
|
|
|
699
832
|
const ok = await pi.setModel(model, { persist: false });
|
|
700
833
|
if (ok) {
|
|
701
834
|
appliedModel = model;
|
|
702
|
-
|
|
835
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, model, ctx);
|
|
703
836
|
|
|
704
837
|
// ADR-005: Adjust active tool set for the selected model's provider capabilities.
|
|
705
838
|
// Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
|
|
@@ -759,7 +892,7 @@ export async function selectAndApplyModel(
|
|
|
759
892
|
const ok = await pi.setModel(model, { persist: false });
|
|
760
893
|
if (!ok) continue;
|
|
761
894
|
appliedModel = model;
|
|
762
|
-
|
|
895
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, model, ctx);
|
|
763
896
|
attemptedPolicyEligible = true;
|
|
764
897
|
if (verbose) {
|
|
765
898
|
ctx.ui.notify(
|
|
@@ -805,18 +938,37 @@ export async function selectAndApplyModel(
|
|
|
805
938
|
const fallbackOk = await pi.setModel(byId, { persist: false });
|
|
806
939
|
if (fallbackOk) {
|
|
807
940
|
appliedModel = byId;
|
|
808
|
-
|
|
941
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, byId, ctx);
|
|
809
942
|
}
|
|
810
943
|
}
|
|
811
944
|
} else {
|
|
812
945
|
appliedModel = startModel;
|
|
813
|
-
|
|
946
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, startModel, ctx);
|
|
814
947
|
}
|
|
815
948
|
}
|
|
816
949
|
}
|
|
817
950
|
}
|
|
818
951
|
|
|
819
|
-
|
|
952
|
+
// If no model branch applied a thinking level (e.g. interactive guided-flow
|
|
953
|
+
// with a `thinking:` block but no per-phase model and no start model), still
|
|
954
|
+
// honor an explicitly configured phase thinking level against the current
|
|
955
|
+
// session model. Only the explicit path runs here — the floored session
|
|
956
|
+
// default is intentionally left untouched so no-config interactive runs keep
|
|
957
|
+
// the user's /model thinking level. (ADR-026)
|
|
958
|
+
if (appliedThinkingLevel == null && explicitThinkingLevel && ctx.model) {
|
|
959
|
+
// Prefer the full registry model (carries reasoning capability so the level
|
|
960
|
+
// can be clamped); fall back to ctx.model. Always route through
|
|
961
|
+
// applyThinkingLevelForModel so the clamp runs whenever capability metadata
|
|
962
|
+
// exists — never a raw verbatim setThinkingLevel that bypasses it (ADR-026).
|
|
963
|
+
const current = resolveModelId(
|
|
964
|
+
`${ctx.model.provider}/${ctx.model.id}`,
|
|
965
|
+
ctx.modelRegistry?.getAvailable?.() ?? [],
|
|
966
|
+
ctx.model.provider,
|
|
967
|
+
) ?? (ctx.model as Model<Api>);
|
|
968
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, explicitThinkingLevel, current, ctx);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
return { routing, appliedModel, appliedThinkingLevel };
|
|
820
972
|
}
|
|
821
973
|
|
|
822
974
|
/**
|
|
@@ -1521,6 +1521,8 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1521
1521
|
}
|
|
1522
1522
|
}
|
|
1523
1523
|
|
|
1524
|
+
let blockingContentViolation: string | null = null;
|
|
1525
|
+
|
|
1524
1526
|
// ── Safety harness: post-unit validation ──
|
|
1525
1527
|
try {
|
|
1526
1528
|
const { loadEffectiveGSDPreferences } = await import("./preferences.js");
|
|
@@ -1668,8 +1670,14 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1668
1670
|
const artifactPath = resolveArtifactForContent(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
1669
1671
|
const contentViolations = validateContent(s.currentUnit.type, artifactPath);
|
|
1670
1672
|
for (const v of contentViolations) {
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
+
if (v.severity === "error") {
|
|
1674
|
+
blockingContentViolation ??= v.reason;
|
|
1675
|
+
logError("safety", `content: ${v.reason}`);
|
|
1676
|
+
ctx.ui.notify(`Content validation: ${v.reason}`, "error");
|
|
1677
|
+
} else {
|
|
1678
|
+
logWarning("safety", `content: ${v.reason}`);
|
|
1679
|
+
ctx.ui.notify(`Content validation: ${v.reason}`, "warning");
|
|
1680
|
+
}
|
|
1673
1681
|
}
|
|
1674
1682
|
} catch (e) {
|
|
1675
1683
|
debugLog("postUnit", { phase: "safety-content-validation", error: String(e) });
|
|
@@ -1868,6 +1876,16 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1868
1876
|
}
|
|
1869
1877
|
}
|
|
1870
1878
|
|
|
1879
|
+
if (blockingContentViolation && triggerArtifactVerified) {
|
|
1880
|
+
triggerArtifactVerified = false;
|
|
1881
|
+
debugLog("postUnit", {
|
|
1882
|
+
phase: "content-validation-blocked-artifact",
|
|
1883
|
+
unitType: s.currentUnit.type,
|
|
1884
|
+
unitId: s.currentUnit.id,
|
|
1885
|
+
reason: blockingContentViolation,
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1871
1889
|
// When artifact verification fails for a unit type that has a known expected
|
|
1872
1890
|
// artifact, ask the caller to retry so it re-dispatches with failure context
|
|
1873
1891
|
// instead of blindly re-dispatching the same unit (#1571).
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection, parseTaskPlanFile } from "./files.js";
|
|
13
|
-
import type { Override
|
|
14
|
-
import { hasVerdict,
|
|
13
|
+
import type { Override } from "./files.js";
|
|
14
|
+
import { hasVerdict, extractVerdict } from "./verdict-parser.js";
|
|
15
15
|
import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
|
|
16
16
|
import {
|
|
17
17
|
resolveMilestoneFile, resolveSliceFile, resolveSlicePath,
|
|
@@ -42,11 +42,11 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
42
42
|
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
43
43
|
import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
|
|
44
44
|
import { classifyProject, type ProjectClassification } from "./detection.js";
|
|
45
|
-
import { hasBrowserRequiredText } from "./browser-evidence.js";
|
|
46
45
|
import { debugLog } from "./debug-logger.js";
|
|
47
46
|
import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
|
|
48
47
|
import { findMilestoneIds } from "./milestone-ids.js";
|
|
49
48
|
import { buildRunUatPresentationForType, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
|
|
49
|
+
import { resolveEffectiveUatType, shouldDispatchUatForContent, type UatType } from "./uat-policy.js";
|
|
50
50
|
|
|
51
51
|
export { buildSkillActivationBlock, buildSkillDiscoveryVars };
|
|
52
52
|
|
|
@@ -286,19 +286,6 @@ function prependContextModeToBlock(
|
|
|
286
286
|
return `${contextMode}\n\n${block}`;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
function resolveEffectiveUatType(content: string): UatType {
|
|
290
|
-
const uatType = getUatType(content);
|
|
291
|
-
if (uatType === "artifact-driven" && hasBrowserRequiredText(content)) {
|
|
292
|
-
return "browser-executable";
|
|
293
|
-
}
|
|
294
|
-
return uatType;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function shouldDispatchUatForContent(content: string, prefs: GSDPreferences | undefined): boolean {
|
|
298
|
-
const uatType = resolveEffectiveUatType(content);
|
|
299
|
-
return !!prefs?.uat_dispatch || uatType !== "artifact-driven" || hasBrowserRequiredText(content);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
289
|
// ─── Executor Constraints ─────────────────────────────────────────────────────
|
|
303
290
|
|
|
304
291
|
/**
|
|
@@ -3543,11 +3530,25 @@ export async function buildReassessRoadmapPrompt(
|
|
|
3543
3530
|
|
|
3544
3531
|
// ─── Reactive Execute Prompt ──────────────────────────────────────────────
|
|
3545
3532
|
|
|
3533
|
+
/**
|
|
3534
|
+
* Build the `with model: "…" and thinking: "…"` suffix injected into a prompt
|
|
3535
|
+
* that instructs the coordinator how to dispatch a `subagent` call. Either or
|
|
3536
|
+
* both may be absent (ADR-026 / #508).
|
|
3537
|
+
*/
|
|
3538
|
+
function subagentCallSuffix(model?: string, thinking?: string): string {
|
|
3539
|
+
const parts: string[] = [];
|
|
3540
|
+
if (model) parts.push(`model: "${model}"`);
|
|
3541
|
+
if (thinking) parts.push(`thinking: "${thinking}"`);
|
|
3542
|
+
return parts.length > 0 ? ` with ${parts.join(" and ")}` : "";
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3546
3545
|
export async function buildReactiveExecutePrompt(
|
|
3547
3546
|
mid: string, midTitle: string, sid: string, sTitle: string,
|
|
3548
3547
|
readyTaskIds: string[], base: string,
|
|
3549
3548
|
subagentModel?: string,
|
|
3550
|
-
opts
|
|
3549
|
+
// Reasoning effort travels inside opts here (not as a positional param) so
|
|
3550
|
+
// existing positional `opts` callers don't shift (#508).
|
|
3551
|
+
opts?: { sessionContextWindow?: number; modelRegistry?: MinimalModelRegistry; sessionProvider?: string; subagentThinking?: string },
|
|
3551
3552
|
): Promise<string> {
|
|
3552
3553
|
const { loadSliceTaskIO, deriveTaskGraph, graphMetrics } = await import("./reactive-graph.js");
|
|
3553
3554
|
|
|
@@ -3640,7 +3641,7 @@ export async function buildReactiveExecutePrompt(
|
|
|
3640
3641
|
`When done, say: "Task ${tid} complete."`,
|
|
3641
3642
|
].join("\n");
|
|
3642
3643
|
|
|
3643
|
-
const modelSuffix = subagentModel
|
|
3644
|
+
const modelSuffix = subagentCallSuffix(subagentModel, opts?.subagentThinking);
|
|
3644
3645
|
subagentSections.push([
|
|
3645
3646
|
`### ${tid}: ${tTitle}`,
|
|
3646
3647
|
"",
|
|
@@ -3724,10 +3725,11 @@ export async function buildParallelResearchSlicesPrompt(
|
|
|
3724
3725
|
slices: Array<{ id: string; title: string }>,
|
|
3725
3726
|
basePath: string,
|
|
3726
3727
|
subagentModel?: string,
|
|
3728
|
+
subagentThinking?: string,
|
|
3727
3729
|
): Promise<string> {
|
|
3728
3730
|
// Build individual research-slice prompts for each slice
|
|
3729
3731
|
const subagentSections: string[] = [];
|
|
3730
|
-
const modelSuffix = subagentModel
|
|
3732
|
+
const modelSuffix = subagentCallSuffix(subagentModel, subagentThinking);
|
|
3731
3733
|
for (const slice of slices) {
|
|
3732
3734
|
const slicePrompt = await buildResearchSlicePrompt(mid, midTitle, slice.id, slice.title, basePath, { contextModeRenderMode: "nested" });
|
|
3733
3735
|
subagentSections.push([
|
|
@@ -3755,6 +3757,7 @@ export async function buildGateEvaluatePrompt(
|
|
|
3755
3757
|
mid: string, midTitle: string, sid: string, sTitle: string,
|
|
3756
3758
|
base: string,
|
|
3757
3759
|
subagentModel?: string,
|
|
3760
|
+
subagentThinking?: string,
|
|
3758
3761
|
): Promise<string> {
|
|
3759
3762
|
// Pull only the gates this turn actually owns (Q3/Q4). Filter via the
|
|
3760
3763
|
// registry so that scope:"slice" gates owned by other turns (Q8) can't
|
|
@@ -3811,7 +3814,7 @@ export async function buildGateEvaluatePrompt(
|
|
|
3811
3814
|
"- `findings`: detailed markdown findings (or empty if omitted)",
|
|
3812
3815
|
].join("\n");
|
|
3813
3816
|
|
|
3814
|
-
const modelSuffix = subagentModel
|
|
3817
|
+
const modelSuffix = subagentCallSuffix(subagentModel, subagentThinking);
|
|
3815
3818
|
subagentSections.push([
|
|
3816
3819
|
`### ${def.id}: ${def.question}`,
|
|
3817
3820
|
"",
|
|
@@ -15,7 +15,25 @@ import { appendEvent } from "./workflow-events.js";
|
|
|
15
15
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
16
16
|
import { clearParseCache } from "./files.js";
|
|
17
17
|
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
isDbAvailable,
|
|
20
|
+
getTask,
|
|
21
|
+
getSlice,
|
|
22
|
+
getSliceTasks,
|
|
23
|
+
getPendingGatesForTurn,
|
|
24
|
+
updateTaskStatus,
|
|
25
|
+
updateSliceStatus,
|
|
26
|
+
insertSlice,
|
|
27
|
+
getMilestone,
|
|
28
|
+
getMilestoneSlices,
|
|
29
|
+
getLatestAssessmentByScope,
|
|
30
|
+
updateMilestoneStatus,
|
|
31
|
+
refreshOpenDatabaseFromDisk,
|
|
32
|
+
getCompletedMilestoneTaskFileHints,
|
|
33
|
+
getMilestoneCommitAttributionShas,
|
|
34
|
+
recordMilestoneCommitAttribution,
|
|
35
|
+
transaction,
|
|
36
|
+
} from "./gsd-db.js";
|
|
19
37
|
import { isValidationTerminal } from "./state.js";
|
|
20
38
|
import { getErrorMessage } from "./error-utils.js";
|
|
21
39
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
@@ -390,8 +408,9 @@ export function verifyExpectedArtifact(
|
|
|
390
408
|
if (gateIds.length === 0) return true;
|
|
391
409
|
|
|
392
410
|
try {
|
|
393
|
-
|
|
394
|
-
const
|
|
411
|
+
if (!isDbAvailable()) return false;
|
|
412
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
413
|
+
const pendingIds = new Set<string>(pending.map((g) => g.gate_id));
|
|
395
414
|
// All dispatched gates must no longer be pending
|
|
396
415
|
for (const gid of gateIds) {
|
|
397
416
|
if (pendingIds.has(gid)) return false;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// GSD auto-mode runtime state
|
|
2
2
|
import { AutoSession } from "./auto/session.js";
|
|
3
3
|
import type { CurrentUnit } from "./auto/session.js";
|
|
4
|
+
import type { SourceObservationStore } from "./source-observations.js";
|
|
4
5
|
import {
|
|
5
6
|
isDeterministicPolicyError,
|
|
6
7
|
isQueuedUserMessageSkip,
|
|
@@ -65,3 +66,7 @@ export function clearToolInvocationError(): void {
|
|
|
65
66
|
if (!autoSession.active) return;
|
|
66
67
|
autoSession.lastToolInvocationError = null;
|
|
67
68
|
}
|
|
69
|
+
|
|
70
|
+
export function getSourceObservationStore(): SourceObservationStore {
|
|
71
|
+
return autoSession.sourceObservations;
|
|
72
|
+
}
|
|
@@ -1557,7 +1557,7 @@ export async function bootstrapAutoSession(
|
|
|
1557
1557
|
s.autoStartTime = Date.now();
|
|
1558
1558
|
s.resourceVersionOnStart = readResourceVersion();
|
|
1559
1559
|
s.pendingQuickTasks = [];
|
|
1560
|
-
s.
|
|
1560
|
+
s.clearCurrentUnit();
|
|
1561
1561
|
s.currentMilestoneId ??=
|
|
1562
1562
|
strandedRecoveryAction?.milestoneId ??
|
|
1563
1563
|
(deepProjectStagePending ? null : state.activeMilestone?.id ?? null);
|