@sema-agent/core 7.53.0 → 7.54.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 +277 -1
- package/LICENSE +3 -1
- package/dist/agents/peer-session-drain.d.ts +0 -1
- package/dist/agents/peer-session-drain.js +0 -2
- package/dist/agents/send-message-tool.js +3 -4
- package/dist/agents/subagent.d.ts +3 -5
- package/dist/agents/subagent.js +18 -11
- package/dist/agents/tool-filter.d.ts +7 -4
- package/dist/agents/tool-filter.js +7 -3
- package/dist/core/a2a.js +4 -2
- package/dist/core/allow-entry.d.ts +1 -0
- package/dist/core/allow-entry.js +1 -0
- package/dist/core/approval-object.d.ts +87 -0
- package/dist/core/approval-object.js +85 -0
- package/dist/core/arg-summary.d.ts +3 -2
- package/dist/core/arg-summary.js +17 -11
- package/dist/core/ask-origin.d.ts +43 -27
- package/dist/core/ask-origin.js +20 -11
- package/dist/core/ask-question.d.ts +0 -1
- package/dist/core/ask-question.js +4 -67
- package/dist/core/ask-unresolvable-notice.d.ts +3 -2
- package/dist/core/auto-compaction.d.ts +49 -50
- package/dist/core/auto-compaction.js +41 -51
- package/dist/core/auto-mode-prompt.d.ts +4 -2
- package/dist/core/auto-mode-prompt.js +4 -3
- package/dist/core/canonical-json.d.ts +69 -0
- package/dist/core/canonical-json.js +130 -8
- package/dist/core/checkpoint-requirements.d.ts +13 -7
- package/dist/core/checkpoint-requirements.js +4 -1
- package/dist/core/checkpoint-store.d.ts +33 -18
- package/dist/core/checkpoint-store.js +5 -4
- package/dist/core/child-clamp-seats.d.ts +45 -6
- package/dist/core/child-clamp-seats.js +56 -4
- package/dist/core/consolidate-scope.d.ts +1 -1
- package/dist/core/cross-boundary-taint.d.ts +213 -0
- package/dist/core/cross-boundary-taint.js +196 -0
- package/dist/core/decision-receipt.d.ts +44 -1
- package/dist/core/decision-receipt.js +16 -0
- package/dist/core/effective-path-target.d.ts +3 -0
- package/dist/core/effective-path-target.js +4 -0
- package/dist/core/engine-notice.d.ts +34 -2
- package/dist/core/engine-notice.js +17 -1
- package/dist/core/engine-storage-backend.d.ts +73 -0
- package/dist/core/engine-storage-backend.js +1 -0
- package/dist/core/file-history-store.d.ts +6 -2
- package/dist/core/file-history-store.js +1 -0
- package/dist/core/gate-fold.js +10 -2
- package/dist/core/gate-lanes.js +30 -21
- package/dist/core/gate-outcome.d.ts +7 -3
- package/dist/core/governance-codes.d.ts +7 -2
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +14 -14
- package/dist/core/hooks.js +1 -2
- package/dist/core/locked-config.d.ts +28 -1
- package/dist/core/locked-config.js +30 -3
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mcp-server-spec.d.ts +66 -9
- package/dist/core/mcp-server-spec.js +52 -19
- package/dist/core/mcp.js +5 -4
- package/dist/core/memory-engine/engine.js +2 -1
- package/dist/core/memory-engine/export-bundle.d.ts +1 -1
- package/dist/core/memory-engine/export-bundle.js +1 -1
- package/dist/core/memory-engine/file-backend.d.ts +2 -6
- package/dist/core/memory-engine/file-backend.js +1 -12
- package/dist/core/memory.d.ts +3 -3
- package/dist/core/mode-policy.d.ts +13 -8
- package/dist/core/mode-policy.js +3 -2
- package/dist/core/mods/kernel/receive.d.ts +2 -1
- package/dist/core/mods/kernel/receive.js +7 -2
- package/dist/core/parent-spec-seat.d.ts +10 -13
- package/dist/core/parent-spec-seat.js +14 -6
- package/dist/core/pause-registry.d.ts +35 -1
- package/dist/core/pause-registry.js +10 -0
- package/dist/core/permission-rule-consent.d.ts +18 -5
- package/dist/core/permission-rule-consent.js +13 -8
- package/dist/core/permission-rule-model.d.ts +29 -6
- package/dist/core/permission-rule-model.js +6 -1
- package/dist/core/permission-rule-org.d.ts +37 -0
- package/dist/core/permission-rule-org.js +34 -42
- package/dist/core/permission-rule-session.js +2 -2
- package/dist/core/permission-rule-store.d.ts +8 -0
- package/dist/core/permission-rule-store.js +1 -0
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/read-only-shell.js +30 -9
- package/dist/core/remote-env.d.ts +41 -1
- package/dist/core/remote-env.js +18 -0
- package/dist/core/resume-startup-cause.d.ts +18 -0
- package/dist/core/resume-startup-cause.js +12 -0
- package/dist/core/runner/approval-feedback.d.ts +46 -0
- package/dist/core/runner/approval-feedback.js +41 -0
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.js +2 -2
- package/dist/core/runner/contracts.d.ts +33 -41
- package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
- package/dist/core/runner/cross-boundary-lane.js +190 -0
- package/dist/core/runner/decide-continuation.d.ts +4 -4
- package/dist/core/runner/decide-continuation.js +3 -1
- package/dist/core/runner/gate-exit.d.ts +32 -12
- package/dist/core/runner/gate-exit.js +75 -33
- package/dist/core/runner/inherited-ask-grants.js +2 -2
- package/dist/core/runner/person-path-rows.d.ts +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
- package/dist/core/runner/prepare-ask-lane.js +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
- package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
- package/dist/core/runner/prepare-config-doors.d.ts +12 -15
- package/dist/core/runner/prepare-config-doors.js +8 -3
- package/dist/core/runner/prepare-context-lane.js +6 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +3 -2
- package/dist/core/runner/prepare-delegation-surface.js +2 -3
- package/dist/core/runner/prepare-execution-env.d.ts +1 -2
- package/dist/core/runner/prepare-execution-env.js +2 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
- package/dist/core/runner/prepare-gate-stations.js +4 -3
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -2
- package/dist/core/runner/prepare-hands-readface.js +1 -1
- package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
- package/dist/core/runner/prepare-inherited-gate.js +1 -0
- package/dist/core/runner/prepare-park-ask.d.ts +1 -1
- package/dist/core/runner/prepare-park-ask.js +9 -3
- package/dist/core/runner/prepare-policy-chain.js +2 -7
- package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
- package/dist/core/runner/prepare-safety-scan.js +34 -27
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
- package/dist/core/runner/prepare-suspend-saga.js +6 -2
- package/dist/core/runner/prepare-task.js +13 -10
- package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
- package/dist/core/runner/prepare-turn-wiring.js +14 -49
- package/dist/core/runner/prepare-wiring-manifest.d.ts +2 -2
- package/dist/core/runner/prepare-wiring-manifest.js +2 -2
- package/dist/core/runner/prepare-workspace-restore.js +2 -2
- package/dist/core/runner/resume-admission.js +9 -9
- package/dist/core/runner/resume-apply.js +4 -4
- package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
- package/dist/core/runner/resume-policy-outcome.js +18 -15
- package/dist/core/runner/resume-preflight.js +2 -2
- package/dist/core/runner/resume-review-outcome.js +3 -3
- package/dist/core/runner/run-leg.js +57 -33
- package/dist/core/runner/run-settle-and-teardown.js +2 -0
- package/dist/core/runner/run-terminal-adoption.js +15 -4
- package/dist/core/runner/session-file-state-replay.d.ts +5 -2
- package/dist/core/runner/session-file-state-replay.js +3 -2
- package/dist/core/runner/stream-steer-verb.js +2 -2
- package/dist/core/runner/tool-face-overlay.d.ts +24 -6
- package/dist/core/runner/tool-face-overlay.js +24 -15
- package/dist/core/runner-deps.d.ts +9 -9
- package/dist/core/session-store.d.ts +35 -16
- package/dist/core/session-store.js +20 -12
- package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
- package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
- package/dist/core/shell-wrapper-table.d.ts +5 -3
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
- package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
- package/dist/core/store-contracts/session-store-contract.js +639 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
- package/dist/core/task-event.d.ts +6 -4
- package/dist/core/task-registry-agent.js +1 -0
- package/dist/core/task-registry-shared.d.ts +5 -0
- package/dist/core/task-registry.d.ts +7 -0
- package/dist/core/task-registry.js +17 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +6 -6
- package/dist/core/tighten-task-spec.d.ts +6 -4
- package/dist/core/tighten-task-spec.js +2 -2
- package/dist/core/tool-catalog-entries.d.ts +1 -1
- package/dist/core/tool-catalog-entries.js +52 -52
- package/dist/core/tool-face-reader.d.ts +49 -0
- package/dist/core/tool-face-reader.js +94 -0
- package/dist/core/tool-face.d.ts +17 -8
- package/dist/core/tool-face.js +1 -0
- package/dist/core/tool-policy.d.ts +64 -23
- package/dist/core/tool-policy.js +62 -56
- package/dist/core/tool-roster.d.ts +46 -28
- package/dist/core/tool-roster.js +91 -14
- package/dist/core/tool-spec-members.js +2 -2
- package/dist/core/tool-spec.d.ts +20 -4
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +24 -2
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +7 -0
- package/dist/core/untrusted-text.js +3 -8
- package/dist/core/user-attachment.d.ts +43 -0
- package/dist/core/user-attachment.js +92 -15
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/harness/types.d.ts +7 -4
- package/dist/engine/llm/types.d.ts +7 -2
- package/dist/engine/llm/types.js +2 -1
- package/dist/engine/session/repo-utils.d.ts +5 -0
- package/dist/engine/session/repo-utils.js +9 -0
- package/dist/engine/session/storage-base.js +2 -2
- package/dist/index.d.ts +23 -9
- package/dist/index.js +19 -8
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +1 -0
- package/dist/orchestration/workflow-governance.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +2 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +3 -0
- package/dist/prompt-assembly/catalog/schema.js +3 -0
- package/dist/prompt-assembly/overlay.js +2 -2
- package/dist/prompt-assembly/select.js +2 -2
- package/dist/prompts/default.d.ts +1 -1
- package/dist/shell/lex.d.ts +87 -8
- package/dist/shell/lex.js +283 -49
- package/dist/stores/file/index.d.ts +8 -6
- package/dist/tools/artifact/artifact-tool.js +10 -0
- package/dist/tools/fs/bash-program-position.d.ts +3 -15
- package/dist/tools/fs/bash-program-position.js +3 -10
- package/dist/tools/fs/bash-readonly-classifier.js +2 -0
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-bash.js +72 -101
- package/dist/tools/fs/fs-read.d.ts +12 -0
- package/dist/tools/fs/fs-read.js +10 -9
- package/dist/tools/fs/fs-shared.d.ts +27 -31
- package/dist/tools/fs/fs-shared.js +12 -15
- package/dist/tools/fs/fs-write.js +1 -1
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/read-deny-home.d.ts +1 -1
- package/dist/tools/fs/read-deny-home.js +5 -4
- package/dist/tools/fs/read-deny.d.ts +16 -3
- package/dist/tools/fs/read-deny.js +12 -9
- package/dist/tools/fs/safety.d.ts +7 -6
- package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
- package/dist/tools/fs/shell-read-bindings.js +15 -16
- package/dist/tools/fs/shell-read-device.js +1 -1
- package/dist/tools/fs/shell-read-plan.js +36 -47
- package/dist/tools/fs/shell-read-word.d.ts +1 -6
- package/dist/tools/fs/shell-read-word.js +2 -20
- package/dist/tools/fs/shell-reentry-text.js +1 -1
- package/dist/tools/web.d.ts +2 -2
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +5654 -5520
- package/wire-changes/core@7.53.0.json +30 -8
- package/wire-changes/core@7.54.0.json +2870 -0
- package/dist/core/shell-scan.d.ts +0 -60
- package/dist/core/shell-scan.js +0 -183
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { readRowBehavior } from "./permission-rule-model.js";
|
|
1
|
+
import { readRowBehavior, RULE_ADD_ORIGINS } from "./permission-rule-model.js";
|
|
2
2
|
import { isValidConsentScope, normalizePersistedRule } from "./permission-rule-store.js";
|
|
3
3
|
function isValidOverlayAdd(add) {
|
|
4
4
|
const a = add;
|
|
5
5
|
if (typeof a?.dot?.actor !== "string" || a.dot.actor === "" || typeof a.dot.counter !== "number" || !Number.isFinite(a.dot.counter))
|
|
6
6
|
return false;
|
|
7
|
-
if (
|
|
7
|
+
if (!RULE_ADD_ORIGINS.some((word) => a.origin === word))
|
|
8
8
|
return false;
|
|
9
9
|
return typeof a.createdAt === "string";
|
|
10
10
|
}
|
|
@@ -45,6 +45,7 @@ import type { PersistedRule, RuleAdd, RuleDot, RuleScope, RuleTombstone } from "
|
|
|
45
45
|
import { type RuleBehavior } from "./permission-rule-model.js";
|
|
46
46
|
import type { RuleSyncDropReason, RuleQuarantineReason } from "./governance-codes.js";
|
|
47
47
|
import type { StoreDurability, StoreFidelity } from "./checkpoint-store.js";
|
|
48
|
+
import type { AssertAllKeysHandled } from "./ask-origin.js";
|
|
48
49
|
/** One store read: the rules as persisted, their tombstones, and the revision they were read at. */
|
|
49
50
|
export interface StoredRules {
|
|
50
51
|
/** Rules with their FULL add sets — tombstoned dots already removed by the backend on read. */
|
|
@@ -92,6 +93,13 @@ export type RuleOwner = {
|
|
|
92
93
|
} | {
|
|
93
94
|
kind: "local-owner";
|
|
94
95
|
};
|
|
96
|
+
/** The owner discriminants as a value: the `kind` words of {@link RuleOwner}, both directions fenced at compile time
|
|
97
|
+
* ({@link RuleOwnerKindsCoverEveryArm} / {@link RuleOwnerArmsCoverEveryKind}). */
|
|
98
|
+
export declare const RULE_OWNER_KINDS: readonly ["principal", "local-owner"];
|
|
99
|
+
/** Compile fence: an arm whose `kind` is not in {@link RULE_OWNER_KINDS} turns the argument into that word. */
|
|
100
|
+
export type RuleOwnerKindsCoverEveryArm = AssertAllKeysHandled<Exclude<RuleOwner["kind"], (typeof RULE_OWNER_KINDS)[number]>>;
|
|
101
|
+
/** Compile fence, the other direction: a word in {@link RULE_OWNER_KINDS} that no arm carries. */
|
|
102
|
+
export type RuleOwnerArmsCoverEveryKind = AssertAllKeysHandled<Exclude<(typeof RULE_OWNER_KINDS)[number], RuleOwner["kind"]>>;
|
|
95
103
|
/** Do two owners name the same bucket? */
|
|
96
104
|
export declare function sameRuleOwner(a: RuleOwner, b: RuleOwner): boolean;
|
|
97
105
|
/** Resolves one owner's durable partition. `undefined` ⇒ a partition that reports zero rules. This is
|
|
@@ -3,6 +3,7 @@ import { canonicalize } from "./canonical-json.js";
|
|
|
3
3
|
import { escapeForDisclosure, isRuleBehavior, isRuleLive, parseRuleText } from "./permission-rule-model.js";
|
|
4
4
|
import { thrownText } from "./thrown-value.js";
|
|
5
5
|
import { validatePath } from "./effective-path-target.js";
|
|
6
|
+
export const RULE_OWNER_KINDS = Object.freeze(["principal", "local-owner"]);
|
|
6
7
|
export function sameRuleOwner(a, b) {
|
|
7
8
|
return a.kind === "principal" ? b.kind === "principal" && a.principal === b.principal : b.kind === "local-owner";
|
|
8
9
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { escapeForDisclosure, isRuleBehavior, parseRuleText } from "./permission-rule-model.js";
|
|
1
|
+
import { escapeForDisclosure, isRuleBehavior, parseRuleText, RULE_ADD_ORIGINS } from "./permission-rule-model.js";
|
|
2
2
|
import { applyTombstones, errText, isProjectScopeRoot, joinFrontiers, joinRuleStates, normalizePersistedRule, readRuleWriteOutcome, ruleSyncVector, sameRuleIdentity, screenRuleSyncState, writerOf, } from "./permission-rule-store.js";
|
|
3
3
|
import { emitTrace } from "./trace.js";
|
|
4
4
|
export const PERMISSION_RULE_SYNC_PATH = "/v1/permission-rules/sync";
|
|
@@ -273,6 +273,7 @@ function pickScopeCaptured(v) {
|
|
|
273
273
|
function pickScope(v) {
|
|
274
274
|
return pickScopeCaptured(v).scope;
|
|
275
275
|
}
|
|
276
|
+
const isRuleAddOrigin = (v) => RULE_ADD_ORIGINS.some((word) => v === word);
|
|
276
277
|
function pickAdd(v) {
|
|
277
278
|
const a = v;
|
|
278
279
|
const dot = pickDot(a?.dot);
|
|
@@ -280,7 +281,7 @@ function pickAdd(v) {
|
|
|
280
281
|
const createdAt = a?.createdAt;
|
|
281
282
|
if (dot === undefined)
|
|
282
283
|
return undefined;
|
|
283
|
-
if (origin
|
|
284
|
+
if (!isRuleAddOrigin(origin))
|
|
284
285
|
return undefined;
|
|
285
286
|
if (typeof createdAt !== "string")
|
|
286
287
|
return undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ShellCommandShape } from "./shell-
|
|
1
|
+
import { type ShellCommandShape } from "./shell-run-candidates.js";
|
|
2
2
|
import { type LineDescriptors } from "../tools/fs/shell-read-device.js";
|
|
3
3
|
/** The reader's answer: read-only, or not — with the first reason the reading stopped on (a sentence a
|
|
4
4
|
* trace or a card can show; never adjudication input). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
|
-
import { readShellCommand } from "./shell-
|
|
2
|
+
import { lexedWordOf, readShellCommand } from "./shell-run-candidates.js";
|
|
3
3
|
import { descriptorsOfPlan, newLineDescriptors, standardDeviceUnrebound } from "../tools/fs/shell-read-device.js";
|
|
4
4
|
import { planShellReads } from "../tools/fs/shell-read-plan.js";
|
|
5
5
|
import { writesOnlyStandardDevices } from "../tools/fs/shell-read-write-targets.js";
|
|
@@ -33,8 +33,7 @@ const TABLE_ROWS = Object.entries(READ_ONLY_COMMAND_TABLE)
|
|
|
33
33
|
.map(([key, row]) => ({ words: key.split(" "), row }))
|
|
34
34
|
.sort((a, b) => b.words.length - a.words.length);
|
|
35
35
|
const READING_REDIRECTS = new Set(["<", "<<", "<<-", "<&", "<<<"]);
|
|
36
|
-
const
|
|
37
|
-
const ASSIGNMENT_NAME = /^([A-Za-z_][A-Za-z0-9_]*)(?:\[[^\]]*\])?\+?=/;
|
|
36
|
+
const BARE_VALUE_CHARACTERS = /^[A-Za-z0-9_./:+-]*$/;
|
|
38
37
|
const FLAG_WORD = /^-[a-zA-Z0-9_-]/;
|
|
39
38
|
const NUMBER_LITERAL = /^[-+]?(0[xX][0-9a-fA-F]+|[0-9]+#[0-9a-zA-Z]+|[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)$/;
|
|
40
39
|
const PRINTF_LENGTH = "[lLhqjzZt]*";
|
|
@@ -90,20 +89,42 @@ export function readOnlyLineObjection(command, cwd) {
|
|
|
90
89
|
return lineStructureObjection(shape) ?? (changesDirectoryBeforeGit(shape, cwd) ? CD_GIT_REASON : undefined);
|
|
91
90
|
}
|
|
92
91
|
function expansionKind(w) {
|
|
92
|
+
const lexed = lexedWordOf(w);
|
|
93
|
+
if (lexed !== undefined && (lexed.unresolved !== undefined || lexed.quotedSpans.some((s) => s.by === "$'")))
|
|
94
|
+
return "variable";
|
|
93
95
|
if (w.expands === false)
|
|
94
96
|
return "none";
|
|
95
|
-
if (
|
|
97
|
+
if (lexed === undefined)
|
|
98
|
+
return "variable";
|
|
99
|
+
const computed = (e) => VALUE_EXPANSIONS.has(e.kind) || e.inner?.some(computed) === true;
|
|
100
|
+
if (lexed.expansions.some((p) => p.expansion !== undefined && computed(p.expansion)))
|
|
96
101
|
return "variable";
|
|
97
102
|
if (w.expands === "many")
|
|
98
103
|
return "glob";
|
|
99
104
|
return "none";
|
|
100
105
|
}
|
|
106
|
+
const VALUE_EXPANSIONS = new Set(["parameter", "command", "process", "arithmetic"]);
|
|
101
107
|
function leadingAssignmentCount(argv) {
|
|
102
108
|
let k = 0;
|
|
103
|
-
while (k < argv.length &&
|
|
109
|
+
while (k < argv.length && lexedWordOf(argv[k])?.assignment?.bare === true)
|
|
104
110
|
k++;
|
|
105
111
|
return k;
|
|
106
112
|
}
|
|
113
|
+
function literalAssignmentValue(a) {
|
|
114
|
+
if (a.subscript !== undefined || a.form !== "scalar" || a.value.unresolved !== undefined || a.value.expansions.length > 0)
|
|
115
|
+
return false;
|
|
116
|
+
const [only, ...rest] = a.value.pieces;
|
|
117
|
+
if (only === undefined)
|
|
118
|
+
return true;
|
|
119
|
+
if (rest.length > 0 || only.literal === undefined)
|
|
120
|
+
return false;
|
|
121
|
+
if (only.quotedBy === undefined)
|
|
122
|
+
return BARE_VALUE_CHARACTERS.test(only.literal);
|
|
123
|
+
const oneRegion = a.value.raw.length === only.literal.length + 2;
|
|
124
|
+
if (only.quotedBy === "'")
|
|
125
|
+
return oneRegion;
|
|
126
|
+
return only.quotedBy === '"' && oneRegion && !/[$`\\]/.test(only.literal);
|
|
127
|
+
}
|
|
107
128
|
function peelBuiltinPrefix(words) {
|
|
108
129
|
let t = words;
|
|
109
130
|
for (;;) {
|
|
@@ -142,11 +163,11 @@ function segmentVerdict(seg, line, bindings) {
|
|
|
142
163
|
}
|
|
143
164
|
const k = leadingAssignmentCount(seg.argv);
|
|
144
165
|
for (const w of seg.argv.slice(0, k)) {
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
166
|
+
const a = lexedWordOf(w).assignment;
|
|
167
|
+
if (!literalAssignmentValue(a))
|
|
147
168
|
return NOT(`the assignment \`${w.raw}\` is not a literal value`);
|
|
148
|
-
if (!ENV_NAMES.has(
|
|
149
|
-
return NOT(`the environment variable \`${
|
|
169
|
+
if (!ENV_NAMES.has(a.name))
|
|
170
|
+
return NOT(`the environment variable \`${a.name}\` can alter what a program does`);
|
|
150
171
|
}
|
|
151
172
|
const run = seg.argv.slice(k);
|
|
152
173
|
if (run.length === 0)
|
|
@@ -66,6 +66,19 @@ export interface WorkspaceHandle {
|
|
|
66
66
|
*/
|
|
67
67
|
deviceId?: string;
|
|
68
68
|
}
|
|
69
|
+
/** The one list of what a {@link WorkspaceHandle} is: every member the interface declares. */
|
|
70
|
+
export declare const WORKSPACE_HANDLE_MEMBERS: ReadonlyArray<keyof WorkspaceHandle>;
|
|
71
|
+
/**
|
|
72
|
+
* A frozen copy of `handle` holding exactly the declared members it carries as strings: shallow-frozen, which is deep here
|
|
73
|
+
* because every member is a string (a decoration or a function member of the source never reaches the copy), and no
|
|
74
|
+
* structured-clone step to fail on an exotic value. Each member is read the way the engine's own handle comparison reads it.
|
|
75
|
+
*
|
|
76
|
+
* ONE copy per live handle: a second call for the same object answers the copy the first call made (the members are read
|
|
77
|
+
* once), so every place the engine hands a checkpointed handle to the outside — the resume preflight's facts, the env
|
|
78
|
+
* factory's {@link ExecutionEnvFactoryContext.resumeWorkspace}, the restore's {@link VmLifecycleOptions.priorHandle} —
|
|
79
|
+
* delivers the same object, not three renderings of one fact.
|
|
80
|
+
*/
|
|
81
|
+
export declare function frozenHandleCopy(handle: WorkspaceHandle): Readonly<WorkspaceHandle>;
|
|
69
82
|
/**
|
|
70
83
|
* A reference to a secret injected at {@link RemoteExecutionEnv.connect}/{@link RemoteExecutionEnv.postResumeInit}
|
|
71
84
|
* time (design/48 §5 gap 7) — never baked into the image. The control plane resolves {@link ref} to a value out of
|
|
@@ -114,8 +127,12 @@ export interface VmLifecycleOptions {
|
|
|
114
127
|
* handle (never echo `priorHandle.mountPath` unhonored) — the engine compares the two and surfaces a
|
|
115
128
|
* divergence observation. Absent on non-resume ops and from pre-1.360 engines (adapters treat absence
|
|
116
129
|
* as the legacy current-config behavior).
|
|
130
|
+
*
|
|
131
|
+
* A frozen copy holding exactly the declared members ({@link WORKSPACE_HANDLE_MEMBERS}) the checkpoint row carries
|
|
132
|
+
* as strings — the SAME object the env factory's {@link ExecutionEnvFactoryContext.resumeWorkspace} was, for the
|
|
133
|
+
* same row — not the stored row's own object: writing to it throws, and a decoration on the stored handle is absent.
|
|
117
134
|
*/
|
|
118
|
-
priorHandle?: WorkspaceHandle
|
|
135
|
+
priorHandle?: Readonly<WorkspaceHandle>;
|
|
119
136
|
}
|
|
120
137
|
/**
|
|
121
138
|
* One chunk streamed from {@link RemoteExecutionEnv.execStream} (design/48 §5 gap 3, council BUG#3). A run is a
|
|
@@ -494,6 +511,29 @@ export interface ExecutionEnvFactoryContext {
|
|
|
494
511
|
* already shares the parent env (and its cwd).
|
|
495
512
|
*/
|
|
496
513
|
parentCwd?: string;
|
|
514
|
+
/**
|
|
515
|
+
* design/380 O1 delivery fence — the workspace a DURABLE RESUME leg is rebuilding: a frozen copy of the
|
|
516
|
+
* {@link WorkspaceHandle} the checkpoint row recorded at suspend, holding exactly the members a handle declares
|
|
517
|
+
* ({@link WORKSPACE_HANDLE_MEMBERS}) that the row carries as strings. Present ONLY on that leg — the key is
|
|
518
|
+
* absent (not an `undefined` value) on every fresh run, and on a resume whose row recorded no workspace
|
|
519
|
+
* handle. Mutating the copy reaches nothing the engine reads.
|
|
520
|
+
*
|
|
521
|
+
* A factory bound to a target (the device lane) **MUST** mint the env on the device
|
|
522
|
+
* `resumeWorkspace.deviceId` names and, when it cannot (offline, busy, the placement moved to another
|
|
523
|
+
* device), **THROW** a typed refusal. It **MUST NOT** connect some other device and leave the engine to
|
|
524
|
+
* notice, and it **MUST NOT** look the current binding up afresh from {@link placementRootSessionId} for
|
|
525
|
+
* this leg. A row recorded without `deviceId` (a non-device lane, or a row older than the field) states no
|
|
526
|
+
* device to honor; the factory then follows its ordinary routing.
|
|
527
|
+
*
|
|
528
|
+
* The minted env's `workspaceHandle()` **MUST** report the device its connection actually reached; it is
|
|
529
|
+
* never copied from `resumeWorkspace`. The engine's comparison of that report against the row (`provider`
|
|
530
|
+
* equal; `deviceId` equal whenever the row carries one) stays as the receipt check and TRUSTS the report: a
|
|
531
|
+
* factory that connected elsewhere and reports so is refused (`resume.env_failed`), only after the wrong
|
|
532
|
+
* connection was made, but one that echoes the fence while connecting elsewhere defeats its own protection
|
|
533
|
+
* and passes. The fence moves no refusal earlier than it was: it runs after the claim, so what a deployment
|
|
534
|
+
* can still catch BEFORE the claim is `RunnerDeps.resumePreflight` alone.
|
|
535
|
+
*/
|
|
536
|
+
resumeWorkspace?: Readonly<WorkspaceHandle>;
|
|
497
537
|
}
|
|
498
538
|
/**
|
|
499
539
|
* A **trusted control-plane** factory that mints a per-task {@link ExecutionEnv} (design/48 §5 answers core
|
package/dist/core/remote-env.js
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
const WORKSPACE_HANDLE_MEMBER_TABLE = { sandboxId: 1, provider: 1, mountPath: 1, snapshotId: 1, sessionToken: 1, restoreMode: 1, deviceId: 1 };
|
|
2
|
+
export const WORKSPACE_HANDLE_MEMBERS = Object.keys(WORKSPACE_HANDLE_MEMBER_TABLE);
|
|
3
|
+
const FROZEN_COPY_OF = new WeakMap();
|
|
4
|
+
export function frozenHandleCopy(handle) {
|
|
5
|
+
const known = FROZEN_COPY_OF.get(handle);
|
|
6
|
+
if (known !== undefined)
|
|
7
|
+
return known;
|
|
8
|
+
const copy = {};
|
|
9
|
+
for (const member of WORKSPACE_HANDLE_MEMBERS) {
|
|
10
|
+
const value = handle[member];
|
|
11
|
+
if (typeof value === "string")
|
|
12
|
+
copy[member] = value;
|
|
13
|
+
}
|
|
14
|
+
const frozen = Object.freeze(copy);
|
|
15
|
+
if (typeof handle === "object" && handle !== null)
|
|
16
|
+
FROZEN_COPY_OF.set(handle, frozen);
|
|
17
|
+
return frozen;
|
|
18
|
+
}
|
|
1
19
|
export const RETRYABLE_REMOTE_ERROR_CODES = [
|
|
2
20
|
"auth_transient",
|
|
3
21
|
"connect_failed",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* unsafe payload, an input the constraints refuse): correct the decision and resubmit.
|
|
24
24
|
*/
|
|
25
25
|
import type { AssertAllKeysHandled } from "./ask-origin.js";
|
|
26
|
+
import type { TerminalFailureDetail } from "./terminal-cause.js";
|
|
26
27
|
/**
|
|
27
28
|
* design/80 D-1: why a consumed checkpoint was {@link import("./checkpoint-store.js").CheckpointStore.reopen | reopened}
|
|
28
29
|
* (resolved → pending). The reason drives re-resume validation (§3 invariant #1): an `env_failed` reopen is a SYSTEM
|
|
@@ -51,6 +52,23 @@ export type ResumeStartupCause = (typeof RESUME_STARTUP_CAUSES)[number];
|
|
|
51
52
|
/** The cause a resume failure's code names; `undefined` when the code is absent or the table does not
|
|
52
53
|
* name it. Every `config.*` code is a configuration door's refusal. */
|
|
53
54
|
export declare function resumeStartupCauseOf(code: string | undefined): ResumeStartupCause | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* The members of a resume refusal's `detail` the parked-resume receipt carries beside its `cause` — the three a
|
|
57
|
+
* {@link import("./checkpoint-store.js").CheckpointError} states where its `code` alone does not say which input or which arm refused:
|
|
58
|
+
* `code` (on `checkpoint.config_refused`: prepare's own code, the word a fresh run of the same bad config reports), `field` (which
|
|
59
|
+
* input carries the refusal) and `reason` (which arm fired). Their words are those families' own; the receipt adds no word of its own.
|
|
60
|
+
*/
|
|
61
|
+
export declare const RESUME_REFUSAL_MEMBERS: readonly ["code", "field", "reason"];
|
|
62
|
+
/** {@link RESUME_REFUSAL_MEMBERS} as the receipt carries them: each a string, each present only when the failure stated it. */
|
|
63
|
+
export type ResumeRefusalDetail = {
|
|
64
|
+
readonly [K in (typeof RESUME_REFUSAL_MEMBERS)[number]]?: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* The refusal members a failed resume stated, read from the failure's coded account ({@link TerminalFailureDetail}, `kind: "coded"`:
|
|
68
|
+
* the `detail` its throw site stated) — never from its sentence. `undefined` when the failure carries no coded account or none of
|
|
69
|
+
* the three members is a string in it.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resumeRefusalDetailOf(account: TerminalFailureDetail | undefined): ResumeRefusalDetail | undefined;
|
|
54
72
|
declare const REOPEN_REASON_OF_CAUSE: {
|
|
55
73
|
readonly environment: "env_failed";
|
|
56
74
|
readonly session_gone: "env_failed";
|
|
@@ -21,6 +21,18 @@ export function resumeStartupCauseOf(code) {
|
|
|
21
21
|
return undefined;
|
|
22
22
|
return CAUSE_OF_CODE.get(code) ?? (code.startsWith("config.") ? "configuration" : undefined);
|
|
23
23
|
}
|
|
24
|
+
export const RESUME_REFUSAL_MEMBERS = Object.freeze(["code", "field", "reason"]);
|
|
25
|
+
export function resumeRefusalDetailOf(account) {
|
|
26
|
+
if (account === undefined || account.kind !== "coded")
|
|
27
|
+
return undefined;
|
|
28
|
+
const out = {};
|
|
29
|
+
for (const member of RESUME_REFUSAL_MEMBERS) {
|
|
30
|
+
const value = Object.hasOwn(account.detail, member) ? account.detail[member] : undefined;
|
|
31
|
+
if (typeof value === "string")
|
|
32
|
+
out[member] = value;
|
|
33
|
+
}
|
|
34
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
35
|
+
}
|
|
24
36
|
const REOPEN_REASON_OF_CAUSE = {
|
|
25
37
|
environment: "env_failed",
|
|
26
38
|
session_gone: "env_failed",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the approving person wrote on the card ({@link ResumeOutcome} `policy_ask` `allow` `feedback`) — the one place that
|
|
3
|
+
* says what counts as written, which decide may carry it, and how it joins the resume continuation.
|
|
4
|
+
*
|
|
5
|
+
* ONE READING of "did the person write anything" ({@link writtenFeedback}): the text with the whitespace the card's input does
|
|
6
|
+
* not keep removed, or nothing when that leaves nothing. The pre-CAS checks and the continuation both ask it, so they cannot
|
|
7
|
+
* disagree about a blank value. (A deny's `reason` keeps its own rule, `decidersNote`: only `""` is blank there.)
|
|
8
|
+
*
|
|
9
|
+
* The words ride the resume continuation user message — the first message after the batch's tool results, once the batch's
|
|
10
|
+
* unanswered siblings have settled — as a user-lane range of their own: outside every engine segment, so a derived view reads
|
|
11
|
+
* them as user speech; verbatim, no fence, no wrapper sentence, no length bound. They are owed with the rest of the
|
|
12
|
+
* continuation: when the batch parks again before the prompt lands they ride the new row as its last parked steer.
|
|
13
|
+
*/
|
|
14
|
+
import { type PendingSteerEntry, type ResumeOutcome } from "../checkpoint-store.js";
|
|
15
|
+
type PolicyAsk = Extract<ResumeOutcome, {
|
|
16
|
+
gate: "policy_ask";
|
|
17
|
+
}>;
|
|
18
|
+
/** The words as the model is to read them, or `undefined` when nothing was written (absent, empty, whitespace-only). */
|
|
19
|
+
export declare function writtenFeedback(feedback: string | undefined): string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Pre-CAS: a WRITTEN feedback is the allow arm's, a person's, and free of the `<system-reminder>` tag (opening or closing — the one
|
|
22
|
+
* judge `sanitizeUntrustedText`, the same rule a deny's `reason` is held to, applied here by the same call). Each is refused
|
|
23
|
+
* (`checkpoint.invalid_outcome`, the row stays pending for a well-formed decide) rather than dropped or delivered as something it
|
|
24
|
+
* is not: a deny's words are `reason`, and a machine's text must never reach the model as the user's. The twin is the captured
|
|
25
|
+
* plain data (its text already held to the string domain by the capture), never the caller's object.
|
|
26
|
+
*/
|
|
27
|
+
export declare function refuseUnfitFeedback(twin: PolicyAsk): void;
|
|
28
|
+
/** The words this resume is to deliver: a person's `allow` carrying a written feedback (the pre-CAS checks have run), else `undefined`. */
|
|
29
|
+
export declare function approvalWordsOf(outcome: ResumeOutcome): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The continuation with the words as its last range. The separator glue before them is engine bytes (its own segment), so the
|
|
32
|
+
* stored message's user-lane range is exactly the words. Appends to `engineSegments` in place; the caller owns both.
|
|
33
|
+
*/
|
|
34
|
+
export declare function withApprovalWords(continuation: string, engineSegments: Array<{
|
|
35
|
+
start: number;
|
|
36
|
+
end: number;
|
|
37
|
+
}>, words: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* The words as the continuation's owed content: the last parked steer, an untrusted one (the carrier that exists for an owed instruction).
|
|
40
|
+
* The frame is remembered by identity ({@link isApprovalWordsFrame}) — never by a member, which the steer store would refuse as an unknown
|
|
41
|
+
* key — so the owed account can count it as what it is (`detail.kind: "approval_feedback"`) and tell a recoverable retry from a loss.
|
|
42
|
+
*/
|
|
43
|
+
export declare function owedApprovalWords(words: string | undefined, inputId: string): Array<Omit<PendingSteerEntry, "seq">>;
|
|
44
|
+
/** Whether `frame` is one {@link owedApprovalWords} minted. */
|
|
45
|
+
export declare function isApprovalWordsFrame(frame: object): boolean;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { CheckpointError } from "../checkpoint-store.js";
|
|
2
|
+
import { sanitizeUntrustedText, sentinelTagRefusal } from "../untrusted-text.js";
|
|
3
|
+
export function writtenFeedback(feedback) {
|
|
4
|
+
const trimmed = feedback?.trim();
|
|
5
|
+
return trimmed === undefined || trimmed === "" ? undefined : trimmed;
|
|
6
|
+
}
|
|
7
|
+
export function refuseUnfitFeedback(twin) {
|
|
8
|
+
const words = writtenFeedback(twin.feedback);
|
|
9
|
+
if (words === undefined)
|
|
10
|
+
return;
|
|
11
|
+
if (twin.decision !== "allow") {
|
|
12
|
+
throw new CheckpointError("checkpoint.invalid_outcome", "resume carried `feedback` on a `deny` — feedback is the approving person's words on an `allow` (a denial's words are `reason`); refusing rather than dropping it silently, the checkpoint stays pending");
|
|
13
|
+
}
|
|
14
|
+
const byPerson = twin.hostDecision.decidedBy === "person";
|
|
15
|
+
if (!byPerson) {
|
|
16
|
+
throw new CheckpointError("checkpoint.invalid_outcome", `resume carried \`feedback\` on a decide made by "${twin.hostDecision.decidedBy}" — feedback is delivered to the model as the user's own words, which only a person's decide can be; refusing rather than attributing a machine's text to the user, the checkpoint stays pending`);
|
|
17
|
+
}
|
|
18
|
+
if (sanitizeUntrustedText(words) !== words) {
|
|
19
|
+
throw new CheckpointError("checkpoint.invalid_outcome", sentinelTagRefusal("resume allow feedback"));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function approvalWordsOf(outcome) {
|
|
23
|
+
return outcome.gate === "policy_ask" && outcome.decision === "allow" ? writtenFeedback(outcome.feedback) : undefined;
|
|
24
|
+
}
|
|
25
|
+
export function withApprovalWords(continuation, engineSegments, words) {
|
|
26
|
+
const glueStart = continuation.length;
|
|
27
|
+
const withGlue = `${continuation}\n\n`;
|
|
28
|
+
engineSegments.push({ start: glueStart, end: withGlue.length });
|
|
29
|
+
return withGlue + words;
|
|
30
|
+
}
|
|
31
|
+
const APPROVAL_WORDS_FRAMES = new WeakSet();
|
|
32
|
+
export function owedApprovalWords(words, inputId) {
|
|
33
|
+
if (words === undefined)
|
|
34
|
+
return [];
|
|
35
|
+
const frame = { text: words, trusted: false, inputId };
|
|
36
|
+
APPROVAL_WORDS_FRAMES.add(frame);
|
|
37
|
+
return [frame];
|
|
38
|
+
}
|
|
39
|
+
export function isApprovalWordsFrame(frame) {
|
|
40
|
+
return APPROVAL_WORDS_FRAMES.has(frame);
|
|
41
|
+
}
|
|
@@ -23,13 +23,13 @@ import { type CompactionSettings } from "../../internal/harness.js";
|
|
|
23
23
|
* because reading it at the moment of the pass — not at prepare — is the whole of what it states.
|
|
24
24
|
*/
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* The post-compaction restore (LONGRUN-2; the reference's post-compact file restore, cli296.js:249523 `attachments`).
|
|
27
27
|
*
|
|
28
28
|
* CC parity: post-compact file re-read is DEFAULT ON (CC hard-codes it;
|
|
29
29
|
* LONGRUN-2 measured ≈2.3 extra read round-trips per compaction without it). `false` opts out; an
|
|
30
30
|
* object customizes caps. Selection set = most recently READ (CC readFileState semantics) with a
|
|
31
|
-
* modified-files fallback inside maybeCompact. Returns `undefined` when
|
|
32
|
-
* task has no hands (no `
|
|
31
|
+
* modified-files fallback inside maybeCompact. Returns `undefined` when the restore is off or the
|
|
32
|
+
* task has no hands (no `compactionRestore` ⇒ nothing can be re-read).
|
|
33
33
|
*/
|
|
34
34
|
export declare function buildWorkingFileAttachments(spec: TaskSpec, prepared: Prepared): MaybeCompactOptions["workingFileAttachments"];
|
|
35
35
|
/**
|
|
@@ -3,10 +3,10 @@ import { buildToolResultRef, OFFLOAD_TOOL_NAME, PERSISTED_OUTPUT_PREFIX, toolRes
|
|
|
3
3
|
import { compactionEnabled, contextOverlayFor } from "../context-settings.js";
|
|
4
4
|
import { DEFAULT_COMPACTION_SETTINGS } from "../../internal/harness.js";
|
|
5
5
|
export function buildWorkingFileAttachments(spec, prepared) {
|
|
6
|
-
if (spec.compaction?.attachWorkingFiles === false || !prepared.
|
|
6
|
+
if (spec.compaction?.attachWorkingFiles === false || !prepared.compactionRestore)
|
|
7
7
|
return undefined;
|
|
8
8
|
return {
|
|
9
|
-
|
|
9
|
+
...prepared.compactionRestore,
|
|
10
10
|
...(prepared.recentlyReadFiles ? { recentlyReadFiles: prepared.recentlyReadFiles } : {}),
|
|
11
11
|
...(prepared.normalizeAttachmentPath ? { normalizePath: prepared.normalizeAttachmentPath } : {}),
|
|
12
12
|
...(prepared.isDedupStubResult ? { isDedupStubResult: prepared.isDedupStubResult } : {}),
|
|
@@ -234,7 +234,7 @@ export interface FrameReceipt {
|
|
|
234
234
|
text: string;
|
|
235
235
|
/** Which frame this receipt settles. A boundary collector must not render a listing whose receipt is
|
|
236
236
|
* still pending (the frame is queued, not yet in the transcript). */
|
|
237
|
-
source: "git_status" | "agent_listing" | "skills_listing" | "date_change" | "output_style";
|
|
237
|
+
source: "git_status" | "agent_listing" | "skills_listing" | "date_change" | "output_style" | "approval_feedback";
|
|
238
238
|
/** Runs inside the `message_end` walk (synchronous, never awaited): advances the run-local record
|
|
239
239
|
* and parks any session write for the next serialization point. */
|
|
240
240
|
commit: (entryId: string) => void;
|
|
@@ -396,17 +396,15 @@ export interface Prepared {
|
|
|
396
396
|
effectiveReadFace?: ContainmentFace;
|
|
397
397
|
/** owned — the same observation on the WRITE seat (`TaskResult.effectiveWriteFace`). */
|
|
398
398
|
effectiveWriteFace?: ContainmentFace;
|
|
399
|
-
/** The normalized deny ADDITIONS in force (deployment ∪ task ∪ checkpoint seed; built-ins
|
|
400
|
-
*
|
|
401
|
-
* copy (the wide-scope working array stays the engine's own). */
|
|
399
|
+
/** The normalized deny ADDITIONS in force (deployment ∪ task ∪ checkpoint seed; built-ins excluded), echoed on
|
|
400
|
+
* `TaskResult.effectiveReadDenyPatterns`. Present iff non-empty; a defensive copy (the working array stays the engine's). */
|
|
402
401
|
effectiveReadDenyPatterns?: readonly import("../../tools/fs/read-deny.js").NormalizedReadDenyEntry[];
|
|
403
402
|
/** The memory-visibility observation prepareMemory minted (echoed on
|
|
404
403
|
* `TaskResult.effectiveMemoryScopes`). Always present on a completed prepare (the memory-less
|
|
405
404
|
* states are their own values); the seat is optional only so a Prepared shape without the phase
|
|
406
405
|
* cannot fabricate one. */
|
|
407
406
|
effectiveMemoryScopes?: import("../types.js").EffectiveMemoryScopes;
|
|
408
|
-
/** The per-task logical cwd ref when a real shell is mounted (else undefined)
|
|
409
|
-
* reads `cwdRef.current` after each tool to detect a `cd` move and emit `workspace_changed`. */
|
|
407
|
+
/** The per-task logical cwd ref when a real shell is mounted (else undefined); read after each tool for `workspace_changed`. */
|
|
410
408
|
cwdRef?: CwdRef;
|
|
411
409
|
/** The root the hand tools resolve root-relative spellings against (present with hands; read-only hands included). */
|
|
412
410
|
handsRoot?: string;
|
|
@@ -478,6 +476,11 @@ export interface Prepared {
|
|
|
478
476
|
* admission died with that leg, so the resumed bytes are judged (and admitted for their pre-spawn re-establishment)
|
|
479
477
|
* on THIS leg — a deny row found now vetoes, an operator's edit is judged on the `rejudge` seat. */
|
|
480
478
|
shellReadCheck?: import("../../tools/fs/shell-read-check.js").ShellReadCheck;
|
|
479
|
+
crossBoundary?: {
|
|
480
|
+
readonly check: import("../cross-boundary-taint.js").CrossBoundaryCheck | undefined;
|
|
481
|
+
settle(): Promise<void>;
|
|
482
|
+
storeWaits(): number;
|
|
483
|
+
};
|
|
481
484
|
/** The ORG adjudication face, re-resolved on a durable RESUME before an approved
|
|
482
485
|
* pending call executes. The resume path bypasses the harness gate by design (a human already
|
|
483
486
|
* adjudicated the checkpointed call), which is exactly where org policy skew is most likely: the
|
|
@@ -1004,56 +1007,42 @@ export interface Prepared {
|
|
|
1004
1007
|
* calls themselves never pass through the recorded seam (they ride the separate compaction-brain
|
|
1005
1008
|
* wrapper), so the snapshot is never polluted by a summary request. */
|
|
1006
1009
|
lastBrainContext: () => CompactionForkContext | undefined;
|
|
1007
|
-
/**
|
|
1008
|
-
*
|
|
1009
|
-
* the
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
|
|
1013
|
-
* skip: a silently missing attachment reads as "file gone", which is a different fact). */
|
|
1014
|
-
readTaskFile?: (path: string) => Promise<string | null | {
|
|
1015
|
-
withheld: {
|
|
1016
|
-
pattern: string;
|
|
1017
|
-
};
|
|
1018
|
-
}>;
|
|
1010
|
+
/** The post-compaction restore (`MaybeCompactOptions.workingFileAttachments.restore`): re-reads the candidates through
|
|
1011
|
+
* the leg's one file reader under the run's synthetic-Read judge — the user attachment's own path read — deduplicated
|
|
1012
|
+
* against the read state the summary leaves, and mints their attachment frames (`readCompactionRestore`); a file it
|
|
1013
|
+
* does not deliver — or whose frame the transcript does not take — is reported (`onError` phase `degraded`,
|
|
1014
|
+
* classification `attachment-read`). Present only with hands. */
|
|
1015
|
+
compactionRestore?: Required<Pick<NonNullable<import("../auto-compaction.js").MaybeCompactOptions["workingFileAttachments"]>, "restore" | "undelivered">>;
|
|
1019
1016
|
/** CC post-compact restore parity (2026-07-03): the task's READ files, most recent
|
|
1020
|
-
* first (from the hands' readFileState `lastReadAt` stamps). The
|
|
1021
|
-
*
|
|
1022
|
-
*
|
|
1023
|
-
* Seeded entries are excluded — their content lives in the system-prompt lane, which
|
|
1024
|
-
* compaction never touches, so re-attaching them into the summary would be a duplicate. */
|
|
1017
|
+
* first (from the hands' readFileState `lastReadAt` stamps). The restore prefers this over the modified set — CC
|
|
1018
|
+
* restores what the model RECENTLY READ, including untouched reference files. Present only with hands.
|
|
1019
|
+
* Seeded entries are excluded — their content lives in the system-prompt lane, which compaction never touches. */
|
|
1025
1020
|
recentlyReadFiles?: () => string[];
|
|
1026
1021
|
/** Canonicalizes a raw (often relative, model-typed) path the
|
|
1027
|
-
* SAME way the hands toolkit does (`resolveKey` against the
|
|
1028
|
-
*
|
|
1022
|
+
* SAME way the hands toolkit does (`resolveKey` against the hands' containment root), so `maybeCompact`'s
|
|
1023
|
+
* kept-tail/instruction-source exclusions compare paths in the SAME
|
|
1029
1024
|
* coordinate `recentlyReadFiles()` already uses — without this a plain string match silently never
|
|
1030
|
-
* fires for the common relative-vs-canonical case. Present only with hands
|
|
1031
|
-
*
|
|
1032
|
-
* already in the same raw coordinate anyway. */
|
|
1025
|
+
* fires for the common relative-vs-canonical case. Present only with hands; absent there is no
|
|
1026
|
+
* containment root to resolve against, and every path source is already in the same raw coordinate anyway. */
|
|
1033
1027
|
normalizeAttachmentPath?: (raw: string) => Promise<string>;
|
|
1034
1028
|
/** Recognizes the hands Read tool's own dedup-stub markers
|
|
1035
1029
|
* ({@link isReadDedupStubResult}), so `maybeCompact`'s kept-tail scan can tell a SUBSTANTIVE Read
|
|
1036
1030
|
* result from a stub hit whose original full transmission may already be summarized away. Present
|
|
1037
|
-
* only with hands
|
|
1031
|
+
* only with hands. */
|
|
1038
1032
|
isDedupStubResult?: (resultText: string) => boolean;
|
|
1039
1033
|
/** Wired to `MaybeCompactOptions.onApplied` by every compaction lane (CC 220 clears readFileState at its
|
|
1040
|
-
* compaction landing site, @388663). Drops
|
|
1041
|
-
* (
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
* deliberately skipped for re-attachment — their existing entry must survive the clear too (same
|
|
1045
|
-
* reasoning as a seeded entry: the model's view of the file did not change).
|
|
1034
|
+
* compaction landing site, @388663). Drops every read-state entry the summary took out of view
|
|
1035
|
+
* (`readFileStateAfterSummary`); the restored files then re-register through their frames' own commits. Present
|
|
1036
|
+
* only with hands. `preserveReadState` carries the files the context the summary leaves still shows — their
|
|
1037
|
+
* existing entry survives the clear (the model's view of the file did not change).
|
|
1046
1038
|
*
|
|
1047
1039
|
* SCOPE — read "every compaction lane" as exactly that and no wider. The request-layer
|
|
1048
1040
|
* stale-result pass takes a Read body off the wire with no compaction at all, and retires its own
|
|
1049
1041
|
* entries at its own landing site (`prepare-context-lane.ts`'s `landStaleResultClears`) through the
|
|
1050
|
-
* SAME function this seat calls, on its `
|
|
1051
|
-
* ways for content to leave. Taken as a claim about every SHRINK mechanism this sentence was true
|
|
1042
|
+
* SAME function this seat calls, on its `transmissions-gone` arm (the guard trim's dropped tool results and attachment frames too):
|
|
1043
|
+
* ONE retirement mechanism, several ways for content to leave. Taken as a claim about every SHRINK mechanism this sentence was true
|
|
1052
1044
|
* of the lanes it named and silently false of the one it did not. */
|
|
1053
|
-
onCompactionApplied?: (
|
|
1054
|
-
path: string;
|
|
1055
|
-
content: string;
|
|
1056
|
-
}>, preserveReadState?: ReadonlyArray<string>) => void;
|
|
1045
|
+
onCompactionApplied?: (preserveReadState: ReadonlyArray<string>) => void;
|
|
1057
1046
|
/** The live diagnostics lane (present only when the gate passed — manager w/ registry +
|
|
1058
1047
|
* write hands + not opted out). `registry` is drained by runtask at turn boundaries; `nudge` is
|
|
1059
1048
|
* called (fire-and-forget) after each successful edit/write so the language server re-analyzes. */
|
|
@@ -1725,6 +1714,9 @@ export interface RunInternals {
|
|
|
1725
1714
|
};
|
|
1726
1715
|
contentSafety: import("../memory-engine/delegation-provenance.js").DelegationContentSafety;
|
|
1727
1716
|
};
|
|
1717
|
+
/** The run TREE's cross-boundary token — the tree's ONE state is reached from it by the engine alone: the spawning leg hands its
|
|
1718
|
+
* own down (the delegation and workflow lanes), so a bit any leg sets is read by every other at its next judgment; a root leg mints one. */
|
|
1719
|
+
crossBoundaryTree?: import("../cross-boundary-taint.js").CrossBoundaryTreeToken;
|
|
1728
1720
|
/**
|
|
1729
1721
|
* The SESSION-scoped org-admission freeze for a SAME-SESSION continuation
|
|
1730
1722
|
* that is NOT a checkpoint resume: a retained background child revived through the in-process resume
|