@sema-agent/core 5.57.0 → 5.58.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 +48 -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/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.js +2 -0
- 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 +207 -0
- package/dist/core/memory-engine/consolidation-driver.js +378 -0
- package/dist/core/memory-engine/consolidation.d.ts +46 -2
- package/dist/core/memory-engine/consolidation.js +1 -0
- 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 +47 -3
- package/dist/core/memory-engine/engine.js +37 -3
- package/dist/core/memory-engine/file-backend.d.ts +1 -1
- package/dist/core/memory-engine/index.d.ts +4 -2
- package/dist/core/memory-engine/index.js +4 -2
- 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-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 +194 -31
- package/dist/core/permission-rule-model.js +93 -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 +21 -14
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +11 -11
- 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 +55 -28
- 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 +123 -70
- 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 +5 -4
- package/dist/index.js +3 -2
- 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 +56 -3
|
@@ -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;
|
|
@@ -17,11 +17,13 @@ export const NON_GOVERNANCE_MEMORY_CODES = new Set([
|
|
|
17
17
|
"memory.session_polluted",
|
|
18
18
|
"memory.harvest_quarantined",
|
|
19
19
|
"memory.delegation_static_mark_waived",
|
|
20
|
+
"memory.consolidation_driver_superseded",
|
|
20
21
|
"memory.challenge_sweep_failed",
|
|
21
22
|
"memory.lineage_settle_failed",
|
|
22
23
|
"memory.challenge_ledger_corrupt",
|
|
23
24
|
"memory.consolidation_recommended",
|
|
24
25
|
"memory.consolidation_committed",
|
|
26
|
+
"memory.consolidation_incomplete",
|
|
25
27
|
"memory.consolidation_conflict",
|
|
26
28
|
"memory.consolidation_refused",
|
|
27
29
|
"memory.consolidation_disabled",
|
package/dist/core/hooks.d.ts
CHANGED
|
@@ -161,7 +161,7 @@ export interface Hooks {
|
|
|
161
161
|
*/
|
|
162
162
|
stopFailure?(ctx: StopFailureContext): void | Promise<void>;
|
|
163
163
|
/**
|
|
164
|
-
* design/134 R5 (CC PermissionDenied parity, SDK 0.3.202
|
|
164
|
+
* design/134 R5 (CC PermissionDenied parity, SDK 0.3.202): runs when the tool gate's
|
|
165
165
|
* adjudicate chain DENY-SHORT-CIRCUITS a tool call — a ToolPolicy deny, a gate tighten (egress /
|
|
166
166
|
* irreversibility / coarse shellGate) whose `ask` resolved to deny (headless auto-deny included), or the
|
|
167
167
|
* plan-mode write-deny. Closes the observation blind spot where a blocked call fires NEITHER postToolUse
|
|
@@ -525,7 +525,7 @@ export interface StopHookContext {
|
|
|
525
525
|
/** Consecutive blocks so far in this run (resets when a stop() call lets the run proceed). */
|
|
526
526
|
consecutiveBlocks: number;
|
|
527
527
|
/**
|
|
528
|
-
* RB-177 (
|
|
528
|
+
* RB-177 (measured downstream) — a view of the conversation this hook is being asked to judge.
|
|
529
529
|
*
|
|
530
530
|
* Until now a Stop hook received two counters and nothing else. That is enough for a hook that asks
|
|
531
531
|
* "have I blocked too often?", and structurally insufficient for the entire class of hooks that ask
|
|
@@ -732,7 +732,7 @@ export interface HookInvocationIdentity {
|
|
|
732
732
|
* other absence-signaling face this module mints — "absent member" must be a fact about THIS object,
|
|
733
733
|
* and a frozen object with an ordinary prototype still answers `insideFork`/`agentName` reads (and
|
|
734
734
|
* `in` probes) from `Object.prototype`, so a prototype write elsewhere in the process could hand
|
|
735
|
-
* every leg a delegation axis the mint never stamped
|
|
735
|
+
* every leg a delegation axis the mint never stamped. `agentName` is sanitized here — it
|
|
736
736
|
* is the only member whose value a model influences.
|
|
737
737
|
*/
|
|
738
738
|
export declare function mintHookInvocationIdentity(facts: HookInvocationIdentity): HookInvocationIdentity;
|
|
@@ -986,20 +986,33 @@ export type OrgGateVerdict = {
|
|
|
986
986
|
/** The overlay's own disclosure lines (engine/deployment-authored), for the operator channel. */
|
|
987
987
|
disclosures: readonly string[];
|
|
988
988
|
};
|
|
989
|
+
/** One member of a {@link PersistedRuleHit} coverage set: a rule's canonical text plus (optionally)
|
|
990
|
+
* its add-dot identity. */
|
|
991
|
+
export interface PersistedRuleHitRule {
|
|
992
|
+
/** The canonical text of one admitting rule. */
|
|
993
|
+
readonly rule: string;
|
|
994
|
+
/** The rule's LIVE add dots (tombstoned adds already filtered by the store's read). Omitted by a
|
|
995
|
+
* lane that has the text but not the dots; the evidence then reports `"not_reported"`. */
|
|
996
|
+
readonly dots?: readonly import("./permission-rule-model.js").RuleDot[];
|
|
997
|
+
}
|
|
989
998
|
/**
|
|
990
|
-
* design/252 G-2 — the
|
|
991
|
-
*
|
|
999
|
+
* design/252 G-2, re-formed by design/375 (BREAKING) — the structured answer a persisted-rule lane
|
|
1000
|
+
* gives: the COVERAGE SET that admits the call. A single rule admitting the whole command is a
|
|
1001
|
+
* one-element set (the historical case); a compound admitted by the conjunction of per-segment rules
|
|
1002
|
+
* (design/375 §5.1) is the set of those rules, in segment order. `rules` is non-empty by contract —
|
|
1003
|
+
* an empty set covers nothing and is not a hit (the normalizer reads it as a clean negative).
|
|
992
1004
|
*
|
|
993
|
-
* Why
|
|
994
|
-
*
|
|
995
|
-
*
|
|
1005
|
+
* Why dots and not an id: a persisted allow rule HAS no scalar id — it is a (text, scope) group whose
|
|
1006
|
+
* identity is the set of add dots that redeemed it, and two concurrently approved records for one text
|
|
1007
|
+
* each carry their own. The set is the identity; a joined string would not be one.
|
|
1008
|
+
*
|
|
1009
|
+
* The pre-375 single-rule object shape (`{ rule, dots? }`) is NOT accepted: on this loosening seam an
|
|
1010
|
+
* unrecognized answer degrades to a clean negative (more asks), never to a match — the safe failure
|
|
1011
|
+
* shape for a lane that missed the same-window upgrade.
|
|
996
1012
|
*/
|
|
997
1013
|
export interface PersistedRuleHit {
|
|
998
|
-
/** The
|
|
999
|
-
readonly
|
|
1000
|
-
/** The matched rule's LIVE add dots (tombstoned adds already filtered by the store's read). Omitted
|
|
1001
|
-
* by a lane that has the text but not the dots; the evidence then reports `"not_reported"`. */
|
|
1002
|
-
readonly dots?: readonly import("./permission-rule-model.js").RuleDot[];
|
|
1014
|
+
/** The coverage set — every rule the decision stands on. Non-empty. */
|
|
1015
|
+
readonly rules: readonly PersistedRuleHitRule[];
|
|
1003
1016
|
}
|
|
1004
1017
|
/**
|
|
1005
1018
|
* design/252 G-2 — the answer a lane gives when it could not READ its store.
|
|
@@ -1014,8 +1027,20 @@ export interface PersistedRuleHit {
|
|
|
1014
1027
|
export interface PersistedRuleUnreadable {
|
|
1015
1028
|
readonly unreadable: true;
|
|
1016
1029
|
}
|
|
1030
|
+
/**
|
|
1031
|
+
* design/375 §5.2② — the CLEAN NEGATIVE that still carries the per-segment coverage table: no rule
|
|
1032
|
+
* admits the whole call, and THESE segments are the ones an eligible rule already covers. Minted by
|
|
1033
|
+
* the lane from the SAME store read that adjudicated the call (snapshot = adjudication snapshot, no
|
|
1034
|
+
* second read), and consumed only by the suggestion face — which puts on the batch offer exactly the
|
|
1035
|
+
* segments this table calls uncovered. Its DECISION meaning is identical to "no rule": the seat is
|
|
1036
|
+
* advisory, and a lane that omits it (or an unreadable one) degrades to all-uncovered, which merely
|
|
1037
|
+
* over-offers (every offered rule still passes the validator at redemption).
|
|
1038
|
+
*/
|
|
1039
|
+
export interface PersistedRuleCoverage {
|
|
1040
|
+
readonly segmentCoverage: readonly import("./permission-rule-model.js").SegmentCoverage[];
|
|
1041
|
+
}
|
|
1017
1042
|
/** Every shape a lane may answer with. A bare string stays valid and unchanged. */
|
|
1018
|
-
export type PersistedRuleAnswer = string | PersistedRuleHit | PersistedRuleUnreadable | undefined;
|
|
1043
|
+
export type PersistedRuleAnswer = string | PersistedRuleHit | PersistedRuleCoverage | PersistedRuleUnreadable | undefined;
|
|
1019
1044
|
/**
|
|
1020
1045
|
* design/252 review r3 — read a foreign {@link OrgGateVerdict} the way the personal-rule answer is read:
|
|
1021
1046
|
* OWN DATA properties only, never the prototype chain, never an accessor.
|
|
@@ -1044,9 +1069,15 @@ export declare function normalizeOrgGateVerdict(answer: unknown, unreadable: str
|
|
|
1044
1069
|
* Normalize the accepted {@link ToolGateInput.persistedRules} answers into one reading.
|
|
1045
1070
|
*
|
|
1046
1071
|
* `{}` = a clean negative (no rule admits this call). `{ unreadable: true }` = the lane could not read
|
|
1047
|
-
* its source. `{ hit }` = a match
|
|
1048
|
-
*
|
|
1049
|
-
*
|
|
1072
|
+
* its source. `{ hit }` = a match, whose `rules` is the non-empty coverage set (design/375). An answer
|
|
1073
|
+
* outside every accepted shape — a number, `null`, an object with neither `rules` nor `unreadable`, an
|
|
1074
|
+
* EMPTY `rules` array, the retired pre-375 `{ rule, dots? }` single-rule object — is read as a clean
|
|
1075
|
+
* negative rather than a match: this is a LOOSENING seam, so an answer nobody can name degrades toward
|
|
1076
|
+
* asking, never toward an allow built on it. All-or-nothing across the set's TEXTS for the same
|
|
1077
|
+
* reason: a set with one unreadable member is a different (smaller) claim than the lane made, and a
|
|
1078
|
+
* decision must not stand on a claim nobody made — one bad member drops the whole answer to the clean
|
|
1079
|
+
* negative. Per-member DOTS stay individually optional (identity lost ⇒ `"not_reported"`, exactly the
|
|
1080
|
+
* single-rule contract).
|
|
1050
1081
|
*
|
|
1051
1082
|
* The hit's dots are COPIED, not aliased. The array travels onto an ask that may sit in front of a
|
|
1052
1083
|
* person for a long time; a lane that retains and mutates its own array would otherwise change what the
|
|
@@ -1055,6 +1086,7 @@ export declare function normalizeOrgGateVerdict(answer: unknown, unreadable: str
|
|
|
1055
1086
|
export declare function normalizePersistedRuleHit(hit: PersistedRuleAnswer): {
|
|
1056
1087
|
hit?: PersistedRuleHit;
|
|
1057
1088
|
unreadable?: true;
|
|
1089
|
+
coverage?: readonly import("./permission-rule-model.js").SegmentCoverage[];
|
|
1058
1090
|
};
|
|
1059
1091
|
/** Inputs to the two-phase tool gate. `adjudicate`/`resolveAsk` are pre-bound to the task abort signal. */
|
|
1060
1092
|
export interface ToolGateInput {
|
|
@@ -1104,7 +1136,7 @@ export interface ToolGateInput {
|
|
|
1104
1136
|
/** The combined tool-policy check (abort-bound), or undefined when no policy is wired (→ allow). */
|
|
1105
1137
|
adjudicate?: (req: ToolCallRequest) => Promise<PermissionResult>;
|
|
1106
1138
|
/** Resolve an `ask` to allow/deny via `onAsk` (abort-bound). Required iff a decision can be `ask`.
|
|
1107
|
-
* G1 three-value
|
|
1139
|
+
* G1 three-value: the result may carry `approverUnavailable` — the live approver affirmed no
|
|
1108
1140
|
* operator is reachable for THIS ask; the gate then re-routes onto the durable park leg (below),
|
|
1109
1141
|
* keeping the carried fail-closed deny when no park is armed. */
|
|
1110
1142
|
resolveAsk: (decision: PermissionResult, req: ToolCallRequest) => Promise<ResolvedAsk>;
|
|
@@ -1163,7 +1195,11 @@ export interface ToolGateInput {
|
|
|
1163
1195
|
probeReason?: string,
|
|
1164
1196
|
/** backlog #239: the STRUCTURED cause (the surviving ask's `probeCause`) — same durable-route errand
|
|
1165
1197
|
* as `probeReason`, already validated at the gate. */
|
|
1166
|
-
probeCause?: import("./checkpoint-store.js").ProbeCause
|
|
1198
|
+
probeCause?: import("./checkpoint-store.js").ProbeCause,
|
|
1199
|
+
/** design/375 §5.2②: the surviving ask's engine-stamped `segmentCoverage` — threaded so the park
|
|
1200
|
+
* mint's offer factory reads the same coverage snapshot on the durable route as the synchronous
|
|
1201
|
+
* mints read off the decision (absent ⇒ all segments uncovered ⇒ over-offer, the safe way). */
|
|
1202
|
+
segmentCoverage?: readonly import("./permission-rule-model.js").SegmentCoverage[]) => Promise<ToolGateResult["suspend"] | ParkAttemptFailed | undefined>;
|
|
1167
1203
|
/**
|
|
1168
1204
|
* design/174 — route a policy `ask` on the reserved question tool to this run's CONTENT-ask channel
|
|
1169
1205
|
* before it can become a park or a refusal. Called in the `ask` branch with the FINAL post-hook,
|
|
@@ -1268,7 +1304,7 @@ export interface ToolGateInput {
|
|
|
1268
1304
|
*/
|
|
1269
1305
|
writeProtectionCheck?: (toolName: string, args: unknown) => import("./write-protect.js").WriteProtectedHit | null;
|
|
1270
1306
|
/**
|
|
1271
|
-
* design/143 批2 (
|
|
1307
|
+
* design/143 批2 (A, CC 2.1.207 auto mode): when present, a surviving `ask` is routed to the
|
|
1272
1308
|
* small-model policy CLASSIFIER before any human/durable resolution:
|
|
1273
1309
|
* - verdict `allow` → the ask resolves to allow (`decisionReason:"classifier"`) — no suspend, no onAsk;
|
|
1274
1310
|
* - verdict `block` → deny (`decisionReason:"classifier"`, `source:"classifier"`; CC `automode-blocked`);
|
|
@@ -1337,22 +1373,26 @@ export interface ToolGateInput {
|
|
|
1337
1373
|
* bullets above are what keep integrity/hook/mandated asks out of that set.
|
|
1338
1374
|
*/
|
|
1339
1375
|
persistedRules?: {
|
|
1340
|
-
/** The rule that admits this call, or `undefined`. Must not throw: a store that cannot
|
|
1341
|
-
* answers "no rule" and discloses on its own channel (fail-closed = more asks).
|
|
1376
|
+
/** The rule COVERAGE that admits this call, or `undefined`. Must not throw: a store that cannot
|
|
1377
|
+
* be read answers "no rule" and discloses on its own channel (fail-closed = more asks).
|
|
1342
1378
|
*
|
|
1343
|
-
* TWO ACCEPTED SHAPES (design/252 G-2
|
|
1344
|
-
*
|
|
1345
|
-
* text plus
|
|
1346
|
-
*
|
|
1347
|
-
*
|
|
1348
|
-
*
|
|
1349
|
-
*
|
|
1379
|
+
* TWO ACCEPTED SHAPES (design/252 G-2 / design/375 BREAKING): the canonical rule TEXT (a
|
|
1380
|
+
* single-rule hit with no identity), or a {@link PersistedRuleHit} carrying the coverage SET —
|
|
1381
|
+
* each member's canonical text plus its add DOTS. A single rule admitting the whole command is a
|
|
1382
|
+
* one-element set; a compound admitted by the per-segment conjunction (design/375 §5.1) is the
|
|
1383
|
+
* set of the covering rules. The dots are a rule's durable identity, and the text is not one (it
|
|
1384
|
+
* reaches a card sanitized and capped); a lane that can name them lets the shadowed-ask evidence
|
|
1385
|
+
* say WHICH stored rules matched rather than merely what they looked like. The retired pre-375
|
|
1386
|
+
* single-rule object shape (`{ rule, dots? }`) is read as a clean negative by the normalizer —
|
|
1387
|
+
* a stale lane degrades toward asking, never toward an allow. */
|
|
1350
1388
|
admits: (req: ToolCallRequest) => Promise<PersistedRuleAnswer>;
|
|
1351
|
-
/** Observation sink for an ask a rule resolved — the allow-side disclosure.
|
|
1389
|
+
/** Observation sink for an ask a rule coverage resolved — the allow-side disclosure. `rules` is
|
|
1390
|
+
* the coverage set's canonical texts in reporting order (design/375: a conjunction names every
|
|
1391
|
+
* rule the decision stands on). Never affects the outcome. */
|
|
1352
1392
|
onResolved?: (info: {
|
|
1353
1393
|
toolName: string;
|
|
1354
1394
|
toolCallId: string;
|
|
1355
|
-
|
|
1395
|
+
rules: readonly string[];
|
|
1356
1396
|
}) => void;
|
|
1357
1397
|
};
|
|
1358
1398
|
/**
|
|
@@ -1380,7 +1420,7 @@ export interface ToolGateInput {
|
|
|
1380
1420
|
/** True iff the reserved question-tool NAME on this leg resolves to the ENGINE's own content-ask
|
|
1381
1421
|
* tool. It is the exemption's real predicate: the name alone is not, because a caller may mount
|
|
1382
1422
|
* its own tool under that name when the first-party one is not mounted, and such a tool has
|
|
1383
|
-
* arbitrary side effects (
|
|
1423
|
+
* arbitrary side effects (confirmed MED). Absent ⇒ `false` ⇒ the call is governed
|
|
1384
1424
|
* like any other, which is the fail-closed default. */
|
|
1385
1425
|
contentAskToolMounted?: boolean;
|
|
1386
1426
|
/** Disclosure sink for the unavailable arm (trace `permission.org_snapshot_unavailable`). Never
|
|
@@ -1398,7 +1438,7 @@ export interface ToolGateInput {
|
|
|
1398
1438
|
* checkpoint store that explicitly declares `redecision.reopen`). Absent ⇒ the whole step does not
|
|
1399
1439
|
* exist and the decision path is byte-identical to a build without it.
|
|
1400
1440
|
*
|
|
1401
|
-
* Semantics (
|
|
1441
|
+
* Semantics (the ruling): inside a declared sandbox, an engine-authored "confirm a potentially
|
|
1402
1442
|
* destructive local action" ask is answered by containment itself — auto-allow + durable
|
|
1403
1443
|
* disclosure (`permission.sandbox_admitted`), never a headless deny that pollutes the model.
|
|
1404
1444
|
* STRICT dominance governs: the leg admits only when EVERY surviving ask on the call is classified
|