@prestyj/cli 5.30.0 → 5.30.2
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/README.md +54 -39
- package/assets/skills/bulletproof/SKILL.md +1 -1
- package/assets/skills/clarify/SKILL.md +1 -1
- package/assets/skills/code-review/SKILL.md +1 -1
- package/assets/skills/compliance-guard/SKILL.md +1 -1
- package/assets/skills/durable/SKILL.md +1 -1
- package/assets/skills/evidence-led-ui/SKILL.md +1 -1
- package/assets/skills/lean/SKILL.md +1 -1
- package/assets/skills/refactoring/SKILL.md +1 -1
- package/assets/skills/root-cause/SKILL.md +1 -1
- package/assets/skills/shared-language/SKILL.md +1 -1
- package/assets/skills/tdd/SKILL.md +1 -1
- package/dist/app-sidecar/app-settings.d.ts +63 -0
- package/dist/app-sidecar/app-settings.js +147 -0
- package/dist/app-sidecar/app-settings.js.map +1 -0
- package/dist/app-sidecar/attachments.d.ts +11 -0
- package/dist/app-sidecar/attachments.js +47 -0
- package/dist/app-sidecar/attachments.js.map +1 -0
- package/dist/app-sidecar/auth-routes.d.ts +3 -0
- package/dist/app-sidecar/auth-routes.js +293 -0
- package/dist/app-sidecar/auth-routes.js.map +1 -0
- package/dist/app-sidecar/autopilot-runner.d.ts +62 -0
- package/dist/app-sidecar/autopilot-runner.js +373 -0
- package/dist/app-sidecar/autopilot-runner.js.map +1 -0
- package/dist/app-sidecar/file-search.d.ts +15 -0
- package/dist/app-sidecar/file-search.js +103 -0
- package/dist/app-sidecar/file-search.js.map +1 -0
- package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
- package/dist/app-sidecar/hf-pull-manager.js +224 -0
- package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
- package/dist/app-sidecar/history-routes.d.ts +3 -0
- package/dist/app-sidecar/history-routes.js +375 -0
- package/dist/app-sidecar/history-routes.js.map +1 -0
- package/dist/app-sidecar/history.d.ts +67 -0
- package/dist/app-sidecar/history.js +23 -0
- package/dist/app-sidecar/history.js.map +1 -0
- package/dist/app-sidecar/http.d.ts +5 -0
- package/dist/app-sidecar/http.js +27 -0
- package/dist/app-sidecar/http.js.map +1 -0
- package/dist/app-sidecar/integration-routes.d.ts +3 -0
- package/dist/app-sidecar/integration-routes.js +286 -0
- package/dist/app-sidecar/integration-routes.js.map +1 -0
- package/dist/app-sidecar/json-mode.d.ts +10 -0
- package/dist/app-sidecar/json-mode.js +73 -0
- package/dist/app-sidecar/json-mode.js.map +1 -0
- package/dist/app-sidecar/keep-awake.d.ts +4 -0
- package/dist/app-sidecar/keep-awake.js +5 -0
- package/dist/app-sidecar/keep-awake.js.map +1 -0
- package/dist/app-sidecar/mcp-routes.d.ts +3 -0
- package/dist/app-sidecar/mcp-routes.js +185 -0
- package/dist/app-sidecar/mcp-routes.js.map +1 -0
- package/dist/app-sidecar/mcp-rows.d.ts +31 -0
- package/dist/app-sidecar/mcp-rows.js +77 -0
- package/dist/app-sidecar/mcp-rows.js.map +1 -0
- package/dist/app-sidecar/nolan-context.d.ts +20 -0
- package/dist/app-sidecar/nolan-context.js +55 -0
- package/dist/app-sidecar/nolan-context.js.map +1 -0
- package/dist/app-sidecar/progress-manager.d.ts +10 -0
- package/dist/app-sidecar/progress-manager.js +116 -0
- package/dist/app-sidecar/progress-manager.js.map +1 -0
- package/dist/app-sidecar/prompt-routes.d.ts +3 -0
- package/dist/app-sidecar/prompt-routes.js +355 -0
- package/dist/app-sidecar/prompt-routes.js.map +1 -0
- package/dist/app-sidecar/repo-polls.d.ts +18 -0
- package/dist/app-sidecar/repo-polls.js +45 -0
- package/dist/app-sidecar/repo-polls.js.map +1 -0
- package/dist/app-sidecar/route-context.d.ts +147 -0
- package/dist/app-sidecar/route-context.js +2 -0
- package/dist/app-sidecar/route-context.js.map +1 -0
- package/dist/app-sidecar/run-control-routes.d.ts +3 -0
- package/dist/app-sidecar/run-control-routes.js +437 -0
- package/dist/app-sidecar/run-control-routes.js.map +1 -0
- package/dist/app-sidecar/session-routes.d.ts +3 -0
- package/dist/app-sidecar/session-routes.js +115 -0
- package/dist/app-sidecar/session-routes.js.map +1 -0
- package/dist/app-sidecar/session-types.d.ts +39 -0
- package/dist/app-sidecar/session-types.js +5 -0
- package/dist/app-sidecar/session-types.js.map +1 -0
- package/dist/app-sidecar/task-routes.d.ts +3 -0
- package/dist/app-sidecar/task-routes.js +232 -0
- package/dist/app-sidecar/task-routes.js.map +1 -0
- package/dist/app-sidecar/usage.d.ts +19 -0
- package/dist/app-sidecar/usage.js +153 -0
- package/dist/app-sidecar/usage.js.map +1 -0
- package/dist/app-sidecar/workspace-routes.d.ts +3 -0
- package/dist/app-sidecar/workspace-routes.js +374 -0
- package/dist/app-sidecar/workspace-routes.js.map +1 -0
- package/dist/app-sidecar.js +541 -3971
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/jiwa.js +2 -0
- package/dist/chat-agents/jiwa.js.map +1 -1
- package/dist/chat-agents/memory.js +2 -0
- package/dist/chat-agents/memory.js.map +1 -1
- package/dist/cli/auth.js +13 -9
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli.js +10 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/core/acceptance-checks.js +3 -9
- package/dist/core/acceptance-checks.js.map +1 -1
- package/dist/core/agent-session/helpers.d.ts +26 -0
- package/dist/core/agent-session/helpers.js +47 -0
- package/dist/core/agent-session/helpers.js.map +1 -0
- package/dist/core/agent-session/mcp-tools.d.ts +68 -0
- package/dist/core/agent-session/mcp-tools.js +195 -0
- package/dist/core/agent-session/mcp-tools.js.map +1 -0
- package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
- package/dist/core/agent-session/run-loop-monitor.js +164 -0
- package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
- package/dist/core/agent-session/transcript-markers.d.ts +57 -0
- package/dist/core/agent-session/transcript-markers.js +166 -0
- package/dist/core/agent-session/transcript-markers.js.map +1 -0
- package/dist/core/agent-session/verification-tracker.d.ts +50 -0
- package/dist/core/agent-session/verification-tracker.js +269 -0
- package/dist/core/agent-session/verification-tracker.js.map +1 -0
- package/dist/core/agent-session.d.ts +27 -87
- package/dist/core/agent-session.js +166 -713
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-providers.js +3 -3
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/autopilot-cycle.d.ts +8 -2
- package/dist/core/autopilot-cycle.js +22 -3
- package/dist/core/autopilot-cycle.js.map +1 -1
- package/dist/core/bundled-agents.js +6 -6
- package/dist/core/bundled-agents.js.map +1 -1
- package/dist/core/checklist-git.d.ts +19 -0
- package/dist/core/checklist-git.js +54 -0
- package/dist/core/checklist-git.js.map +1 -0
- package/dist/core/checklist-items.d.ts +10 -1
- package/dist/core/checklist-items.js +22 -0
- package/dist/core/checklist-items.js.map +1 -1
- package/dist/core/checklist-prompt.d.ts +14 -3
- package/dist/core/checklist-prompt.js +38 -8
- package/dist/core/checklist-prompt.js.map +1 -1
- package/dist/core/checklist-snapshot.d.ts +5 -1
- package/dist/core/checklist-snapshot.js +20 -3
- package/dist/core/checklist-snapshot.js.map +1 -1
- package/dist/core/checklist-store.d.ts +5 -1
- package/dist/core/checklist-store.js +35 -4
- package/dist/core/checklist-store.js.map +1 -1
- package/dist/core/context-limits.js +1 -1
- package/dist/core/context-limits.js.map +1 -1
- package/dist/core/event-bus.d.ts +1 -1
- package/dist/core/event-bus.js +39 -13
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/extensions/plugin-bundles.js +4 -2
- package/dist/core/extensions/plugin-bundles.js.map +1 -1
- package/dist/core/hashline.d.ts +10 -8
- package/dist/core/hashline.js.map +1 -1
- package/dist/core/mcp/client.js +2 -0
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/loopback.d.ts +2 -2
- package/dist/core/mcp/loopback.js +2 -2
- package/dist/core/mcp/shared-pool.js +4 -3
- package/dist/core/mcp/shared-pool.js.map +1 -1
- package/dist/core/persistent-shell.js +2 -1
- package/dist/core/persistent-shell.js.map +1 -1
- package/dist/core/plan-handoff.d.ts +30 -0
- package/dist/core/plan-handoff.js +10 -0
- package/dist/core/plan-handoff.js.map +1 -0
- package/dist/core/plan-submission-gate.d.ts +28 -0
- package/dist/core/plan-submission-gate.js +27 -0
- package/dist/core/plan-submission-gate.js.map +1 -0
- package/dist/core/process-manager.js +9 -1
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-health-scan.d.ts +109 -0
- package/dist/core/project-health-scan.js +673 -0
- package/dist/core/project-health-scan.js.map +1 -0
- package/dist/core/project-health-score.d.ts +41 -0
- package/dist/core/project-health-score.js +257 -0
- package/dist/core/project-health-score.js.map +1 -0
- package/dist/core/prompt-commands.js +44 -6
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-storage.d.ts +1 -0
- package/dist/core/session-storage.js +1 -1
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/skills.js +6 -9
- package/dist/core/skills.js.map +1 -1
- package/dist/core/style-packs/index.js +2 -11
- package/dist/core/style-packs/index.js.map +1 -1
- package/dist/core/style-packs/packs.d.ts +3 -12
- package/dist/core/style-packs/packs.js +132 -173
- package/dist/core/style-packs/packs.js.map +1 -1
- package/dist/core/subagent-manager.js +11 -6
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-receipt.js +3 -4
- package/dist/core/subagent-receipt.js.map +1 -1
- package/dist/core/ui-adoption.js +2 -0
- package/dist/core/ui-adoption.js.map +1 -1
- package/dist/core/ui-registry.js +5 -4
- package/dist/core/ui-registry.js.map +1 -1
- package/dist/core/verification-evidence.d.ts +21 -2
- package/dist/core/verification-evidence.js +283 -8
- package/dist/core/verification-evidence.js.map +1 -1
- package/dist/core/verification-gate.js +4 -2
- package/dist/core/verification-gate.js.map +1 -1
- package/dist/core/verify-commands.js +2 -3
- package/dist/core/verify-commands.js.map +1 -1
- package/dist/modes/agent-home-mode.js +1 -4
- package/dist/modes/agent-home-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.js +13 -8
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/system-prompt.js +70 -87
- package/dist/system-prompt.js.map +1 -1
- package/dist/tools/ask-user.js +13 -74
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/bash.d.ts +3 -1
- package/dist/tools/bash.js +28 -84
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/checklist.d.ts +7 -14
- package/dist/tools/checklist.js +22 -41
- package/dist/tools/checklist.js.map +1 -1
- package/dist/tools/code-nav.js +7 -29
- package/dist/tools/code-nav.js.map +1 -1
- package/dist/tools/edit.d.ts +4 -9
- package/dist/tools/edit.js +175 -65
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/enter-plan.js +2 -7
- package/dist/tools/enter-plan.js.map +1 -1
- package/dist/tools/exit-plan.js +2 -3
- package/dist/tools/exit-plan.js.map +1 -1
- package/dist/tools/find.js +3 -4
- package/dist/tools/find.js.map +1 -1
- package/dist/tools/grep.js +9 -20
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/index.js +10 -7
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/ls.js +3 -3
- package/dist/tools/ls.js.map +1 -1
- package/dist/tools/prompt-hints.js +34 -47
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/read-only-bash.js +3 -0
- package/dist/tools/read-only-bash.js.map +1 -1
- package/dist/tools/read.js +8 -20
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/search-code.js +4 -12
- package/dist/tools/search-code.js.map +1 -1
- package/dist/tools/skill.js +13 -7
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent-control.js +7 -22
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent.js +1 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/task-output.js +4 -15
- package/dist/tools/task-output.js.map +1 -1
- package/dist/tools/task-send.js +5 -17
- package/dist/tools/task-send.js.map +1 -1
- package/dist/tools/task-stop.js +2 -2
- package/dist/tools/task-stop.js.map +1 -1
- package/dist/tools/tool-search.js +2 -7
- package/dist/tools/tool-search.js.map +1 -1
- package/dist/tools/tool-tiers.d.ts +21 -4
- package/dist/tools/tool-tiers.js +44 -17
- package/dist/tools/tool-tiers.js.map +1 -1
- package/dist/tools/web-fetch.js +7 -33
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/write.js +3 -4
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/App.js +20 -26
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/components/Footer.js +1 -2
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/ui/components/InputArea.js +0 -2
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/ToolExecution.js +4 -3
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +7 -6
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/sessions.js +1 -5
- package/dist/ui/sessions.js.map +1 -1
- package/dist/ui/utils/highlight.d.ts +0 -5
- package/dist/ui/utils/highlight.js +3 -49
- package/dist/ui/utils/highlight.js.map +1 -1
- package/dist/ui/utils/markdown-renderer.d.ts +6 -0
- package/dist/ui/utils/markdown-renderer.js +21 -5
- package/dist/ui/utils/markdown-renderer.js.map +1 -1
- package/dist/utils/process.js +3 -3
- package/dist/utils/process.js.map +1 -1
- package/dist/utils/shared-poll.d.ts +37 -0
- package/dist/utils/shared-poll.js +104 -0
- package/dist/utils/shared-poll.js.map +1 -0
- package/package.json +8 -8
- package/dist/core/api-benchmark.d.ts +0 -63
- package/dist/core/api-benchmark.js +0 -381
- package/dist/core/api-benchmark.js.map +0 -1
- package/dist/core/bash-spawn-benchmark.d.ts +0 -1
- package/dist/core/bash-spawn-benchmark.js +0 -139
- package/dist/core/bash-spawn-benchmark.js.map +0 -1
- package/dist/core/cache-warm-benchmark.d.ts +0 -21
- package/dist/core/cache-warm-benchmark.js +0 -170
- package/dist/core/cache-warm-benchmark.js.map +0 -1
- package/dist/core/fast-apply-benchmark.d.ts +0 -25
- package/dist/core/fast-apply-benchmark.js +0 -284
- package/dist/core/fast-apply-benchmark.js.map +0 -1
- package/dist/core/hashline-edit-benchmark.d.ts +0 -88
- package/dist/core/hashline-edit-benchmark.js +0 -518
- package/dist/core/hashline-edit-benchmark.js.map +0 -1
- package/dist/core/semantic-search-benchmark.d.ts +0 -36
- package/dist/core/semantic-search-benchmark.js +0 -211
- package/dist/core/semantic-search-benchmark.js.map +0 -1
- package/dist/core/speed-benchmark.d.ts +0 -132
- package/dist/core/speed-benchmark.js +0 -410
- package/dist/core/speed-benchmark.js.map +0 -1
- package/dist/ui/activity-phrases.d.ts +0 -10
- package/dist/ui/activity-phrases.js +0 -184
- package/dist/ui/activity-phrases.js.map +0 -1
- package/dist/ui/components/PlanApproval.d.ts +0 -7
- package/dist/ui/components/PlanApproval.js +0 -60
- package/dist/ui/components/PlanApproval.js.map +0 -1
- package/dist/ui/components/PlanBanner.d.ts +0 -5
- package/dist/ui/components/PlanBanner.js +0 -31
- package/dist/ui/components/PlanBanner.js.map +0 -1
- package/dist/ui/components/PlanProgress.d.ts +0 -6
- package/dist/ui/components/PlanProgress.js +0 -30
- package/dist/ui/components/PlanProgress.js.map +0 -1
- package/dist/ui/hooks/useMinDisplayTime.d.ts +0 -10
- package/dist/ui/hooks/useMinDisplayTime.js +0 -34
- package/dist/ui/hooks/useMinDisplayTime.js.map +0 -1
- package/dist/ui/hooks/useSessionManager.d.ts +0 -12
- package/dist/ui/hooks/useSessionManager.js +0 -43
- package/dist/ui/hooks/useSessionManager.js.map +0 -1
- package/dist/ui/hooks/useSlashCommands.d.ts +0 -6
- package/dist/ui/hooks/useSlashCommands.js +0 -11
- package/dist/ui/hooks/useSlashCommands.js.map +0 -1
- package/dist/ui/terminal-history-spacing.d.ts +0 -1
- package/dist/ui/terminal-history-spacing.js +0 -2
- package/dist/ui/terminal-history-spacing.js.map +0 -1
- package/dist/ui/utils/markdown-cache.d.ts +0 -10
- package/dist/ui/utils/markdown-cache.js +0 -58
- package/dist/ui/utils/markdown-cache.js.map +0 -1
- package/dist/ui/utils/token-to-ansi.d.ts +0 -8
- package/dist/ui/utils/token-to-ansi.js +0 -323
- package/dist/ui/utils/token-to-ansi.js.map +0 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type NolanTurnPayload, type AutopilotMarkerPayload, type AppMarkerPayload, type SessionEntry, type SessionManager, type TurnMetricPayload } from "../session-manager.js";
|
|
2
|
+
import type { CompactionAnchorRemap } from "../compaction/compactor.js";
|
|
3
|
+
/**
|
|
4
|
+
* Display-only transcript history recorded against a session file: Nolan Grout
|
|
5
|
+
* turns, autopilot verdicts, app markers and per-turn metrics. NEVER part of
|
|
6
|
+
* the LLM message history — persisted as `custom` entries (parentId null, so
|
|
7
|
+
* never on the message DAG) and reloaded on resume so the transcript renders
|
|
8
|
+
* the same rows the live run showed. Persistence is a no-op while the session
|
|
9
|
+
* has no file (transient sessions keep markers in memory only).
|
|
10
|
+
*/
|
|
11
|
+
export declare class TranscriptMarkers {
|
|
12
|
+
private readonly getSessionManager;
|
|
13
|
+
private readonly getSessionPath;
|
|
14
|
+
private nolanTurns;
|
|
15
|
+
private autopilotMarkers;
|
|
16
|
+
private appMarkers;
|
|
17
|
+
private turnMetrics;
|
|
18
|
+
constructor(getSessionManager: () => SessionManager, getSessionPath: () => string);
|
|
19
|
+
getNolanTurns(): NolanTurnPayload[];
|
|
20
|
+
getAutopilotMarkers(): AutopilotMarkerPayload[];
|
|
21
|
+
getAppMarkers(): AppMarkerPayload[];
|
|
22
|
+
getTurnMetrics(): TurnMetricPayload[];
|
|
23
|
+
/** Summed cost when every recorded turn has a known price, else undefined. */
|
|
24
|
+
knownCostUsd(): number | undefined;
|
|
25
|
+
/** Drop everything — display-only history belongs to the OLD session. */
|
|
26
|
+
clear(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Restore from a loaded session file. The leaf is passed so each marker also
|
|
29
|
+
* carries its FILE-order position, the fallback used when a legacy anchor is
|
|
30
|
+
* out of range (see RecordedPosition).
|
|
31
|
+
*/
|
|
32
|
+
restore(entries: SessionEntry[], leafId: string | null | undefined): void;
|
|
33
|
+
/**
|
|
34
|
+
* Rebase every transcript anchor (Nolan turns, autopilot verdicts, app markers)
|
|
35
|
+
* onto a freshly compacted message list.
|
|
36
|
+
*/
|
|
37
|
+
remapAnchors(remap: CompactionAnchorRemap | undefined): void;
|
|
38
|
+
recordNolanTurn(question: string, reply: string, afterMessageCount: number): Promise<void>;
|
|
39
|
+
recordAutopilotMarker(phase: AutopilotMarkerPayload["phase"], extra: {
|
|
40
|
+
reason?: string;
|
|
41
|
+
body?: string;
|
|
42
|
+
} | undefined, afterMessageCount: number): Promise<void>;
|
|
43
|
+
recordAppMarker(kind: AppMarkerPayload["kind"], data: Record<string, unknown>, afterMessageCount: number): Promise<void>;
|
|
44
|
+
/** Keep a turn metric in memory; {@link persistTurnMetric} writes it. */
|
|
45
|
+
addTurnMetric(payload: TurnMetricPayload): void;
|
|
46
|
+
persistTurnMetric(payload: TurnMetricPayload): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Re-append everything to the current session file. Called after a
|
|
49
|
+
* continuation/compaction file is created so display-only history isn't lost
|
|
50
|
+
* when the session is rewritten (those rewrites only re-persist messages).
|
|
51
|
+
* Each marker keeps its original `afterMessageCount` anchor.
|
|
52
|
+
*/
|
|
53
|
+
rePersistAll(): Promise<void>;
|
|
54
|
+
private rePersistTurnMetrics;
|
|
55
|
+
private rePersist;
|
|
56
|
+
private append;
|
|
57
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { NOLAN_TURN_CUSTOM_KIND, AUTOPILOT_MARKER_CUSTOM_KIND, APP_MARKER_CUSTOM_KIND, } from "../session-manager.js";
|
|
3
|
+
import { remapAnchorForCompaction, stripRecordedPosition } from "../session-history.js";
|
|
4
|
+
/**
|
|
5
|
+
* Display-only transcript history recorded against a session file: Nolan Grout
|
|
6
|
+
* turns, autopilot verdicts, app markers and per-turn metrics. NEVER part of
|
|
7
|
+
* the LLM message history — persisted as `custom` entries (parentId null, so
|
|
8
|
+
* never on the message DAG) and reloaded on resume so the transcript renders
|
|
9
|
+
* the same rows the live run showed. Persistence is a no-op while the session
|
|
10
|
+
* has no file (transient sessions keep markers in memory only).
|
|
11
|
+
*/
|
|
12
|
+
export class TranscriptMarkers {
|
|
13
|
+
getSessionManager;
|
|
14
|
+
getSessionPath;
|
|
15
|
+
// Nolan Grout (mentor agent) turns. Each carries the non-system message count at
|
|
16
|
+
// record time so the webview can interleave them chronologically.
|
|
17
|
+
nolanTurns = [];
|
|
18
|
+
// Autopilot Nolan (auto-reviewer) verdict markers (prompted / done / human /
|
|
19
|
+
// capped), so a resumed session shows the identical Nolan bubble the live run
|
|
20
|
+
// showed instead of dropping it or replaying a raw verdict.
|
|
21
|
+
autopilotMarkers = [];
|
|
22
|
+
// Generic app transcript markers (plan-mode banner, task header, error rows,
|
|
23
|
+
// user-bubble display hints).
|
|
24
|
+
appMarkers = [];
|
|
25
|
+
turnMetrics = [];
|
|
26
|
+
constructor(getSessionManager, getSessionPath) {
|
|
27
|
+
this.getSessionManager = getSessionManager;
|
|
28
|
+
this.getSessionPath = getSessionPath;
|
|
29
|
+
}
|
|
30
|
+
getNolanTurns() {
|
|
31
|
+
return this.nolanTurns;
|
|
32
|
+
}
|
|
33
|
+
getAutopilotMarkers() {
|
|
34
|
+
return this.autopilotMarkers;
|
|
35
|
+
}
|
|
36
|
+
getAppMarkers() {
|
|
37
|
+
return this.appMarkers;
|
|
38
|
+
}
|
|
39
|
+
getTurnMetrics() {
|
|
40
|
+
return this.turnMetrics.map((metric) => ({
|
|
41
|
+
...metric,
|
|
42
|
+
usage: { ...metric.usage },
|
|
43
|
+
timing: { ...metric.timing },
|
|
44
|
+
cost: { ...metric.cost },
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
/** Summed cost when every recorded turn has a known price, else undefined. */
|
|
48
|
+
knownCostUsd() {
|
|
49
|
+
return this.turnMetrics.length > 0 && this.turnMetrics.every((m) => m.cost.status === "known")
|
|
50
|
+
? this.turnMetrics.reduce((sum, m) => sum + (m.cost.status === "known" ? m.cost.usd : 0), 0)
|
|
51
|
+
: undefined;
|
|
52
|
+
}
|
|
53
|
+
/** Drop everything — display-only history belongs to the OLD session. */
|
|
54
|
+
clear() {
|
|
55
|
+
this.nolanTurns = [];
|
|
56
|
+
this.autopilotMarkers = [];
|
|
57
|
+
this.appMarkers = [];
|
|
58
|
+
this.turnMetrics = [];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Restore from a loaded session file. The leaf is passed so each marker also
|
|
62
|
+
* carries its FILE-order position, the fallback used when a legacy anchor is
|
|
63
|
+
* out of range (see RecordedPosition).
|
|
64
|
+
*/
|
|
65
|
+
restore(entries, leafId) {
|
|
66
|
+
const sessionManager = this.getSessionManager();
|
|
67
|
+
this.nolanTurns = sessionManager.getNolanTurns(entries, leafId);
|
|
68
|
+
this.autopilotMarkers = sessionManager.getAutopilotMarkers(entries, leafId);
|
|
69
|
+
this.appMarkers = sessionManager.getAppMarkers(entries, leafId);
|
|
70
|
+
this.turnMetrics = sessionManager.getTurnMetrics(entries);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Rebase every transcript anchor (Nolan turns, autopilot verdicts, app markers)
|
|
74
|
+
* onto a freshly compacted message list.
|
|
75
|
+
*/
|
|
76
|
+
remapAnchors(remap) {
|
|
77
|
+
if (!remap)
|
|
78
|
+
return;
|
|
79
|
+
const move = (payload) => ({
|
|
80
|
+
...payload,
|
|
81
|
+
afterMessageCount: remapAnchorForCompaction(payload.afterMessageCount, remap),
|
|
82
|
+
});
|
|
83
|
+
this.nolanTurns = this.nolanTurns.map(move);
|
|
84
|
+
this.autopilotMarkers = this.autopilotMarkers.map(move);
|
|
85
|
+
this.appMarkers = this.appMarkers.map(move);
|
|
86
|
+
}
|
|
87
|
+
async recordNolanTurn(question, reply, afterMessageCount) {
|
|
88
|
+
const payload = { version: 1, question, reply, afterMessageCount };
|
|
89
|
+
this.nolanTurns.push(payload);
|
|
90
|
+
await this.append(NOLAN_TURN_CUSTOM_KIND, payload);
|
|
91
|
+
}
|
|
92
|
+
async recordAutopilotMarker(phase, extra, afterMessageCount) {
|
|
93
|
+
const payload = {
|
|
94
|
+
version: 1,
|
|
95
|
+
phase,
|
|
96
|
+
afterMessageCount,
|
|
97
|
+
...(extra?.reason !== undefined ? { reason: extra.reason } : {}),
|
|
98
|
+
...(extra?.body !== undefined ? { body: extra.body } : {}),
|
|
99
|
+
};
|
|
100
|
+
this.autopilotMarkers.push(payload);
|
|
101
|
+
await this.append(AUTOPILOT_MARKER_CUSTOM_KIND, payload);
|
|
102
|
+
}
|
|
103
|
+
async recordAppMarker(kind, data, afterMessageCount) {
|
|
104
|
+
const payload = { version: 1, kind, afterMessageCount, data };
|
|
105
|
+
this.appMarkers.push(payload);
|
|
106
|
+
await this.append(APP_MARKER_CUSTOM_KIND, payload);
|
|
107
|
+
}
|
|
108
|
+
/** Keep a turn metric in memory; {@link persistTurnMetric} writes it. */
|
|
109
|
+
addTurnMetric(payload) {
|
|
110
|
+
this.turnMetrics.push(payload);
|
|
111
|
+
}
|
|
112
|
+
async persistTurnMetric(payload) {
|
|
113
|
+
const sessionPath = this.getSessionPath();
|
|
114
|
+
if (sessionPath)
|
|
115
|
+
await this.getSessionManager().appendTurnMetric(sessionPath, payload);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Re-append everything to the current session file. Called after a
|
|
119
|
+
* continuation/compaction file is created so display-only history isn't lost
|
|
120
|
+
* when the session is rewritten (those rewrites only re-persist messages).
|
|
121
|
+
* Each marker keeps its original `afterMessageCount` anchor.
|
|
122
|
+
*/
|
|
123
|
+
async rePersistAll() {
|
|
124
|
+
await this.rePersistTurnMetrics();
|
|
125
|
+
await this.rePersist(NOLAN_TURN_CUSTOM_KIND, this.nolanTurns);
|
|
126
|
+
await this.rePersist(AUTOPILOT_MARKER_CUSTOM_KIND, this.autopilotMarkers);
|
|
127
|
+
await this.rePersist(APP_MARKER_CUSTOM_KIND, this.appMarkers);
|
|
128
|
+
}
|
|
129
|
+
async rePersistTurnMetrics() {
|
|
130
|
+
if (!this.getSessionPath())
|
|
131
|
+
return;
|
|
132
|
+
for (const metric of this.turnMetrics) {
|
|
133
|
+
await this.getSessionManager().appendTurnMetric(this.getSessionPath(), metric);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async rePersist(kind, payloads) {
|
|
137
|
+
if (!this.getSessionPath())
|
|
138
|
+
return;
|
|
139
|
+
for (const payload of payloads) {
|
|
140
|
+
const entry = {
|
|
141
|
+
type: "custom",
|
|
142
|
+
kind,
|
|
143
|
+
id: crypto.randomUUID(),
|
|
144
|
+
parentId: null,
|
|
145
|
+
timestamp: new Date().toISOString(),
|
|
146
|
+
data: stripRecordedPosition(payload),
|
|
147
|
+
};
|
|
148
|
+
await this.getSessionManager().appendEntry(this.getSessionPath(), entry);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async append(kind, payload) {
|
|
152
|
+
const sessionPath = this.getSessionPath();
|
|
153
|
+
if (!sessionPath)
|
|
154
|
+
return;
|
|
155
|
+
const entry = {
|
|
156
|
+
type: "custom",
|
|
157
|
+
kind,
|
|
158
|
+
id: crypto.randomUUID(),
|
|
159
|
+
parentId: null,
|
|
160
|
+
timestamp: new Date().toISOString(),
|
|
161
|
+
data: payload,
|
|
162
|
+
};
|
|
163
|
+
await this.getSessionManager().appendEntry(sessionPath, entry);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=transcript-markers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-markers.js","sourceRoot":"","sources":["../../../src/core/agent-session/transcript-markers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AgentToolCallEndEvent, AgentToolCallStartEvent } from "@prestyj/agent";
|
|
2
|
+
import type { BackgroundProcess } from "../process-manager.js";
|
|
3
|
+
import { type VerificationGate } from "../verification-gate.js";
|
|
4
|
+
/** A tool call observed between its start and end events. */
|
|
5
|
+
export interface TrackedToolCall {
|
|
6
|
+
name: string;
|
|
7
|
+
args: Record<string, unknown>;
|
|
8
|
+
revision: number;
|
|
9
|
+
sourceSnapshot?: string | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Host-observed verification evidence: which files this run mutated, which
|
|
13
|
+
* tool calls are in flight (with their pre-run workspace snapshot), and which
|
|
14
|
+
* background checks still owe an exit code. Feeds the session's
|
|
15
|
+
* {@link VerificationGate}; persistence stays with the session.
|
|
16
|
+
*/
|
|
17
|
+
export declare class VerificationTracker {
|
|
18
|
+
private readonly gate;
|
|
19
|
+
private readonly cwd;
|
|
20
|
+
private readonly listProcesses;
|
|
21
|
+
private readonly fileEditCounts;
|
|
22
|
+
private readonly toolCalls;
|
|
23
|
+
private readonly backgroundVerification;
|
|
24
|
+
/** The bash tool runs under bash with pipefail (not the Windows cmd.exe
|
|
25
|
+
* fallback), so checks with read-only commands around them may count. */
|
|
26
|
+
private readonly posixShell;
|
|
27
|
+
constructor(gate: VerificationGate, cwd: string, listProcesses: () => BackgroundProcess[], posixShell?: boolean);
|
|
28
|
+
private classify;
|
|
29
|
+
recordFileMutated(relative: string): void;
|
|
30
|
+
/** Per-run reset of mutated files and in-flight calls. */
|
|
31
|
+
resetRun(): void;
|
|
32
|
+
/** Drop background checks whose process no longer exists. */
|
|
33
|
+
pruneBackground(liveProcessIds: ReadonlySet<string>): void;
|
|
34
|
+
clearBackground(): void;
|
|
35
|
+
getToolCall(toolCallId: string): TrackedToolCall | undefined;
|
|
36
|
+
/** Track a starting call. Resolves true when verification state must be persisted. */
|
|
37
|
+
recordToolCallStart(event: AgentToolCallStartEvent): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Fold a finished call into the gate. Only host-observed successful
|
|
40
|
+
* mutations and trustworthy check results affect approval. The model's text
|
|
41
|
+
* is never evidence. Resolves true when verification state changed.
|
|
42
|
+
*/
|
|
43
|
+
recordToolCallEnd(event: AgentToolCallEndEvent, call: TrackedToolCall | undefined, planMode: boolean): Promise<boolean>;
|
|
44
|
+
/** Settle every background check whose process has exited. Resolves true if any changed. */
|
|
45
|
+
settleFinishedBackground(): Promise<boolean>;
|
|
46
|
+
/** In-flight or unconfirmed evidence, else the gate's own problem. */
|
|
47
|
+
verificationProblem(): string | null;
|
|
48
|
+
private recordFinishedBackgroundVerification;
|
|
49
|
+
private finishSnapshotVerification;
|
|
50
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { autoBackgroundedId, REVIEW_REJECTED_BEFORE_START } from "../../tools/bash.js";
|
|
2
|
+
import { editTargetPaths } from "../../tools/edit-targets.js";
|
|
3
|
+
import { isCheckOwnFile, extractAddedLines, isCodeFilePath, isVerificationCommand, } from "../verification-gate.js";
|
|
4
|
+
import { classifyVerificationCommand } from "../verification-evidence.js";
|
|
5
|
+
import { captureVerificationSnapshot } from "../verification-snapshot.js";
|
|
6
|
+
import { resolveShell } from "../shell.js";
|
|
7
|
+
/**
|
|
8
|
+
* Host-observed verification evidence: which files this run mutated, which
|
|
9
|
+
* tool calls are in flight (with their pre-run workspace snapshot), and which
|
|
10
|
+
* background checks still owe an exit code. Feeds the session's
|
|
11
|
+
* {@link VerificationGate}; persistence stays with the session.
|
|
12
|
+
*/
|
|
13
|
+
export class VerificationTracker {
|
|
14
|
+
gate;
|
|
15
|
+
cwd;
|
|
16
|
+
listProcesses;
|
|
17
|
+
fileEditCounts = new Map();
|
|
18
|
+
toolCalls = new Map();
|
|
19
|
+
backgroundVerification = new Map();
|
|
20
|
+
/** The bash tool runs under bash with pipefail (not the Windows cmd.exe
|
|
21
|
+
* fallback), so checks with read-only commands around them may count. */
|
|
22
|
+
posixShell;
|
|
23
|
+
constructor(gate, cwd, listProcesses, posixShell = !resolveShell("").isCmdFallback) {
|
|
24
|
+
this.gate = gate;
|
|
25
|
+
this.cwd = cwd;
|
|
26
|
+
this.listProcesses = listProcesses;
|
|
27
|
+
this.posixShell = posixShell;
|
|
28
|
+
}
|
|
29
|
+
classify(command) {
|
|
30
|
+
return classifyVerificationCommand(command, { posixShell: this.posixShell });
|
|
31
|
+
}
|
|
32
|
+
recordFileMutated(relative) {
|
|
33
|
+
this.fileEditCounts.set(relative, (this.fileEditCounts.get(relative) ?? 0) + 1);
|
|
34
|
+
}
|
|
35
|
+
/** Per-run reset of mutated files and in-flight calls. */
|
|
36
|
+
resetRun() {
|
|
37
|
+
this.fileEditCounts.clear();
|
|
38
|
+
this.toolCalls.clear();
|
|
39
|
+
}
|
|
40
|
+
/** Drop background checks whose process no longer exists. */
|
|
41
|
+
pruneBackground(liveProcessIds) {
|
|
42
|
+
for (const id of this.backgroundVerification.keys()) {
|
|
43
|
+
if (!liveProcessIds.has(id))
|
|
44
|
+
this.backgroundVerification.delete(id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
clearBackground() {
|
|
48
|
+
this.backgroundVerification.clear();
|
|
49
|
+
}
|
|
50
|
+
getToolCall(toolCallId) {
|
|
51
|
+
return this.toolCalls.get(toolCallId);
|
|
52
|
+
}
|
|
53
|
+
/** Track a starting call. Resolves true when verification state must be persisted. */
|
|
54
|
+
async recordToolCallStart(event) {
|
|
55
|
+
const tracked = {
|
|
56
|
+
name: event.name,
|
|
57
|
+
args: event.args ?? {},
|
|
58
|
+
revision: this.gate.revision,
|
|
59
|
+
};
|
|
60
|
+
this.toolCalls.set(event.toolCallId, tracked);
|
|
61
|
+
const startClassification = event.name === "bash" && typeof event.args?.command === "string"
|
|
62
|
+
? this.classify(event.args.command)
|
|
63
|
+
: null;
|
|
64
|
+
if (startClassification &&
|
|
65
|
+
typeof event.args?.command === "string" &&
|
|
66
|
+
(isVerificationCommand(event.args.command) ||
|
|
67
|
+
startClassification.accepted ||
|
|
68
|
+
// Must match the tool_call_end predicate: a snapshot-eligible
|
|
69
|
+
// command that never captured a "before" snapshot is misread at
|
|
70
|
+
// the end as an uncomparable workspace and re-arms the gate.
|
|
71
|
+
startClassification.snapshotEligible === true)) {
|
|
72
|
+
// A check that can rewrite files (--fix, build scripts, emitters)
|
|
73
|
+
// invalidates earlier in-flight evidence AND marks the run as
|
|
74
|
+
// touched. A check that is merely UNRECOGNIZED (`make test`, `deno
|
|
75
|
+
// test`) rewrites nothing we can point to: bumping the revision for
|
|
76
|
+
// it poisoned the gate on green output and re-armed the hook into
|
|
77
|
+
// every later question turn.
|
|
78
|
+
this.gate.recordVerificationAttempt();
|
|
79
|
+
const classification = startClassification;
|
|
80
|
+
if (classification.snapshotEligible && event.args.persist !== true) {
|
|
81
|
+
const call = tracked;
|
|
82
|
+
call.sourceSnapshot = await captureVerificationSnapshot(this.cwd, [
|
|
83
|
+
...this.fileEditCounts.keys(),
|
|
84
|
+
]);
|
|
85
|
+
if (call.sourceSnapshot === null)
|
|
86
|
+
this.gate.requireFreshVerification(true, event.args.command);
|
|
87
|
+
}
|
|
88
|
+
else if ((classification.accepted && event.args.persist !== true) ||
|
|
89
|
+
(!classification.accepted && classification.mayMutate)) {
|
|
90
|
+
// Flag the workspace unknown only when tool_call_end can resolve
|
|
91
|
+
// it: a bounded check records pass/fail, a file-rewriting command
|
|
92
|
+
// bumps the revision. An unrecognized read-only check (`biome ci`)
|
|
93
|
+
// or a persistent-shell run records nothing at the end, so
|
|
94
|
+
// flagging it left verified work Unverified forever — and
|
|
95
|
+
// autopilot silently refused every later turn.
|
|
96
|
+
this.gate.requireFreshVerification(!classification.accepted && classification.mayMutate, event.args.command);
|
|
97
|
+
}
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Fold a finished call into the gate. Only host-observed successful
|
|
104
|
+
* mutations and trustworthy check results affect approval. The model's text
|
|
105
|
+
* is never evidence. Resolves true when verification state changed.
|
|
106
|
+
*/
|
|
107
|
+
async recordToolCallEnd(event, call, planMode) {
|
|
108
|
+
const name = call?.name ?? "";
|
|
109
|
+
const args = call?.args;
|
|
110
|
+
let verificationChanged = false;
|
|
111
|
+
// In plan mode write/edit can only touch `.ezcoder/plans/*.md`; a code-file
|
|
112
|
+
// write there was refused (refusals return text, not isError). Counting
|
|
113
|
+
// it as a change left "unverified" work that blocked plan approval.
|
|
114
|
+
if (!event.isError && args && !planMode) {
|
|
115
|
+
if (name === "edit" || name === "write") {
|
|
116
|
+
// Check-owning files (tsconfig.json, pytest.ini, vitest.config.ts …)
|
|
117
|
+
// are tracked even when they are not source code: editing one is how
|
|
118
|
+
// a red suite is turned green without fixing anything. A multi-file
|
|
119
|
+
// edit records every file; its combined diff is scanned for each.
|
|
120
|
+
const addedText = name === "write"
|
|
121
|
+
? String(args.content ?? "")
|
|
122
|
+
: extractAddedLines(event.details?.diff ?? event.result);
|
|
123
|
+
for (const filePath of editTargetPaths(args)) {
|
|
124
|
+
if (isCodeFilePath(filePath) || isCheckOwnFile(filePath)) {
|
|
125
|
+
this.gate.recordMutation(filePath, addedText);
|
|
126
|
+
verificationChanged = true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (args && call && name === "bash") {
|
|
132
|
+
const command = typeof args.command === "string" ? args.command : "";
|
|
133
|
+
const classification = this.classify(command);
|
|
134
|
+
if (args.review === true && event.result === REVIEW_REJECTED_BEFORE_START) {
|
|
135
|
+
// The core tool rejected its arguments BEFORE spawning. Never mint
|
|
136
|
+
// a pass, or poison the failed-check ledger with an unexecuted check.
|
|
137
|
+
// A child's output cannot match: bash always prefixes it with Exit code.
|
|
138
|
+
this.gate.recordRejectedCheck(command, REVIEW_REJECTED_BEFORE_START);
|
|
139
|
+
delete call.sourceSnapshot;
|
|
140
|
+
verificationChanged = true;
|
|
141
|
+
}
|
|
142
|
+
else if (classification.accepted || classification.snapshotEligible) {
|
|
143
|
+
// A foreground check that outlived the default budget was moved to
|
|
144
|
+
// the background, not failed: track it to its real exit the same way.
|
|
145
|
+
const autoBackgroundId = event.isError ? undefined : autoBackgroundedId(event.result);
|
|
146
|
+
if ((autoBackgroundId !== undefined || args.run_in_background === true) &&
|
|
147
|
+
!event.isError &&
|
|
148
|
+
args.persist !== true) {
|
|
149
|
+
const id = autoBackgroundId ?? /^ID:\s*(\S+)/m.exec(event.result)?.[1];
|
|
150
|
+
// No parseable ID means the check cannot be tracked to a real exit
|
|
151
|
+
// code — no evidence either way. Recording a FAILURE here made
|
|
152
|
+
// every later green run of a different spelling look owed.
|
|
153
|
+
if (id)
|
|
154
|
+
this.backgroundVerification.set(id, {
|
|
155
|
+
revision: call.revision,
|
|
156
|
+
command,
|
|
157
|
+
...(classification.snapshotEligible
|
|
158
|
+
? { sourceSnapshot: call.sourceSnapshot ?? null }
|
|
159
|
+
: {}),
|
|
160
|
+
});
|
|
161
|
+
else if (classification.snapshotEligible)
|
|
162
|
+
this.gate.requireFreshVerification(true, command);
|
|
163
|
+
}
|
|
164
|
+
else if (args.persist === true) {
|
|
165
|
+
// Persistent-shell checks are not bounded evidence (steering can
|
|
166
|
+
// interleave): neither a pass nor a failure. A recorded failure
|
|
167
|
+
// here blocked approval for sessions that prefer the shell.
|
|
168
|
+
}
|
|
169
|
+
else if (classification.snapshotEligible) {
|
|
170
|
+
await this.finishSnapshotVerification({ command, revision: call.revision, sourceSnapshot: call.sourceSnapshot ?? null }, !event.isError && /^Exit code:\s*0(?:\s|$)/i.test(event.result.trim()));
|
|
171
|
+
verificationChanged = true;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
if (!event.isError && /^Exit code:\s*0(?:\s|$)/i.test(event.result.trim())) {
|
|
175
|
+
this.gate.recordVerification(call.revision, command);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
this.gate.recordFailedVerification(command, call.revision);
|
|
179
|
+
}
|
|
180
|
+
verificationChanged = true;
|
|
181
|
+
}
|
|
182
|
+
delete call.sourceSnapshot;
|
|
183
|
+
}
|
|
184
|
+
else if (classification.candidate) {
|
|
185
|
+
// Green but untrusted: remember WHY so the demand can tell the
|
|
186
|
+
// agent which command shape actually clears the gate.
|
|
187
|
+
this.gate.recordRejectedCheck(command, classification.reason);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!event.isError && args && name === "task_output" && typeof args.id === "string") {
|
|
191
|
+
verificationChanged =
|
|
192
|
+
(await this.recordFinishedBackgroundVerification(args.id)) || verificationChanged;
|
|
193
|
+
}
|
|
194
|
+
return verificationChanged;
|
|
195
|
+
}
|
|
196
|
+
/** Settle every background check whose process has exited. Resolves true if any changed. */
|
|
197
|
+
async settleFinishedBackground() {
|
|
198
|
+
let backgroundChanged = false;
|
|
199
|
+
for (const id of this.backgroundVerification.keys()) {
|
|
200
|
+
backgroundChanged =
|
|
201
|
+
(await this.recordFinishedBackgroundVerification(id)) || backgroundChanged;
|
|
202
|
+
}
|
|
203
|
+
return backgroundChanged;
|
|
204
|
+
}
|
|
205
|
+
/** In-flight or unconfirmed evidence, else the gate's own problem. */
|
|
206
|
+
verificationProblem() {
|
|
207
|
+
if ([...this.toolCalls.values()].some((call) => call.sourceSnapshot !== undefined)) {
|
|
208
|
+
return "Unverified: a build is still running or its workspace comparison is pending.";
|
|
209
|
+
}
|
|
210
|
+
return (this.gate.verificationProblem() ??
|
|
211
|
+
(this.backgroundVerification.size > 0
|
|
212
|
+
? "Unverified: a background check is still running or its result has not been confirmed."
|
|
213
|
+
: null));
|
|
214
|
+
}
|
|
215
|
+
async recordFinishedBackgroundVerification(id) {
|
|
216
|
+
const started = this.backgroundVerification.get(id);
|
|
217
|
+
const proc = this.listProcesses().find((entry) => entry.id === id);
|
|
218
|
+
if (!started || !proc || proc.exitCode === null)
|
|
219
|
+
return false;
|
|
220
|
+
if (started.sourceSnapshot !== undefined) {
|
|
221
|
+
await this.finishSnapshotVerification(started, proc.exitCode === 0);
|
|
222
|
+
}
|
|
223
|
+
else if (proc.exitCode === 0) {
|
|
224
|
+
this.gate.recordVerification(started.revision, started.command);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
this.gate.recordFailedVerification(started.command, started.revision);
|
|
228
|
+
}
|
|
229
|
+
this.backgroundVerification.delete(id);
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
async finishSnapshotVerification(check, passed) {
|
|
233
|
+
const after = check.sourceSnapshot
|
|
234
|
+
? await captureVerificationSnapshot(this.cwd, [...this.fileEditCounts.keys()])
|
|
235
|
+
: null;
|
|
236
|
+
const classification = this.classify(check.command);
|
|
237
|
+
const recordFailure = (revision) => {
|
|
238
|
+
if (classification.ambiguousFailure) {
|
|
239
|
+
this.gate.recordRejectedCheck(check.command, "exit status cannot tell a failed check from a failed read-only command");
|
|
240
|
+
}
|
|
241
|
+
else if (revision === undefined) {
|
|
242
|
+
this.gate.recordFailedVerification(check.command);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
this.gate.recordFailedVerification(check.command, revision);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
if (after === null || after !== check.sourceSnapshot) {
|
|
249
|
+
this.gate.requireFreshVerification(true, check.command);
|
|
250
|
+
this.gate.recordRejectedCheck(check.command, after === null
|
|
251
|
+
? "Workspace inputs could not be compared; run a read-only check after the command"
|
|
252
|
+
: "Command changed workspace inputs; run checks against the changed source");
|
|
253
|
+
if (!passed)
|
|
254
|
+
recordFailure();
|
|
255
|
+
}
|
|
256
|
+
else if (passed) {
|
|
257
|
+
if (classification.snapshotPreserveOnly) {
|
|
258
|
+
this.gate.recordRejectedCheck(check.command, classification.reason);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
this.gate.recordVerification(check.revision, check.command);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
recordFailure(check.revision);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=verification-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-tracker.js","sourceRoot":"","sources":["../../../src/core/agent-session/verification-tracker.ts"],"names":[],"mappings":"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"}
|