@sema-agent/core 7.11.1 → 7.12.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 +41 -0
- package/dist/core/auto-mode-arming.d.ts +10 -14
- package/dist/core/auto-mode-arming.js +3 -9
- package/dist/core/auto-mode-defaults.d.ts +0 -2
- package/dist/core/auto-mode-defaults.js +0 -1
- package/dist/core/auto-mode-rebuild.d.ts +6 -13
- package/dist/core/auto-mode-rebuild.js +0 -2
- package/dist/core/auto-mode.d.ts +30 -89
- package/dist/core/auto-mode.js +12 -59
- package/dist/core/checkpoint-store.d.ts +1 -3
- package/dist/core/gate-fold.js +1 -9
- package/dist/core/gate-lanes.js +15 -9
- package/dist/core/hooks.d.ts +6 -0
- package/dist/core/runner/compaction-knobs.d.ts +45 -0
- package/dist/core/runner/compaction-knobs.js +3 -0
- package/dist/core/runner/contracts.d.ts +49 -10
- package/dist/core/runner/denial-limit-arms.d.ts +10 -13
- package/dist/core/runner/denial-limit-arms.js +9 -7
- package/dist/core/runner/gate-exit.js +9 -1
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +1 -1
- package/dist/core/runner/prepare-caps-and-workflow.js +0 -5
- package/dist/core/runner/prepare-suspend-saga.d.ts +0 -2
- package/dist/core/runner/prepare-suspend-saga.js +2 -10
- package/dist/core/runner/prepare-task.js +1 -1
- package/dist/core/runner/prepare-wiring-manifest.d.ts +1 -1
- package/dist/core/runner/prepare-wiring-manifest.js +1 -8
- package/dist/core/runner/run-attachment-seats.d.ts +22 -0
- package/dist/core/runner/run-attachment-seats.js +187 -0
- package/dist/core/runner/run-brain-sinks.d.ts +29 -0
- package/dist/core/runner/run-brain-sinks.js +61 -0
- package/dist/core/runner/run-clock-and-content.d.ts +52 -0
- package/dist/core/runner/run-clock-and-content.js +26 -0
- package/dist/core/runner/run-compaction-machinery.d.ts +35 -0
- package/dist/core/runner/run-compaction-machinery.js +98 -0
- package/dist/core/runner/run-git-lane.d.ts +64 -0
- package/dist/core/runner/run-git-lane.js +102 -0
- package/dist/core/runner/run-identity-wiring.d.ts +77 -0
- package/dist/core/runner/run-identity-wiring.js +85 -0
- package/dist/core/runner/run-leg.d.ts +106 -0
- package/dist/core/runner/run-leg.js +462 -0
- package/dist/core/runner/run-notification-lane.d.ts +55 -0
- package/dist/core/runner/run-notification-lane.js +128 -0
- package/dist/core/runner/run-reasoning-seat.d.ts +27 -0
- package/dist/core/runner/run-reasoning-seat.js +48 -0
- package/dist/core/runner/run-recovery-lanes.d.ts +54 -0
- package/dist/core/runner/run-recovery-lanes.js +180 -0
- package/dist/core/runner/run-settle-and-teardown.d.ts +109 -0
- package/dist/core/runner/run-settle-and-teardown.js +324 -0
- package/dist/core/runner/run-stop-and-final-verify.d.ts +32 -0
- package/dist/core/runner/run-stop-and-final-verify.js +159 -0
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +38 -0
- package/dist/core/runner/run-telemetry-and-budget-seats.js +159 -0
- package/dist/core/runner/run-terminal-adoption.d.ts +99 -0
- package/dist/core/runner/run-terminal-adoption.js +120 -0
- package/dist/core/runner/run-tool-mount-facts.d.ts +26 -0
- package/dist/core/runner/run-tool-mount-facts.js +58 -0
- package/dist/core/runner/run-turn-boundary.d.ts +0 -35
- package/dist/core/runner/run-turn-boundary.js +1 -3
- package/dist/core/runner/runtask.d.ts +14 -3
- package/dist/core/runner/runtask.js +125 -2102
- package/dist/core/runner-deps.d.ts +4 -14
- package/dist/core/store-contracts/workflow-journal-store-contract.d.ts +7 -0
- package/dist/core/store-contracts/workflow-journal-store-contract.js +85 -0
- package/dist/core/tool-policy.d.ts +37 -93
- package/dist/core/tool-policy.js +1 -11
- package/dist/core/trace.d.ts +6 -7
- package/dist/core/wiring-manifest.d.ts +5 -22
- package/dist/core/wiring-manifest.js +3 -11
- package/dist/core/workflow-journal-store.d.ts +35 -4
- package/dist/core/workflow-journal-store.js +19 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/orchestration/workflow.js +2 -0
- package/dist/stores/file/workflow-journal-store.d.ts +7 -10
- package/dist/stores/file/workflow-journal-store.js +2 -4
- package/dist/tools/fs/fs-bash.js +3 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +10 -10
package/dist/core/gate-lanes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decisionText, describeThrown } from "./tool-policy.js";
|
|
2
2
|
import { askOriginOf, classifierMayAnswer } from "./ask-origin.js";
|
|
3
|
-
import { denialLimitFallbackMessage, unarmedWindow } from "./auto-mode.js";
|
|
3
|
+
import { CLASSIFIER_PARSE_FAILURE_DENY_MESSAGE, classifierUnavailableDenyMessage, denialLimitFallbackMessage, unarmedWindow } from "./auto-mode.js";
|
|
4
4
|
import { inlineUntrusted } from "./untrusted-text.js";
|
|
5
5
|
import { isRuleBehavior } from "./permission-rule-model.js";
|
|
6
6
|
import { ASK_USER_QUESTION_TOOL_NAME } from "./ask-question.js";
|
|
@@ -388,9 +388,17 @@ export async function runGateLanes(pass) {
|
|
|
388
388
|
...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}),
|
|
389
389
|
};
|
|
390
390
|
}
|
|
391
|
-
else if (verdict.kind === "
|
|
392
|
-
|
|
393
|
-
|
|
391
|
+
else if (verdict.kind === "unavailable") {
|
|
392
|
+
pass.decision = {
|
|
393
|
+
action: "deny",
|
|
394
|
+
message: classifierUnavailableDenyMessage(toolName, verdict.cause),
|
|
395
|
+
decisionReason: "classifier",
|
|
396
|
+
classifierUnavailable: { cause: verdict.cause },
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
const reason = verdict.kind === "block" ? (verdict.reason ? inlineUntrusted(verdict.reason) : "") : CLASSIFIER_PARSE_FAILURE_DENY_MESSAGE;
|
|
401
|
+
const category = verdict.kind === "block" && verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
394
402
|
const tracked = input.autoMode.denialTracking?.recordBlock();
|
|
395
403
|
if (tracked?.limitReached === true) {
|
|
396
404
|
const fallbackAsk = {
|
|
@@ -405,15 +413,13 @@ export async function runGateLanes(pass) {
|
|
|
405
413
|
else {
|
|
406
414
|
pass.decision = {
|
|
407
415
|
action: "deny",
|
|
408
|
-
message: `auto-mode classifier blocked this call${reason ? `: ${reason}` : category ? `: [${category}]` : ""}
|
|
416
|
+
message: verdict.kind === "block" ? `auto-mode classifier blocked this call${reason ? `: ${reason}` : category ? `: [${category}]` : ""}` : reason,
|
|
409
417
|
decisionReason: "classifier",
|
|
410
418
|
};
|
|
411
|
-
pass.deniedBy = "classifier";
|
|
412
419
|
}
|
|
413
420
|
}
|
|
414
|
-
|
|
415
|
-
pass.
|
|
416
|
-
}
|
|
421
|
+
if (pass.decision.action === "deny")
|
|
422
|
+
pass.deniedBy = "classifier";
|
|
417
423
|
}
|
|
418
424
|
if (input.sandboxAdmission !== undefined &&
|
|
419
425
|
pass.decision.action === "ask" &&
|
package/dist/core/hooks.d.ts
CHANGED
|
@@ -411,6 +411,12 @@ export interface PermissionDeniedPayload {
|
|
|
411
411
|
* settled none.
|
|
412
412
|
*/
|
|
413
413
|
gate: GateOutcome;
|
|
414
|
+
/** #661 (additive): present ⇔ this deny is the auto-mode classifier's UNAVAILABILITY (`deniedBy: "classifier"`
|
|
415
|
+
* with the verdict's cause word) — the structured half of the deny text's "the classifier is temporarily
|
|
416
|
+
* unavailable" sentence. A classifier BLOCK or parse-failure deny carries no member here. */
|
|
417
|
+
classifierUnavailable?: {
|
|
418
|
+
readonly cause: import("./auto-mode.js").AutoModeUnavailableCause;
|
|
419
|
+
};
|
|
414
420
|
/** {@link HookSeatSignal} — this invocation's own abort signal. On an OBSERVATION seat the deny has
|
|
415
421
|
* already happened and nothing this callback does can change it, so the signal says exactly one
|
|
416
422
|
* thing: stop reading, nobody is waiting for your answer any more. */
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The run loop's three compaction knobs (design/393 S5): the consecutive-failure breaker trip, the anti-thrash
|
|
3
|
+
* regrowth factor and the effective-compaction epsilon. They were declared at the turn-boundary lane and the driver
|
|
4
|
+
* reached DOWN for them; the recovery lane (the forced-compaction pass the prompt-too-long and guard-chain arms
|
|
5
|
+
* share) reads the same three, and a lane may not name a sibling lane — so the three values sank to the machinery
|
|
6
|
+
* stratum, where the two lanes and the driver all reach down for them. Values verbatim, comments included.
|
|
7
|
+
*
|
|
8
|
+
* No `run-` family prefix, for the reason initial-run-state.ts gives: a module the lanes stand on is not a driven
|
|
9
|
+
* lane, and the prefix would put it under the phase-api gate and the run-lanes glob.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* §17.4 (design/64 GAP-25): stop attempting within-task compaction after this many CONSECUTIVE
|
|
13
|
+
* failures in one task — a never-recovering summary gateway must not burn an API call at every turn
|
|
14
|
+
* boundary (CC: MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3). Reset on any success; an open breaker also
|
|
15
|
+
* skips the end-of-task attempt in `finish()` (teardown unaffected). Per-task scope.
|
|
16
|
+
*
|
|
17
|
+
* RB-190 — this used to say "a flaky/never-recovering gateway", and the word `flaky` was not true. Because
|
|
18
|
+
* any success zeroes the counter, a gateway that alternates never reaches three CONSECUTIVE failures and
|
|
19
|
+
* the breaker never opens; it keeps paying for a call at every failed boundary, indefinitely.
|
|
20
|
+
*
|
|
21
|
+
* The behaviour is right and stays: a gateway succeeding half the time is compacting half the time, and
|
|
22
|
+
* opening the breaker on it would disable compaction outright and let the context overflow — trading a
|
|
23
|
+
* wasted call for a failed task. What was wrong is the comment claiming a guarantee the code does not
|
|
24
|
+
* make. An alternating gateway is deliberately NOT caught here; if that ever needs catching it wants a
|
|
25
|
+
* different signal (a failure RATE over a window), not a consecutive counter.
|
|
26
|
+
*/
|
|
27
|
+
export declare const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;
|
|
28
|
+
/**
|
|
29
|
+
* §25.2 anti-thrash (LONGRUN-1b, search [84]): after a compaction, the context must regrow past
|
|
30
|
+
* (tokensBefore − freed) × this factor — the post-compaction size in trigger units — before another
|
|
31
|
+
* summary call fires. An EFFECTIVE compaction (freed large) leaves the floor far below the threshold,
|
|
32
|
+
* so behavior is unchanged; an INEFFECTIVE one (small window, chunky turns, large summary ⇒ freed
|
|
33
|
+
* small, still at/over the threshold) raises the floor so attempts space out instead of firing at
|
|
34
|
+
* every boundary (measured: 26/39 boundaries, +135% wall). The floor binds only when post-compaction
|
|
35
|
+
* size > threshold/1.5 ≈ compaction freed <33% headroom. Degrades gracefully: the retained summary
|
|
36
|
+
* chain keeps early facts; only the un-summarized tail falls back to trim.
|
|
37
|
+
*/
|
|
38
|
+
export declare const COMPACTION_REGROWTH_FACTOR = 1.5;
|
|
39
|
+
/**
|
|
40
|
+
* design/84 Seam C reuse guard (b): a compaction that frees fewer than this many (structural) tokens is
|
|
41
|
+
* treated as NO-EFFECTIVE-COMPACTION and does NOT raise the anti-thrash floor. Guards against a reused
|
|
42
|
+
* provider summary (or a pathological LLM summary) that reclaims no headroom yet suppresses the next real
|
|
43
|
+
* summary by inflating the floor to trigger×factor.
|
|
44
|
+
*/
|
|
45
|
+
export declare const COMPACTION_FREED_EPSILON = 256;
|
|
@@ -22,7 +22,7 @@ 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, MaybeCompactOptions, RapidRefillState } from "../auto-compaction.js";
|
|
25
|
+
import type { CompactionForkContext, CompactionPhaseDurations, 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";
|
|
@@ -1778,14 +1778,6 @@ export interface RunInternals {
|
|
|
1778
1778
|
* channel, same posture as every other field here.
|
|
1779
1779
|
*/
|
|
1780
1780
|
sessionReadStates?: SessionReadFileStates;
|
|
1781
|
-
/**
|
|
1782
|
-
* #616 — the Runner's per-session breaker ledger ({@link import("../auto-mode.js").AutoModeBreakerLedger}):
|
|
1783
|
-
* the arming site's `onBreakerOpen` wrap records a trip here, the wiring-manifest phase of a LATER leg of
|
|
1784
|
-
* the same session reads the most recent one onto `autoMode.breaker`. Always set by the Runner's own
|
|
1785
|
-
* prepare call (overriding any caller value, like `sessionReadStates` beside it); absent on a standalone
|
|
1786
|
-
* prepareTask, where no trip is recorded and none is reported. Trusted internals channel.
|
|
1787
|
-
*/
|
|
1788
|
-
autoModeBreakerLedger?: import("../auto-mode.js").AutoModeBreakerLedger;
|
|
1789
1781
|
onTaskNotification?: (notification: TaskNotificationPayload,
|
|
1790
1782
|
/** Injection tier (design/373 — the ladder is LIVE): "next" = the running turn's next boundary
|
|
1791
1783
|
* (arrival order, consecutive frames batch); "later" = the run's would-otherwise-stop seat
|
|
@@ -2041,7 +2033,14 @@ export interface ParkAsk {
|
|
|
2041
2033
|
* Grouped by lifecycle semantics per the B15 pre-recon partition. Function members start as inert
|
|
2042
2034
|
* placeholders and are assigned at their ORIGINAL declaration sites (the original code could not
|
|
2043
2035
|
* call them earlier either — TDZ proved it). Not on the npm face; this extraction is what enabled
|
|
2044
|
-
* createTurnBoundary / createHarnessHandlers (
|
|
2036
|
+
* createTurnBoundary / createHarnessHandlers (三期; both are run lanes of their own since design/393 S2).
|
|
2037
|
+
*
|
|
2038
|
+
* WRITERS, by group (design/393 S5 — the driver mints the zero value, initial-run-state.ts, and hands it to every
|
|
2039
|
+
* lane as a borrowed-mutable seat): `telemetry` / `degrade` / `limits` / `budget` initial values and function
|
|
2040
|
+
* members — the telemetry-and-budget-seats lane; `counters` / `attach` initial values — the attachment-seats lane
|
|
2041
|
+
* (the clock lane zeroes `counters.walltimeSyncBackstopFired`; the tool-mount facts only read); the per-turn writes — the harness-handlers lane
|
|
2042
|
+
* (`turn`, `counters`, `limits`, `budget`), the turn-boundary lane (`counters`, `attach`, `budget`) and the
|
|
2043
|
+
* recovery lane (`counters.compactionFloor`, `attach.attachState`); the settle-time reads stay the driver's.
|
|
2045
2044
|
*/
|
|
2046
2045
|
export interface RunState {
|
|
2047
2046
|
telemetry: {
|
|
@@ -2468,6 +2467,46 @@ export interface ManualCompactRef {
|
|
|
2468
2467
|
emitMooted?: (reason: string) => void;
|
|
2469
2468
|
closed?: boolean;
|
|
2470
2469
|
}
|
|
2470
|
+
/**
|
|
2471
|
+
* design/393 S6 — the end-of-task compaction pass's outcome (`Runner.finish`'s return): what the terminal-adoption lane
|
|
2472
|
+
* hands the settle lane, which reads it for the `compacted` frame, the phase-timings frame and the detector reset. Named
|
|
2473
|
+
* once here so the two lanes and the method spell one type.
|
|
2474
|
+
*/
|
|
2475
|
+
export type EndOfTaskCompaction = {
|
|
2476
|
+
compacted: boolean;
|
|
2477
|
+
tokensBefore?: number;
|
|
2478
|
+
triggerTokens?: number;
|
|
2479
|
+
postTriggerTokens?: number;
|
|
2480
|
+
durationMs?: number;
|
|
2481
|
+
phaseDurations?: CompactionPhaseDurations;
|
|
2482
|
+
firstKeptEntryId?: string;
|
|
2483
|
+
attachedFiles?: Array<{
|
|
2484
|
+
path: string;
|
|
2485
|
+
chars: number;
|
|
2486
|
+
truncated: boolean;
|
|
2487
|
+
}>;
|
|
2488
|
+
modelFallback?: true;
|
|
2489
|
+
fallbackReason?: "window";
|
|
2490
|
+
clampedRatio?: number;
|
|
2491
|
+
clampReason?: "budget" | "tolerance";
|
|
2492
|
+
} | undefined;
|
|
2493
|
+
/**
|
|
2494
|
+
* design/393 S6 — the notification lane's BINDINGS: the run-notification-lane's own four `let`s as ONE seat (getters
|
|
2495
|
+
* and setters over the lane's variables, never a copy). The identity-wiring lane binds `harness` / `sessionId` /
|
|
2496
|
+
* `ident` the moment `prepared` exists (the lane's closures read them by variable — the routing listener, the park
|
|
2497
|
+
* destination, the injection entry); the leg lane flips `live` in its finally, from which point every notification
|
|
2498
|
+
* parks per session for the next run. One seat, four slots; nothing copies a binding out of it.
|
|
2499
|
+
*/
|
|
2500
|
+
export interface NotificationLaneBindings {
|
|
2501
|
+
harness: AgentHarness | undefined;
|
|
2502
|
+
sessionId: string | undefined;
|
|
2503
|
+
ident: () => {
|
|
2504
|
+
eventId?: string;
|
|
2505
|
+
parentToolCallId?: string;
|
|
2506
|
+
sourceTaskId?: string;
|
|
2507
|
+
};
|
|
2508
|
+
live: boolean;
|
|
2509
|
+
}
|
|
2471
2510
|
/** design/144 §2 — the `notify()` bridge: `runLocked` binds `inject` the moment the task-notification lane exists. */
|
|
2472
2511
|
export interface NotifyRef {
|
|
2473
2512
|
inject?: (n: TaskNotificationPayload, opts?: {
|
|
@@ -32,8 +32,7 @@ export interface InheritedAutoMode {
|
|
|
32
32
|
* recorded recipe — `rebuildAutoModeDecider` hands back a decider and its arming, nothing live)
|
|
33
33
|
* carries no denial tracker, and an entry with a decider but no tracker would count nothing: the
|
|
34
34
|
* rebuilt classifier could block without bound on the redeemed leg, the exact gap the limit closes.
|
|
35
|
-
* Attach a FRESH tracker (a fresh COUNT is the documented cross-process semantics
|
|
36
|
-
* restarts the same way) under the ancestor's recorded BOUNDS tightened by this deployment's own
|
|
35
|
+
* Attach a FRESH tracker (a fresh COUNT is the documented cross-process semantics) under the ancestor's recorded BOUNDS tightened by this deployment's own
|
|
37
36
|
* (#556, `tightenDenialLimit` — the same rule and the same call the arming fold makes, so the
|
|
38
37
|
* recipe's account of the criteria and the tracker's actual bounds cannot drift). Before #556 the
|
|
39
38
|
* bounds came from this deployment alone, so an ancestor that allowed three consecutive blocks
|
|
@@ -84,8 +83,8 @@ export type InheritedAsk = Extract<PermissionResult, {
|
|
|
84
83
|
}>;
|
|
85
84
|
/** The members of a surviving ask that ride onto the approval request with a COMPUTED value — what the
|
|
86
85
|
* four request mint stations (the gate's own and the three inherited-lane ones) spread after the seats
|
|
87
|
-
* they spell themselves: the ask's origin word, its denial-limit fallback and
|
|
88
|
-
* fact (#616). */
|
|
86
|
+
* they spell themselves: the ask's origin word, its denial-limit fallback and a policy-declared
|
|
87
|
+
* classifier-unavailable fact (#616; the engine's own fact rides the DENY since #661). */
|
|
89
88
|
export interface AskRequestCarry {
|
|
90
89
|
origin?: AskOrigin;
|
|
91
90
|
denialLimitFallback?: DenialLimitFallback;
|
|
@@ -117,18 +116,15 @@ export type InheritedClassifierJudgment<A extends InheritedAsk> =
|
|
|
117
116
|
kind: "deny";
|
|
118
117
|
result: PermissionResult;
|
|
119
118
|
}
|
|
120
|
-
/** Proceed to the frozen approver with `ask`: the incoming ask unchanged (classifier
|
|
121
|
-
*
|
|
119
|
+
/** Proceed to the frozen approver with `ask`: the incoming ask unchanged (classifier excluded or not
|
|
120
|
+
* armed), or — at the bound — the fallback ask minted from it (`mintedHere`).
|
|
122
121
|
* `fallback` is the member riding the ask either way (an incoming one is a deeper ancestor's).
|
|
123
122
|
* `origin` is the ask's word under the station facts, threaded to the request mint: on the two
|
|
124
123
|
* unchanged-ask branches it is the SAME read the exclusion judged by (a caller-owned decision with a
|
|
125
124
|
* stateful accessor cannot answer the exclusion with one word and the card with another); on the
|
|
126
125
|
* bound branch it is derived from the re-spoken ask this station minted (its own object). */
|
|
127
|
-
/** `ask` is the incoming ask unchanged
|
|
128
|
-
* carrying `classifierUnavailable: { cause }` (#
|
|
129
|
-
* wrapper arms hand back to the gate when the frozen approver answers unavailable (the inherited-unavailable
|
|
130
|
-
* float), and the gate's own park carry reads the fact off the decision it parks — a side member on this
|
|
131
|
-
* judgment would have been lost on that route (codex r1). The request mint reads the same object. */
|
|
126
|
+
/** `ask` is the incoming ask unchanged (the caller's own object); an UNAVAILABLE round never reaches this arm —
|
|
127
|
+
* it is a `deny` carrying `classifierUnavailable: { cause }` (#661). */
|
|
132
128
|
| {
|
|
133
129
|
kind: "resolve";
|
|
134
130
|
ask: A;
|
|
@@ -142,8 +138,9 @@ export type InheritedClassifierJudgment<A extends InheritedAsk> =
|
|
|
142
138
|
* auto-allow (and the streak resets); `block` below the bound ⇒ deny, the exact verdict the ancestor's
|
|
143
139
|
* gate would have produced; `block` AT the bound ⇒ the ask is re-spoken in the classifier's voice as
|
|
144
140
|
* the fallback (`decisionReason:"classifier"`, `requiresRealApproval`, the member carrying counts +
|
|
145
|
-
* window) for the arm to resolve at the frozen approver;
|
|
146
|
-
*
|
|
141
|
+
* window) for the arm to resolve at the frozen approver; `parse_error` ⇒ the same block path with the CC
|
|
142
|
+
* parse-failure sentence (counted); `unavailable` ⇒ a DENY that says so, carrying the fact (#661, CC
|
|
143
|
+
* 2.1.250 form); excluded / no classifier ⇒ the incoming ask, unchanged. The member may ALREADY be on the incoming
|
|
147
144
|
* ask (a deeper ancestor's fallback, minted inside the nested fold — the case the exclusion names):
|
|
148
145
|
* it rides to the approver and the headless arm unchanged, whichever tracker minted it; only a
|
|
149
146
|
* tracker that counted THIS streak is reset by the person's later allow (`mintedHere`).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow } from "../auto-mode.js";
|
|
1
|
+
import { CLASSIFIER_PARSE_FAILURE_DENY_MESSAGE, classifierUnavailableDenyMessage, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow } from "../auto-mode.js";
|
|
2
2
|
import { sanitizeAutoModeArmingRecipe, tightenDenialLimit } from "../auto-mode-arming.js";
|
|
3
3
|
import { deliverEngineNotice } from "../types.js";
|
|
4
4
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
@@ -85,19 +85,21 @@ export async function judgeInheritedClassifier(opts) {
|
|
|
85
85
|
autoMode.denialTracking?.recordAllow();
|
|
86
86
|
return { kind: "allow" };
|
|
87
87
|
}
|
|
88
|
-
if (verdict.kind
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
if (verdict.kind === "unavailable") {
|
|
89
|
+
return {
|
|
90
|
+
kind: "deny",
|
|
91
|
+
result: { action: "deny", message: classifierUnavailableDenyMessage(req.toolName, verdict.cause), decisionReason: "classifier", classifierUnavailable: { cause: verdict.cause } },
|
|
92
|
+
};
|
|
91
93
|
}
|
|
92
|
-
const reason = verdict.reason ? inlineUntrusted(verdict.reason) : "";
|
|
93
|
-
const category = verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
94
|
+
const reason = verdict.kind === "block" ? (verdict.reason ? inlineUntrusted(verdict.reason) : "") : CLASSIFIER_PARSE_FAILURE_DENY_MESSAGE;
|
|
95
|
+
const category = verdict.kind === "block" && verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
94
96
|
const tracked = autoMode.denialTracking?.recordBlock();
|
|
95
97
|
if (tracked?.limitReached !== true) {
|
|
96
98
|
return {
|
|
97
99
|
kind: "deny",
|
|
98
100
|
result: {
|
|
99
101
|
action: "deny",
|
|
100
|
-
message: `auto-mode classifier blocked ${opts.subject} at an inherited ancestor layer${reason ? `: ${reason}` : category ? `: [${category}]` : ""}`,
|
|
102
|
+
message: verdict.kind === "block" ? `auto-mode classifier blocked ${opts.subject} at an inherited ancestor layer${reason ? `: ${reason}` : category ? `: [${category}]` : ""}` : `${reason} (${opts.subject}, at an inherited ancestor layer)`,
|
|
101
103
|
decisionReason: "classifier",
|
|
102
104
|
},
|
|
103
105
|
};
|
|
@@ -103,7 +103,15 @@ export async function exitGate(pass) {
|
|
|
103
103
|
if (pass.deniedBy === undefined)
|
|
104
104
|
throw new Error(`the tool gate refused "${toolName}" without a refusing layer — every deny site attributes itself`);
|
|
105
105
|
const gate = mintGateOutcome({ deniedBy: pass.deniedBy, ...(ledger.settled !== undefined ? { settled: ledger.settled } : {}) });
|
|
106
|
-
await notifyPermissionDenied({
|
|
106
|
+
await notifyPermissionDenied({
|
|
107
|
+
toolName,
|
|
108
|
+
input: cloneObserverInput(pass.currentInput),
|
|
109
|
+
toolCallId,
|
|
110
|
+
reason: denyReason,
|
|
111
|
+
gate,
|
|
112
|
+
...(input.identity !== undefined ? { identity: input.identity } : {}),
|
|
113
|
+
...(pass.decision.action === "deny" && pass.decision.classifierUnavailable !== undefined ? { classifierUnavailable: { cause: pass.decision.classifierUnavailable.cause } } : {}),
|
|
114
|
+
});
|
|
107
115
|
return {
|
|
108
116
|
block: true,
|
|
109
117
|
reason: formatHookFeedback(denyReason, input.reminderMark),
|
|
@@ -49,7 +49,7 @@ export interface PrepareCapsAndWorkflowInput {
|
|
|
49
49
|
deps: RunnerDeps;
|
|
50
50
|
/** borrowed-readonly — the trusted spawn-side channel; the Workflow mount forwards `rootSessionId`, `placementRoot`,
|
|
51
51
|
* `onTaskNotification`, `workflowDepth`, and the capture-floor getter reads `memoryCaptureAncestors`. */
|
|
52
|
-
internals: Pick<RunInternals, "rootSessionId" | "placementRoot" | "onTaskNotification" | "workflowDepth" | "memoryCaptureAncestors" | "workflowParkedResume"
|
|
52
|
+
internals: Pick<RunInternals, "rootSessionId" | "placementRoot" | "onTaskNotification" | "workflowDepth" | "memoryCaptureAncestors" | "workflowParkedResume"> | undefined;
|
|
53
53
|
/** borrowed-readonly — the acquired session; the classifier leg rebuilds its transcript window from `buildContext`. */
|
|
54
54
|
session: Pick<StoredSession, "buildContext">;
|
|
55
55
|
/** borrowed-readonly — the acquired session id (operator-line context, the refusal codes' phase record). */
|
|
@@ -195,11 +195,6 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
195
195
|
autoModeDenialTracking = createAutoModeDenialTracker(am.denialLimit);
|
|
196
196
|
autoModeDecider = createAutoModeDecider({
|
|
197
197
|
...(am.timeoutMs !== undefined ? { timeoutMs: am.timeoutMs } : {}),
|
|
198
|
-
...(am.failureThreshold !== undefined ? { failureThreshold: am.failureThreshold } : {}),
|
|
199
|
-
onBreakerOpen: (info) => {
|
|
200
|
-
internals?.autoModeBreakerLedger?.record(sessionId, { openedAtMs: Date.now(), lastCause: info.lastCause, failures: info.consecutiveFailures, runId });
|
|
201
|
-
am.onBreakerOpen?.(info);
|
|
202
|
-
},
|
|
203
198
|
onClassified: (info) => emitTrace(deps.tracer, () => ({
|
|
204
199
|
kind: "auto_mode.classified",
|
|
205
200
|
version: 1,
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
* the boundary parks and the park closure key off `saga`'s presence, so the orchestrator grows no branch.
|
|
18
18
|
*/
|
|
19
19
|
import type { AgentHarness, ExecutionEnv } from "../../internal/harness.js";
|
|
20
|
-
import type { AutoModeDecider } from "../auto-mode.js";
|
|
21
20
|
import type { OwnOrgAdmissionVerdict } from "../memory-admission.js";
|
|
22
21
|
import type { RemoteExecutionEnv, SnapshotId } from "../remote-env.js";
|
|
23
22
|
import type { CheckpointStore, SerializedCheckpointState } from "../checkpoint-store.js";
|
|
@@ -128,7 +127,6 @@ export interface PrepareSuspendSagaInput {
|
|
|
128
127
|
/** borrowed-readonly — the auto-mode intent (seat ∨ live ∨ seed), carried while the latch is healthy. */
|
|
129
128
|
autoModeIntent: boolean;
|
|
130
129
|
/** borrowed-readonly — the auto-mode decider, or undefined (the latch-health reading only). */
|
|
131
|
-
autoModeDecider: AutoModeDecider | undefined;
|
|
132
130
|
/** borrowed-readonly — the inherited admitted org scopes, or undefined (copied onto the row). */
|
|
133
131
|
inheritedAdmittedOrgScopes: readonly string[] | undefined;
|
|
134
132
|
/** borrowed-readonly — this leg's OWN org verdict seat; `current` is read at mint time. Not written here. */
|
|
@@ -77,16 +77,8 @@ export async function compensateUnparkedPause(remoteEnv, snapshotId, io) {
|
|
|
77
77
|
function stampPlacementRootSessionId(placementRootResolved) {
|
|
78
78
|
return placementValueOrAbsent(placementRootResolved);
|
|
79
79
|
}
|
|
80
|
-
function autoModeLatchHealthy(d) {
|
|
81
|
-
try {
|
|
82
|
-
return d.breakerOpen() !== true && typeof d.consecutiveFailures === "function" && d.consecutiveFailures() === 0;
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
80
|
export function prepareSuspendSaga(input) {
|
|
89
|
-
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, inheritedParentConstraints, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, autoModeIntent,
|
|
81
|
+
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, inheritedParentConstraints, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, autoModeIntent, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
|
|
90
82
|
if (!gateMachineryActive)
|
|
91
83
|
return { saga: undefined };
|
|
92
84
|
const inFlightSpendMicroUsd = () => {
|
|
@@ -140,7 +132,7 @@ export function prepareSuspendSaga(input) {
|
|
|
140
132
|
const constraintDigest = (inheritedParentConstraints?.length ?? 0) > 0
|
|
141
133
|
? constraintChainDigest(constraintChain)
|
|
142
134
|
: seedInheritedGate?.constraintDigest;
|
|
143
|
-
const autoModeIntentCarried = autoModeIntent
|
|
135
|
+
const autoModeIntentCarried = autoModeIntent;
|
|
144
136
|
return inheritedAncestorRules !== undefined ||
|
|
145
137
|
inheritedShellGate !== undefined ||
|
|
146
138
|
autoModeIntentCarried ||
|
|
@@ -678,7 +678,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
678
678
|
});
|
|
679
679
|
}
|
|
680
680
|
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash });
|
|
681
|
-
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, inheritedParentConstraints, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, autoModeIntent,
|
|
681
|
+
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, inheritedParentConstraints, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, autoModeIntent, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
682
682
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
683
683
|
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedBash, shellGatedMonitor, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
684
684
|
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedBash, shellGatedMonitor, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash });
|
|
@@ -46,7 +46,7 @@ export interface PrepareWiringManifestInput {
|
|
|
46
46
|
deps: RunnerDeps;
|
|
47
47
|
/** borrowed-readonly — the trusted spawn-side channel: `questionFaceStripped`, `isDelegatedChild`, `onTaskNotification`,
|
|
48
48
|
* `peerSelfRef`, `explicitAgentName` (the drain), `insideFork` / `agentName` / `parentToolCallId` (the identity). */
|
|
49
|
-
internals: Pick<RunInternals, "questionFaceStripped" | "isDelegatedChild" | "onTaskNotification" | "peerSelfRef" | "explicitAgentName" | "insideFork" | "agentName" | "parentToolCallId"
|
|
49
|
+
internals: Pick<RunInternals, "questionFaceStripped" | "isDelegatedChild" | "onTaskNotification" | "peerSelfRef" | "explicitAgentName" | "insideFork" | "agentName" | "parentToolCallId"> | undefined;
|
|
50
50
|
/** borrowed-readonly — the resume leg, or undefined (the manifest's leg derivation reads presence only). */
|
|
51
51
|
resume: Pick<PrepareResume, "seed"> | undefined;
|
|
52
52
|
/** borrowed-readonly — the acquired session id. */
|
|
@@ -199,14 +199,7 @@ export function prepareWiringManifest(input) {
|
|
|
199
199
|
memoryAdmissionWired: deps.memoryScopeAdmission !== undefined,
|
|
200
200
|
retentionPolicyWired: deps.retentionPolicy !== undefined,
|
|
201
201
|
...(modelGateManifest !== undefined ? { modelGate: modelGateManifest } : {}),
|
|
202
|
-
autoMode: {
|
|
203
|
-
armed: autoModeArmReason === "armed",
|
|
204
|
-
reason: autoModeArmReason,
|
|
205
|
-
...(() => {
|
|
206
|
-
const trip = internals?.autoModeBreakerLedger?.lastTrip(sessionId);
|
|
207
|
-
return trip !== undefined ? { breaker: trip } : {};
|
|
208
|
-
})(),
|
|
209
|
-
},
|
|
202
|
+
autoMode: { armed: autoModeArmReason === "armed", reason: autoModeArmReason },
|
|
210
203
|
mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
|
|
211
204
|
tools: toolRoster,
|
|
212
205
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TaskSpec } from "../types.js";
|
|
2
|
+
import type { Prepared, ResumeRun, RunnerDepsSeat, RunState } from "./contracts.js";
|
|
3
|
+
export interface RunAttachmentSeatsInput<R> {
|
|
4
|
+
/** borrowed-readonly — the task spec: the attachments config and the `finalVerification` opt-in. */
|
|
5
|
+
spec: TaskSpec;
|
|
6
|
+
/** borrowed-mutable — the leg's prepared seat: `announcedListingsRef` is seeded; the session, the listing faces,
|
|
7
|
+
* the date-change / instruction-source / size-guideline faces, the tool effects and the reminder mark are read. */
|
|
8
|
+
prepared: Prepared;
|
|
9
|
+
/** borrowed-readonly — the resume plan when this leg resumes a checkpoint (its `announcedListings` mirror is the first seed rung). */
|
|
10
|
+
resume: ResumeRun | undefined;
|
|
11
|
+
/** borrowed-mutable — the run's mutable state: this lane is the WRITER of the `counters` and `attach` groups' initial
|
|
12
|
+
* values (later writers: the harness handlers, the boundary, the recovery pass). */
|
|
13
|
+
rs: RunState;
|
|
14
|
+
/** borrowed-readonly — the Runner's deployment deps, read once for `probeInstructionSources`. */
|
|
15
|
+
runner: RunnerDepsSeat;
|
|
16
|
+
/** borrowed-readonly — the lanes after this one, entered in this lane's last continuation (the seats it wrote are on `rs`). */
|
|
17
|
+
next: (seats: RunAttachmentSeatsResult) => Promise<R>;
|
|
18
|
+
}
|
|
19
|
+
/** Nothing comes back: the lane's products are the `counters` / `attach` groups it wrote on the borrowed run state. */
|
|
20
|
+
export interface RunAttachmentSeatsResult {
|
|
21
|
+
}
|
|
22
|
+
export declare function runAttachmentSeats<R>(input: RunAttachmentSeatsInput<R>): Promise<R>;
|