@sema-agent/core 7.6.0 → 7.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/dist/agents/agent-transcript-tool.d.ts +2 -2
- package/dist/agents/cascade.d.ts +2 -3
- package/dist/agents/repair-loop.d.ts +2 -2
- package/dist/agents/retain-ledger.d.ts +2 -3
- package/dist/agents/send-message-tool.d.ts +2 -2
- package/dist/agents/session-util.d.ts +2 -2
- package/dist/agents/subagent.d.ts +3 -4
- package/dist/agents/teacher.d.ts +2 -2
- package/dist/agents/team.d.ts +2 -2
- package/dist/agents/verify.d.ts +5 -6
- package/dist/core/agent-definition.d.ts +172 -0
- package/dist/core/agent-definition.js +1 -0
- package/dist/core/checkpoint-store.d.ts +8 -4
- package/dist/core/delegation-frames.d.ts +298 -0
- package/dist/core/delegation-frames.js +21 -0
- package/dist/core/engine-notice.d.ts +555 -0
- package/dist/core/engine-notice.js +55 -0
- package/dist/core/gate-fold.d.ts +12 -0
- package/dist/core/gate-fold.js +158 -0
- package/dist/core/gate-lanes.d.ts +93 -0
- package/dist/core/gate-lanes.js +626 -0
- package/dist/core/hands-band.d.ts +134 -0
- package/dist/core/hands-band.js +1 -0
- package/dist/core/hooks.d.ts +20 -101
- package/dist/core/hooks.js +53 -854
- package/dist/core/mcp-failure.d.ts +43 -5
- package/dist/core/mcp-failure.js +31 -14
- package/dist/core/mcp-server-spec.d.ts +217 -0
- package/dist/core/mcp-server-spec.js +1 -0
- package/dist/core/model-seat.d.ts +99 -0
- package/dist/core/model-seat.js +1 -0
- package/dist/core/reminder-mint.d.ts +10 -0
- package/dist/core/reminder-mint.js +3 -0
- package/dist/core/runner/contracts.d.ts +382 -6
- package/dist/core/runner/gate-exit.d.ts +177 -9
- package/dist/core/runner/gate-exit.js +70 -1
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +2 -7
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -7
- package/dist/core/runner/prepare-run-refs.d.ts +12 -0
- package/dist/core/runner/prepare-run-refs.js +5 -0
- package/dist/core/runner/prepare-task.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +4 -71
- package/dist/core/runner/runtask.js +18 -6
- package/dist/core/runner-deps.d.ts +1416 -0
- package/dist/core/runner-deps.js +1 -0
- package/dist/core/runtime-caps.d.ts +164 -0
- package/dist/core/runtime-caps.js +1 -0
- package/dist/core/task-event.d.ts +910 -0
- package/dist/core/task-event.js +1 -0
- package/dist/core/task-limits.d.ts +110 -0
- package/dist/core/task-limits.js +1 -0
- package/dist/core/task-result.d.ts +809 -0
- package/dist/core/task-result.js +1 -0
- package/dist/core/task-spec.d.ts +1370 -0
- package/dist/core/task-spec.js +1 -0
- package/dist/core/task-stream.d.ts +382 -0
- package/dist/core/task-stream.js +1 -0
- package/dist/core/tool-spec.d.ts +1174 -0
- package/dist/core/tool-spec.js +1 -0
- package/dist/core/types.d.ts +26 -7691
- package/dist/core/types.js +2 -76
- package/dist/core/warm-resume.d.ts +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/orchestration/goal.d.ts +2 -2
- package/dist/orchestration/run-spec.d.ts +2 -2
- package/dist/orchestration/run-workflow-tool.d.ts +3 -3
- package/dist/orchestration/workflow.d.ts +4 -4
- package/dist/scenarios/scenario-registry.d.ts +3 -3
- package/dist/scenarios/teacher-quickstart.d.ts +2 -2
- package/dist/server/http.d.ts +2 -2
- package/dist/stores/file/fs-atomic.d.ts +88 -12
- package/dist/stores/file/fs-atomic.js +184 -55
- package/dist/stores/file/index.d.ts +1 -0
- package/dist/stores/file/index.js +1 -0
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +9 -1
|
@@ -22,29 +22,35 @@ import type { WorkflowSizeGuideline } from "../../orchestration/workflow-size-gu
|
|
|
22
22
|
import type { ToolManifestRow } from "../../prompt-assembly/tool-catalog.js";
|
|
23
23
|
import type { CwdRef, ReadFace } from "../../tools/fs/index.js";
|
|
24
24
|
import type { MaterializedA2a } from "../a2a.js";
|
|
25
|
-
import type { CompactionForkContext } from "../auto-compaction.js";
|
|
25
|
+
import type { CompactionForkContext, MaybeCompactOptions, RapidRefillState } from "../auto-compaction.js";
|
|
26
26
|
import type { AutoModeArmingRecipe } from "../auto-mode-arming.js";
|
|
27
27
|
import type { AutoModeDecider, AutoModeDenialTracker } from "../auto-mode.js";
|
|
28
28
|
import type { CacheBreakDetector, ToolFingerprintInput } from "../cache-break-detector.js";
|
|
29
|
-
import type { Checkpoint, CheckpointState, CheckpointToken, PlatformLimitReason, ResourceLedger, ResourceLimitReason, SerializedCheckpointState } from "../checkpoint-store.js";
|
|
29
|
+
import type { ActorAssertion, Checkpoint, CheckpointState, CheckpointStore, CheckpointToken, PendingSteerEntry, PlatformLimitReason, ReopenReason, ResourceLedger, ResourceLimitReason, ResumeOutcome, SerializedCheckpointState } from "../checkpoint-store.js";
|
|
30
30
|
import type { ClearedProjectionLedger, ContextEditMachine, OccurrenceIndex } from "../context-edit.js";
|
|
31
|
-
import type { HookInvocationIdentity, Hooks, OrgGateVerdict, PermissionDeniedPayload, ToolGateInput } from "../hooks.js";
|
|
31
|
+
import type { HookInvocationIdentity, Hooks, OrgGateVerdict, PermissionDeniedPayload, PostToolBatchCall, PostToolBatchResult, ToolGateInput } from "../hooks.js";
|
|
32
32
|
import type { MaterializedMcp } from "../mcp.js";
|
|
33
33
|
import type { MemoryEngine } from "../memory-engine/engine.js";
|
|
34
34
|
import type { HarvestReport, MemorySessionHandle } from "../memory-engine/types.js";
|
|
35
35
|
import type { SessionPermissionRules } from "../session-policy-store.js";
|
|
36
36
|
import type { RecoveredOrphan } from "../session-reconcile.js";
|
|
37
|
-
import type { StoredSession } from "../session.js";
|
|
38
|
-
import type {
|
|
37
|
+
import type { SessionStore, StoredSession } from "../session.js";
|
|
38
|
+
import type { TaskOutcome } from "../task-outcome.js";
|
|
39
|
+
import type { ModelPricing } from "../pricing.js";
|
|
40
|
+
import type { PushQueue } from "../push-queue.js";
|
|
41
|
+
import type { SystemInjectionPriority, TaskNotificationPayload } from "../task-notification.js";
|
|
39
42
|
import type { OnAsk, PermissionResult, ResolvedAsk, ToolCallRequest, ToolPolicy } from "../tool-policy.js";
|
|
40
43
|
import type { RemoteExecutionEnv, SnapshotId, WorkspaceHandle } from "../remote-env.js";
|
|
41
44
|
import type { ToolDisclosureManifest } from "../trace.js";
|
|
42
|
-
import type { NestedUsageAccum, RunnerDeps, TaskEvent, TaskResult, TaskSpec, ToolActivity, ToolEffect } from "../types.js";
|
|
45
|
+
import type { AgentDefinition, Brain, CompactOutcome, NestedUsageAccum, RunnerDeps, TaskEvent, TaskResult, TaskSpec, TaskStream, ToolActivity, ToolEffect } from "../types.js";
|
|
43
46
|
import type { WiringManifest } from "../wiring-manifest.js";
|
|
44
47
|
import type { ActiveSkillFrame } from "./active-skill-scope.js";
|
|
48
|
+
import type { BudgetAxis } from "./assemble-result.js";
|
|
45
49
|
import type { GitStatusLaneRef } from "./git-status-frame.js";
|
|
46
50
|
import type { SessionReadFileStates } from "./prepare-hands-readface.js";
|
|
47
51
|
import type { BlockedRef, OutputRef, SkillListingEntry } from "./synthetic-tools.js";
|
|
52
|
+
import type { createAttachmentState, WriteFamily } from "./turn-attachments.js";
|
|
53
|
+
import type { cacheFamilyOf } from "./usage-accounting.js";
|
|
48
54
|
/**
|
|
49
55
|
* The frozen task-start snapshot of the caller's tool-face control arrays: produced by the
|
|
50
56
|
* config-doors phase, read by the hands/read-face phase. Named here rather than reached for as
|
|
@@ -1970,3 +1976,373 @@ export interface ParkAsk {
|
|
|
1970
1976
|
* lane is not armed (the gate then keeps the synchronous onAsk path). */
|
|
1971
1977
|
suspendAsk: ToolGateInput["suspendAsk"];
|
|
1972
1978
|
}
|
|
1979
|
+
/**
|
|
1980
|
+
* design/157 B15 二期 — `runLocked`'s per-run mutable state, EXPLICIT. These fields started as loose
|
|
1981
|
+
* `let`/`const` bindings in the R2 declaration hub; the extraction kept every assignment at its
|
|
1982
|
+
* original site and order (binding-form-only rewrite — the event-snapshot pin held the run
|
|
1983
|
+
* byte-identical), and later work has since added fields directly here (see the per-field notes).
|
|
1984
|
+
* Grouped by lifecycle semantics per the B15 pre-recon partition. Function members start as inert
|
|
1985
|
+
* placeholders and are assigned at their ORIGINAL declaration sites (the original code could not
|
|
1986
|
+
* call them earlier either — TDZ proved it). Not on the npm face; this extraction is what enabled
|
|
1987
|
+
* makeTurnBoundary / makeHarnessHandlers (三期, both in runtask.ts).
|
|
1988
|
+
*/
|
|
1989
|
+
export interface RunState {
|
|
1990
|
+
telemetry: {
|
|
1991
|
+
cacheFamily: ReturnType<typeof cacheFamilyOf>;
|
|
1992
|
+
pricing: ModelPricing;
|
|
1993
|
+
/** RB-368 ([2076]): whether the CURRENT serving model has a configured price table (a
|
|
1994
|
+
* `RunnerDeps.pricing` entry or a `Model.cost` declaration). When neither exists,
|
|
1995
|
+
* `modelCostToPricing(undefined)` yields an all-zero table and every computed cost is a
|
|
1996
|
+
* fabricated 0 — indistinguishable from "declared free". This flag keeps the two apart so
|
|
1997
|
+
* the DISCLOSURE faces (trace frames, public stats) can go absent instead of lying; the
|
|
1998
|
+
* internal budget coordinate (`stats.costMicroUsd`) stays numeric either way. */
|
|
1999
|
+
pricingConfigured: boolean;
|
|
2000
|
+
/** RB-368: sticky — some spend was ACCOUNTED while `pricingConfigured` was false (a mid-task
|
|
2001
|
+
* model switch can flip pricedness, so per-call state isn't enough for the task total). Once
|
|
2002
|
+
* true, the task-level cost total is an undercount and its faces are omitted. */
|
|
2003
|
+
unpricedSpend: boolean;
|
|
2004
|
+
tracer: TaskSpec["tracer"];
|
|
2005
|
+
taskId: string;
|
|
2006
|
+
/** #499 — the run's engine-minted identity, so the task.start/task.end pair carries it from ONE
|
|
2007
|
+
* seat (the same place taskId is published). Empty only before the run body assigns it. */
|
|
2008
|
+
runId: string;
|
|
2009
|
+
taskStart: number;
|
|
2010
|
+
taskStartMonotonic: number;
|
|
2011
|
+
cacheBreakReported: boolean;
|
|
2012
|
+
};
|
|
2013
|
+
degrade: {
|
|
2014
|
+
degradeToModel: Model | undefined;
|
|
2015
|
+
degraded: TaskResult["degraded"];
|
|
2016
|
+
outputErrorStreak: number;
|
|
2017
|
+
outputInvalid: boolean;
|
|
2018
|
+
recordDegraded: (info: NonNullable<TaskResult["degraded"]>, toModel?: Model) => void;
|
|
2019
|
+
};
|
|
2020
|
+
limits: {
|
|
2021
|
+
turnsExceeded: boolean;
|
|
2022
|
+
budgetHit: "exceeded" | "precall" | undefined;
|
|
2023
|
+
/** design/164 — WHICH budget axis tripped, set at the same instant as {@link budgetHit} so the
|
|
2024
|
+
* terminal can name it (`limits.max_tokens_exceeded` vs `limits.max_cost_exceeded`). Tokens
|
|
2025
|
+
* outrank cost when both are over at the same boundary (the documented attribution order). */
|
|
2026
|
+
budgetAxis: BudgetAxis | undefined;
|
|
2027
|
+
/** design/164 件四/件五 — the TYPED terminal an EXTERNAL cause (a dying execution environment, an
|
|
2028
|
+
* exhausted governance window) recorded when it could not suspend the run durably. Set together with
|
|
2029
|
+
* the abort it triggers, and adopted as the run's `threw` once the loop settles, so the caller gets
|
|
2030
|
+
* `env.lifetime_expired` / `usage.window_exhausted` instead of the anonymous error an abort produces.
|
|
2031
|
+
* Same carrier shape as `brainCallGuardrailRef.timedOut`, and for the same reason: the harness turns a
|
|
2032
|
+
* loop throw into an error assistant message that strips the error object. */
|
|
2033
|
+
platformTerminal: (Error & {
|
|
2034
|
+
code?: string;
|
|
2035
|
+
retryAfterMs?: number;
|
|
2036
|
+
}) | undefined;
|
|
2037
|
+
outputRetryCap: number;
|
|
2038
|
+
effectiveMaxTurns: number | undefined;
|
|
2039
|
+
};
|
|
2040
|
+
budget: {
|
|
2041
|
+
remainingMicroUsd: number | undefined;
|
|
2042
|
+
maxCostMicroUsd: number | undefined;
|
|
2043
|
+
/** design/164 — tokens still available on the cross-slice allocation (`resourceSuspend.totalTokens`
|
|
2044
|
+
* minus everything earlier slices spent), or `undefined` when no total is set. */
|
|
2045
|
+
remainingTokens: number | undefined;
|
|
2046
|
+
/** This slice's EFFECTIVE token ceiling = `min(limits.maxTokens, remainingTokens)`. The exact mirror
|
|
2047
|
+
* of `maxCostMicroUsd`. `undefined` = no token ceiling; `0` is a real, exhausted ceiling. */
|
|
2048
|
+
maxTokensWindow: number | undefined;
|
|
2049
|
+
/** The axis that is over its ceiling right now, or `undefined` when neither is — a predicate that
|
|
2050
|
+
* ALSO carries the attribution, so no caller can set `budgetHit` without an axis. */
|
|
2051
|
+
overBudget: () => BudgetAxis | undefined;
|
|
2052
|
+
streamCancel: boolean;
|
|
2053
|
+
callOutputChars: number;
|
|
2054
|
+
lastStreamBudgetCheck: number;
|
|
2055
|
+
projectedOverBudget: () => BudgetAxis | undefined;
|
|
2056
|
+
};
|
|
2057
|
+
turn: {
|
|
2058
|
+
callStartAt: number | undefined;
|
|
2059
|
+
firstTokenAt: number | undefined;
|
|
2060
|
+
turnUsage: {
|
|
2061
|
+
inputTokens: number;
|
|
2062
|
+
totalInputTokens: number;
|
|
2063
|
+
outputTokens: number;
|
|
2064
|
+
cacheReadTokens: number;
|
|
2065
|
+
cacheWriteTokens: number;
|
|
2066
|
+
costMicroUsd: number;
|
|
2067
|
+
} | undefined;
|
|
2068
|
+
turnUsageMissing: boolean;
|
|
2069
|
+
turnStopReason: string | undefined;
|
|
2070
|
+
lastTurnHadToolCalls: boolean;
|
|
2071
|
+
/** B15 三期使能:design/134 §3.1b postToolBatch 的本回合聚集批(每回合边界消费并重置 — 回合语义,故归 turn)。 */
|
|
2072
|
+
toolBatch: PostToolBatchCall[];
|
|
2073
|
+
};
|
|
2074
|
+
counters: {
|
|
2075
|
+
/** design/164 — how many LIMIT-APPROACH frames have been injected this run (0..2). Also the
|
|
2076
|
+
* one-shot latch itself: each frame fires when the count is still below its index. */
|
|
2077
|
+
approachNoticesSent: number;
|
|
2078
|
+
/** B15 三期使能:R9 引用的 R3/压缩区 latch(walltime 收尾 latch — preemptIgnoredReported 同族)。 */
|
|
2079
|
+
walltimeSyncBackstopFired: boolean;
|
|
2080
|
+
/** B15 三期终件补遗:压缩地板/背压 latch — rs.counters.compactionFloor 跨 drainManualCompact(写)/R9(读写)/收尾(读)三方共享,rs.counters.trimForceBackoff 为 R9 跨调用 latch(同款只改绑定不改时机)。 */
|
|
2081
|
+
compactionFloor: number;
|
|
2082
|
+
trimForceBackoff: boolean;
|
|
2083
|
+
repetitionCuts: number;
|
|
2084
|
+
repetitionSpared: number;
|
|
2085
|
+
repetitionEvents: Array<{
|
|
2086
|
+
turn: number;
|
|
2087
|
+
action: "cut" | "spared";
|
|
2088
|
+
rule: "char-run" | "unit-loop";
|
|
2089
|
+
period: number;
|
|
2090
|
+
reps: number;
|
|
2091
|
+
segment: string;
|
|
2092
|
+
}>;
|
|
2093
|
+
REPETITION_EVENTS_CAP: number;
|
|
2094
|
+
preemptIgnoredReported: boolean;
|
|
2095
|
+
wroteThisRun: boolean;
|
|
2096
|
+
finalVerifyInjections: number;
|
|
2097
|
+
groundingSignalPreR9: boolean;
|
|
2098
|
+
groundingSignalPostR9: boolean;
|
|
2099
|
+
cadenceTurns: number;
|
|
2100
|
+
};
|
|
2101
|
+
attach: {
|
|
2102
|
+
attachmentsCfg: TaskSpec["attachments"];
|
|
2103
|
+
agentListingOn: boolean;
|
|
2104
|
+
skillsListingOn: boolean;
|
|
2105
|
+
attachState: ReturnType<typeof createAttachmentState> | undefined;
|
|
2106
|
+
dateState: {
|
|
2107
|
+
announcedDate: string;
|
|
2108
|
+
} | undefined;
|
|
2109
|
+
instrProbe: RunnerDeps["probeInstructionSources"];
|
|
2110
|
+
instrState: {
|
|
2111
|
+
lastAnnouncedHash: Map<string, string | null>;
|
|
2112
|
+
} | undefined;
|
|
2113
|
+
/** #20 lane — the Workflow tool card's advisory size guideline as last ANNOUNCED to the model,
|
|
2114
|
+
* plus the live boundary-time read (Prepared.workflowSizeGuideline). Same deliberate posture as
|
|
2115
|
+
* `dateState`/`instrState`: NOT an AttachmentState member, one field, zero reducers. */
|
|
2116
|
+
sizeGuidelineState: {
|
|
2117
|
+
announcedGuideline: WorkflowSizeGuideline;
|
|
2118
|
+
current: () => WorkflowSizeGuideline;
|
|
2119
|
+
} | undefined;
|
|
2120
|
+
/** B15 三期使能:boundary 注入计数(→ stats.mechanisms.attachmentsInjected;attachState 注入族语义,故归 attach)。 */
|
|
2121
|
+
attachmentsInjected: number;
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
/** design/171 §6.3 parity, LIVE leg — one accepted live steer's REPLAY identity, the twin of the parked
|
|
2125
|
+
* queue's `samePendingSteerPayload`. `payload` is the exact string handed to the harness, so the text,
|
|
2126
|
+
* the speaker envelope and the trust framing all fold into it; `trusted` is kept SEPARATELY from those
|
|
2127
|
+
* framed bytes so a text that spells its own `<system-reminder>` wrapper can never read as the trusted
|
|
2128
|
+
* arm's byte-equal twin. `actor` carries the attribution the ledger frame reports. */
|
|
2129
|
+
export interface AcceptedSteerInput {
|
|
2130
|
+
payload: string;
|
|
2131
|
+
trusted: boolean;
|
|
2132
|
+
/** design/373 (R2-F3) — the NORMALIZED priority the call delivered under (absent input ⇒ "next"),
|
|
2133
|
+
* the replay identity's sixth axis: same id + same text at a DIFFERENT tier is not a replay —
|
|
2134
|
+
* a `next` input re-sent as `now` answering "idempotent success" without the interrupt would be
|
|
2135
|
+
* a disposition lie, so it refuses `duplicate_input_id` like any other identity mismatch. */
|
|
2136
|
+
priority: SystemInjectionPriority;
|
|
2137
|
+
actor?: ActorAssertion;
|
|
2138
|
+
}
|
|
2139
|
+
/**
|
|
2140
|
+
* Config re-supplied to {@link Runner.resume} (design/45). A suspended task's tools / model / policy /
|
|
2141
|
+
* hooks cannot be reconstructed from a checkpoint token (the session stores neither tool implementations
|
|
2142
|
+
* nor the hand band), so the caller's trusted control plane re-supplies the same {@link TaskSpec} it ran
|
|
2143
|
+
* with — minus the conversation bits: `sessionId` comes from the checkpoint and `objective` is replaced by
|
|
2144
|
+
* an internally-generated continuation, so both are omitted.
|
|
2145
|
+
*/
|
|
2146
|
+
export type ResumeTaskConfig = Omit<TaskSpec, "objective" | "sessionId">;
|
|
2147
|
+
/** design/45 resume plan threaded from {@link Runner.resume} into the shared run loop. */
|
|
2148
|
+
export interface ResumeRun {
|
|
2149
|
+
cp: Checkpoint;
|
|
2150
|
+
/**
|
|
2151
|
+
* RB-152 (2026-07-25, 按面收口): did the APPROVED ACTION actually begin executing?
|
|
2152
|
+
*
|
|
2153
|
+
* The reopen compensation used to key on an error-code whitelist (`resume.env_failed` /
|
|
2154
|
+
* `resume.session_not_found` / `resume.tool_unavailable`). That is a proxy for the thing that actually
|
|
2155
|
+
* matters, and every time a NEW way to exit without running the action appeared, the whitelist did not
|
|
2156
|
+
* know about it: a caller's abort landing anywhere between the CAS and `tool.execute` — across
|
|
2157
|
+
* `SessionStore.acquire` (pluggable, cross-network on a durable backend), the MCP reconnect, the env
|
|
2158
|
+
* rebuild, `resumeVM`, tool materialization — produced a `failed` result with NO errorCode, no reopen,
|
|
2159
|
+
* and a human approval consumed for work that never happened. Two rounds of fixes (RB-77, RB-109) each
|
|
2160
|
+
* moved that window rather than closing it, because both extended the whitelist.
|
|
2161
|
+
*
|
|
2162
|
+
* This binds the compensation to the FACT instead: set the instant before `tool.execute` for the gated
|
|
2163
|
+
* call (the same `onExecuteStart` signal the orphan-reconcile split already trusts). Every terminal —
|
|
2164
|
+
* throw OR returned result — asks one question: was the checkpoint consumed while this stayed false?
|
|
2165
|
+
*/
|
|
2166
|
+
pendingActionStarted?: boolean;
|
|
2167
|
+
/** Validated against `cp.gate.kind` at the resume entry: human/irreversible_ask→`policy_ask`,
|
|
2168
|
+
* resource_limit→`resource_limit` (design/74), needs_review→`dry_run_review` (design/76 §2.5),
|
|
2169
|
+
* plan_review→`plan_review` (design/80 D-B). The gate-match guard in `resumeStream` enforces the
|
|
2170
|
+
* correlation. design/144 §3: `wake` is the NON-GATE arm — only a checkpoint awaiting NO gate
|
|
2171
|
+
* decision passes the resume entry with it (gate purity, `wake.gate_pending`); the run loop skips
|
|
2172
|
+
* `applyResumeDecision` for it (no pending action to resolve) and re-enters via the continuation +
|
|
2173
|
+
* pendingSteer tail alone. */
|
|
2174
|
+
outcome: Extract<ResumeOutcome, {
|
|
2175
|
+
gate: "policy_ask" | "resource_limit" | "dry_run_review" | "plan_review" | "wake";
|
|
2176
|
+
}>;
|
|
2177
|
+
/** design/144 §3 (X5) — the wake's own operator message, validated (`validatePendingSteer`) at the
|
|
2178
|
+
* resume entry and carried SEPARATELY from the checkpoint's parked `pendingSteer`: a message-bearing
|
|
2179
|
+
* wake of a checkpoint that ALSO holds a parked steer must deliver BOTH (park order: parked first,
|
|
2180
|
+
* wake message second), each under its own trusted framing — the old merge-into-the-slot shape
|
|
2181
|
+
* silently DISPLACED the parked (undelivered) supervisor steer. Wake outcomes only. */
|
|
2182
|
+
wakeMessage?: Omit<PendingSteerEntry, "seq">;
|
|
2183
|
+
/** design/373 §4.3 (D2) — the userPromptSubmit screen's `additionalContext` for {@link wakeMessage},
|
|
2184
|
+
* captured at the resume ENTRY (the message is screened once, pre-CAS, on the resuming process's
|
|
2185
|
+
* hook) and delivered by the drain as the engine's own reminder AHEAD of the wake frame — carrying
|
|
2186
|
+
* it forward is what keeps the hook single-run (re-screening at the drain would be the double-run
|
|
2187
|
+
* §4.3-3 reserves for the cross-process parked leg). Present only when a wake message passed a
|
|
2188
|
+
* screen that supplied context. */
|
|
2189
|
+
wakeMessageHookContext?: string;
|
|
2190
|
+
/** Compensation hook (design/45/49): called iff the resumed run fails with `resume.env_failed` (post-CAS
|
|
2191
|
+
* workspace `resumeVM` failed) OR `resume.tool_unavailable` (P-7: the approved tool vanished) — in both
|
|
2192
|
+
* the CAS already consumed the checkpoint but the pending action never ran. `resumeStream` supplies a
|
|
2193
|
+
* closure that reopens the checkpoint (`resolved → pending`) so a retry re-resumes the SAME suspended work
|
|
2194
|
+
* instead of losing it to a forced "re-initiate". design/80 D-1 (reopen-by-reason): the `reason` is
|
|
2195
|
+
* recorded on the reopened row so the next re-resume validates per reason — an `env_failed` reopen must
|
|
2196
|
+
* replay the persisted winner (a system retry of the approved action), while a `tool_unavailable` reopen
|
|
2197
|
+
* lets a human re-decide with the tool present (a fresh decision is allowed — preserves P-7). */
|
|
2198
|
+
onEnvRestoreFailed?: (reason: ReopenReason) => Promise<void>;
|
|
2199
|
+
/** RB-471/FR-C1 — set in the run body right after `applyResumeDecision` completes: the negative-
|
|
2200
|
+
* decision twin of `pendingActionStarted`. A reject/deny consumes its gate BY BEING DELIVERED, and
|
|
2201
|
+
* this bit is the delivery fact — every throw-arm cause (prepare failure, `session_not_found`, a
|
|
2202
|
+
* pre-delivery abort) and the walltime-exhausted settle fire BEFORE it is set, so an undelivered
|
|
2203
|
+
* negative decision still reopens as `env_failed` (the retry replays the persisted decision; it
|
|
2204
|
+
* never re-asks — design/80 D-1), closing the RB-152/RB-70 loss class the first RB-471 cut reopened. */
|
|
2205
|
+
decisionDelivered?: boolean;
|
|
2206
|
+
}
|
|
2207
|
+
/**
|
|
2208
|
+
* What {@link TaskStream.destroy} needs to reap a SUSPENDED task (design/51 §4). Captured (stashed) onto
|
|
2209
|
+
* the stream handle the moment a run assembles `status:"suspended"` — `finish()` deliberately left the
|
|
2210
|
+
* paused env + committed checkpoint alive for resume, so without this stash they'd be unreachable (the
|
|
2211
|
+
* `Prepared`, and its `ownedEnv`, are GC'd once the run promise settles). `env` is `undefined` for a
|
|
2212
|
+
* process-local suspend (no remote env to reap — only the checkpoint is expired).
|
|
2213
|
+
*/
|
|
2214
|
+
export interface SuspendReap {
|
|
2215
|
+
env: Prepared["ownedEnv"];
|
|
2216
|
+
token: CheckpointToken;
|
|
2217
|
+
scope: string;
|
|
2218
|
+
store: CheckpointStore;
|
|
2219
|
+
/** The suspended task's session — for onError correlation only (the `token` is a capability and must
|
|
2220
|
+
* NEVER be logged, checkpoint-store.ts §6). */
|
|
2221
|
+
sessionId: string;
|
|
2222
|
+
}
|
|
2223
|
+
/** B15 三期终件 — R9(回合边界全域:压缩/attachments 注入/提醒节律/预算判决)工厂。
|
|
2224
|
+
* 正文自 runLocked 逐字搬迁(this 面经 runnerHooks 闭包打包,B13 #coreView 同款);模块级符号
|
|
2225
|
+
* 同文件直见不经 deps;可变运行态全在 rs(B15 二期+使能车),deps 全部为 const 稳定引用。 */
|
|
2226
|
+
export interface TurnBoundaryDeps {
|
|
2227
|
+
spec: TaskSpec;
|
|
2228
|
+
queue: PushQueue<TaskEvent>;
|
|
2229
|
+
/** The run loop's own latch — read for `userHalted` (the public `TaskStream.halt()` verb, which sets
|
|
2230
|
+
* the harness stop latch directly, not through the ctx primitive `Prepared.stopRequestedRef`
|
|
2231
|
+
* mirrors): a halted boundary has no next request either, so the bundle is not collected there. */
|
|
2232
|
+
loopLatch: {
|
|
2233
|
+
readonly userHalted: boolean;
|
|
2234
|
+
};
|
|
2235
|
+
manualCompactRef: {
|
|
2236
|
+
requested: boolean;
|
|
2237
|
+
waiters: Array<{
|
|
2238
|
+
resolve: (outcome: CompactOutcome) => void;
|
|
2239
|
+
signal?: AbortSignal;
|
|
2240
|
+
instructions?: string;
|
|
2241
|
+
}>;
|
|
2242
|
+
};
|
|
2243
|
+
todoToolMounted: boolean;
|
|
2244
|
+
taskToolsMounted: boolean;
|
|
2245
|
+
walltimeMonotonicDeadline: number | undefined;
|
|
2246
|
+
timeout: {
|
|
2247
|
+
fired: boolean;
|
|
2248
|
+
latenessMs?: number;
|
|
2249
|
+
clear: () => void;
|
|
2250
|
+
};
|
|
2251
|
+
ident: () => {
|
|
2252
|
+
eventId: string;
|
|
2253
|
+
parentToolCallId?: string;
|
|
2254
|
+
sourceTaskId?: string;
|
|
2255
|
+
};
|
|
2256
|
+
postToolBatchHook: ((batch: PostToolBatchCall[], meta?: {
|
|
2257
|
+
injectedThisTurn: "final_verification" | "finalize";
|
|
2258
|
+
}, ctx?: import("../hooks.js").PostToolBatchContext) => PostToolBatchResult | undefined | Promise<PostToolBatchResult | undefined>) | undefined;
|
|
2259
|
+
batchArgs: Map<string, unknown> | undefined;
|
|
2260
|
+
compactionBrain: Brain;
|
|
2261
|
+
withinTaskCompaction: boolean;
|
|
2262
|
+
compactionBreaker: {
|
|
2263
|
+
failures: number;
|
|
2264
|
+
};
|
|
2265
|
+
windowSafetyOptions: (mainModel: Model) => Pick<MaybeCompactOptions, "fallbackBudget" | "onWindowSafety">;
|
|
2266
|
+
rapidRefill: RapidRefillState;
|
|
2267
|
+
drainManualCompact: (outcome: CompactOutcome) => void;
|
|
2268
|
+
runnerHooks: {
|
|
2269
|
+
onError: RunnerDeps["onError"];
|
|
2270
|
+
seamCCompactionOptions: (prepared: Prepared) => Pick<MaybeCompactOptions, "summaryProvider" | "onCompaction" | "maxConsecutiveProviderReuse" | "consecutiveProviderReuse"> | undefined;
|
|
2271
|
+
compactionHookOptions: (spec: TaskSpec, sessionId: string, trigger: "auto" | "manual" | "forced") => Pick<MaybeCompactOptions, "trigger" | "preCompact" | "postCompact">;
|
|
2272
|
+
recordCompactionReuse: (prepared: Prepared, comp: {
|
|
2273
|
+
compacted: boolean;
|
|
2274
|
+
reused?: boolean;
|
|
2275
|
+
}) => void;
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
/** design/157 B15 尾件 — R5(harness 事件处理器族)的依赖包。全部为 runLocked 内声明顺序早于
|
|
2279
|
+
* 工厂调用点的 const 稳定引用 + 三个 runLocked 形参;this 面(deps.onError)经 runnerHooks 打包
|
|
2280
|
+
* (B13 #coreView / R9 TurnBoundaryDeps 同款)。*/
|
|
2281
|
+
export interface HarnessHandlersDeps {
|
|
2282
|
+
spec: TaskSpec;
|
|
2283
|
+
queue: PushQueue<TaskEvent>;
|
|
2284
|
+
internals: RunInternals | undefined;
|
|
2285
|
+
ident: () => {
|
|
2286
|
+
eventId: string;
|
|
2287
|
+
parentToolCallId?: string;
|
|
2288
|
+
sourceTaskId?: string;
|
|
2289
|
+
};
|
|
2290
|
+
parentToolCallId: string | undefined;
|
|
2291
|
+
subagentName: string | undefined;
|
|
2292
|
+
pushContent: (e: TaskEvent) => void;
|
|
2293
|
+
emitCommitted: (entryId: string, role: "user" | "assistant" | "toolResult", toolCallId?: string) => void;
|
|
2294
|
+
startedToolCallIds: Set<string>;
|
|
2295
|
+
toolStartAt: Map<string, number>;
|
|
2296
|
+
writeFamilyOf: (name: string) => WriteFamily | undefined;
|
|
2297
|
+
toolLabels: Map<string, string>;
|
|
2298
|
+
postToolBatchHook: ((batch: PostToolBatchCall[], meta?: {
|
|
2299
|
+
injectedThisTurn: "final_verification" | "finalize";
|
|
2300
|
+
}, ctx?: import("../hooks.js").PostToolBatchContext) => PostToolBatchResult | undefined | Promise<PostToolBatchResult | undefined>) | undefined;
|
|
2301
|
+
batchArgs: Map<string, unknown> | undefined;
|
|
2302
|
+
runnerHooks: {
|
|
2303
|
+
onError: RunnerDeps["onError"];
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
/**
|
|
2307
|
+
* The Runner as the modules it drives and the compositions over it see it — the delegation tools
|
|
2308
|
+
* (Agent / SendMessage / AgentTranscript), the repair, verify, cascade, teacher and team loops, the
|
|
2309
|
+
* workflow and goal orchestrations, the scenario registry, the HTTP server, `warmResume`, and the
|
|
2310
|
+
* orchestrator's own trusted `runnerSelf` seat. Every one of them used to name the `Runner` CLASS
|
|
2311
|
+
* through `import type`, which is a type edge from below the runner back up into it — a cycle the
|
|
2312
|
+
* direction gate could only carry as an exemption, and one that reached the orchestrator through the
|
|
2313
|
+
* delegation tools (prepare-task → send-message-tool → runtask).
|
|
2314
|
+
*
|
|
2315
|
+
* THE MEMBER SET IS MEASURED, NOT DESIGNED: it is exactly the union of what those consumers read off a
|
|
2316
|
+
* Runner today (a TS-Program census over `src/`, pinned in test/runner-self-seat.test.ts so a member
|
|
2317
|
+
* nobody reads reds as dead weight and a consumer reaching for a member outside it reds as a widening).
|
|
2318
|
+
* `swapModels`, `sideQuery` and the constructor are NOT here — no consumer reaches them; a host that
|
|
2319
|
+
* needs them holds the class. The class implements this interface, so the two cannot drift apart.
|
|
2320
|
+
*
|
|
2321
|
+
* Signatures are spelled out (not `Pick<Runner, …>`), because naming the class from here would be the
|
|
2322
|
+
* very edge this seat exists to remove.
|
|
2323
|
+
*/
|
|
2324
|
+
export interface RunnerSelfSeat {
|
|
2325
|
+
/** The session store this Runner was constructed over — the delegation tools acquire / release / fork through it. */
|
|
2326
|
+
readonly sessions: SessionStore;
|
|
2327
|
+
/** The deployment agent + model catalog, READ-ONLY (a fresh copy per read; the definitions are the shared objects). */
|
|
2328
|
+
readonly agentCatalog: {
|
|
2329
|
+
agents?: AgentDefinition[];
|
|
2330
|
+
builtinAgents?: boolean;
|
|
2331
|
+
models?: Record<string, Model>;
|
|
2332
|
+
};
|
|
2333
|
+
/** The deployment-level gating baseline (deps toolPolicy / hooks) as delegate wrappers — for assemblers that compose with it. */
|
|
2334
|
+
readonly gateBaseline: {
|
|
2335
|
+
toolPolicy?: RunnerDeps["toolPolicy"];
|
|
2336
|
+
hooks?: RunnerDeps["hooks"];
|
|
2337
|
+
};
|
|
2338
|
+
/** Fire `RunnerDeps.onTaskOutcome` through the swallow-guarded chokepoint (thin compositions emit at their terminal state). */
|
|
2339
|
+
emitTaskOutcome(outcome: TaskOutcome): void;
|
|
2340
|
+
/** Run a task to completion. `internals` is the TRUSTED run-scoped channel (never a TaskSpec field). */
|
|
2341
|
+
runTask(spec: TaskSpec, internals?: RunInternals): Promise<TaskResult>;
|
|
2342
|
+
/** Streaming form of {@link RunnerSelfSeat.runTask}; `resume` is the run loop's resume plan, `internals` the trusted channel. */
|
|
2343
|
+
runTaskStream(spec: TaskSpec, resume?: ResumeRun, internals?: RunInternals): TaskStream;
|
|
2344
|
+
/** Resume a suspended task from its checkpoint token with the caller's decision, to completion. */
|
|
2345
|
+
resume(token: CheckpointToken, outcome: ResumeOutcome, taskConfig: ResumeTaskConfig, internals?: RunInternals): Promise<TaskResult>;
|
|
2346
|
+
/** Streaming form of {@link RunnerSelfSeat.resume}: the pre-CAS guards and the CAS run first, then the live stream is returned. */
|
|
2347
|
+
resumeStream(token: CheckpointToken, outcome: ResumeOutcome, taskConfig: ResumeTaskConfig, internals?: RunInternals): Promise<TaskStream>;
|
|
2348
|
+
}
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
* and who asked. The gate accumulates two facts on its way to an exit (WHO refused, written once at the
|
|
4
|
-
* refusing site; WHAT was settled, written at the resolution site) and hands them here; this module
|
|
5
|
-
* assembles the record, runs the invariant screen, and refuses a record the engine composed wrong. Every
|
|
6
|
-
* projection of the outcome (the deny observer's payload, the call's `tool_end` frame, the engine's
|
|
7
|
-
* per-call sideband) is the object minted here, never a re-derivation.
|
|
2
|
+
* The tool gate's RECORD FLOOR — everything about how one gate pass is recorded and how it ends:
|
|
8
3
|
*
|
|
9
|
-
*
|
|
4
|
+
* - the ONE mint of a {@link GateOutcome} ({@link mintGateOutcome}) — the record of what a tool-gate pass
|
|
5
|
+
* decided, what ask it settled and who asked. The gate accumulates two facts on its way to an exit (WHO
|
|
6
|
+
* refused, written once at the refusing site; WHAT was settled, written at the resolution site) and hands
|
|
7
|
+
* them here; the mint assembles the record, runs the invariant screen, and refuses a record the engine
|
|
8
|
+
* composed wrong. Every projection of the outcome (the deny observer's payload, the call's `tool_end`
|
|
9
|
+
* frame, the engine's per-call sideband) is the object minted here, never a re-derivation;
|
|
10
|
+
* - the settlement LEDGER of a pass ({@link createSettlementLedger}) — the one rule every attestation read
|
|
11
|
+
* goes through;
|
|
12
|
+
* - the PASS RECORD ({@link GatePass}) — the per-call cells the gate's station groups read and write, and
|
|
13
|
+
* the hook-machinery seats they borrow, built once per call by `runToolGate` and handed to every station;
|
|
14
|
+
* - the EXITS — the two phase-1 short-circuits ({@link engineFailClosedExit}, {@link hookDenyExit}) and the
|
|
15
|
+
* single deny / allow exit of the adjudicate chain ({@link exitGate}), the only places a pass turns into a
|
|
16
|
+
* `ToolGateResult`; plus the two observer-facing helpers every exit uses (the payload isolation clone and
|
|
17
|
+
* the deployment-lane crash report).
|
|
18
|
+
*
|
|
19
|
+
* A floor module (layer 0 of the prepare/run path): the two station modules (`gate-fold.ts`, `gate-lanes.ts`)
|
|
20
|
+
* and the gate's dispatch in `hooks.ts` all reach DOWN for it, and it reaches down only for the vocabulary,
|
|
21
|
+
* the reminder envelope and the text helpers. Its `import type` edges up to `hooks.ts` name the gate's public
|
|
22
|
+
* contract (`ToolGateInput`, `ToolGateResult`, the observer payload), which stays declared there.
|
|
10
23
|
*/
|
|
11
24
|
import { type DeniedBy, type GateOutcome, type Settlement } from "../gate-outcome.js";
|
|
12
|
-
import type { AskOrigin } from "../ask-origin.js";
|
|
13
|
-
import { type PermissionResult, type ResolvedAsk } from "../tool-policy.js";
|
|
25
|
+
import type { AskOrigin, AskOriginFacts } from "../ask-origin.js";
|
|
26
|
+
import { type PermissionResult, type ResolvedAsk, type ToolCallRequest } from "../tool-policy.js";
|
|
27
|
+
import type { SafeNotifier } from "../safe-notify.js";
|
|
28
|
+
import type { HookSeatOutcome, PermissionDeniedPayload, PreToolUseResult, ToolGateInput, ToolGateResult } from "../hooks.js";
|
|
14
29
|
/** The ask a gate pass settled, as the gate captured it at its resolution site: the settlement the
|
|
15
30
|
* resolver composed and the origin word the ask carried. Both or neither (invariant I1). */
|
|
16
31
|
export interface SettledAsk {
|
|
@@ -72,3 +87,156 @@ export declare function createSettlementLedger(call: {
|
|
|
72
87
|
toolCallId: string;
|
|
73
88
|
toolName: string;
|
|
74
89
|
}): SettlementLedger;
|
|
90
|
+
/**
|
|
91
|
+
* 1.256 复审 MED-1 — observe-only payload isolation for {@link import("../hooks.js").Hooks.permissionDenied}:
|
|
92
|
+
* clone the tool args before they ride the observer payload, so a hook mutating `payload.input` can never
|
|
93
|
+
* pollute the LIVE args object (later events / audit records share it). Same posture as the postToolUseFailure
|
|
94
|
+
* details clone (the gate-stations phase): `structuredClone` first; a non-structured-cloneable graph
|
|
95
|
+
* (functions/handles) falls back to a SHALLOW plain object/array copy (top-level mutation isolated);
|
|
96
|
+
* a non-object primitive passes through as-is (immutable anyway).
|
|
97
|
+
*/
|
|
98
|
+
export declare function cloneObserverInput(input: unknown): unknown;
|
|
99
|
+
/** RB-442: hand the crash itself to the deployment's trace lane (`onError(phase:"hook")`), never letting a
|
|
100
|
+
* throwing sink alter the fail-closed outcome — the same swallow posture as every other observer here.
|
|
101
|
+
* Shared by the gate's dispatch (the phase-1 crash arm, the seat-bound refusal), the reversibility probe's
|
|
102
|
+
* two failure arms and the approved-edit re-screen. */
|
|
103
|
+
export declare function traceHookCrash(input: ToolGateInput, err: unknown, notifier: SafeNotifier): void;
|
|
104
|
+
/**
|
|
105
|
+
* The PreToolUse screening face as the gate's stations see it — the hook machinery of `runToolGate` (the seat
|
|
106
|
+
* runner, the per-call seat bound, the fresh per-screening context, the result screen, the two fail-closed
|
|
107
|
+
* reason texts) behind three methods, so the approved-edit re-screen in the lanes runs the SAME screening the
|
|
108
|
+
* phase-1 pass ran without the lanes module reaching into the hook machinery. Present on the pass exactly when
|
|
109
|
+
* a `preToolUse` face is wired.
|
|
110
|
+
*/
|
|
111
|
+
export interface PreToolUseScreening {
|
|
112
|
+
/** Run the deployment's PreToolUse face over `args` under the seat bound. The answer is the SEAT's, unscreened —
|
|
113
|
+
* the caller passes it through {@link PreToolUseScreening.screened} in the seat's own continuation. The seat
|
|
114
|
+
* promise is returned as is (no wrapping `async`): what the gate does after the face answers — the policy in
|
|
115
|
+
* phase 1, the re-check in the edit chain — runs on the tick the seat settles, as it did when this call was the
|
|
116
|
+
* seat runner's own; a wrapper that screened the answer inside a second `async` cost one more tick there. An
|
|
117
|
+
* expired seat is reported, not thrown; a crashing face rejects. */
|
|
118
|
+
screen(args: unknown): Promise<HookSeatOutcome<PreToolUseResult | undefined>>;
|
|
119
|
+
/** The result screen over an answered seat's value: an out-of-contract decision becomes the ordinary hook deny. */
|
|
120
|
+
screened(answer: PreToolUseResult | undefined): PreToolUseResult | undefined;
|
|
121
|
+
/** The model-facing text for a face that THREW while screening `subject`. */
|
|
122
|
+
crashReason(subject: string, err: unknown): string;
|
|
123
|
+
/** The model-facing text for a face that never ANSWERED while screening `subject` (the timeout arm also
|
|
124
|
+
* reports on the deployment lane; a task-abort expiry does not). */
|
|
125
|
+
unansweredReason(subject: string, cause: "timeout" | "aborted"): Promise<string>;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* ONE gate pass — the record the station groups (`runGateFold`, `runGateLanes`) and the exits read and write,
|
|
129
|
+
* built once per call by `runToolGate` before the screening pass. What used to be the closure-captured `let`
|
|
130
|
+
* cells of a 1 500-line function are its MUTABLE cells (each written by the station named on it, read by the
|
|
131
|
+
* ones after); what the stations borrow from the hook machinery are its SEATS (fixed for the pass). Ownership
|
|
132
|
+
* classes follow the phase-Input convention: `borrowed-readonly` = fixed for the pass, the stations only read
|
|
133
|
+
* it; `borrowed-mutable` = a cell a station writes.
|
|
134
|
+
*/
|
|
135
|
+
export interface GatePass {
|
|
136
|
+
/** borrowed-readonly — the gate's input: every deployment seat the stations read by name (`egress`,
|
|
137
|
+
* `orgRules`, `persistedRules`, `autoMode`, …), and the identity / reminder mark the exits stamp. */
|
|
138
|
+
readonly input: ToolGateInput;
|
|
139
|
+
/** borrowed-readonly — the gate's event, read ONCE at entry (the dispatch's entry destructure): the exit compares the
|
|
140
|
+
* final args against THIS event's input, never against a re-read of the input record. */
|
|
141
|
+
readonly event: ToolGateInput["event"];
|
|
142
|
+
/** borrowed-readonly — the deployment's policy face, captured ONCE at entry before the screening pass. The fold
|
|
143
|
+
* adjudicates through it and the edit chain re-adjudicates through the SAME binding: a stateful accessor on the
|
|
144
|
+
* input cannot hand the fold one policy and the approved-edit re-check another (or none). */
|
|
145
|
+
readonly adjudicate: ToolGateInput["adjudicate"];
|
|
146
|
+
/** borrowed-readonly — the ask resolver, captured ONCE at entry (same rule: the first-round resolution and the edit
|
|
147
|
+
* round's re-ask resolve through one binding). */
|
|
148
|
+
readonly resolveAsk: ToolGateInput["resolveAsk"];
|
|
149
|
+
/** borrowed-readonly — the durable park closure, captured ONCE at entry (the three park sites hand it the same
|
|
150
|
+
* thirteen seats; presence is judged off this one read). */
|
|
151
|
+
readonly suspendAsk: ToolGateInput["suspendAsk"];
|
|
152
|
+
/** borrowed-readonly — `input.event.toolName`, read once. */
|
|
153
|
+
readonly toolName: string;
|
|
154
|
+
/** borrowed-readonly — `input.event.toolCallId`, read once. */
|
|
155
|
+
readonly toolCallId: string;
|
|
156
|
+
/** borrowed-readonly — design/384: ONE read of the per-call signal for the whole gate call (the one-read
|
|
157
|
+
* discipline the settlement screen already states): every conditional seat invocation (the three wait
|
|
158
|
+
* seats plus the three suspendAsk park sites) judges presence and passes the value from this same cell, so
|
|
159
|
+
* a stateful accessor cannot answer the arity check with a signal and the call with something else. */
|
|
160
|
+
readonly callSignal: AbortSignal | undefined;
|
|
161
|
+
/** borrowed-readonly — RB-463: the one host-callback isolation scope of this gate call (the deny observer,
|
|
162
|
+
* the hook-error trace sink, the org and rule lanes' disclosure sinks). */
|
|
163
|
+
readonly notifier: SafeNotifier;
|
|
164
|
+
/** borrowed-readonly — the settlement LEDGER of this pass (the binding is fixed; the ledger's own methods
|
|
165
|
+
* are how the resolution sites write it — one rule per read, see {@link createSettlementLedger}). */
|
|
166
|
+
readonly ledger: SettlementLedger;
|
|
167
|
+
/** borrowed-readonly — the ONE emission seat of the deny observer for this pass, bounded and contained like
|
|
168
|
+
* every other seat (the hook machinery owns the seat runner; the exits call this). */
|
|
169
|
+
readonly notifyPermissionDenied: (payload: Omit<PermissionDeniedPayload, "signal">) => Promise<void>;
|
|
170
|
+
/** borrowed-readonly — the PreToolUse screening face ({@link PreToolUseScreening}), or undefined when no
|
|
171
|
+
* `preToolUse` face is wired (the edit chain then re-screens nothing, as before). */
|
|
172
|
+
readonly screening: PreToolUseScreening | undefined;
|
|
173
|
+
/** borrowed-readonly — the station group that runs AFTER the fold (the lanes: org layer, rule lane, classifier,
|
|
174
|
+
* parks, resolution, edit chain, and the exit they end in), handed the pass by the fold's LAST station on the
|
|
175
|
+
* fold's own completing tick. A seat rather than an import because the two station modules sit on one layer
|
|
176
|
+
* and may not name each other; a seat rather than a second `await` in the dispatch because that await is a
|
|
177
|
+
* suspension point of its own: the org face and the rule store read HOST state the host may refresh
|
|
178
|
+
* concurrently, and the tick on which they are consulted is the contract — when the station bodies were one
|
|
179
|
+
* function, the org face was invoked in the same continuation that ran the last tighten, and a refresh queued
|
|
180
|
+
* behind the policy's answer could not land in between. Returns the gate result (a park's suspension or the
|
|
181
|
+
* exit's record). Writer: the dispatch (`runToolGate`, which wires `runGateLanes`). Reader: the fold's tail. */
|
|
182
|
+
readonly afterFold: (pass: GatePass) => Promise<ToolGateResult>;
|
|
183
|
+
/** borrowed-mutable — the FINAL args: the model's input, rewritten by the phase-1 hook, by the policy
|
|
184
|
+
* rewrite on the ask path, by the content-ask lane's presented snapshot and by the exits' rewrite fold.
|
|
185
|
+
* Writers: the dispatch (phase 1), the lanes, the exits. */
|
|
186
|
+
currentInput: unknown;
|
|
187
|
+
/** borrowed-mutable — the adjudication request. Minted over the model's input so the record is whole from
|
|
188
|
+
* the first station, and RE-MINTED by the adjudication station over the FINAL post-screen args (the
|
|
189
|
+
* pre-existing `const req` site); `args` is re-pointed at the policy rewrite on the ask path and at the
|
|
190
|
+
* content-ask lane's presented snapshot. Writers: the fold (mint), the lanes (`args`). */
|
|
191
|
+
req: ToolCallRequest;
|
|
192
|
+
/** borrowed-mutable — the PreToolUse `additionalContext` collected for this call (pushed into; the binding
|
|
193
|
+
* is fixed). Writers: the dispatch (phase 1), the lanes (sandbox admission note, the edit re-screen). */
|
|
194
|
+
readonly preToolContext: string[];
|
|
195
|
+
/** borrowed-mutable — the phase-1 hook's ASK, remembered for the fold. Only ever an ask (assigned under the
|
|
196
|
+
* `r.action === "ask"` arm); typed as the narrowed member so the fold's reconstruction reads the ask-only
|
|
197
|
+
* fields without a runtime re-test that could, if it ever failed, silently skip the promotion (i.e. loosen).
|
|
198
|
+
* Writer: the dispatch (phase 1). Readers: the fold, the sandbox-admission conjunct. */
|
|
199
|
+
hookAsk: Extract<PermissionResult, {
|
|
200
|
+
action: "ask";
|
|
201
|
+
}> | undefined;
|
|
202
|
+
/** borrowed-mutable — set by a park attempt that FAILED (see `ParkAttemptFailed`). Read at the single deny
|
|
203
|
+
* exit — whatever the fallback chain then decides to say, it says it knowing the park was tried first.
|
|
204
|
+
* Writers: the three park sites. */
|
|
205
|
+
parkFailed: string | undefined;
|
|
206
|
+
/** borrowed-mutable — WHO refused, written ONCE by the refusing site (a direct policy / org / classifier
|
|
207
|
+
* deny, a hook re-screen refusal, the write-protection re-judge, the edit chain's cap, an ask resolution
|
|
208
|
+
* that ended as a refusal). The exit mints the outcome from it beside the ledger's `settled`; a refusal
|
|
209
|
+
* that reaches the exit without it is an engine defect and the mint throws. */
|
|
210
|
+
deniedBy: DeniedBy | undefined;
|
|
211
|
+
/** borrowed-mutable — the standing verdict. The no-policy default until the adjudication station writes the
|
|
212
|
+
* policy's answer; then rewritten by every station that changes the verdict (fold, tightens, org, rule
|
|
213
|
+
* lane, stamp, classifier, sandbox, content lane, resolution, edit chain). */
|
|
214
|
+
decision: PermissionResult;
|
|
215
|
+
/** borrowed-mutable — which of the gate's OWN post-fold tightens minted the standing ask, if one did — an
|
|
216
|
+
* input of the ask-origin derivation (`AskOriginFacts.tightened`). Written at most once per pass: every
|
|
217
|
+
* tighten fires only over a surviving `allow`, and the first one to fire leaves an `ask` the others do not
|
|
218
|
+
* touch. Recorded by the gate rather than read off `decisionReason` because that member is a policy's to
|
|
219
|
+
* compose (a policy stamping `"safety"` on its own ask must read as `policy`). Writer: the fold. */
|
|
220
|
+
tightenedBy: AskOriginFacts["tightened"];
|
|
221
|
+
/** borrowed-mutable — the rewrite remembered BEFORE a hook-ask promotion / tighten, re-applied on the
|
|
222
|
+
* approved path (a redaction is not cancelled because a person confirmed). Writer: the fold. Readers: the
|
|
223
|
+
* fold's probe and write-protection judges, the lanes, the allow exit. */
|
|
224
|
+
policyRewrite: unknown;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The engine's fail-closed block of phase 1 — the PreToolUse face THREW or never ANSWERED, so the engine
|
|
228
|
+
* decides, on its own rule, that the call does not run. design/134 R5 BOUNDARY (deliberate asymmetry with
|
|
229
|
+
* {@link hookDenyExit} — do NOT unify the two): a hook `deny` is the HOOK's decision and the observer
|
|
230
|
+
* exclusion covers it; a crash / an unanswered seat produces no decision at all, so the deny OBSERVER fires
|
|
231
|
+
* here — an attribution channel whose job is "why was this call denied" must see an engine deny, or the
|
|
232
|
+
* deployment's only evidence of a broken hook is a tool that mysteriously stops working.
|
|
233
|
+
*/
|
|
234
|
+
export declare function engineFailClosedExit(pass: GatePass, reason: string): Promise<ToolGateResult>;
|
|
235
|
+
/** The hook's OWN deny in phase 1. design/134 R5: a PreToolUse hook deny does NOT fire `permissionDenied`
|
|
236
|
+
* (the exclusion recorded on `Hooks.permissionDenied`) — this return stays observer-free. */
|
|
237
|
+
export declare function hookDenyExit(pass: GatePass, r: PreToolUseResult): ToolGateResult;
|
|
238
|
+
/**
|
|
239
|
+
* The exit of the adjudicate chain — the pass has a standing `deny` or `allow` (every ask was resolved or
|
|
240
|
+
* parked before this), and this is where it becomes the gate result and the ONE record of the pass.
|
|
241
|
+
*/
|
|
242
|
+
export declare function exitGate(pass: GatePass): Promise<ToolGateResult>;
|