@sema-agent/core 7.15.0 → 7.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +202 -0
- package/dist/agents/builtin-agents.d.ts +3 -3
- package/dist/agents/cross-session-envelope.d.ts +0 -1
- package/dist/agents/cross-session-envelope.js +0 -1
- package/dist/agents/peer-notices.d.ts +0 -9
- package/dist/agents/peer-notices.js +0 -63
- package/dist/agents/subagent.js +7 -15
- package/dist/brain/request-params.d.ts +2 -2
- package/dist/config/defaults.d.ts +0 -7
- package/dist/config/defaults.js +0 -2
- package/dist/core/artifact-host.d.ts +218 -0
- package/dist/core/artifact-host.js +92 -0
- package/dist/core/ask-origin.d.ts +29 -3
- package/dist/core/ask-origin.js +17 -9
- package/dist/core/ask-question.d.ts +25 -0
- package/dist/core/ask-question.js +4 -0
- package/dist/core/ask-unresolvable-notice.d.ts +30 -21
- package/dist/core/ask-unresolvable-notice.js +16 -8
- package/dist/core/auto-compaction.d.ts +10 -10
- package/dist/core/auto-mode-arming.d.ts +2 -2
- package/dist/core/background-agent-store.d.ts +5 -5
- package/dist/core/background-shell.d.ts +1 -1
- package/dist/core/checkpoint-execution-record.d.ts +0 -3
- package/dist/core/checkpoint-execution-record.js +0 -4
- package/dist/core/checkpoint-store.d.ts +71 -99
- package/dist/core/checkpoint-store.js +9 -16
- package/dist/core/context-edit.d.ts +36 -104
- package/dist/core/context-edit.js +37 -60
- package/dist/core/effective-path-target.d.ts +68 -8
- package/dist/core/effective-path-target.js +42 -30
- package/dist/core/engine-notice.d.ts +46 -32
- package/dist/core/env-budget.d.ts +31 -0
- package/dist/core/env-budget.js +39 -0
- package/dist/core/exec-output-tail.d.ts +5 -5
- package/dist/core/file-history-store.js +3 -6
- package/dist/core/fs-write-gate-policy.d.ts +1 -1
- package/dist/core/fs-write-gate-policy.js +3 -3
- package/dist/core/gate-lanes.js +9 -15
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +4 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +18 -17
- package/dist/core/lsp-session.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/lsp.js +5 -4
- package/dist/core/mcp.d.ts +5 -5
- package/dist/core/mcp.js +4 -48
- package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
- package/dist/core/memory-engine/delegation-settlement.js +128 -39
- package/dist/core/memory-engine/engine.d.ts +9 -8
- package/dist/core/memory-engine/engine.js +115 -120
- package/dist/core/memory-engine/file-backend.d.ts +17 -5
- package/dist/core/memory-engine/file-backend.js +78 -34
- package/dist/core/memory-engine/index.d.ts +2 -2
- package/dist/core/memory-engine/index.js +2 -2
- package/dist/core/memory-engine/layout.d.ts +152 -54
- package/dist/core/memory-engine/layout.js +441 -104
- package/dist/core/memory-engine/types.d.ts +8 -3
- package/dist/core/memory-engine/types.js +5 -0
- package/dist/core/memory-recall.d.ts +0 -8
- package/dist/core/memory.d.ts +1 -1
- package/dist/core/oracle-isolation.js +2 -2
- package/dist/core/parent-spec-seat.d.ts +66 -0
- package/dist/core/parent-spec-seat.js +47 -0
- package/dist/core/permission-rule-model.d.ts +11 -6
- package/dist/core/permission-rule-model.js +53 -37
- package/dist/core/permission-rules.js +8 -3
- package/dist/core/protocol-naming.d.ts +2 -2
- package/dist/core/remote-env.d.ts +1 -1
- package/dist/core/retired-keys.d.ts +19 -0
- package/dist/core/retired-keys.js +15 -0
- package/dist/core/runner/abort-race.d.ts +3 -3
- package/dist/core/runner/active-skill-scope.d.ts +2 -2
- package/dist/core/runner/active-skill-scope.js +3 -3
- package/dist/core/runner/assemble-result.d.ts +42 -40
- package/dist/core/runner/assemble-result.js +5 -4
- package/dist/core/runner/checkpoint-scope.d.ts +4 -4
- package/dist/core/runner/clock-and-limits.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.d.ts +35 -99
- package/dist/core/runner/compaction-knobs.d.ts +4 -4
- package/dist/core/runner/compaction-seams.d.ts +5 -5
- package/dist/core/runner/contracts.d.ts +232 -233
- package/dist/core/runner/decide-continuation.d.ts +6 -6
- package/dist/core/runner/denial-limit-arms.d.ts +8 -8
- package/dist/core/runner/derived-route-fallback.d.ts +2 -2
- package/dist/core/runner/gate-exit.d.ts +6 -6
- package/dist/core/runner/gate-exit.js +15 -1
- package/dist/core/runner/git-status-frame.d.ts +7 -7
- package/dist/core/runner/halt-attribution.d.ts +35 -0
- package/dist/core/runner/halt-attribution.js +16 -0
- package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
- package/dist/core/runner/memory-capture-optout.d.ts +1 -1
- package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
- package/dist/core/runner/memory-consolidation.d.ts +6 -8
- package/dist/core/runner/memory-consolidation.js +0 -1
- package/dist/core/runner/park-commit.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.d.ts +19 -19
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
- package/dist/core/runner/prepare-artifact.d.ts +53 -0
- package/dist/core/runner/prepare-artifact.js +77 -0
- package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
- package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +9 -7
- package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
- package/dist/core/runner/prepare-config-doors.d.ts +24 -24
- package/dist/core/runner/prepare-config-doors.js +5 -2
- package/dist/core/runner/prepare-context-lane.d.ts +8 -8
- package/dist/core/runner/prepare-context-lane.js +2 -13
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +3 -3
- package/dist/core/runner/prepare-file-history.js +3 -52
- package/dist/core/runner/prepare-gate-stations.d.ts +5 -5
- package/dist/core/runner/prepare-hands-readface.d.ts +35 -38
- package/dist/core/runner/prepare-hands-readface.js +3 -2
- package/dist/core/runner/prepare-inherited-gate.d.ts +9 -6
- package/dist/core/runner/prepare-inherited-gate.js +7 -8
- package/dist/core/runner/prepare-listings.d.ts +3 -3
- package/dist/core/runner/prepare-lsp.d.ts +3 -3
- package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
- package/dist/core/runner/prepare-memory.d.ts +4 -6
- package/dist/core/runner/prepare-memory.js +10 -9
- package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
- package/dist/core/runner/prepare-park-ask.d.ts +6 -6
- package/dist/core/runner/prepare-policy-chain.d.ts +7 -7
- package/dist/core/runner/prepare-policy-chain.js +15 -30
- package/dist/core/runner/prepare-prompt-assembly.js +1 -1
- package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
- package/dist/core/runner/prepare-question-face.d.ts +4 -4
- package/dist/core/runner/prepare-run-refs.d.ts +11 -11
- package/dist/core/runner/prepare-safety-scan.d.ts +2 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
- package/dist/core/runner/prepare-suspend-saga.js +0 -2
- package/dist/core/runner/prepare-task.d.ts +12 -12
- package/dist/core/runner/prepare-task.js +10 -9
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
- package/dist/core/runner/prepare-wiring-manifest.js +9 -7
- package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
- package/dist/core/runner/remote-env-retry.d.ts +3 -3
- package/dist/core/runner/resume-admission.d.ts +1 -1
- package/dist/core/runner/resume-admission.js +2 -1
- package/dist/core/runner/resume-claim.d.ts +1 -1
- package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
- package/dist/core/runner/resume-internals-and-config.js +4 -0
- package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
- package/dist/core/runner/resume-preflight.d.ts +1 -1
- package/dist/core/runner/resume-review-outcome.d.ts +1 -1
- package/dist/core/runner/retired-runner-deps.d.ts +3 -0
- package/dist/core/runner/retired-runner-deps.js +7 -0
- package/dist/core/runner/run-brain-sinks.d.ts +1 -1
- package/dist/core/runner/run-clock-and-content.d.ts +4 -4
- package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
- package/dist/core/runner/run-git-lane.d.ts +1 -1
- package/dist/core/runner/run-harness-handlers.d.ts +2 -2
- package/dist/core/runner/run-harness-handlers.js +2 -3
- package/dist/core/runner/run-identity-wiring.d.ts +4 -4
- package/dist/core/runner/run-leg.d.ts +3 -3
- package/dist/core/runner/run-notification-lane.d.ts +2 -2
- package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
- package/dist/core/runner/run-settle-and-teardown.d.ts +5 -5
- package/dist/core/runner/run-settle-and-teardown.js +3 -1
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
- package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
- package/dist/core/runner/runtask.d.ts +14 -14
- package/dist/core/runner/session-file-state-replay.d.ts +3 -3
- package/dist/core/runner/session-file-state-replay.js +3 -3
- package/dist/core/runner/session-rule-policy.d.ts +2 -2
- package/dist/core/runner/session-rule-policy.js +3 -4
- package/dist/core/runner/steer-admission.d.ts +2 -2
- package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
- package/dist/core/runner/stream-halt-verbs.js +1 -1
- package/dist/core/runner/stream-reap.d.ts +1 -1
- package/dist/core/runner/stream-steer-verb.js +1 -4
- package/dist/core/runner/synthetic-tools.d.ts +8 -8
- package/dist/core/runner/teardown-bounded.d.ts +2 -2
- package/dist/core/runner/tool-defer-gate.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +33 -33
- package/dist/core/runner/tool-end-body.d.ts +3 -3
- package/dist/core/runner/tool-face-overlay.d.ts +2 -2
- package/dist/core/runner/tool-output-projection.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +53 -53
- package/dist/core/runner/usage-accounting.d.ts +4 -4
- package/dist/core/runner/workspace-path.d.ts +1 -1
- package/dist/core/runner/workspace-path.js +3 -0
- package/dist/core/runner-deps.d.ts +30 -49
- package/dist/core/safe-notify.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +4 -4
- package/dist/core/session.d.ts +2 -2
- package/dist/core/skill-tool-specifier.d.ts +1 -1
- package/dist/core/skills-directory.d.ts +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
- package/dist/core/strategy-store.d.ts +8 -11
- package/dist/core/task-event.d.ts +20 -17
- package/dist/core/task-limits.d.ts +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +5 -5
- package/dist/core/task-registry-monitor.d.ts +2 -2
- package/dist/core/task-registry-shared.d.ts +27 -27
- package/dist/core/task-registry-shared.js +3 -13
- package/dist/core/task-registry.d.ts +8 -8
- package/dist/core/task-result.d.ts +37 -37
- package/dist/core/task-spec.d.ts +5 -5
- package/dist/core/task-stream.d.ts +16 -11
- package/dist/core/tool-catalog-entries.d.ts +1 -0
- package/dist/core/tool-catalog-entries.js +5 -0
- package/dist/core/tool-conformance.d.ts +0 -2
- package/dist/core/tool-conformance.js +1 -3
- package/dist/core/tool-errors.d.ts +5 -0
- package/dist/core/tool-errors.js +1 -0
- package/dist/core/tool-policy.d.ts +51 -22
- package/dist/core/tool-policy.js +28 -5
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +11 -11
- package/dist/core/tool-spec.d.ts +34 -38
- package/dist/core/tools.d.ts +2 -2
- package/dist/core/trace.d.ts +12 -15
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +4 -3
- package/dist/core/workflow-journal-store.d.ts +11 -11
- package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
- package/dist/engine/execution-env/node-execution-env.js +4 -2
- package/dist/engine/harness/agent-harness.d.ts +47 -4
- package/dist/engine/harness/agent-harness.js +52 -9
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +15 -8
- package/dist/engine/loop/types.d.ts +5 -0
- package/dist/index.d.ts +21 -16
- package/dist/index.js +17 -12
- package/dist/internal/harness.d.ts +1 -0
- package/dist/orchestration/run-spec.d.ts +3 -0
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +12 -6
- package/dist/orchestration/run-workflow-tool.js +23 -5
- package/dist/orchestration/workflow-primitives.d.ts +4 -2
- package/dist/orchestration/workflow-primitives.js +1 -4
- package/dist/orchestration/workflow-types.d.ts +34 -4
- package/dist/orchestration/workflow-types.js +2 -0
- package/dist/orchestration/workflow.d.ts +39 -7
- package/dist/orchestration/workflow.js +234 -113
- package/dist/prompt-assembly/assemble.d.ts +2 -2
- package/dist/prompt-assembly/assemble.js +9 -9
- package/dist/prompt-assembly/composer.d.ts +6 -7
- package/dist/prompt-assembly/composer.js +10 -10
- package/dist/prompt-assembly/epoch.js +1 -1
- package/dist/prompt-assembly/event-registry.d.ts +0 -21
- package/dist/prompt-assembly/packs/sema-default.js +30 -30
- package/dist/prompt-assembly/types.d.ts +14 -14
- package/dist/prompts/coordinator.d.ts +0 -13
- package/dist/prompts/coordinator.js +0 -3
- package/dist/stores/file/checkpoint-store.js +1 -5
- package/dist/stores/file/file-history-store.js +2 -2
- package/dist/stores/file/permission-rule-store.d.ts +4 -35
- package/dist/stores/file/permission-rule-store.js +4 -148
- package/dist/tools/artifact/artifact-text.d.ts +62 -0
- package/dist/tools/artifact/artifact-text.js +68 -0
- package/dist/tools/artifact/artifact-tool.d.ts +52 -0
- package/dist/tools/artifact/artifact-tool.js +351 -0
- package/dist/tools/artifact/local-stub.d.ts +26 -0
- package/dist/tools/artifact/local-stub.js +296 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +114 -48
- package/dist/tools/fs/bash-readonly-classifier.js +171 -60
- package/dist/tools/fs/encoding.d.ts +31 -40
- package/dist/tools/fs/fs-bash.d.ts +49 -45
- package/dist/tools/fs/fs-bash.js +19 -27
- package/dist/tools/fs/fs-pdf.d.ts +8 -8
- package/dist/tools/fs/fs-search-tools.d.ts +4 -4
- package/dist/tools/fs/fs-search-tools.js +5 -2
- package/dist/tools/fs/fs-shared.d.ts +146 -158
- package/dist/tools/fs/fs-shared.js +3 -11
- package/dist/tools/fs/fs-write.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
- package/dist/tools/fs/index.d.ts +78 -78
- package/dist/tools/fs/index.js +4 -1
- package/dist/tools/fs/notebook.d.ts +24 -25
- package/dist/tools/fs/pdf.d.ts +3 -3
- package/dist/tools/fs/read-deny.d.ts +22 -22
- package/dist/tools/fs/read-face.d.ts +21 -24
- package/dist/tools/fs/repo-map.d.ts +8 -8
- package/dist/tools/fs/safety.d.ts +233 -130
- package/dist/tools/fs/safety.js +131 -31
- package/dist/tools/fs/search.d.ts +63 -71
- package/dist/tools/fs/search.js +8 -6
- package/package.json +6 -2
- package/test/export-surface.snapshot.json +119 -39
|
@@ -1,37 +1,38 @@
|
|
|
1
1
|
import type { AssistantMessage } from "../../internal/llm.js";
|
|
2
2
|
import type { NestedUsage, PausedCause, TaskResult, TaskSpec, TerminalCause } from "../types.js";
|
|
3
|
+
import type { HaltConsumption } from "../../internal/harness.js";
|
|
3
4
|
/** Per-task usage/cost accumulator (filled across the run loop, surfaced as `TaskResult.stats`). */
|
|
4
5
|
export interface Stats {
|
|
5
6
|
turns: number;
|
|
6
7
|
tokens: number;
|
|
7
|
-
/**
|
|
8
|
+
/** Total tool calls executed (one per `tool_start`). Spread into `TaskResult.stats`. */
|
|
8
9
|
toolCalls: number;
|
|
9
|
-
/**
|
|
10
|
+
/** Prompt tokens that MISSED the cache (Anthropic-protocol `input_tokens` shape). */
|
|
10
11
|
promptTokens: number;
|
|
11
12
|
cachedTokens: number;
|
|
12
13
|
cacheWriteTokens: number;
|
|
13
14
|
cacheWriteTokensLong: number;
|
|
14
15
|
outputTokens: number;
|
|
15
16
|
cacheHitRate?: number;
|
|
16
|
-
/**
|
|
17
|
+
/** Cache-INCLUSIVE prompt total (`promptTokens + cachedTokens + cacheWriteTokens*`) — the
|
|
17
18
|
* billing/window/hit-rate denominator. Required (not derived) so a new accumulation site that forgets
|
|
18
19
|
* it fails the type check instead of silently reporting a total short by its own leg. */
|
|
19
20
|
totalInputTokens: number;
|
|
20
21
|
costMicroUsd: number;
|
|
21
|
-
/**
|
|
22
|
+
/** Present (`true`) when at least one model round of this leg reported NO usage frame (the brain's
|
|
22
23
|
* own `usageMissing` mark on the assistant message: an aborted / errored / usage-less provider reply). The
|
|
23
24
|
* numeric fields stay required and stay what was COUNTED — with this key present they are a LOWER BOUND,
|
|
24
25
|
* not a measurement ("0 is unknown, not free"). Absent ⇔ every round reported usage. */
|
|
25
26
|
usageMissing?: true;
|
|
26
27
|
nested?: NestedUsage;
|
|
27
|
-
/** Post-task memory-consolidation usage
|
|
28
|
+
/** Post-task memory-consolidation usage; set after the result is assembled. Kept out of
|
|
28
29
|
* the budget gate (`overBudget` reads `costMicroUsd`/`tokens`, never this). */
|
|
29
30
|
memory?: {
|
|
30
31
|
tokens: number;
|
|
31
32
|
costMicroUsd: number;
|
|
32
33
|
applied: number;
|
|
33
34
|
};
|
|
34
|
-
/**
|
|
35
|
+
/** Human-review burden. Wall-clock approval-gate wait + count, bucketed by
|
|
35
36
|
* `gate.kind`, accumulated across resume legs. Set by the run loop from the per-task human-review
|
|
36
37
|
* accumulator (synchronous `resolveAsk` timing + durable resume latency). **NOT an LLM cost** — never
|
|
37
38
|
* folded into `costMicroUsd`/`costBreakdown`/the budget gate (same budget-excluded treatment as `memory`).
|
|
@@ -65,21 +66,21 @@ export interface Stats {
|
|
|
65
66
|
segment: string;
|
|
66
67
|
}>;
|
|
67
68
|
};
|
|
68
|
-
/**
|
|
69
|
+
/** Within-task compaction LLM cost (micro-USD), accumulated by
|
|
69
70
|
* `recordCompactionUsage` as a SEPARATE running total because that cost IS folded into `costMicroUsd`
|
|
70
71
|
* (so it can't be re-derived from `costMicroUsd` alone). The {@link costBreakdown.compactionMicroUsd}
|
|
71
72
|
* source. Run-loop internal — not a public `TaskResult.stats` field. */
|
|
72
73
|
compactionMicroUsd?: number;
|
|
73
74
|
/**
|
|
74
|
-
*
|
|
75
|
+
* A thin FINANCE TAXONOMY of the LLM-derived costs the engine actually
|
|
75
76
|
* prices, decomposing the task's spend into report categories (no new persisted structure — derived from
|
|
76
77
|
* the cost sources that already exist). CORE = LLM-token-derived ONLY; the SERVICE adds the infra axes it
|
|
77
78
|
* owns (tool-call / sandbox-walltime / egress — it has the k8s cost data) and composes them with this.
|
|
78
79
|
* Each category is ≥ 0 and the parts reconcile to the independently-summed LLM total
|
|
79
80
|
* (`llmRoot + nestedSubagent + compaction` — `memory` is a separate, budget-excluded line, see its doc).
|
|
80
81
|
* Filled in assembleResult for `llmRoot`/`nestedSubagent`/`compaction`; the `memoryConsolidation` line is
|
|
81
|
-
* permanently 0 since
|
|
82
|
-
* public stats contract; an engine-plane re-mount
|
|
82
|
+
* permanently 0 since B19 retired the runner-integrated consolidation pass (field kept — it is
|
|
83
|
+
* public stats contract; an engine-plane re-mount would fill it again).
|
|
83
84
|
*/
|
|
84
85
|
costBreakdown?: {
|
|
85
86
|
/** Root-agent LLM cost (micro-USD): `costMicroUsd` MINUS the sub-categories already folded into it
|
|
@@ -97,29 +98,29 @@ export interface Stats {
|
|
|
97
98
|
compactionMicroUsd: number;
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
|
-
/**
|
|
101
|
+
/** The two cumulative budget ceilings a task can trip. Tokens outrank cost when both are
|
|
101
102
|
* over at the same boundary. */
|
|
102
103
|
export type BudgetAxis = "tokens" | "cost";
|
|
103
104
|
/**
|
|
104
105
|
* The terminal-state flags the run loop hands {@link assembleResult} — the typed contract between the
|
|
105
|
-
* loop and result assembly (
|
|
106
|
+
* loop and result assembly (exported so it's grep-able and tests can construct it).
|
|
106
107
|
*/
|
|
107
108
|
export interface ResultFlags {
|
|
108
109
|
threw: unknown;
|
|
109
|
-
/**
|
|
110
|
+
/** The run's ENGINE-minted identity (`Prepared.runId`), echoed verbatim on
|
|
110
111
|
* `TaskResult.runId`. Pure pass-through on every terminal: assembly neither mints nor derives it
|
|
111
112
|
* (a caller reaching assembly at all has completed prepare, so the value exists), and a
|
|
112
113
|
* hand-constructed flags bag without one simply produces a result without one. */
|
|
113
114
|
runId?: string;
|
|
114
|
-
/**
|
|
115
|
+
/** The EFFECTIVE (resolved) model id that served the task — echoed on `TaskResult.model`. */
|
|
115
116
|
model?: string;
|
|
116
|
-
/**
|
|
117
|
+
/** Some spend was accounted while the serving model had NO configured price table
|
|
117
118
|
* (no `RunnerDeps.pricing` entry, no `Model.cost`). The numeric total is then a fabricated
|
|
118
119
|
* undercount — `stats.costMicroUsd`/`costBreakdown` are OMITTED from the public result instead of
|
|
119
120
|
* reporting a 0 indistinguishable from "declared free". The internal accumulator (budget gate's
|
|
120
121
|
* coordinate) is untouched. */
|
|
121
122
|
unpricedSpend?: boolean;
|
|
122
|
-
/**
|
|
123
|
+
/** Prepare-time rewind disclosures to echo on `TaskResult.rewindNotes`.
|
|
123
124
|
* Pure pass-through — assembly neither adds nor filters (a rewind that FAILED never reaches here; it
|
|
124
125
|
* throws at prepare and lands in the `threw` slot as a terminal errorCode). */
|
|
125
126
|
rewindNotes?: TaskResult["rewindNotes"];
|
|
@@ -134,37 +135,36 @@ export interface ResultFlags {
|
|
|
134
135
|
* path the terminal is `completed`, and this is what tells that completion apart from a natural
|
|
135
136
|
* one — the model did not finish; the person stopped it and the run awaits their direction). */
|
|
136
137
|
haltedOnUserRejection?: boolean;
|
|
137
|
-
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
/** design/174 final-round: call ids of answered-but-never-collected questions, echoed on
|
|
138
|
+
/** the harness's STATEMENT of what the run's halt did (see `HaltConsumption`):
|
|
139
|
+
* the loop's report that the halt's cut settled the final turn, and/or the boundary consult that
|
|
140
|
+
* stopped the loop for the halt's request. This is the ONLY input to `TaskResult.haltedByUser`
|
|
141
|
+
* (`haltConsumed`, halt-attribution.ts) and to slot 9.7 — the assembly never infers causation from the
|
|
142
|
+
* final's shape or from the verb's acceptance. A halt that was accepted but consumed nothing (the run
|
|
143
|
+
* ended for its own reason first) leaves this empty: the original terminal stands and the seat is
|
|
144
|
+
* NOT signed (the settle lane mints `task.halt_unconsumed` for it). */
|
|
145
|
+
haltConsumption?: HaltConsumption;
|
|
146
|
+
/** Call ids of answered-but-never-collected questions, echoed on
|
|
147
147
|
* `TaskResult.strandedHumanAnswers`. Pure pass-through; empty/absent ⇒ the field is omitted. The
|
|
148
148
|
* optional `onError` alert is NOT the disclosure — this mandatory result face is. */
|
|
149
149
|
strandedHumanAnswers?: TaskResult["strandedHumanAnswers"];
|
|
150
|
-
/**
|
|
150
|
+
/** The run's remote-workspace lifecycle failures, echoed on `TaskResult.remoteEnvFailures`.
|
|
151
151
|
* Pure pass-through (assembly neither adds nor filters) and INDEPENDENT of the status/errorCode chain:
|
|
152
152
|
* a refused `suspendVM` still ends the task exactly the way it did before — this only stops the eleven
|
|
153
153
|
* distinct codes from arriving as one anonymous `limits.max_turns_exceeded`. Empty/absent ⇒ the field is omitted. */
|
|
154
154
|
remoteEnvFailures?: TaskResult["remoteEnvFailures"];
|
|
155
|
-
/**
|
|
155
|
+
/** The run's effective read posture (resolved face + normalized deny
|
|
156
156
|
* additions), echoed on `TaskResult.effectiveReadFace` / `.effectiveReadDenyPatterns`. Pure
|
|
157
157
|
* pass-through (assembly neither adds nor filters) and INDEPENDENT of the status/errorCode chain:
|
|
158
158
|
* the posture is a fact about the leg that ran, whatever terminal it reached — a post-completion
|
|
159
159
|
* spawner folds it stricter-wins into follow-on legs; every other consumer may ignore it. */
|
|
160
160
|
effectiveReadFace?: TaskResult["effectiveReadFace"];
|
|
161
161
|
effectiveReadDenyPatterns?: TaskResult["effectiveReadDenyPatterns"];
|
|
162
|
-
/**
|
|
162
|
+
/** The memory-visibility observation, echoed on
|
|
163
163
|
* `TaskResult.effectiveMemoryScopes`. Pure pass-through on every terminal, same law as the
|
|
164
164
|
* read-posture seats above: present iff prepare completed (the memory-less states are their own
|
|
165
165
|
* values — absence means only "prepare never ran to completion"). */
|
|
166
166
|
effectiveMemoryScopes?: TaskResult["effectiveMemoryScopes"];
|
|
167
|
-
/**
|
|
167
|
+
/** The leg's effective reasoning resolution, echoed on `TaskResult.effectiveReasoning`.
|
|
168
168
|
* Pure pass-through on every terminal (same law as the read-posture seats): the SAME object the
|
|
169
169
|
* `reasoning.resolved` trace frame carried (runtask resolves once per leg — two faces, one mint);
|
|
170
170
|
* absent when thinking was off/unset for the leg, so the key is omitted. */
|
|
@@ -188,7 +188,7 @@ export interface ResultFlags {
|
|
|
188
188
|
* and the run takes the completed floor. Absent/false = the abort's ordinary reading. */
|
|
189
189
|
answerSettled?: boolean;
|
|
190
190
|
budgetHit?: "exceeded" | "precall";
|
|
191
|
-
/**
|
|
191
|
+
/** Which budget ceiling the hit belongs to. Set together with {@link budgetHit} at every
|
|
192
192
|
* site that records one; it picks the terminal code (`limits.max_tokens_exceeded` vs
|
|
193
193
|
* `limits.max_cost_exceeded`), so a hit without an axis would be an unattributable terminal. */
|
|
194
194
|
budgetAxis?: BudgetAxis;
|
|
@@ -198,7 +198,7 @@ export interface ResultFlags {
|
|
|
198
198
|
* the loop folded it into a text-only failure message, so the typed code rides this flag. */
|
|
199
199
|
gitCoreOverBudget?: boolean;
|
|
200
200
|
outputInvalid?: boolean;
|
|
201
|
-
/**
|
|
201
|
+
/** A re-suspend was refused because the task already suspended `maxSuspends` times
|
|
202
202
|
* (a resume/restart loop). It aborted the run (no `threw`) but must read as `failed`/`suspend.loop`,
|
|
203
203
|
* NOT `suspended` — slotted ABOVE `suspendRef` and the aborted branches (this suspend never minted a
|
|
204
204
|
* checkpoint, so `suspendRef` is unset anyway; the ordering makes the intent explicit). */
|
|
@@ -278,13 +278,13 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
|
|
|
278
278
|
/**
|
|
279
279
|
* Build the final {@link TaskResult} from the run's terminal state. **The errorCode priority chain is a
|
|
280
280
|
* public contract** (callers `switch` on these strings) — first match wins, in this exact order
|
|
281
|
-
* (
|
|
281
|
+
* (red-line #3, do not reorder):
|
|
282
282
|
* 1. `outputInvalid` → `"output.invalid"`
|
|
283
|
-
* 2. degenerate → `"output.degenerate"` + `salvagedOutput` (
|
|
283
|
+
* 2. degenerate → `"output.degenerate"` + `salvagedOutput` (wins over budget/timeout)
|
|
284
284
|
* 3. `budgetHit` → `"limits.max_tokens_exceeded"` | `"limits.max_cost_exceeded"` (by `budgetAxis`;
|
|
285
285
|
* the pre-call estimate rejection and the after-spend crossing share the code — the distinction
|
|
286
286
|
* lives in `errorMessage`, not in a second code)
|
|
287
|
-
* 3.5 `suspendLoop` → `"suspend.loop"` (
|
|
287
|
+
* 3.5 `suspendLoop` → `"suspend.loop"` (the re-suspend cap; deterministic root
|
|
288
288
|
* cause, above `threw` because it owns the abort)
|
|
289
289
|
* 4. `threw` + walltime → `"limits.max_walltime_exceeded"`
|
|
290
290
|
* 5. `threw` + turns → `"limits.max_turns_exceeded"`
|
|
@@ -293,18 +293,20 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
|
|
|
293
293
|
* 8. `blockedReason` → status `"blocked"` (no errorCode)
|
|
294
294
|
* 8.5 `paused` → status by the pause's registry row (`suspended` for an approval / resource
|
|
295
295
|
* slice / platform pause, `needs_review` + `"review.pending"` for a plan or dry-run review) +
|
|
296
|
-
* checkpointToken/gate (
|
|
296
|
+
* checkpointToken/gate (a deliberate durable pause beats the abort it used, but
|
|
297
297
|
* yields to a real budget/threw failure above)
|
|
298
298
|
* 9. `abortedLive` | stopReason aborted → `"limits.max_walltime_exceeded"` | `"limits.max_turns_exceeded"` | undefined
|
|
299
299
|
* (audit A-1: hoisted ABOVE no-final — the loop exits cleanly on abort, so `final` may be a
|
|
300
300
|
* normal message or absent; a plain user interrupt carries NO errorCode — switch on `status`),
|
|
301
|
-
* EXCEPT when the aborted `final` is the bare halt's OWN cut artifact (`haltOwnsAbortedFinal
|
|
301
|
+
* EXCEPT when the aborted `final` is the bare halt's OWN cut artifact (`haltOwnsAbortedFinal`: the
|
|
302
|
+
* loop reported the halt's cut settled the final turn — never shape inference),
|
|
302
303
|
* and EXCEPT when the answer had already settled (`answerSettled`: a clean `"stop"` final, not
|
|
303
304
|
* partial) — a stop landing on the run's tail cuts no work, so the run falls through to 12
|
|
304
305
|
* (`completed`, the answer as `result`, no `limits.*` code for the axis; three axes, one law)
|
|
305
|
-
* 9.7 `
|
|
306
|
-
* bare user halt — the verb working, not a defect; below the
|
|
307
|
-
* abort/limit that also fired owns the terminal and the halt rides as
|
|
306
|
+
* 9.7 halt CONSUMED (`haltConsumed(flags.haltConsumption)`) + (no `final` | the halt's own aborted
|
|
307
|
+
* `final`) → status `"completed"` (a bare user halt — the verb working, not a defect; below the
|
|
308
|
+
* aborts on purpose, a real abort/limit that also fired owns the terminal and the halt rides as
|
|
309
|
+
* the pass-through seat; an accepted-but-unconsumed halt never reaches this slot)
|
|
308
310
|
* 10. no `final` → status `"failed"`
|
|
309
311
|
* 11. stopReason error → brain `[code]` prefix (or `"conflict"` from the storage-layer flag)
|
|
310
312
|
* 12. else → `"completed"`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
|
|
2
2
|
import { extractErrorCode, stripErrorCodePrefix } from "../../brain/errors.js";
|
|
3
3
|
import { terminalProjection } from "./terminal-projection.js";
|
|
4
|
+
import { haltConsumed } from "./halt-attribution.js";
|
|
4
5
|
const SALVAGE_ELIGIBLE_TERMINALS = new Set([
|
|
5
6
|
"output.degenerate",
|
|
6
7
|
"limits.max_tokens_exceeded",
|
|
@@ -47,7 +48,7 @@ export function answerSettled(final, continuationCut = false) {
|
|
|
47
48
|
export function terminalCauseOf(final, stats, flags) {
|
|
48
49
|
let terminal;
|
|
49
50
|
let apiFailure;
|
|
50
|
-
const haltOwnsAbortedFinal = flags.
|
|
51
|
+
const haltOwnsAbortedFinal = flags.haltConsumption?.turnCut === "halt" &&
|
|
51
52
|
final?.stopReason === "aborted" &&
|
|
52
53
|
!flags.abortedLive &&
|
|
53
54
|
flags.abortedForTimeout !== true &&
|
|
@@ -103,7 +104,7 @@ export function terminalCauseOf(final, stats, flags) {
|
|
|
103
104
|
const code = flags.abortedForTimeout ? "limits.max_walltime_exceeded" : flags.abortedForTurns ? "limits.max_turns_exceeded" : undefined;
|
|
104
105
|
terminal = { kind: "failed", ...(code !== undefined ? { code } : {}), message: final?.errorMessage ?? (flags.abortedForTurns ? "max turns exceeded" : "run aborted") };
|
|
105
106
|
}
|
|
106
|
-
else if (flags.
|
|
107
|
+
else if (haltConsumed(flags.haltConsumption) && (!final || haltOwnsAbortedFinal)) {
|
|
107
108
|
terminal = { kind: "completed" };
|
|
108
109
|
}
|
|
109
110
|
else if (!final) {
|
|
@@ -155,7 +156,7 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
|
|
|
155
156
|
const result = text;
|
|
156
157
|
let salvagedOutput;
|
|
157
158
|
const { terminal, apiFailure } = terminalCauseOf(final, stats, flags);
|
|
158
|
-
const {
|
|
159
|
+
const { errorCode } = terminalProjection(terminal);
|
|
159
160
|
if (errorCode !== undefined && SALVAGE_ELIGIBLE_TERMINALS.has(errorCode)) {
|
|
160
161
|
salvagedOutput = text.trim() || undefined;
|
|
161
162
|
}
|
|
@@ -164,6 +165,6 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
|
|
|
164
165
|
void _internalCompaction;
|
|
165
166
|
if (flags.unpricedSpend)
|
|
166
167
|
delete publicStats.costMicroUsd;
|
|
167
|
-
const stampHaltedByUser = flags.
|
|
168
|
+
const stampHaltedByUser = haltConsumed(flags.haltConsumption);
|
|
168
169
|
return { taskId, ...(flags.runId !== undefined ? { runId: flags.runId } : {}), sessionId, terminal, ...(flags.model !== undefined ? { model: flags.model } : {}), result: result.trim(), salvagedOutput, ...(apiFailure !== undefined ? { apiFailure } : {}), ...(retryAfterMs !== undefined ? { retryAfterMs } : {}), ...(flags.rewindNotes !== undefined && flags.rewindNotes.length > 0 ? { rewindNotes: flags.rewindNotes } : {}), ...(flags.editedFiles !== undefined && flags.editedFiles.length > 0 ? { editedFiles: flags.editedFiles } : {}), ...(flags.haltedOnUserRejection === true ? { haltedOnUserRejection: true } : {}), ...(stampHaltedByUser ? { haltedByUser: true } : {}), ...(flags.remoteEnvFailures !== undefined && flags.remoteEnvFailures.length > 0 ? { remoteEnvFailures: [...flags.remoteEnvFailures] } : {}), ...(flags.strandedHumanAnswers !== undefined && flags.strandedHumanAnswers.length > 0 ? { strandedHumanAnswers: flags.strandedHumanAnswers } : {}), ...(flags.effectiveReadFace !== undefined ? { effectiveReadFace: flags.effectiveReadFace } : {}), ...(flags.effectiveReadDenyPatterns !== undefined && flags.effectiveReadDenyPatterns.length > 0 ? { effectiveReadDenyPatterns: flags.effectiveReadDenyPatterns } : {}), ...(flags.effectiveMemoryScopes !== undefined ? { effectiveMemoryScopes: flags.effectiveMemoryScopes } : {}), ...(flags.effectiveReasoning !== undefined ? { effectiveReasoning: flags.effectiveReasoning } : {}), stats: publicStats };
|
|
169
170
|
}
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
* the driver (the restore fold) and runtask (the resume rung) reach DOWN for the same names. Pure: a constant and two
|
|
6
6
|
* string functions.
|
|
7
7
|
*/
|
|
8
|
-
/**
|
|
8
|
+
/** The multi-tenant scope used when a durable suspend fires for an IRREVERSIBLE tool in an
|
|
9
9
|
* unattended deployment that did NOT opt into `durableApproval` (so there is no caller-supplied scope). The
|
|
10
10
|
* checkpoint carries this scope; resume reads it back from the checkpoint (`cp.scope`), so it is
|
|
11
11
|
* self-consistent without needing the original `TaskSpec`. Kept distinct from any tenant key to make an
|
|
12
12
|
* unattended irreversible suspend auditable as such. */
|
|
13
13
|
export declare const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* The SINGLE derivation of a durable-suspend checkpoint's scope (both gate mint
|
|
16
16
|
* sites + the bg-watcher park lane's expire compensation/arbitration consume THIS; a re-derived copy
|
|
17
17
|
* that drifted was the exact bug the park tests caught — expire against the wrong scope silently
|
|
18
18
|
* no-ops). `|| DEFAULT` (not `??`): an EMPTY-string principal must not become a shared scope bucket.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* That rule is stated twice in this file and was enforced on ONE of the two
|
|
21
21
|
* inputs — the principal half used `||`, the `durableApproval.scope` half used `??`, so an empty string
|
|
22
22
|
* arriving through the scope field (a config-centre / env lookup that came back blank is the realistic
|
|
23
23
|
* source) sailed through as the literal scope `""`. Two different tenants both landed in that one bucket,
|
|
@@ -33,7 +33,7 @@ export declare function checkpointScopeOf(spec: {
|
|
|
33
33
|
principal?: string;
|
|
34
34
|
}): string;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* The ONE spelling of the placement fields' empty-string discipline: `""` is absence
|
|
37
37
|
* wearing clothes (the resume entry's principal-rung posture), and every placement read that must
|
|
38
38
|
* treat it so — the resume rung's two sides (runtask), the restore fold's seed and the suspend
|
|
39
39
|
* stamp — goes through THIS helper, so three sites cannot drift into three readings. Deliberately
|
|
@@ -18,7 +18,7 @@ import type { PlatformLimitReason } from "../checkpoint-store.js";
|
|
|
18
18
|
import type { TaskSpec } from "../types.js";
|
|
19
19
|
import type { Prepared } from "./contracts.js";
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* The LIMIT-APPROACH frames, the successor to the retired deadline-nudge family. Two facts
|
|
22
22
|
* make them a different mechanism, not a rename:
|
|
23
23
|
* - they are measured in BUDGET (the tightest armed axis's fill ratio), not in wall-clock, so they need
|
|
24
24
|
* no throughput estimate and cannot mis-fire on a starved event loop;
|
|
@@ -36,7 +36,7 @@ export declare function limitApproachFrames(index: 0 | 1, axis: string, percent:
|
|
|
36
36
|
/**
|
|
37
37
|
* Resolve the effective turn cap. `undefined` = no turn cap; `0` (explicit) = unbounded.
|
|
38
38
|
*
|
|
39
|
-
*
|
|
39
|
+
* This is now a pure read of what the caller wrote. The two clauses it used to carry —
|
|
40
40
|
* "a wall-clock bound was set, so drop the turn cap" and "neither was set, so apply the engine's
|
|
41
41
|
* safety net" — are both gone: the axes no longer interact (each binds on its own), and there is no
|
|
42
42
|
* engine-side net to apply. A task with no `maxTurns` has no turn ceiling.
|
|
@@ -88,7 +88,7 @@ export declare function awaitChargeWithSlowDisclosure<T>(charge: Promise<T>, onS
|
|
|
88
88
|
*/
|
|
89
89
|
export declare function raceUntilDeadline<T>(p: Promise<T>, deadline: number): Promise<T | typeof GOVERNANCE_READ_STALLED>;
|
|
90
90
|
/**
|
|
91
|
-
*
|
|
91
|
+
* The TYPED terminal for an external stop cause that could NOT be suspended durably.
|
|
92
92
|
* Carried on `rs.limits.platformTerminal` and adopted as the run's `threw`, so the caller reads the cause
|
|
93
93
|
* on `TaskResult.errorCode` (`errorCodeOf` lifts `.code`) instead of the anonymous error an abort produces.
|
|
94
94
|
* `retryAfterMs` rides the error object because a wait hint has no `TaskResult` seat — a host reads it from
|
|
@@ -5,7 +5,7 @@ import type { Context } from "../../internal/llm.js";
|
|
|
5
5
|
import { type ToolResultStore } from "../tool-result-store.js";
|
|
6
6
|
import type { Prepared } from "./contracts.js";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* The maybeCompact call arguments that MUST be assembled identically on all three
|
|
9
9
|
* of runtask's compaction lanes (turn boundary / prompt-too-long recovery / end-of-task).
|
|
10
10
|
*
|
|
11
11
|
* Those lanes carried three hand-copied assemblies whose own comments said "must not silently
|
|
@@ -30,100 +30,36 @@ import type { Prepared } from "./contracts.js";
|
|
|
30
30
|
*/
|
|
31
31
|
export declare function buildWorkingFileAttachments(spec: TaskSpec, prepared: Prepared): MaybeCompactOptions["workingFileAttachments"];
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* standing instructions every other turn has been reading — and it loses them exactly where the
|
|
37
|
-
* summary REPLACES the transcript that carried them, so the loss is durable.
|
|
33
|
+
* `MaybeCompactOptions.contextInstructionFiles`: the deployment's instruction-file content (the CLAUDE.md
|
|
34
|
+
* family) delivered to the SUMMARIZER, assembled once here and spread on all three lanes — the compaction
|
|
35
|
+
* boundary is where the summary REPLACES the transcript that carried those instructions.
|
|
38
36
|
*
|
|
39
|
-
*
|
|
40
|
-
* the RAW loader text
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* "repository-controlled DATA, not instructions to obey", and this seat hands the same bytes to the
|
|
62
|
-
* summarizer with instruction standing for the summarization task. Delivery THROUGH a host callback
|
|
63
|
-
* is not host AUTHORSHIP: a prior agent, or anyone who can land a commit, can write a
|
|
64
|
-
* "## Compact Instructions" section, and the mint's neutralization stops tag breakout — not a
|
|
65
|
-
* sentence asking for a fact to be left out of the summary that replaces the transcript.
|
|
66
|
-
* Why it is nevertheless this value: the seat's own contract names this path ("hosts pass the same
|
|
67
|
-
* instruction-file content their prompt assembly mounts... on the runner path"), the parity form this
|
|
68
|
-
* channel exists to reach reads the user's and the project's instruction files at every boundary with
|
|
69
|
-
* exactly this standing, and the two alternatives are worse for reasons above rather than better.
|
|
70
|
-
* The standing is also narrower than the framing gap suggests — the section's preamble scopes it to
|
|
71
|
-
* guidance about HOW to summarize and classifies the rest as background — and a deployment that does
|
|
72
|
-
* not want it has two exits that need no code: do not wire the loader, or return content it vouches
|
|
73
|
-
* for. Recorded as an open design candidate rather than built here, because it is a contract change
|
|
74
|
-
* and not a wiring one: a SEPARATE deployment-vouched summarization-instructions seat, leaving
|
|
75
|
-
* repository-derived context at data tier.
|
|
76
|
-
*
|
|
77
|
-
* RULING ① — BOTH summary forms, no per-form split. Fork eligibility is decided per pass INSIDE
|
|
78
|
-
* maybeCompact (main-model-only, recorded-request-present, not lossy), so a call site cannot say
|
|
79
|
-
* "independent form only"; the closest approximation — pass the seat only when `prepared.compModel`
|
|
80
|
-
* is set, since an independent compaction model has no main prefix to fork — leaves the hole the
|
|
81
|
-
* wrong way round: the configuration it does NOT cover (no compaction model) is precisely the one
|
|
82
|
-
* where a fork degrades mid-pass to the independent form, which would then run WITHOUT the files.
|
|
83
|
-
* Feeding both forms closes that case by construction, and the library face already handles the fork
|
|
84
|
-
* half (the section rides the APPENDED instruction message, never the cached prefix, so the fork's
|
|
85
|
-
* whole economic point is untouched).
|
|
86
|
-
*
|
|
87
|
-
* RULING ② — no new size knob. The bound is the library's own `fitContextInstructionFilesSection`
|
|
88
|
-
* (independent form: cap against the compaction model's window, disclosed elision, and a complete
|
|
89
|
-
* yield when not even the framing fits). Its three KNOWN LIMITS are accepted here KNOWINGLY, as the
|
|
90
|
-
* pre-condition of this wiring rather than something it discovered: a token-dense payload (CJK,
|
|
91
|
-
* emoji) can pass a chars-domain fit and still overflow the gateway's tokenizer; an unknown
|
|
92
|
-
* `contextWindow` leaves the section unbounded (the conversation clamp declines to guess there too);
|
|
93
|
-
* and the FORK form cannot fit at all — its bound is a prompt-too-long that degrades ONCE to the
|
|
94
|
-
* independent form, which the engine's own note records as real but NOT total (an oversize rejection
|
|
95
|
-
* the classifier cannot read as prompt-too-long returns terminally instead).
|
|
96
|
-
*
|
|
97
|
-
* HOW BIG THAT ACCEPTANCE ACTUALLY IS — measured, because the sentence above is easy to read more
|
|
98
|
-
* comfortably than it deserves. The fitted form is NOT the default path: when a fork is eligible and
|
|
99
|
-
* the model answers in its envelope, the fork IS the pass, and its section is delivered WHOLE at any
|
|
100
|
-
* size. The independent form — the only one that fits — runs when there is no fork to take or the
|
|
101
|
-
* fork's answer did not conform. Both facts are pinned in the REF-A2 suite (a 55 KB payload: whole on
|
|
102
|
-
* the fork, elided on the independent fallback). And when a limit does bite, the failure is not a
|
|
103
|
-
* quiet degradation: the section is a FIXED part of the request, the reactive retry loop may drop
|
|
104
|
-
* only CONVERSATION groups, so a request the SECTION overflowed cannot converge and the boundary
|
|
105
|
-
* fails — the task loses that compaction (or that prompt-too-long recovery, or its end-of-task
|
|
106
|
-
* summary) rather than sending a shorter one. The exposure is what the wiring widened: this was
|
|
107
|
-
* previously reachable only by hosts calling the library directly, and is now reachable by every
|
|
108
|
-
* deployment that wires `loadProjectMemory` with a large instruction file and an unknown or small
|
|
109
|
-
* window. Making the section participate in the retry loop is the structural answer; it is a change
|
|
110
|
-
* to that loop's contract, tracked at the library face, and a runner-side knob would only move the
|
|
111
|
-
* decision to a place with less information.
|
|
112
|
-
*
|
|
113
|
-
* WHAT IT COSTS, measured rather than rounded: every deployment that wires `loadProjectMemory` now
|
|
114
|
-
* sends its instruction-file content plus EXACTLY 716 chars of framing (the preamble and the fence)
|
|
115
|
-
* on EVERY summarization request, both forms, once per pass — where a real project instruction file
|
|
116
|
-
* in this family runs to tens of KB, so the payload, not the framing, is the bill. The number is
|
|
117
|
-
* pinned in the REF-A2 suite against the engine's own renderer, so a preamble edit shows up as a
|
|
118
|
-
* changed assertion rather than as prose drifting away from the code it describes.
|
|
119
|
-
* Deployments that never wired the loader pay nothing: the key is absent, not
|
|
120
|
-
* `undefined`, so their requests are byte-identical to the pre-wiring shape on the independent and
|
|
121
|
-
* UPDATE passes (the FORK form appends its ~860-char authority clause with or without the seat, and
|
|
122
|
-
* always did).
|
|
37
|
+
* Contract:
|
|
38
|
+
* - Bytes = `Prepared.projectInstructionContent`, the RAW loader text captured under the same non-blank
|
|
39
|
+
* predicate that composes the project layer. Not the assembled `memoryBlock` (model-authored in-band
|
|
40
|
+
* bytes would gain an instructing envelope), not the COMPOSED project block (`contextInstructionFilesSection`
|
|
41
|
+
* neutralizes the whole authority family, `user_memory`/`scope` included), not `instructionSources`
|
|
42
|
+
* (path + hash only). Raw text in, one fence at the mint.
|
|
43
|
+
* - Provenance: REPOSITORY-CONTROLLED text delivered through a host callback — delivery is not authorship;
|
|
44
|
+
* the mint's neutralization stops tag breakout, not a sentence asking for an omission. Two no-code exits
|
|
45
|
+
* for a deployment that does not want it: do not wire the loader, or return vouched content. A separate
|
|
46
|
+
* deployment-vouched summarization-instructions seat is an open design candidate, not built here.
|
|
47
|
+
* - Both summary forms, no per-form split: fork eligibility is decided per pass inside maybeCompact, and the
|
|
48
|
+
* form NOT covered by a `compModel`-gated split is exactly the fork that degrades mid-pass to the
|
|
49
|
+
* independent form; the section rides the APPENDED instruction message, never the cached prefix.
|
|
50
|
+
* - No new size knob: the bound is `fitContextInstructionFilesSection` (independent form only). Its three
|
|
51
|
+
* known limits are accepted knowingly: a token-dense payload can pass a chars-domain fit and still overflow;
|
|
52
|
+
* an unknown `contextWindow` leaves the section unbounded; the FORK form cannot fit and degrades ONCE. When
|
|
53
|
+
* a limit bites the boundary FAILS (the section is a fixed request part the retry loop cannot drop) — the
|
|
54
|
+
* task loses that compaction rather than sending a shorter one; making the section participate in the
|
|
55
|
+
* retry loop is a library-face contract change, tracked there.
|
|
56
|
+
* - Cost: instruction-file content + exactly 716 chars of framing on every summarization request, both
|
|
57
|
+
* forms, once per pass (pinned in the REF-A2 suite). Deployments that never wired the loader pay nothing:
|
|
58
|
+
* the key is ABSENT, so their requests are byte-identical to the pre-wiring shape.
|
|
123
59
|
*/
|
|
124
60
|
export declare function contextInstructionFilesOption(prepared: Prepared): Partial<Pick<MaybeCompactOptions, "contextInstructionFiles">>;
|
|
125
61
|
/**
|
|
126
|
-
*
|
|
62
|
+
* The CC-form fork seam, assembled identically on all three lanes (REF-A2): the
|
|
127
63
|
* summary request forks the main lane's latest real request (recorded by prepare-task's provider
|
|
128
64
|
* shim) instead of re-serializing the conversation into an independent full-price request.
|
|
129
65
|
* `maybeCompact` consults the accessor per pass and only when the summary model IS the main model;
|
|
@@ -135,7 +71,7 @@ export declare function contextInstructionFilesOption(prepared: Prepared): Parti
|
|
|
135
71
|
* clearStale content blanking, the aggregate tool-result/media caps, the orphan sweep), that
|
|
136
72
|
* projection is missing history the summary would PERMANENTLY replace — measured live: a fork of a
|
|
137
73
|
* trimmed request loses the fact-survival suite's fact; a fork of a clearStale'd request summarizes
|
|
138
|
-
* `[tool result cleared …]` markers
|
|
74
|
+
* `[tool result cleared …]` markers. That guard lives at the RECORDING side
|
|
139
75
|
* (prepare-task arms `requestLossyRef` per request build; a lossy request records `undefined`), so
|
|
140
76
|
* every lane degrades to the independent form — which reads the FULL session — automatically.
|
|
141
77
|
*
|
|
@@ -145,12 +81,12 @@ export declare function contextInstructionFilesOption(prepared: Prepared): Parti
|
|
|
145
81
|
*/
|
|
146
82
|
export declare function forkContextOption(prepared: Prepared, disable: boolean): Pick<MaybeCompactOptions, "forkContext">;
|
|
147
83
|
/**
|
|
148
|
-
*
|
|
84
|
+
* Compaction-boundary center-candidate adoption. Absent (an empty object, NOT a
|
|
149
85
|
* `centerAdoption: undefined` key) = restate as before; a boundary re-pin hashes the same artifact
|
|
150
86
|
* identity on every lane.
|
|
151
87
|
*/
|
|
152
88
|
export declare function centerAdoptionOption(prepared: Prepared): Partial<Pick<MaybeCompactOptions, "centerAdoption">>;
|
|
153
|
-
/**
|
|
89
|
+
/** Defaults (object-present, field-absent). Named per the magic-number rule. */
|
|
154
90
|
export declare const STALE_OFFLOAD_DEFAULT_KEEP_RECENT_PER_TOOL = 3;
|
|
155
91
|
export declare const STALE_OFFLOAD_DEFAULT_MIN_SAVINGS_CHARS = 2000;
|
|
156
92
|
/** Resolved (validated, defaulted) knob — see {@link resolveStaleToolResultOffload}. */
|
|
@@ -159,7 +95,7 @@ export interface ResolvedStaleToolResultOffload {
|
|
|
159
95
|
minSavingsChars: number;
|
|
160
96
|
}
|
|
161
97
|
/**
|
|
162
|
-
*
|
|
98
|
+
* Validate + default the spec knob. Fail-loud on non-finite/negative/fractional
|
|
163
99
|
* values (a computed NaN silently re-defaulting is the ||0-fold this repo's engineering code bans);
|
|
164
100
|
* `undefined` knob ⇒ `undefined` (feature completely off).
|
|
165
101
|
*/
|
|
@@ -171,14 +107,14 @@ export declare function resolveStaleToolResultOffload(knob: StaleToolResultOfflo
|
|
|
171
107
|
* crossing the staleness line as newer same-tool results arrive) rewrites that message's bytes
|
|
172
108
|
* once, invalidating the provider cache from that position for one request — a bounded,
|
|
173
109
|
* once-per-result break the `minSavingsChars` floor is there to amortize.
|
|
174
|
-
* Deliberately NOT `offloadPagebackHint` (the
|
|
110
|
+
* Deliberately NOT `offloadPagebackHint` (the preview's hint): that hint's wording is a
|
|
175
111
|
* function of the LIVE reachable-tool set, and this pointer is re-derived per request — a mid-run
|
|
176
112
|
* ToolSearch activation would flip its bytes and break the very prefix stability this file pins.
|
|
177
|
-
* The reader is named by its real mounted name (
|
|
113
|
+
* The reader is named by its real mounted name (`read_tool_result` is a
|
|
178
114
|
* retired alias — a model following it burned a rejected call first). */
|
|
179
115
|
export declare function buildStaleOffloadPointer(toolName: string, ref: string, chars: number): string;
|
|
180
116
|
/**
|
|
181
|
-
*
|
|
117
|
+
* The request-side projection: replace STALE same-tool results with byte-stable
|
|
182
118
|
* pointers. "Stale" = has ≥ `keepRecentPerTool` NEWER results of the same tool name in this request
|
|
183
119
|
* — a monotone predicate (a result never gains "recency" back), so a replacement decision made on
|
|
184
120
|
* one request holds on every later one and re-derivation is deterministic: no run-scoped mutable
|
|
@@ -194,7 +130,7 @@ export declare function buildStaleOffloadPointer(toolName: string, ref: string,
|
|
|
194
130
|
* tool-call ids carry no cross-turn uniqueness contract), readable back via `read_tool_result`.
|
|
195
131
|
*/
|
|
196
132
|
export declare function projectStaleToolResults(context: Context, cfg: ResolvedStaleToolResultOffload, store: ToolResultStore, sessionId: string,
|
|
197
|
-
/** Run-scoped cache of refs already persisted by THIS run
|
|
133
|
+
/** Run-scoped cache of refs already persisted by THIS run: without it the
|
|
198
134
|
* write-once `put` is still re-issued every request — on the file backend that is a
|
|
199
135
|
* write-then-discard round-trip per stale result per turn. Caller owns the Set's lifetime. */
|
|
200
136
|
writtenRefs: Set<string>): Promise<Context>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The run loop's three compaction knobs
|
|
2
|
+
* The run loop's three compaction knobs: the consecutive-failure breaker trip, the anti-thrash
|
|
3
3
|
* regrowth factor and the effective-compaction epsilon. They were declared at the turn-boundary lane and the driver
|
|
4
4
|
* reached DOWN for them; the recovery lane (the forced-compaction pass the prompt-too-long and guard-chain arms
|
|
5
5
|
* share) reads the same three, and a lane may not name a sibling lane — so the three values sank to the machinery
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* lane, and the prefix would put it under the phase-api gate and the run-lanes glob.
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
|
-
* §17.4
|
|
12
|
+
* §17.4: stop attempting within-task compaction after this many CONSECUTIVE
|
|
13
13
|
* failures in one task — a never-recovering summary gateway must not burn an API call at every turn
|
|
14
14
|
* boundary (CC: MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3). Reset on any success; an open breaker also
|
|
15
15
|
* skips the end-of-task attempt in `finish()` (teardown unaffected). Per-task scope.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* This used to say "a flaky/never-recovering gateway", and the word `flaky` was not true. Because
|
|
18
18
|
* any success zeroes the counter, a gateway that alternates never reaches three CONSECUTIVE failures and
|
|
19
19
|
* the breaker never opens; it keeps paying for a call at every failed boundary, indefinitely.
|
|
20
20
|
*
|
|
@@ -37,7 +37,7 @@ export declare const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;
|
|
|
37
37
|
*/
|
|
38
38
|
export declare const COMPACTION_REGROWTH_FACTOR = 1.5;
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* A compaction that frees fewer than this many (structural) tokens is
|
|
41
41
|
* treated as NO-EFFECTIVE-COMPACTION and does NOT raise the anti-thrash floor. Guards against a reused
|
|
42
42
|
* provider summary (or a pathological LLM summary) that reclaims no headroom yet suppresses the next real
|
|
43
43
|
* summary by inflating the floor to trigger×factor.
|
|
@@ -2,17 +2,17 @@ import type { MaybeCompactOptions } from "../auto-compaction.js";
|
|
|
2
2
|
import type { TaskSpec } from "../types.js";
|
|
3
3
|
import type { Prepared, RunnerDepsSeat } from "./contracts.js";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* The cost-optimization compaction options threaded into BOTH `maybeCompact` call
|
|
6
6
|
* sites (within-task turn boundary + `finish()`). All three fields come from `RunnerDeps` (a trusted
|
|
7
7
|
* FUNCTION seam — never `TaskSpec`, which is serializable/durable-resumable/untrusted-caller). The
|
|
8
8
|
* Runner OWNS the consecutive-reuse counter (`prepared.compactionReuseRef`) so the
|
|
9
9
|
* `maxConsecutiveProviderReuse` drift guard spans the whole task across both sites: it FEEDS the current
|
|
10
10
|
* count in as `consecutiveProviderReuse`, and {@link recordCompactionReuse} updates it from the result.
|
|
11
11
|
* Returns `undefined` when no provider is wired (so the call site spreads nothing → byte-identical to
|
|
12
|
-
* the
|
|
12
|
+
* the prior behavior).
|
|
13
13
|
*/
|
|
14
14
|
export declare function seamCCompactionOptions(runner: RunnerDepsSeat, prepared: Prepared): Pick<MaybeCompactOptions, "summaryProvider" | "onCompaction" | "maxConsecutiveProviderReuse" | "consecutiveProviderReuse"> | undefined;
|
|
15
|
-
/**
|
|
15
|
+
/** Resolve the pre/postCompact lifecycle callbacks (whole-slot `spec.hooks ??
|
|
16
16
|
* deps.hooks`, same resolution as the stop hook) and wrap each in a SWALLOW+TRACE shell before
|
|
17
17
|
* threading them into maybeCompact. The wrapper owns the observability half of the R3 MED contract
|
|
18
18
|
* (maybeCompact swallows defensively too, but has no sink): a throwing callback is reported via
|
|
@@ -20,7 +20,7 @@ export declare function seamCCompactionOptions(runner: RunnerDepsSeat, prepared:
|
|
|
20
20
|
* reported as ignored (maybeCompact enforces the ignore — blocking a compaction the provider/trim
|
|
21
21
|
* layer already demanded would kill the run). */
|
|
22
22
|
export declare function compactionHookOptions(runner: RunnerDepsSeat, spec: TaskSpec, sessionId: string, trigger: "auto" | "manual" | "forced",
|
|
23
|
-
/**
|
|
23
|
+
/** The leg's identity envelope, spread onto both compaction contexts by the wrappers
|
|
24
24
|
* below (the compaction module builds its contexts below the runner and cannot know the leg;
|
|
25
25
|
* the wrapper is the runner's seam). Every runner call site supplies `prepared.hookIdentity`;
|
|
26
26
|
* optional only so a context built without a leg stays honestly identity-less. */
|
|
@@ -33,7 +33,7 @@ seatBound?: {
|
|
|
33
33
|
timeoutMs: number;
|
|
34
34
|
signal?: AbortSignal;
|
|
35
35
|
}): Pick<MaybeCompactOptions, "trigger" | "preCompact" | "postCompact">;
|
|
36
|
-
/**
|
|
36
|
+
/** Fold a finished compaction's `reused` flag into the run-scoped consecutive-reuse
|
|
37
37
|
* counter: a reused (provider) summary increments it, a real (LLM) summary resets it to 0. A no-op
|
|
38
38
|
* compaction (`compacted:false`) leaves the counter untouched. No-op when no provider is wired. */
|
|
39
39
|
export declare function recordCompactionReuse(runner: RunnerDepsSeat, prepared: Prepared, comp: {
|