@sema-agent/core 5.57.0 → 5.59.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 +96 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +2 -2
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +5 -5
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +8 -1
- package/dist/brain/route-adjudicator.js +8 -1
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.d.ts +37 -10
- package/dist/core/governance-codes.js +54 -1
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/memory-engine/consolidation-driver.d.ts +211 -0
- package/dist/core/memory-engine/consolidation-driver.js +427 -0
- package/dist/core/memory-engine/consolidation.d.ts +119 -3
- package/dist/core/memory-engine/consolidation.js +22 -1
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +143 -10
- package/dist/core/memory-engine/engine.js +149 -23
- package/dist/core/memory-engine/file-backend.d.ts +14 -2
- package/dist/core/memory-engine/file-backend.js +3 -0
- package/dist/core/memory-engine/index.d.ts +6 -3
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/layout.js +20 -6
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-engine/types.d.ts +17 -0
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +185 -36
- package/dist/core/permission-rule-consent.js +219 -44
- package/dist/core/permission-rule-model.d.ts +235 -31
- package/dist/core/permission-rule-model.js +105 -35
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +24 -17
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +11 -11
- package/dist/core/runner/runtask.js +4 -4
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +5 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +2 -2
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +113 -28
- package/dist/core/tool-policy.js +80 -1
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +164 -86
- package/dist/core/types.js +4 -3
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +10 -10
- package/dist/engine/llm/types.d.ts +14 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -4
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +8 -8
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +1 -1
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +4 -4
- package/dist/tools/worktree.d.ts +5 -5
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +1826 -3
package/dist/core/auto-mode.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type AutoModeVerdict = {
|
|
|
33
33
|
* optional): a free-scan lets a prompt-injected preamble seed the verdict; our contract-anchored
|
|
34
34
|
* parse costs only a fallback to the original human chain on the mismatch, never a silent allow.
|
|
35
35
|
*
|
|
36
|
-
* Strictness is polarity-asymmetric (
|
|
36
|
+
* Strictness is polarity-asymmetric (confirmed HIGH):
|
|
37
37
|
* - an ALLOW must be UNAMBIGUOUS: `<block>no</block>` followed by anything but whitespace —
|
|
38
38
|
* a second conflicting `<block>yes</block>`, trailing prose, any tail at all — violates the
|
|
39
39
|
* contract and maps to `parse_error` (the ask flows the original human chain, never a silent
|
|
@@ -55,17 +55,17 @@ export interface AutoModeClassifyInput {
|
|
|
55
55
|
askMessage?: string;
|
|
56
56
|
}
|
|
57
57
|
/** The pluggable model leg: given the classify input, return the model's raw text response.
|
|
58
|
-
* Deployment-injected (roster cheap tier per
|
|
58
|
+
* Deployment-injected (roster cheap tier per); MAY throw / reject — the decider fail-closes. */
|
|
59
59
|
export type AutoModeClassifyFn = (input: AutoModeClassifyInput, signal?: AbortSignal) => Promise<string>;
|
|
60
60
|
export interface AutoModeDeciderOptions {
|
|
61
61
|
classify: AutoModeClassifyFn;
|
|
62
62
|
/** Hard cap on one classification round-trip. Default 15_000 ms (sema 裁量 — CC's constant is not
|
|
63
63
|
* established; a permission gate must not stall the whole run on a slow classifier). */
|
|
64
64
|
timeoutMs?: number;
|
|
65
|
-
/** Consecutive-failure threshold that opens the session breaker (default 3
|
|
65
|
+
/** Consecutive-failure threshold that opens the session breaker (default 3 "连续 N 失败").
|
|
66
66
|
* Failures = unavailable(error|timeout) + parse_error. A successful round (allow/block) resets it. */
|
|
67
67
|
failureThreshold?: number;
|
|
68
|
-
/** Fired ONCE when the breaker opens (
|
|
68
|
+
/** Fired ONCE when the breaker opens ("本 session 退回非 auto + 一次性告警"). */
|
|
69
69
|
onBreakerOpen?: (info: {
|
|
70
70
|
consecutiveFailures: number;
|
|
71
71
|
lastCause: string;
|
|
@@ -74,7 +74,7 @@ export interface AutoModeDeciderOptions {
|
|
|
74
74
|
export interface AutoModeDecider {
|
|
75
75
|
/** Never rejects. Any internal failure surfaces as `unavailable`/`parse_error` (fail-closed). */
|
|
76
76
|
decide(input: AutoModeClassifyInput, signal?: AbortSignal): Promise<AutoModeVerdict>;
|
|
77
|
-
/** True once the session breaker has opened (it never half-opens:
|
|
77
|
+
/** True once the session breaker has opened (it never half-opens: is a SESSION fallback
|
|
78
78
|
* to non-auto, not a retry window — a flapping classifier must not oscillate the permission mode). */
|
|
79
79
|
breakerOpen(): boolean;
|
|
80
80
|
}
|
|
@@ -28,10 +28,10 @@ export interface BackgroundAgentRecord {
|
|
|
28
28
|
/** The child's store session id — the transcript / resume anchor. Absent at put (the child session
|
|
29
29
|
* is minted AFTER registration); bound via a follow-up CAS update. */
|
|
30
30
|
sessionId?: string;
|
|
31
|
-
/** Spawn-time root linkage
|
|
31
|
+
/** Spawn-time root linkage — the durable enumeration key for task-scoped rows
|
|
32
32
|
* ({@link BackgroundAgentStore.listBySession}) and the restart read leg of the access predicate. */
|
|
33
33
|
parentSessionId?: string;
|
|
34
|
-
/**
|
|
34
|
+
/** the ROOT host session of the delegation tree (fixed point down the internals
|
|
35
35
|
* chain; equals parentSessionId at depth 1). The recovery-face enumeration anchor: after a
|
|
36
36
|
* restart, intermediate spawner sessions are dead ends — "everything under this host session"
|
|
37
37
|
* keys on THIS field (listBySession matches it as a second arm), not on an alias walk. */
|
|
@@ -46,7 +46,7 @@ export interface BackgroundAgentRecord {
|
|
|
46
46
|
/** design/151 §3.1d (HIGH-3): the WRITING process instance id (random per registry instance). A
|
|
47
47
|
* fallback read of a `running` row whose writer is not the reading instance serves an HONEST
|
|
48
48
|
* "outcome unknown here" — never a fabricated "running" liveness claim.
|
|
49
|
-
* S3 revival ORDER OBLIGATION
|
|
49
|
+
* S3 revival ORDER OBLIGATION: a cross-process revival must first CAS this field
|
|
50
50
|
* over to the reviving instance's writerId (the claim), THEN register-with-id — a fresh lane's
|
|
51
51
|
* first write against a row still carrying the dead process's writerId reads back "foreign" and
|
|
52
52
|
* poisons itself by design. Claim-CAS first is the only sequence the adjudication admits. */
|
|
@@ -78,7 +78,7 @@ export interface BackgroundAgentRecord {
|
|
|
78
78
|
status: "running" | "parked" | "completed" | "failed" | "killed";
|
|
79
79
|
/** Open enum (task-registry `StopSource` mirror). */
|
|
80
80
|
stoppedBy?: string;
|
|
81
|
-
/**
|
|
81
|
+
/** The cross-channel completion correlation id
|
|
82
82
|
* (task-registry `SemaTaskHandle.completionId` mirror). Written alongside `status`/`settledAt` at
|
|
83
83
|
* the same durable terminal write that lands them, so a cross-restart fallback read (`TaskOutput`
|
|
84
84
|
* after the writing process is gone) REPLAYS this exact value — there is no second mint point here,
|
|
@@ -110,7 +110,7 @@ export interface BackgroundAgentRecord {
|
|
|
110
110
|
* to preserve. */
|
|
111
111
|
finalOutputFull?: string;
|
|
112
112
|
/** The child's failure text (registry `handle.error` mirror; the reap-stop sentinel never lands here).
|
|
113
|
-
* RB-237
|
|
113
|
+
* RB-237: the stale-running reap flip ALSO writes its attribution here (`??`-guarded) —
|
|
114
114
|
* `error` is the field the durable serving face renders (`serveDurableAgentRow`), while `summary`
|
|
115
115
|
* has no reader on that face, so an attribution written only to `summary` was invisible: a host
|
|
116
116
|
* crash read as a bare `failed` + "(no result text)". */
|
|
@@ -200,9 +200,9 @@ export declare class BackgroundAgentStoreError extends Error {
|
|
|
200
200
|
* legitimate owner (the spawn-time task ids are dead). The live registry still does not grant the
|
|
201
201
|
* parentSessionId leg (an intermediate session must not steer a sibling turn's running child);
|
|
202
202
|
* the ROOT arm, however, is now on BOTH faces — RB-236 (2026-07-29) aligned the live `canAccess`
|
|
203
|
-
* with this predicate's
|
|
203
|
+
* with this predicate's root-session arm, closing the "running grandchild is not_found to
|
|
204
204
|
* the session that owns the tree" window. Durable rows remain the settled/read/revive face.
|
|
205
|
-
* Cross-session same-scope reads stay not_found (
|
|
205
|
+
* Cross-session same-scope reads stay not_found (content-axis ruling).
|
|
206
206
|
*
|
|
207
207
|
* Scope is FAIL-CLOSED both ways (`undefined` never matches) — records are put with a real scope.
|
|
208
208
|
*/
|
|
@@ -232,24 +232,24 @@ export declare function canAccessAgentRecord(record: Pick<BackgroundAgentRecord,
|
|
|
232
232
|
* writer does not heartbeat — the child is durably suspended, silence is its normal state; the
|
|
233
233
|
* checkpoint-bound reconciliation sweep, not row age, owns its cleanup). With no options, reap is
|
|
234
234
|
* a no-op (retention is always an explicit policy).
|
|
235
|
-
* Sizing
|
|
235
|
+
* Sizing: a LIVE writer renews its running rows' `updatedAt` every
|
|
236
236
|
* `DURABLE_AGENT_HEARTBEAT_MS` (60s — task-registry writer lease), so row age measures SILENCE —
|
|
237
|
-
* of the WRITER PROCESS, specifically
|
|
237
|
+
* of the WRITER PROCESS, specifically: a wedged child inside a healthy
|
|
238
238
|
* process keeps renewing and never goes stale, by design (in-process supervision owns that case).
|
|
239
239
|
* Set `staleRunningMaxAgeMs` ≥ 10× the heartbeat (≥10min). A premature flip still self-heals:
|
|
240
240
|
* the live writer's settle reads the row back, adopts the bumped rev (writerId match) and
|
|
241
241
|
* re-CASes the real terminal truth over the reaper's guess.
|
|
242
242
|
* ⚠️ Row deletion does NOT release the child SESSION (the store cannot reach the session store) —
|
|
243
|
-
* the blessed reap path is the registry-side orchestration (design/151 §3.1 MED-7 +
|
|
243
|
+
* the blessed reap path is the registry-side orchestration (design/151 §3.1 MED-7 +
|
|
244
244
|
* C-2): it conditionally DELETES the row under its re-verified rev first, and only a WINNING
|
|
245
245
|
* delete releases the transcript session (release-first destroyed a live transcript when a
|
|
246
246
|
* concurrent revive won the CAS after the release). Calling raw `reap` alone strands transcripts.
|
|
247
|
-
* Cross-process caveat
|
|
247
|
+
* Cross-process caveat: a revive's durable `running` transition rides the async
|
|
248
248
|
* lane — between the in-memory revive and its flush, a DIFFERENT process's sweep still holds a
|
|
249
249
|
* terminal-looking row whose rev the flush has not yet bumped. In-process sweeps are gated on the
|
|
250
250
|
* live handle; cross-process revival (S3) must claim-CAS FIRST (see {@link BackgroundAgentRecord.writerId}).
|
|
251
251
|
*/
|
|
252
|
-
/** RB-237
|
|
252
|
+
/** RB-237: the stale-running reap flip's attribution, written to BOTH `summary` (legacy
|
|
253
253
|
* slot, kept for any out-of-repo reader) and `error` (the field {@link canAccessAgentRecord}-gated
|
|
254
254
|
* durable serving actually renders). One exported constant so the two store implementations (in-memory
|
|
255
255
|
* here, file twin) can never drift apart (RB-74/RB-111 family). Wording carries CC 2.1.220's three
|
|
@@ -307,29 +307,29 @@ export interface BackgroundAgentStore {
|
|
|
307
307
|
*/
|
|
308
308
|
updateIf(handle: string, scope: string, record: BackgroundAgentRecord, expect: BackgroundAgentUpdateIfExpect): Promise<boolean>;
|
|
309
309
|
/** Rows whose durable session anchor (`sessionScoped ? owner : parentSessionId`) OR root anchor
|
|
310
|
-
* (`rootSessionId
|
|
310
|
+
* (`rootSessionId` — the whole delegation tree under one host session) equals
|
|
311
311
|
* `sessionId`, newest-first by `spawnedAt`. Content-free projections (HIGH-1). `opts.status`
|
|
312
312
|
* filters one state; `opts.limit` keeps the newest N after the sort. */
|
|
313
313
|
listBySession(scope: string, sessionId: string, opts?: {
|
|
314
314
|
status?: BackgroundAgentRecord["status"];
|
|
315
315
|
limit?: number;
|
|
316
316
|
}): Promise<BackgroundAgentRowSummary[]>;
|
|
317
|
-
/**
|
|
317
|
+
/** ALL of a scope's rows (content-free, newest-first): the joint-reap orchestration's
|
|
318
318
|
* enumeration face (`TaskRegistry.reapDurableAgents` — conditional delete first, session release
|
|
319
|
-
* only after a winning delete
|
|
319
|
+
* only after a winning delete). Deployment-op context, not a model-serving face —
|
|
320
320
|
* model-facing reads stay behind {@link canAccessAgentRecord}. */
|
|
321
321
|
listByScope(scope: string, opts?: {
|
|
322
322
|
status?: BackgroundAgentRecord["status"];
|
|
323
323
|
limit?: number;
|
|
324
324
|
}): Promise<BackgroundAgentRowSummary[]>;
|
|
325
|
-
/**
|
|
326
|
-
*
|
|
325
|
+
/** row-precise removal (the joint-reap deletion arm). Returns false on a miss.
|
|
326
|
+
* `expect.rev` makes it CONDITIONAL — a live writer's concurrent revival (heartbeat
|
|
327
327
|
* adopt bumps rev) must beat the reaper's stale snapshot, so the joint reap always deletes with
|
|
328
328
|
* the rev it just re-verified. */
|
|
329
329
|
delete(handle: string, scope: string, expect?: {
|
|
330
330
|
rev: number;
|
|
331
331
|
}): Promise<boolean>;
|
|
332
|
-
/**
|
|
332
|
+
/** Enumerate the scopes that currently hold rows, so a deployment-op
|
|
333
333
|
* retention loop can drive {@link TaskRegistry.reapDurableAgents} per scope without external
|
|
334
334
|
* bookkeeping (a local backend under multi-tenant use otherwise grows principal-scoped rows
|
|
335
335
|
* forever). Optional: a store whose deployment tracks scopes elsewhere (pg: SELECT DISTINCT)
|
|
@@ -359,7 +359,7 @@ export interface BackgroundAgentStore {
|
|
|
359
359
|
* run after the owning process exits) to fire.
|
|
360
360
|
* Every write is a rev-CAS — a live writer's concurrent transition wins and the sweep just skips.
|
|
361
361
|
*
|
|
362
|
-
* SPLIT-BRAIN FENCE (件1
|
|
362
|
+
* SPLIT-BRAIN FENCE (件1): failing a row whose PARKING PROCESS is still alive would
|
|
363
363
|
* desynchronize its live handle (poll keeps saying parked, TaskStop mis-reports). An in-process
|
|
364
364
|
* deployment therefore calls {@link import("./task-registry.js").TaskRegistry.reconcileParkedAgents}
|
|
365
365
|
* (which handles ITS OWN handles live, then delegates here with `excludeWriterId` = its writerId);
|
|
@@ -388,7 +388,7 @@ export interface BackgroundAgentQuery {
|
|
|
388
388
|
scope: string;
|
|
389
389
|
/**
|
|
390
390
|
* Session-anchored enumeration: a row qualifies when its durable anchor
|
|
391
|
-
* (`sessionScoped ? owner : parentSessionId`) OR its `rootSessionId` (
|
|
391
|
+
* (`sessionScoped ? owner : parentSessionId`) OR its `rootSessionId` (the whole
|
|
392
392
|
* delegation tree under one host session) equals this. ABSENT ⇒ scope-wide enumeration.
|
|
393
393
|
*/
|
|
394
394
|
sessionId?: string;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 这是一个 **env 上的可选能力**(非一种独立 env 类型),所以不 `extends ExecutionEnv` —— 用交叉类型挂到具体实现上,并经
|
|
7
7
|
* {@link hasBackgroundShell} 运行时检测(对齐 remote-env.ts 的 `hasDestroy`/`isRemoteExecutionEnv` 模式,零 vendor 接口改动)。
|
|
8
8
|
*
|
|
9
|
-
* 设计裁定(经
|
|
9
|
+
* 设计裁定(经 + workflow 5-lens 双轨证伪式复审收敛,design/103 v2):
|
|
10
10
|
* - **不跨 durable suspend**:后台进程在每条退出路径被 dispose;Runner 必须在 suspendVM **之前** 调
|
|
11
11
|
* {@link BackgroundShellCapability.disposeBackgroundShells}(detached job 不在 suspendVM 的 in-flight 契约射程内)。
|
|
12
12
|
* - **越界隔离**:`pollBackground`/`killBackground` 的 shellId MUST 被校验为本 env 自己 spawn 过的;非本 env 走 `not_found`。
|
|
@@ -83,7 +83,7 @@ export interface BackgroundShellCapability {
|
|
|
83
83
|
readonly defaultBgTimeoutSec: number;
|
|
84
84
|
/** 后台 timeout **硬上限**(秒)。fail-closed 到有限值 —— **绝不允许无界**(design/103 §3.6)。 */
|
|
85
85
|
readonly maxBgTimeoutSec: number;
|
|
86
|
-
/** design/116 detach(
|
|
86
|
+
/** design/116 detach([C]):env 是否支持把前台 exec 的运行中子进程「领养」为后台(exec options 的
|
|
87
87
|
* `detachSignal`)。缺省/false ⇒ detach 请求被忽略(exec 继续前台跑完)。 */
|
|
88
88
|
readonly supportsDetach?: boolean;
|
|
89
89
|
/** design/128 T1-1 留驻声明(TB 2026-07-08 翻红回归修):env 声明后台进程 **outlive the run** ——
|
|
@@ -116,7 +116,7 @@ export interface BackgroundShellCapability {
|
|
|
116
116
|
* review 必须在 `suspendVM` 之前**(design/103 §3.7;detached job 不在 suspendVM in-flight 契约内,不能指望 adapter 隐式处理)。
|
|
117
117
|
* Best-effort,MUST NOT throw(像 `cleanup`/`destroy`)。幂等。
|
|
118
118
|
*
|
|
119
|
-
*
|
|
119
|
+
* `except`(可选):这些 shellId **留活**(session 驻留 persistent Monitor 的进程 —— 它的全部意义
|
|
120
120
|
* 就是跨 turn 存活;run-end 全灭会留下「registry handle 活着、进程死了」的孤儿 watch)。不认识此参数的旧
|
|
121
121
|
* 实现照旧全灭 = 今天的行为(诚实降级,not silent corruption:watcher 会打出 env-death 终态通知)。
|
|
122
122
|
* suspend/review 前的 dispose **不带** except(挂起整个 VM,进程死亡是既有契约)。
|
|
@@ -133,7 +133,7 @@ export interface BackgroundShellCapability {
|
|
|
133
133
|
*/
|
|
134
134
|
export declare function hasBackgroundShell(env: ExecutionEnv): env is ExecutionEnv & BackgroundShellCapability;
|
|
135
135
|
/**
|
|
136
|
-
*
|
|
136
|
+
* RB-164 — the ONE way core runs an env-level background sweep.
|
|
137
137
|
*
|
|
138
138
|
* ## Why a single entry point
|
|
139
139
|
* `disposeBackgroundShells` lives in the execution-env layer and cannot reach the task registry, so the
|
|
@@ -256,7 +256,7 @@ export declare function riskSeverity(axes: {
|
|
|
256
256
|
irreversible?: boolean;
|
|
257
257
|
shell?: boolean;
|
|
258
258
|
}): 1 | 2 | 3 | 4 | 5;
|
|
259
|
-
/** design S1e
|
|
259
|
+
/** design S1e: the char cap for the {@link CheckpointSummary.toolInput} BOUNDED raw preview of a
|
|
260
260
|
* `tool_approval` pendingAction's `args` (`JSON.stringify`-ed). Caps the `listByScope` payload size; over-cap
|
|
261
261
|
* is truncated with a trailing `…`. Bounded raw (NOT neutralized) — redaction is the consumer's job (echo-only). */
|
|
262
262
|
export declare const MAX_TOOL_INPUT_PREVIEW_CHARS = 512;
|
|
@@ -340,8 +340,8 @@ export interface PendingSteerInput {
|
|
|
340
340
|
* NO clock/random, so the SAME call ⇒ an IDENTICAL descriptor (pinned by a test).
|
|
341
341
|
*
|
|
342
342
|
* **Determinism contract = plain-DATA args** (the real flow: model-JSON / hook-rewritten plain objects). A
|
|
343
|
-
* Proxy whose `ownKeys` trap returns a DIFFERENT key set per call is OUT OF CONTRACT — JS cannot detect a
|
|
344
|
-
*
|
|
343
|
+
* Proxy whose `ownKeys` trap returns a DIFFERENT key set per call is OUT OF CONTRACT — JS cannot detect a
|
|
344
|
+
* Proxy, so its (display-only) digest may vary. This NEVER affects a security/budget/mint
|
|
345
345
|
* decision: `riskDescriptor` is INERT (no core path reads it to gate), so an out-of-contract input can at worst
|
|
346
346
|
* degrade an inbox preview, never a permission outcome.
|
|
347
347
|
*
|
|
@@ -695,22 +695,30 @@ export type PendingAction = {
|
|
|
695
695
|
toolName: string;
|
|
696
696
|
/** Post-hook (design/37-rewritten) args to execute on `allow`. */
|
|
697
697
|
args: unknown;
|
|
698
|
-
/**
|
|
698
|
+
/** (additive) — the tool's approval display projection of `args`, minted alongside the
|
|
699
699
|
* row (see AgentTool.approvalPreview; control-char-sanitized + 16KiB-clamped at mint).
|
|
700
700
|
* **UNTRUSTED, ADVISORY**: inboxes must escape contextually and surface `args` alongside.
|
|
701
701
|
* NEVER read by the resume path (args + boundInputHash stay the sole execution contract). */
|
|
702
702
|
preview?: unknown;
|
|
703
|
-
/** design/179 §4
|
|
704
|
-
*
|
|
705
|
-
*
|
|
706
|
-
*
|
|
707
|
-
*
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
*
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
|
|
703
|
+
/** design/179 §4, re-formed by design/375 §3.1/§3.3 (BREAKING — replaces the retired
|
|
704
|
+
* `ruleSuggestions` seat; a pre-375 inbox reading a new row simply finds no offers and renders
|
|
705
|
+
* no "don't ask again" option, fail toward asking) — the persistable allow-rule OFFERS this
|
|
706
|
+
* parked call could be covered by, minted from the SAME post-hook args the row executes.
|
|
707
|
+
* Advisory display metadata for the approval inbox's "stop asking me this" option; never read
|
|
708
|
+
* by the resume path, and never a rule by itself (minting one goes through the approval-record
|
|
709
|
+
* protocol). Absent when no rule lane is armed, the command is one the lane cannot speak for,
|
|
710
|
+
* or the parked ask is one a persisted rule could not clear (mandated marks / a real-approval
|
|
711
|
+
* demand / a shadowed matching rule).
|
|
712
|
+
* CONTRACT (same as the synchronous `AskRequest.ruleOffers` — see
|
|
713
|
+
* {@link import("./permission-rule-model.js").RuleOffer}): at most 2 offers, the whole-string
|
|
714
|
+
* EXACT single always index 0 when present, the BATCH offer (choosing it is one yes to ALL of
|
|
715
|
+
* its 1..5 per-segment rules at once) always last; selection indices are keyed against this
|
|
716
|
+
* order (redemption TICKETS are keyed on the consent record's flat CANDIDATE list instead —
|
|
717
|
+
* a chosen offer is redeemed via `redeemRuleBatch`), per-element parse with single-row
|
|
718
|
+
* degrade on an unknown `kind` and
|
|
719
|
+
* original-index preservation. The park→resume redemption chain walks the same consent
|
|
720
|
+
* protocol as the synchronous card — there is no second form. */
|
|
721
|
+
ruleOffers?: readonly import("./permission-rule-model.js").RuleOffer[];
|
|
714
722
|
/**
|
|
715
723
|
* design/80 D-1 §2 (slice 1a.2): the server-minted **opaque** boundInputHash of {@link args} — a
|
|
716
724
|
* SHA-256 (hex) via {@link import("./canonical-json.js").boundInputHashOf}, computed ONCE here at
|
|
@@ -797,7 +805,7 @@ export interface CheckpointState {
|
|
|
797
805
|
pattern: string;
|
|
798
806
|
caseSensitive: boolean;
|
|
799
807
|
}>;
|
|
800
|
-
/**
|
|
808
|
+
/** REDUNDANT governance marker: `true` iff the row's gate was minted WITH a
|
|
801
809
|
* {@link RealApprovalGateBit}. v8's bit-required invariant was version-keyed and v9 (face)
|
|
802
810
|
* outranks v8 in the stamp, so without this a v9 GOVERNED row whose `gate.realApproval` member
|
|
803
811
|
* was dropped in storage would pass pre-CAS and be redeemable on an unwired worker — the exact
|
|
@@ -895,7 +903,7 @@ export interface CheckpointState {
|
|
|
895
903
|
* :707384-707399 under the `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` gate — the cloud-worker restart
|
|
896
904
|
* leg, exactly sema's durable-resume shape): the background tasks (pending/running, this run's
|
|
897
905
|
* owner triple) still ALIVE at suspend. Background processes never survive a suspend (design/103
|
|
898
|
-
* §3.7 unconditional dispose +
|
|
906
|
+
* §3.7 unconditional dispose + killed receipts), so on resume any snapshot entry NOT
|
|
899
907
|
* alive in the resume leg's registry is an ORPHAN — aggregated into ONE CC-verbatim "The container
|
|
900
908
|
* was restarted…" reminder appended to the resume continuation (single message: header +
|
|
901
909
|
* `- description (task id)` list + re-create instruction; never a per-task barrage). A survivor
|
|
@@ -910,7 +918,7 @@ export interface CheckpointState {
|
|
|
910
918
|
description?: string;
|
|
911
919
|
}>;
|
|
912
920
|
/**
|
|
913
|
-
*
|
|
921
|
+
* the hands band's LOGICAL working directory at suspend (`handsCwdRef.current` —
|
|
914
922
|
* moved by `cd` and by EnterWorktree). Without it a resume silently reset the task cwd to the task root:
|
|
915
923
|
* relative Read/Edit/Write paths and Bash commands then operated somewhere else than the model believes.
|
|
916
924
|
* Absent when the task has no tracked cwd (no real shell / read-only hands). The directory itself is
|
|
@@ -918,7 +926,7 @@ export interface CheckpointState {
|
|
|
918
926
|
*/
|
|
919
927
|
handsCwd?: string;
|
|
920
928
|
/**
|
|
921
|
-
*
|
|
929
|
+
* the ACTIVE EnterWorktree session at suspend (worktree.ts keeps it in a shared
|
|
922
930
|
* serializable ref, not a closure-only var, precisely so it lands here). Without it a resume LOST the
|
|
923
931
|
* session: ExitWorktree became a no-op (the unchanged worktree could never be removed), a second
|
|
924
932
|
* EnterWorktree was wrongly accepted, and `handsCwd` pointed into a worktree the tooling no longer
|
|
@@ -1145,7 +1153,7 @@ export declare const TOKEN_CHECKPOINT_VERSION = 5;
|
|
|
1145
1153
|
*/
|
|
1146
1154
|
export declare const ORG_ADMISSION_CHECKPOINT_VERSION = 6;
|
|
1147
1155
|
/**
|
|
1148
|
-
* F-012 (2026-08-09 — the ORG_ADMISSION_CHECKPOINT_VERSION precedent replayed a fifth time
|
|
1156
|
+
* F-012 (2026-08-09 — the ORG_ADMISSION_CHECKPOINT_VERSION precedent replayed a fifth time
|
|
1149
1157
|
* falsification-style finding): the schema version a suspend stamps when its state carries the F-012 durable
|
|
1150
1158
|
* enforcement fields — `inheritedGate.constraintChain`/`constraintDigest` (the frozen ancestor
|
|
1151
1159
|
* projection chain the resume-edit re-adjudication executes) or `delegationProvenance` (the monotonic
|
|
@@ -1463,7 +1471,7 @@ export interface Checkpoint {
|
|
|
1463
1471
|
*/
|
|
1464
1472
|
rev?: number;
|
|
1465
1473
|
/**
|
|
1466
|
-
* design S1d (source-tag persistence
|
|
1474
|
+
* design S1d (source-tag persistence): the issuing task's session id, stamped at the
|
|
1467
1475
|
* APPROVAL suspend mint so a supervisor inbox can attribute a paused/awaiting checkpoint to the worker that
|
|
1468
1476
|
* raised it (the durable analog of {@link import("./tool-policy.js").AskRequest}.sourceTaskId — the durable
|
|
1469
1477
|
* suspend path does NOT invoke `onAsk`, so the synchronous source identity is captured here instead). It is
|
|
@@ -1546,14 +1554,14 @@ export interface CheckpointSummary {
|
|
|
1546
1554
|
* suspend — projected so the inbox shows WHICH call awaits a decision without an N+1 `getCheckpoint`.
|
|
1547
1555
|
* `undefined` for a non-`tool_approval` pendingAction (resource_limit / plan_review / task_done).
|
|
1548
1556
|
*
|
|
1549
|
-
* **ABSENCE SHAPE (contract
|
|
1557
|
+
* **ABSENCE SHAPE (contract)** — shared by every optional field on this projection: a
|
|
1550
1558
|
* tool-less park (`resource_limit` / `plan_review` / `task_done` — none of which binds a tool call)
|
|
1551
1559
|
* gets the key **OMITTED**, never `null` and never a present-but-`undefined` property. The
|
|
1552
1560
|
* `PendingAction` arms for those kinds declare no tool/binding fields at all, so there is nothing to
|
|
1553
1561
|
* project; `summarizeCheckpoint` spreads them conditionally for exactly this reason. A consumer
|
|
1554
1562
|
* therefore tests presence (`"toolCallId" in summary`), and a re-projecting service (BFF / SDK wire
|
|
1555
1563
|
* face) must not materialize the keys as `null` on the way out. Pinned in
|
|
1556
|
-
* `test/checkpoint-store.test.ts` ("
|
|
1564
|
+
* `test/checkpoint-store.test.ts` ("tool-less park …"). */
|
|
1557
1565
|
toolCallId?: string;
|
|
1558
1566
|
/** The pending tool's name ({@link PendingAction} `tool_approval.toolName`) when this is an approval suspend.
|
|
1559
1567
|
* OMITTED (not `null`) for a non-`tool_approval` pendingAction — see {@link toolCallId}'s absence-shape note. */
|
|
@@ -1565,13 +1573,13 @@ export interface CheckpointSummary {
|
|
|
1565
1573
|
* this lightweight `listByScope` projection). Deliberately NOT a new `content_ask` checkpoint gate kind (that
|
|
1566
1574
|
* would cross the durable-checkpoint once-only-winner / reaper-deadline / batch invariants — the DoR). */
|
|
1567
1575
|
contentKind?: "content_ask";
|
|
1568
|
-
/** design S1e
|
|
1576
|
+
/** design S1e: when the checkpoint was created ({@link Checkpoint.createdAt}, epoch ms) —
|
|
1569
1577
|
* projected so a supervisor inbox can sort/age pending entries (oldest-first triage) in ONE `listByScope`
|
|
1570
1578
|
* call, no N+1 `getCheckpoint`. ECHO-ONLY display/triage; always present (a Checkpoint always has a
|
|
1571
1579
|
* `createdAt`). */
|
|
1572
1580
|
createdAt?: number;
|
|
1573
1581
|
/**
|
|
1574
|
-
* design S1e
|
|
1582
|
+
* design S1e: a **BOUNDED, UNREDACTED** raw preview of the pending tool call's input
|
|
1575
1583
|
* ({@link PendingAction} `tool_approval.args` `JSON.stringify`-ed, truncated to {@link
|
|
1576
1584
|
* MAX_TOOL_INPUT_PREVIEW_CHARS} chars with a `…` marker when over) — projected so a supervisor inbox shows
|
|
1577
1585
|
* WHAT a paused tool call will do without an N+1 `getCheckpoint`. `undefined` for a non-`tool_approval`
|
|
@@ -1600,7 +1608,7 @@ export interface CheckpointSummary {
|
|
|
1600
1608
|
* workspace at all. ECHO-ONLY display/triage — nothing gates on it. Mirrors `TaskResult.workspaceRestoreMode`.
|
|
1601
1609
|
*/
|
|
1602
1610
|
restoreMode?: "snapshot" | "park_only";
|
|
1603
|
-
/**
|
|
1611
|
+
/** the tool's approval display projection ({@link PendingAction} `preview`),
|
|
1604
1612
|
* projected so the ONE-CALL inbox (`listByScope`) can render a rich confirmation without an N+1
|
|
1605
1613
|
* `get`. Same trust posture as `toolInput`: **UNTRUSTED, advisory display metadata** (strings are
|
|
1606
1614
|
* sanitized of control chars at mint but may still carry model-authored markdown — renderers must
|
|
@@ -2180,7 +2188,7 @@ export interface CheckpointStore {
|
|
|
2180
2188
|
*/
|
|
2181
2189
|
listByScope?(scope: string): Promise<CheckpointSummary[]>;
|
|
2182
2190
|
/**
|
|
2183
|
-
*
|
|
2191
|
+
* Deployment seam: the DISTINCT scopes that currently have at least one PENDING checkpoint — the
|
|
2184
2192
|
* enumeration face `listByScope` lacks. A host keeping its own scope registry (e.g. a sidecar file for a
|
|
2185
2193
|
* cross-scope inbox) can rebuild it from the data itself when the registry is lost/corrupt, instead of the
|
|
2186
2194
|
* enumeration silently going empty and pending approvals turning invisible. Scoped to PENDING deliberately:
|
|
@@ -118,7 +118,7 @@ export interface ContextEditOptions {
|
|
|
118
118
|
persist: (toolCallId: string, fullText: string) => string;
|
|
119
119
|
};
|
|
120
120
|
/**
|
|
121
|
-
* design/123 D3 (
|
|
121
|
+
* design/123 D3 (= fable-M5) — ANCHORED accounting start: `estimateContextTokens(messages,
|
|
122
122
|
* charsPerToken).tokens` for the SAME message array. When set, the trigger gate AND the internal
|
|
123
123
|
* bookkeeping start from this usage-anchored value instead of the pure structural sum (which
|
|
124
124
|
* underestimates code by ~25% and CJK by 60–75% — the defense would self-certify and pass
|
|
@@ -8,7 +8,7 @@ import type { Model } from "../internal/llm.js";
|
|
|
8
8
|
* budget, dropping older regular messages at a safe boundary (never starting on an orphan
|
|
9
9
|
* toolResult). Returns the original array when already within budget.
|
|
10
10
|
*
|
|
11
|
-
* design/123 D3 (
|
|
11
|
+
* design/123 D3 (= fable-M5) — anchored accounting: when `anchoredTotalTokens`
|
|
12
12
|
* (= `estimateContextTokens(messages, charsPerToken).tokens` for the SAME array) is provided, the
|
|
13
13
|
* trigger gate and the internal bookkeeping start from the usage-anchored value instead of the
|
|
14
14
|
* structural sum (which underestimates code/CJK and lets over-window requests through). Dropping a
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* what the model needs) — dropping the head as it overflows, plus a count of dropped bytes for a visible marker.
|
|
7
7
|
*
|
|
8
8
|
* This lives in `src/core/` — NOT `src/vendor/` — on purpose: it is OUR robustness invariant, shared by the
|
|
9
|
-
* (currently-vendored) NodeExecutionEnv AND a downstream exec adapter (service host/ssh/adb/docker/k8s
|
|
9
|
+
* (currently-vendored) NodeExecutionEnv AND a downstream exec adapter (service host/ssh/adb/docker/k8s).
|
|
10
10
|
* One implementation + ONE model-facing marker text = zero drift, and the public export points at a STABLE path
|
|
11
11
|
* that survives the planned de-vendoring (when NodeExecutionEnv is naturalized out of `src/vendor/`, nothing rebinds).
|
|
12
12
|
*/
|
|
@@ -35,18 +35,18 @@ export declare class RollingTailBuffer {
|
|
|
35
35
|
text: string;
|
|
36
36
|
droppedBytes: number;
|
|
37
37
|
};
|
|
38
|
-
/** RB-234
|
|
38
|
+
/** RB-234: the retained window's RAW bytes — cursor slicing must happen in the byte domain
|
|
39
39
|
* (re-encoding a lossily-decoded string inflates every invalid byte to a 3-byte U+FFFD and lands
|
|
40
40
|
* byte cursors on the wrong offsets). */
|
|
41
41
|
bytes(): Buffer;
|
|
42
|
-
/** RB-234
|
|
42
|
+
/** RB-234: head-eviction count ALONE — the retention window is [headDroppedBytes, pushed-total)
|
|
43
43
|
* in the accepted-byte domain; source skips must not shift this origin. */
|
|
44
44
|
headDroppedBytes(): number;
|
|
45
|
-
/** RB-234
|
|
45
|
+
/** RB-234: source-skip count alone (see {@link recordSkippedBytes}) — poll disclosure reports
|
|
46
46
|
* the per-poll increment of this figure instead of silently absorbing it into the window origin. */
|
|
47
47
|
sourceSkippedBytes(): number;
|
|
48
48
|
}
|
|
49
|
-
/** RB-234
|
|
49
|
+
/** RB-234: per-stream cursor state for incremental (poll-style) consumption of a
|
|
50
50
|
* {@link RollingTailBuffer}. All counters live in the ACCEPTED-byte domain (bytes actually pushed);
|
|
51
51
|
* source skips are tracked separately for disclosure. Module-level export (not on the package
|
|
52
52
|
* surface) so the slice arithmetic is unit-pinnable without an 8MB integration harness. */
|
|
@@ -65,7 +65,7 @@ export interface StreamCursorState {
|
|
|
65
65
|
/** Fresh cursor state over a new tail. */
|
|
66
66
|
export declare function newStreamCursorState(tail?: RollingTailBuffer): StreamCursorState;
|
|
67
67
|
/**
|
|
68
|
-
* RB-234
|
|
68
|
+
* RB-234: slice the undelivered increment out of a rolling tail — in the BYTE domain, decoded
|
|
69
69
|
* incrementally. Replaces the former decode→re-encode→byte-offset-subarray shape, which mixed two
|
|
70
70
|
* domains: byte cursors landed inside a re-encoded string whose length differs from the raw stream as
|
|
71
71
|
* soon as any invalid-UTF-8 byte sits in the window (each inflates to a 3-byte U+FFFD), making every
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** rel path of `child` under `root` in "/" form (win root) / verbatim form (posix root); null when not under.
|
|
2
|
-
*
|
|
2
|
+
* fold "\" only under a WIN-family root ({@link isWinFormPath}); a POSIX tree may legally
|
|
3
3
|
* contain literal backslashes in FILE NAMES, and folding them corrupted both the manifest key and the
|
|
4
4
|
* restore target. */
|
|
5
5
|
declare function relUnder(root: string, child: string): string | null;
|
|
@@ -41,20 +41,20 @@ export interface FileSnapshotStore {
|
|
|
41
41
|
reap(scope: string, keepKeys: string[]): Promise<number>;
|
|
42
42
|
/** Every snapshot key in `scope` (order unspecified). The enumeration counterpart of {@link reap} (which
|
|
43
43
|
* already iterates the same set internally) — exposed for a cross-backend session EXPORT (service 2c
|
|
44
|
-
* session-sync
|
|
44
|
+
* session-sync): list a session's snapshot keys to move its {entries + file snapshots} to another
|
|
45
45
|
* backend. A durable backend implements it as a `SELECT key WHERE scope = ?`. */
|
|
46
46
|
listKeys(scope: string): Promise<string[]>;
|
|
47
47
|
/**
|
|
48
|
-
* 2c session-sync
|
|
48
|
+
* 2c session-sync: the manifest (`relPath → blobHash`) for `(scope, key)`, or `null` if absent — to
|
|
49
49
|
* EXPORT a snapshot's content to another backend. Pairs with {@link getBlob} for CONTENT-ADDRESSED (deduped)
|
|
50
50
|
* blob transfer: the caller fetches each distinct hash ONCE across all of a session's snapshots. Optional — a
|
|
51
51
|
* backend that supports cross-backend snapshot export implements it.
|
|
52
52
|
*/
|
|
53
53
|
exportManifest?(scope: string, key: string): Promise<Map<string, string> | null>;
|
|
54
|
-
/** 2c session-sync
|
|
54
|
+
/** 2c session-sync: the content-addressed bytes for `hash` (undefined if absent). */
|
|
55
55
|
getBlob?(hash: string): Promise<Uint8Array | undefined>;
|
|
56
56
|
/**
|
|
57
|
-
* 2c session-sync
|
|
57
|
+
* 2c session-sync: STORE a snapshot INTO this store from another store's {@link exportManifest} +
|
|
58
58
|
* {@link getBlob} output — the import-side mirror that closes the cross-backend transfer loop. For each DISTINCT
|
|
59
59
|
* blob hash in `manifest`, fetch its bytes via `srcGetBlob`, VERIFY content-address integrity
|
|
60
60
|
* (`sha256(bytes) === hash`), and store it (content-addressed dedup); THEN record `(scope, key) → manifest`.
|
|
@@ -70,7 +70,7 @@ export interface FileSnapshotStore {
|
|
|
70
70
|
*/
|
|
71
71
|
importManifest?(scope: string, key: string, manifest: Map<string, string>, srcGetBlob: (hash: string) => Promise<Uint8Array | undefined>): Promise<FileSnapshotResult>;
|
|
72
72
|
/**
|
|
73
|
-
* 2c session-sync
|
|
73
|
+
* 2c session-sync: STORE a single content-addressed blob — the symmetric WRITE side of {@link getBlob},
|
|
74
74
|
* for a two-phase PUSH (upload blobs, THEN import the manifest that references them). VERIFIES content-address
|
|
75
75
|
* integrity (`sha256(bytes) === hash`) so a corrupt/mismatched upload can never contaminate the store (a later
|
|
76
76
|
* getBlob/restore would otherwise return wrong content); a mismatch → `read_failed`, nothing stored. IMMUTABLE +
|
|
@@ -105,7 +105,7 @@ export declare const DEFAULT_SNAPSHOT_BOUNDS: FileSnapshotBounds;
|
|
|
105
105
|
* bugs the dual-review fixed). Fail-CLOSED: an enumerate/read/bound failure returns an error and the caller must
|
|
106
106
|
* NOT persist a partial manifest. Never throws.
|
|
107
107
|
*
|
|
108
|
-
*
|
|
108
|
+
* vanished-file tolerance: a file that DISAPPEARED between enumerate and read (`not_found`) is OMITTED
|
|
109
109
|
* from the manifest instead of failing the whole capture. This is semantically SAFE — the E19 snapshot runs
|
|
110
110
|
* concurrently with a live tree (the `done` frame is emitted BEFORE the snapshot, so shell-side per-turn
|
|
111
111
|
* markers, `.git/index.lock`, editor swap files etc. legitimately vanish mid-walk), and omitting a
|
|
@@ -128,7 +128,7 @@ export declare function captureManifest(env: ExecutionEnv, root: string, bounds:
|
|
|
128
128
|
}>;
|
|
129
129
|
/**
|
|
130
130
|
* CONVERGE the tree under `root` to `manifest`, loading each captured file's bytes via `getBlob`. **The
|
|
131
|
-
* env-operating + security-critical half a durable backend MUST reuse.** Order is load-bearing (
|
|
131
|
+
* env-operating + security-critical half a durable backend MUST reuse.** Order is load-bearing (+
|
|
132
132
|
* Opus M1): PHASE 1 removes every current symlink (neutralizes a `dir -> /outside` ancestor that writeFile would
|
|
133
133
|
* otherwise follow OUT of root) + every file created since; PHASE 2 writes each captured file, clearing a
|
|
134
134
|
* directory that now occupies a file's path first. Never throws.
|
|
@@ -23,8 +23,8 @@ export interface AddWorktreeOptions {
|
|
|
23
23
|
* when its `ctx.isolation === "worktree"` and returns the result (with `destroy`); for a non-isolated task it
|
|
24
24
|
* returns the SHARED base env (no `destroy`) so the Runner never tears the base down.
|
|
25
25
|
*
|
|
26
|
-
* ISOLATE-ONLY
|
|
27
|
-
* decides verify/merge in userland. Caveats
|
|
26
|
+
* ISOLATE-ONLY: the runtime never merges — the orchestrator script reads each worktree's result and
|
|
27
|
+
* decides verify/merge in userland. Caveats: `git worktree` isolates the git WORKING COPY, not
|
|
28
28
|
* arbitrary shell access (bash can still reach the host — sandbox separately); UNCOMMITTED changes in the base
|
|
29
29
|
* repo are absent in the child (detached HEAD); a worktree orphaned by a process crash is reaped by
|
|
30
30
|
* {@link pruneWorktrees} (userland — there is no Runner hook for post-kill cleanup).
|
|
@@ -41,7 +41,7 @@ export declare function addWorktree(baseEnv: ExecutionEnv, opts: AddWorktreeOpti
|
|
|
41
41
|
* HRD-PTL-11: the exec Result used to be discarded, so every caller had to ASSUME the prune landed — and
|
|
42
42
|
* ExitWorktree's "already gone externally" leg told the model "stale git worktree metadata was pruned"
|
|
43
43
|
* on a claim it could not have checked. Same fail-loud treatment {@link removeWorktree} already got
|
|
44
|
-
*
|
|
44
|
+
* Report the outcome, let the caller decide what to say. Never throws (a throwing env
|
|
45
45
|
* lands on the same `{ok:false}`), so a caller that ignores the value behaves exactly as before. */
|
|
46
46
|
export declare function pruneWorktrees(baseEnv: ExecutionEnv, repoRoot: string): Promise<{
|
|
47
47
|
ok: true;
|
|
@@ -68,15 +68,42 @@ export type RuleSyncDropReason = keyof typeof RULE_SYNC_DROP_CODES;
|
|
|
68
68
|
* fence arm / local screening). `own_actor_forged` is inbound-only by construction. */
|
|
69
69
|
export type RuleQuarantineReason = Exclude<RuleSyncDropReason, "own_actor_forged">;
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
71
|
+
* WHO a notice code is for. `"user"` = a session-scoped disclosure the end user of that session is
|
|
72
|
+
* entitled to see (safe to project onto that session's event stream); `"operator"` = a
|
|
73
|
+
* deployment/config/ops fact for whoever runs the process.
|
|
74
|
+
*
|
|
75
|
+
* Two values, deliberately. "Can this notice be routed to a session" is NOT an audience value — it
|
|
76
|
+
* is the presence of `EngineNotice.sessionId`, a per-EMISSION fact. A third value would fold a
|
|
77
|
+
* routing property into an entitlement vocabulary, and the two answer different questions: several
|
|
78
|
+
* codes below carry a session attribution while the person entitled to the fact is still the
|
|
79
|
+
* operator (a failed offload write, a routing fallback, a consolidation recommendation).
|
|
80
|
+
*/
|
|
81
|
+
export type NoticeAudience = "user" | "operator";
|
|
82
|
+
/**
|
|
83
|
+
* The CLOSED catalog of EngineNotice codes this engine mints — the enumeration half of the
|
|
84
|
+
* presentation registry below, and the thing a consumer's own audience table can be diffed against
|
|
85
|
+
* (that is the point of exporting it: a downstream table with a row missing, or a row for a code
|
|
86
|
+
* this engine no longer mints, is a mechanically detectable disagreement rather than an argument).
|
|
87
|
+
*
|
|
88
|
+
* Kept in LOCKSTEP with {@link NOTICE_AUDIENCE} by the compiler (`satisfies Record<EngineNoticeCode,
|
|
89
|
+
* …>` below: a catalog entry with no audience row, or an audience row for a non-member, is a tsc
|
|
90
|
+
* error — a mirrored enumeration that is only checked at runtime is a mirror that drifts). The
|
|
91
|
+
* other half — "is the catalog itself still complete?" — cannot be a type: `EngineNotice.code` is
|
|
92
|
+
* declared `string` (a host may forward its own), so the gate test (governance-codes.test.ts) scans
|
|
93
|
+
* src/ for notice mint shapes and names any code that is minted but unregistered, or registered but
|
|
94
|
+
* no longer minted.
|
|
95
|
+
*/
|
|
96
|
+
export declare const ENGINE_NOTICE_CODES: readonly ["config.env_timeout_discarded", "config.materialize_env_discarded", "config.models_swapped", "config.read_face_deployment_clamped", "config.tool_model_gate_removed", "config.tool_model_gate_unknown_class", "config.tool_model_gate_env_invalid", "delegation.transcript_integrity", "mcp.revocation_probe_failed", "workflow.governance_key_stripped", "memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "memory.consolidation_recommended", "memory.consolidation_committed", "memory.consolidation_conflict", "memory.consolidation_incomplete", "memory.consolidation_refused", "route.fallback_to_primary", "route.base_url_changed_key_unchanged", "task.user_steer_undrained", "task.user_followup_undrained", "task.injection_priority_unimplemented", "tool_result.offload_put_failed"];
|
|
97
|
+
/** A code this engine mints (see {@link ENGINE_NOTICE_CODES}). NOT the type of
|
|
98
|
+
* `EngineNotice.code`, which stays `string` — a host forwarding its own notices through the same
|
|
99
|
+
* sink is a supported shape, and narrowing that field would break it. */
|
|
100
|
+
export type EngineNoticeCode = (typeof ENGINE_NOTICE_CODES)[number];
|
|
101
|
+
/**
|
|
102
|
+
* The presentation-tier registry — see {@link NOTICE_AUDIENCE_TABLE} for the per-row judgment.
|
|
103
|
+
* The exported TYPE stays the open `Record<string, …>` on purpose: a consumer indexing it with a
|
|
104
|
+
* runtime string (a code off a wire, a host's own) must keep compiling. The lockstep with
|
|
105
|
+
* {@link ENGINE_NOTICE_CODES} is enforced on the table above, where narrowing costs nobody anything.
|
|
79
106
|
*/
|
|
80
|
-
export declare const NOTICE_AUDIENCE: Readonly<Record<string,
|
|
107
|
+
export declare const NOTICE_AUDIENCE: Readonly<Record<string, NoticeAudience>>;
|
|
81
108
|
/** The audience for `code` — table lookup with the conservative `"operator"` default. */
|
|
82
|
-
export declare function noticeAudienceOf(code: string):
|
|
109
|
+
export declare function noticeAudienceOf(code: string): NoticeAudience;
|