@sema-agent/core 7.17.7 → 7.19.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 +233 -13
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +1 -0
- package/dist/agents/subagent.js +5 -0
- package/dist/agents/teacher.js +1 -0
- package/dist/agents/verify.js +3 -0
- package/dist/brain/anthropic.js +6 -3
- package/dist/brain/open-responses.js +10 -4
- package/dist/brain/openai.js +5 -2
- package/dist/brain/reasoning.d.ts +13 -13
- package/dist/brain/reasoning.js +2 -2
- package/dist/brain/route-adjudicator.d.ts +18 -0
- package/dist/brain/route-adjudicator.js +16 -0
- package/dist/brain/stream-engine.js +2 -1
- package/dist/brain/stream-shared.d.ts +3 -0
- package/dist/brain/stream-shared.js +1 -0
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/artifact-host.d.ts +41 -4
- package/dist/core/artifact-host.js +18 -2
- package/dist/core/ask-origin.d.ts +16 -0
- package/dist/core/ask-origin.js +8 -0
- package/dist/core/auto-mode-arming.d.ts +6 -0
- package/dist/core/auto-mode-arming.js +5 -5
- package/dist/core/auto-mode-defaults.d.ts +43 -15
- package/dist/core/auto-mode-defaults.js +4 -1
- package/dist/core/auto-mode.d.ts +184 -59
- package/dist/core/auto-mode.js +188 -13
- package/dist/core/checkpoint-store.d.ts +23 -2
- package/dist/core/checkpoint-store.js +2 -2
- package/dist/core/engine-notice.d.ts +77 -1
- package/dist/core/engine-notice.js +7 -0
- package/dist/core/gate-fold.js +5 -1
- package/dist/core/gate-lanes.js +9 -8
- package/dist/core/gate-outcome.d.ts +42 -2
- package/dist/core/gate-outcome.js +23 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +14 -0
- package/dist/core/hook-seats.d.ts +66 -0
- package/dist/core/hook-seats.js +37 -0
- package/dist/core/hooks.d.ts +1 -1
- package/dist/core/read-root-candidate.d.ts +12 -0
- package/dist/core/read-root-candidate.js +24 -0
- package/dist/core/roles.d.ts +9 -1
- package/dist/core/roles.js +4 -0
- package/dist/core/runner/advertised-writable-dirs.d.ts +8 -3
- package/dist/core/runner/assemble-result.d.ts +2 -1
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/classifier-ladder.d.ts +227 -0
- package/dist/core/runner/classifier-ladder.js +214 -0
- package/dist/core/runner/contracts.d.ts +71 -13
- package/dist/core/runner/decide-continuation.d.ts +1 -3
- package/dist/core/runner/decide-continuation.js +1 -7
- package/dist/core/runner/deferral-census.d.ts +52 -0
- package/dist/core/runner/deferral-census.js +44 -0
- package/dist/core/runner/denial-limit-arms.js +2 -2
- package/dist/core/runner/derived-route-fallback.d.ts +8 -4
- package/dist/core/runner/derived-route-fallback.js +8 -3
- package/dist/core/runner/gate-exit.d.ts +12 -0
- package/dist/core/runner/gate-exit.js +6 -3
- package/dist/core/runner/prepare-artifact.d.ts +10 -2
- package/dist/core/runner/prepare-artifact.js +5 -4
- package/dist/core/runner/prepare-ask-lane.js +1 -0
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +43 -55
- package/dist/core/runner/prepare-config-doors.d.ts +7 -1
- package/dist/core/runner/prepare-config-doors.js +13 -13
- package/dist/core/runner/prepare-defer-classify.d.ts +13 -19
- package/dist/core/runner/prepare-defer-classify.js +8 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +26 -0
- package/dist/core/runner/prepare-gate-stations.js +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +24 -7
- package/dist/core/runner/prepare-hands-readface.js +60 -24
- package/dist/core/runner/prepare-inherited-gate.d.ts +17 -4
- package/dist/core/runner/prepare-inherited-gate.js +10 -2
- package/dist/core/runner/prepare-lsp.d.ts +2 -2
- package/dist/core/runner/prepare-lsp.js +1 -1
- package/dist/core/runner/prepare-policy-chain.js +2 -0
- package/dist/core/runner/prepare-project-context.d.ts +5 -1
- package/dist/core/runner/prepare-project-context.js +7 -4
- package/dist/core/runner/prepare-prompt-inputs.d.ts +4 -2
- package/dist/core/runner/prepare-prompt-inputs.js +4 -1
- package/dist/core/runner/prepare-run-refs.d.ts +9 -1
- package/dist/core/runner/prepare-run-refs.js +3 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +5 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -2
- package/dist/core/runner/prepare-task.js +19 -14
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +5 -0
- package/dist/core/runner/prepare-tool-disclosure-mount.js +10 -2
- package/dist/core/runner/prepare-turn-wiring.d.ts +8 -4
- package/dist/core/runner/prepare-turn-wiring.js +3 -2
- package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -5
- package/dist/core/runner/prepare-wiring-manifest.js +5 -2
- package/dist/core/runner/resume-apply.js +3 -3
- package/dist/core/runner/resume-checkpoint-screen.js +7 -0
- package/dist/core/runner/run-harness-handlers.js +4 -1
- package/dist/core/runner/run-identity-wiring.js +6 -2
- package/dist/core/runner/run-leg.d.ts +2 -0
- package/dist/core/runner/run-leg.js +45 -45
- package/dist/core/runner/run-notification-lane.js +55 -27
- package/dist/core/runner/run-settle-and-teardown.js +1 -0
- package/dist/core/runner/run-terminal-adoption.js +16 -13
- package/dist/core/runner/run-turn-boundary.js +15 -5
- package/dist/core/runner/runtask.d.ts +6 -5
- package/dist/core/runner/runtask.js +26 -14
- package/dist/core/runner/skill-base-dir.d.ts +54 -0
- package/dist/core/runner/skill-base-dir.js +42 -0
- package/dist/core/runner/synthetic-tools.d.ts +83 -48
- package/dist/core/runner/synthetic-tools.js +69 -32
- package/dist/core/runner/tool-defer-gate.d.ts +22 -9
- package/dist/core/runner/tool-defer-gate.js +15 -5
- package/dist/core/runner/tool-disclosure.d.ts +5 -0
- package/dist/core/runner/tool-disclosure.js +2 -0
- package/dist/core/runner/tool-progress-lane.d.ts +42 -0
- package/dist/core/runner/tool-progress-lane.js +61 -0
- package/dist/core/runner/turn-attachments.d.ts +43 -12
- package/dist/core/runner/turn-attachments.js +58 -14
- package/dist/core/runner-deps.d.ts +48 -7
- package/dist/core/sensitive-path-policy.d.ts +58 -17
- package/dist/core/sensitive-path-policy.js +33 -5
- package/dist/core/skill-listing-budget.d.ts +112 -0
- package/dist/core/skill-listing-budget.js +58 -0
- package/dist/core/swappable-deps.d.ts +9 -7
- package/dist/core/swappable-deps.js +7 -3
- package/dist/core/task-event.d.ts +96 -29
- package/dist/core/task-notification.d.ts +142 -16
- package/dist/core/task-notification.js +106 -0
- package/dist/core/task-result.d.ts +9 -1
- package/dist/core/task-spec.d.ts +46 -3
- package/dist/core/tighten-task-spec.js +7 -5
- package/dist/core/tool-model-gate.d.ts +1 -1
- package/dist/core/tool-policy.d.ts +19 -4
- package/dist/core/tool-policy.js +6 -7
- package/dist/core/tool-search-setting.d.ts +78 -0
- package/dist/core/tool-search-setting.js +90 -0
- package/dist/core/tool-spec.d.ts +45 -4
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.js +1 -1
- package/dist/core/wiring-manifest.d.ts +46 -0
- package/dist/core/wiring-manifest.js +9 -1
- package/dist/core/write-protect.d.ts +8 -3
- package/dist/core/write-protect.js +8 -5
- package/dist/engine/execution-env/node-execution-env.js +10 -4
- package/dist/engine/harness/agent-harness.d.ts +42 -0
- package/dist/engine/harness/agent-harness.js +61 -29
- package/dist/engine/loop/agent-loop.d.ts +68 -3
- package/dist/engine/loop/agent-loop.js +109 -16
- package/dist/index.d.ts +13 -8
- package/dist/index.js +11 -7
- package/dist/internal/harness.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +6 -1
- package/dist/orchestration/workflow-governance.d.ts +7 -1
- package/dist/orchestration/workflow-governance.js +9 -5
- package/dist/orchestration/workflow-primitives.d.ts +3 -0
- package/dist/orchestration/workflow-primitives.js +6 -1
- package/dist/orchestration/workflow-types.d.ts +48 -13
- package/dist/orchestration/workflow-types.js +1 -1
- package/dist/orchestration/workflow.js +45 -17
- package/dist/prompt-assembly/epoch.js +2 -0
- package/dist/prompt-assembly/packs/sema-default.js +2 -2
- package/dist/prompt-assembly/section-usage.d.ts +26 -0
- package/dist/prompt-assembly/section-usage.js +10 -0
- package/dist/prompt-assembly/types.d.ts +8 -6
- package/dist/prompts/default.d.ts +13 -0
- package/dist/prompts/default.js +16 -8
- package/dist/tools/artifact/artifact-text.d.ts +10 -1
- package/dist/tools/artifact/artifact-text.js +6 -3
- package/dist/tools/artifact/artifact-tool.d.ts +12 -2
- package/dist/tools/artifact/artifact-tool.js +203 -70
- package/dist/tools/artifact/conformance.d.ts +56 -0
- package/dist/tools/artifact/conformance.js +349 -0
- package/dist/tools/artifact/local-stub.js +1 -1
- package/dist/tools/artifact/reject-breaker.d.ts +28 -0
- package/dist/tools/artifact/reject-breaker.js +42 -0
- package/dist/tools/fs/bash-lexer.d.ts +132 -0
- package/dist/tools/fs/bash-lexer.js +563 -0
- package/dist/tools/fs/bash-program-position.d.ts +142 -0
- package/dist/tools/fs/bash-program-position.js +125 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +81 -16
- package/dist/tools/fs/bash-readonly-classifier.js +180 -558
- package/dist/tools/fs/containment-face.d.ts +89 -0
- package/dist/tools/fs/containment-face.js +81 -0
- package/dist/tools/fs/fs-bash.d.ts +46 -1
- package/dist/tools/fs/fs-bash.js +165 -25
- package/dist/tools/fs/fs-read.d.ts +1 -1
- package/dist/tools/fs/fs-search-tools.d.ts +3 -3
- package/dist/tools/fs/fs-write.d.ts +4 -3
- package/dist/tools/fs/fs-write.js +9 -9
- package/dist/tools/fs/index.d.ts +24 -5
- package/dist/tools/fs/index.js +18 -6
- package/dist/tools/fs/read-deny.d.ts +4 -3
- package/dist/tools/fs/repo-map.d.ts +2 -2
- package/dist/tools/fs/safety.d.ts +18 -3
- package/dist/tools/fs/safety.js +11 -4
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +99 -13
- package/wire-changes/core@7.17.7.json +49 -0
- package/wire-changes/core@7.18.0.json +1273 -0
- package/wire-changes/core@7.19.0.json +457 -0
- package/dist/tools/fs/read-face.d.ts +0 -68
- package/dist/tools/fs/read-face.js +0 -47
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* contract (`ToolGateInput`, `ToolGateResult`, the observer payload), which stays declared there.
|
|
23
23
|
*/
|
|
24
24
|
import { type ClassifierDenyCause, type DeniedBy, type GateOutcome, type Settlement } from "../gate-outcome.js";
|
|
25
|
+
import type { AutoModeClassifierRound } from "../auto-mode.js";
|
|
25
26
|
import type { AskOrigin, AskOriginFacts } from "../ask-origin.js";
|
|
26
27
|
import { type PermissionResult, type ResolvedAsk, type ToolCallRequest } from "../tool-policy.js";
|
|
27
28
|
import type { SafeNotifier } from "../safe-notify.js";
|
|
@@ -40,6 +41,10 @@ export interface GateExitFacts {
|
|
|
40
41
|
deniedBy?: DeniedBy;
|
|
41
42
|
cause?: ClassifierDenyCause;
|
|
42
43
|
settled?: SettledAsk;
|
|
44
|
+
/** The classifier CLASSIFICATION this pass ran, when it ran one on a decider that can name its model.
|
|
45
|
+
* Orthogonal to `deniedBy`: one that ALLOWED is attributed too (a fallback model's allow is exactly the case
|
|
46
|
+
* an operator needs to see), which is why it rides the disposition's shared member, not the deny arm. */
|
|
47
|
+
classifier?: AutoModeClassifierRound;
|
|
43
48
|
}
|
|
44
49
|
/**
|
|
45
50
|
* Mint the outcome. A defect here is an ENGINE defect (a refusing site that did not say who refused, a
|
|
@@ -220,6 +225,13 @@ export interface GatePass {
|
|
|
220
225
|
* re-check when an inherited station's attested deny arrives through the chain; undefined for a ruling
|
|
221
226
|
* block and every non-classifier deny. The exit mints `GateDisposition.cause` from it. */
|
|
222
227
|
denyCause: ClassifierDenyCause | undefined;
|
|
228
|
+
/** borrowed-mutable — the classifier CLASSIFICATION this pass ran ({@link AutoModeClassifierRound}).
|
|
229
|
+
* Written ONCE by the gate's classifier step from the verdict the decider handed back, on EVERY arm (allow
|
|
230
|
+
* included — a fallback model's allow is the fact the record exists for); absent when no classifier was
|
|
231
|
+
* consulted or the decider could name no model. Both exits mint `GateDisposition.classifier` from it.
|
|
232
|
+
* OPTIONAL rather than `| undefined` (the `probeUnanswered` form): the dispatch that builds the pass is
|
|
233
|
+
* not a station of this lane and has nothing to declare here. */
|
|
234
|
+
classifierRound?: AutoModeClassifierRound;
|
|
223
235
|
/** borrowed-mutable — the standing verdict. The no-policy default until the adjudication station writes the
|
|
224
236
|
* policy's answer; then rewritten by every station that changes the verdict (fold, tightens, org, rule
|
|
225
237
|
* lane, stamp, classifier, sandbox, content lane, resolution, edit chain). */
|
|
@@ -4,8 +4,11 @@ import { inlineUntrusted } from "../untrusted-text.js";
|
|
|
4
4
|
import { formatHookFeedback } from "../reminder-mint.js";
|
|
5
5
|
export function mintGateOutcome(facts) {
|
|
6
6
|
const settlement = facts.settled !== undefined ? Object.freeze({ ...facts.settled.settlement, who: Object.freeze({ ...facts.settled.settlement.who }) }) : undefined;
|
|
7
|
+
const attribution = facts.classifier !== undefined ? Object.freeze({ ...facts.classifier, ...(facts.classifier.fallback !== undefined ? { fallback: Object.freeze({ ...facts.classifier.fallback }) } : {}) }) : undefined;
|
|
7
8
|
const outcome = Object.freeze({
|
|
8
|
-
disposition: Object.freeze(facts.deniedBy !== undefined
|
|
9
|
+
disposition: Object.freeze(facts.deniedBy !== undefined
|
|
10
|
+
? { kind: "denied", deniedBy: facts.deniedBy, ...(facts.cause !== undefined ? { cause: facts.cause } : {}), ...(attribution !== undefined ? { classifier: attribution } : {}) }
|
|
11
|
+
: { kind: "allowed", ...(attribution !== undefined ? { classifier: attribution } : {}) }),
|
|
9
12
|
...(facts.settled !== undefined ? { settlement: settlement, origin: facts.settled.origin } : {}),
|
|
10
13
|
});
|
|
11
14
|
const defects = screenGateOutcome(outcome);
|
|
@@ -114,7 +117,7 @@ export async function exitGate(pass) {
|
|
|
114
117
|
}
|
|
115
118
|
if (pass.deniedBy === undefined)
|
|
116
119
|
throw new Error(`the tool gate refused "${toolName}" without a refusing layer — every deny site attributes itself`);
|
|
117
|
-
const gate = mintGateOutcome({ deniedBy: pass.deniedBy, ...(pass.denyCause !== undefined ? { cause: pass.denyCause } : {}), ...(ledger.settled !== undefined ? { settled: ledger.settled } : {}) });
|
|
120
|
+
const gate = mintGateOutcome({ deniedBy: pass.deniedBy, ...(pass.denyCause !== undefined ? { cause: pass.denyCause } : {}), ...(ledger.settled !== undefined ? { settled: ledger.settled } : {}), ...(pass.classifierRound !== undefined ? { classifier: pass.classifierRound } : {}) });
|
|
118
121
|
const unresolvable = askUnresolvableCauseOf(pass.decision, { toolCallId, toolName }) ?? unresolvableCauseOfSettlement(gate);
|
|
119
122
|
if (unresolvable !== undefined) {
|
|
120
123
|
const cause = unresolvable;
|
|
@@ -142,7 +145,7 @@ export async function exitGate(pass) {
|
|
|
142
145
|
}
|
|
143
146
|
return {
|
|
144
147
|
updatedInput: pass.currentInput === event.input ? undefined : pass.currentInput,
|
|
145
|
-
gate: mintGateOutcome(ledger.settled !== undefined ? { settled: ledger.settled } : {}),
|
|
148
|
+
gate: mintGateOutcome({ ...(ledger.settled !== undefined ? { settled: ledger.settled } : {}), ...(pass.classifierRound !== undefined ? { classifier: pass.classifierRound } : {}) }),
|
|
146
149
|
preToolContext: pass.preToolContext,
|
|
147
150
|
};
|
|
148
151
|
}
|
|
@@ -7,13 +7,18 @@
|
|
|
7
7
|
* face) exactly as `Read` does, then reads the bytes once from the execution env. A local stub's store
|
|
8
8
|
* (`capabilities.storageDir`) must lie OUTSIDE every root the run may write or read — a ledger the model can
|
|
9
9
|
* edit through the fs tools is not a trust boundary — and a store inside one refuses the mount, naming both.
|
|
10
|
+
* The store is a path on THIS process's filesystem; a root is the execution env's canonical key. The two are
|
|
11
|
+
* compared as identities under one spelling family only when both spell the same family (`within` reads both
|
|
12
|
+
* under the root's family); a root of the other family names a filesystem the store cannot be on, and no
|
|
13
|
+
* containment claim is made against it.
|
|
10
14
|
* Synchronous: the stretch has no await (the file read is a closure the tool calls later).
|
|
11
15
|
*/
|
|
12
16
|
import type { ExecutionEnv } from "../../internal/harness.js";
|
|
17
|
+
import type { OnAsk } from "../tool-policy.js";
|
|
13
18
|
import { type ArtifactPlane } from "../artifact-host.js";
|
|
14
19
|
import { RosterBuilder } from "../tool-roster.js";
|
|
15
20
|
import type { AgentTool, RunnerDeps } from "../types.js";
|
|
16
|
-
import type { ReadDenyMatcher,
|
|
21
|
+
import type { ReadDenyMatcher, ContainmentFace } from "../../tools/fs/index.js";
|
|
17
22
|
import type { Prepared } from "./contracts.js";
|
|
18
23
|
export interface PrepareArtifactInput {
|
|
19
24
|
/** borrowed-readonly — the deployment's hosting seat and the notice sink the refusal arm announces on. */
|
|
@@ -26,6 +31,9 @@ export interface PrepareArtifactInput {
|
|
|
26
31
|
sessionId: string;
|
|
27
32
|
/** borrowed-readonly — the spawned name this run carries, when any (call-context attribution only). */
|
|
28
33
|
agentName: string | undefined;
|
|
34
|
+
/** borrowed-readonly — the run's effective approver (`spec.onAsk ?? deps.onAsk`, the seat the tool gate resolves at):
|
|
35
|
+
* the tool's shared-read consent gate rides it as a mount dep (a core mount's execute ctx is minimal). */
|
|
36
|
+
onAsk: OnAsk | undefined;
|
|
29
37
|
/** borrowed-readonly — the run's resolved env: the byte source of a published local file. */
|
|
30
38
|
executionEnv: ExecutionEnv;
|
|
31
39
|
/** borrowed-readonly — the canonical task root the fs fence contains reads to; undefined ⇒ no local-file publish. */
|
|
@@ -35,7 +43,7 @@ export interface PrepareArtifactInput {
|
|
|
35
43
|
/** borrowed-readonly — the read-deny matcher in force for the run, when any. */
|
|
36
44
|
readDenyMatcher: ReadDenyMatcher | undefined;
|
|
37
45
|
/** borrowed-readonly — the resolved read face (`"open"` lifts root containment for reads). */
|
|
38
|
-
resolvedReadFace:
|
|
46
|
+
resolvedReadFace: ContainmentFace | undefined;
|
|
39
47
|
/** borrowed-readonly — the tracked-cwd cell; `current` is read per call as the relative-path base. */
|
|
40
48
|
handsCwdRef: Prepared["cwdRef"];
|
|
41
49
|
/** borrowed-mutable — the run's roster builder; writer here: ONE mount when the seat is valid. */
|
|
@@ -5,10 +5,10 @@ import { RosterBuilder } from "../tool-roster.js";
|
|
|
5
5
|
import { defineTool } from "../tools.js";
|
|
6
6
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
7
7
|
import { physicalPathOfExisting } from "../physical-path.js";
|
|
8
|
-
import { resolveKey, violationDetails, violationText, withinAnyRoot } from "../../tools/fs/safety.js";
|
|
8
|
+
import { pathFamilyOf, resolveKey, violationDetails, violationText, withinAnyRoot } from "../../tools/fs/safety.js";
|
|
9
9
|
import { createArtifactTool } from "../../tools/artifact/artifact-tool.js";
|
|
10
10
|
export function prepareArtifact(input) {
|
|
11
|
-
const { deps, runId, taskId, sessionId, agentName, executionEnv, rootCanonical, additionalRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames } = input;
|
|
11
|
+
const { deps, runId, taskId, sessionId, agentName, onAsk, executionEnv, rootCanonical, additionalRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames } = input;
|
|
12
12
|
const host = deps.artifactHost;
|
|
13
13
|
if (host === undefined)
|
|
14
14
|
return { artifactPlane: undefined };
|
|
@@ -26,7 +26,8 @@ export function prepareArtifact(input) {
|
|
|
26
26
|
const storageDir = verdict.capabilities.storageDir;
|
|
27
27
|
if (storageDir !== undefined && rootCanonical !== undefined) {
|
|
28
28
|
const real = physicalPathOfExisting(storageDir);
|
|
29
|
-
const
|
|
29
|
+
const storeFamily = pathFamilyOf({ root: real });
|
|
30
|
+
const inside = [rootCanonical, ...additionalRootsCanonical].find((root) => pathFamilyOf({ root }) === storeFamily && withinAnyRoot([root], real));
|
|
30
31
|
if (inside !== undefined)
|
|
31
32
|
return refuse(`the local artifact store ${storageDir} lies inside a root this run may reach through its file tools (${inside}); put the store outside every task root and additional directory`);
|
|
32
33
|
}
|
|
@@ -56,7 +57,7 @@ export function prepareArtifact(input) {
|
|
|
56
57
|
return { ok: false, reason: "too_large", size: r.value.byteLength, limit: maxBytes, judgedOn: "bytes" };
|
|
57
58
|
return { ok: true, key: rk.key, bytes: r.value };
|
|
58
59
|
};
|
|
59
|
-
const artifactSpec = createArtifactTool({ host, capabilities: verdict.capabilities, runId, taskId, sessionId, ...(agentName !== undefined ? { agentName } : {}), readLocalFile });
|
|
60
|
+
const artifactSpec = createArtifactTool({ host, capabilities: verdict.capabilities, runId, taskId, sessionId, ...(agentName !== undefined ? { agentName } : {}), readLocalFile, ...(onAsk !== undefined ? { onAsk } : {}) });
|
|
60
61
|
roster.mount(firstPartyOffload(defineTool(artifactSpec)), { source: "builtin", mountedBy: "optional" });
|
|
61
62
|
envHandToolNames.add(ARTIFACT_TOOL_NAME);
|
|
62
63
|
return { artifactPlane: verdict.capabilities.plane };
|
|
@@ -102,6 +102,7 @@ export function prepareAskLane(input) {
|
|
|
102
102
|
...(decision.action === "ask" ? gateAskCarry(decision, isLiveApproverSeat(onAsk), autoModeDenialTracking) : {}),
|
|
103
103
|
...(decision.action === "ask" && decision.probeReason !== undefined ? { probeReason: decision.probeReason } : {}),
|
|
104
104
|
...(decision.action === "ask" && decision.probeCause !== undefined ? { probeCause: decision.probeCause } : {}),
|
|
105
|
+
...(decision.action === "ask" && decision.probeReadRootCandidate !== undefined ? { readRootCandidate: decision.probeReadRootCandidate } : {}),
|
|
105
106
|
...(decision.action === "ask" && decision.ruleEvidence !== undefined ? { ruleEvidence: decision.ruleEvidence } : {}),
|
|
106
107
|
}, onAsk, composedCallSignal(callSignal), lateAskSettlementObserver({ toolName: req.toolName, toolCallId: req.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError }));
|
|
107
108
|
const waitMs = Math.max(0, now() - t0);
|
|
@@ -33,7 +33,7 @@ import type { OnAsk } from "../tool-policy.js";
|
|
|
33
33
|
import type { RunnerDeps, RuntimeCaps, TaskEvent, TaskSpec, ToolExecuteContext } from "../types.js";
|
|
34
34
|
import type { AutoModeArmFact } from "../wiring-manifest.js";
|
|
35
35
|
import type { AssertAllKeysHandled } from "../ask-origin.js";
|
|
36
|
-
import type {
|
|
36
|
+
import type { ContainmentFace } from "../../tools/fs/index.js";
|
|
37
37
|
import type { InheritedGate, Prepared, RunInternals, RunnerSelfSeat, ToolFaceSnapshot } from "./contracts.js";
|
|
38
38
|
import { type BlockedRef } from "./synthetic-tools.js";
|
|
39
39
|
import { RosterBuilder } from "../tool-roster.js";
|
|
@@ -91,7 +91,9 @@ export interface PrepareCapsAndWorkflowInput {
|
|
|
91
91
|
frozenOnAsk: OnAsk | undefined;
|
|
92
92
|
/** borrowed-readonly — the parent SPEC seat the children inherit (minted once by the inherited-gate phase; the Workflow mount's dep, the same value the delegation ctx carries). */ parentSpecSeat: ParentSpecSeat;
|
|
93
93
|
/** borrowed-readonly — the ONE read-face carrier expression (the Workflow mount's parentReadFace getter calls it). */
|
|
94
|
-
carrierReadFace: () =>
|
|
94
|
+
carrierReadFace: () => ContainmentFace | undefined;
|
|
95
|
+
/** borrowed-readonly — the same carrier expression on the WRITE seat. */
|
|
96
|
+
carrierWriteFace: () => ContainmentFace | undefined;
|
|
95
97
|
/** borrowed-readonly — the filtered display-forwarding wrapper (the Workflow mount's forwardEvent; absent ⇒ no key). */
|
|
96
98
|
forwardEvent: ((e: TaskEvent) => void) | undefined;
|
|
97
99
|
/** borrowed-readonly — the child-chain assembly (the Workflow mount's inheritedGateForChildren). */
|
|
@@ -5,34 +5,20 @@ import { CROSS_SESSION_CLASSIFIER_RULE } from "../../agents/cross-session-envelo
|
|
|
5
5
|
import { createRunWorkflowTool } from "../../orchestration/run-workflow-tool.js";
|
|
6
6
|
import { isSelfOrchestrationActive } from "../../orchestration/workflow-script-runner.js";
|
|
7
7
|
import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
|
|
8
|
-
import { thinkingOffExpressible } from "../../brain/reasoning.js";
|
|
9
8
|
import { autoModeArmingRecipeOf } from "../auto-mode-arming.js";
|
|
10
|
-
import { AUTO_MODE_CLASSIFIER_LOW_REASONING_BUDGET_TOKENS, AUTO_MODE_CLASSIFIER_MAX_TOKENS } from "../auto-mode-defaults.js";
|
|
11
9
|
import { buildAutoModePrompt, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
|
|
12
|
-
import { createAutoModeDecider, createAutoModeDenialTracker } from "../auto-mode.js";
|
|
10
|
+
import { autoModeClassifierFallbackOf, autoModeRoundNotAsked, createAutoModeDecider, createAutoModeDenialTracker } from "../auto-mode.js";
|
|
13
11
|
import { checkpointStoreOfSeat } from "../checkpoint-seat.js";
|
|
14
12
|
import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, resolveComplianceDenies } from "../compliance.js";
|
|
15
13
|
import { createPresentPlanTool, createEnterPlanModeTool } from "../present-plan-tool.js";
|
|
16
|
-
import { resolveTaskModel } from "../roles.js";
|
|
17
14
|
import { brainToRuntime } from "../runtime.js";
|
|
18
15
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
19
|
-
import { emitTrace } from "../trace.js";
|
|
20
16
|
import { defineTool, isDefineToolProduct, rebindDefineToolCtx } from "../tools.js";
|
|
21
17
|
const MOUNT_REMEDY = "author it as a plain-object ToolSpec (own `name` and `execute`), hand the defineTool product itself, or wrap a product through the supported wrapper form (a fresh object re-stamped with `stampDefineToolBrand` whose rebind re-wraps the rebound product)";
|
|
22
18
|
import { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "../runtime-caps.js";
|
|
23
19
|
import { derivedRouteFallsBack } from "./derived-route-fallback.js";
|
|
20
|
+
import { CLASSIFIER_ATTEMPT_SUFFIX, CLASSIFIER_THINK_SEAT, announceClassifierRoleDefaulted, classifierLadderRungs, classifierReplyAsksAgain, classifierReplyFailure, classifierReplyVerdictText, classifierRoundObserver, classifierRungSeat, classifierSeatModel } from "./classifier-ladder.js";
|
|
24
21
|
import { REPORT_FINDINGS_TOOL_NAME, createReportBlockedTool, createReportFindingsTool } from "./synthetic-tools.js";
|
|
25
|
-
function classifierReplyText(reply) {
|
|
26
|
-
return reply.content
|
|
27
|
-
.filter((c) => c.type === "text")
|
|
28
|
-
.map((c) => c.text)
|
|
29
|
-
.join("");
|
|
30
|
-
}
|
|
31
|
-
function classifierReplyEmptyAtCap(reply) {
|
|
32
|
-
if (classifierReplyText(reply) !== "")
|
|
33
|
-
return false;
|
|
34
|
-
return reply.stopReason === "length" || (reply.stopReason === "error" && reply.errorKind === "length_empty");
|
|
35
|
-
}
|
|
36
22
|
import { RosterBuilder, callerMountSource } from "../tool-roster.js";
|
|
37
23
|
function assembleParentCaptureState(o, i, ctl, ancestors) {
|
|
38
24
|
const build = (optedOut, indeterminate) => ({
|
|
@@ -112,7 +98,7 @@ function autoModeArmReasonOf(intent, facePresent, caps, capsFaulted) {
|
|
|
112
98
|
return { armed: true, reason: "armed" };
|
|
113
99
|
}
|
|
114
100
|
export async function prepareCapsAndWorkflow(input) {
|
|
115
|
-
const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, carrierReadFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, autoModeIntent, peerLaneActive, peerSendMessageBuiltIn, runnerSelf } = input;
|
|
101
|
+
const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, autoModeIntent, peerLaneActive, peerSendMessageBuiltIn, runnerSelf } = input;
|
|
116
102
|
const roster = new RosterBuilder(toolEffects);
|
|
117
103
|
for (const t of spec.tools ?? []) {
|
|
118
104
|
const mounted = mountCallerTool(t);
|
|
@@ -211,53 +197,54 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
211
197
|
const autoModeArmReason = autoModeArmReasonOf(autoModeIntent, deps.autoMode !== undefined, runtimeCaps, runtimeCapsFaulted);
|
|
212
198
|
if (autoModeIntent && deps.autoMode !== undefined && runtimeCaps?.autoMode !== false) {
|
|
213
199
|
const am = deps.autoMode;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
catch {
|
|
219
|
-
classifierModel = model;
|
|
220
|
-
}
|
|
221
|
-
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId })) {
|
|
200
|
+
const classifierSeat = classifierSeatModel({ deps, main: model });
|
|
201
|
+
let classifierModel = classifierSeat.model;
|
|
202
|
+
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId, onBrokenPairing: autoModeClassifierFallbackOf(am.classifierFallback) === "none" ? "refuse" : "fall_back" })) {
|
|
222
203
|
classifierModel = model;
|
|
223
204
|
}
|
|
205
|
+
announceClassifierRoleDefaulted({ onNotice: deps.onNotice, seat: { ...classifierSeat, model: classifierModel }, ...(sessionId !== undefined ? { sessionId } : {}), ...(runId !== undefined ? { runId } : {}) });
|
|
224
206
|
const classifierLaneRule = peerLaneActive && peerSendMessageBuiltIn;
|
|
225
207
|
const classifierSystemPrompt = buildAutoModePrompt(classifierLaneRule ? { ...am, crossSessionMessagesRule: CROSS_SESSION_CLASSIFIER_RULE } : am);
|
|
226
208
|
const classifierRuntime = brainToRuntime(deps.brain);
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
const classifierSeat = thinkingOffExpressible(classifierModel) ? classifierOffSeat : classifierLowSeat;
|
|
209
|
+
const classifierRungs = classifierLadderRungs(am.classifierFallback, classifierModel, model);
|
|
210
|
+
const roundPrompt = new WeakMap();
|
|
230
211
|
autoModeDenialTracking = createAutoModeDenialTracker(am.denialLimit);
|
|
231
212
|
autoModeDecider = createAutoModeDecider({
|
|
232
213
|
...(am.timeoutMs !== undefined ? { timeoutMs: am.timeoutMs } : {}),
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
(
|
|
248
|
-
const userPrompt = renderAutoModeWindow(known, am.window) + renderAutoModeAction(input);
|
|
249
|
-
const classifierAuth = await spec.getApiKeyAndHeaders?.(classifierModel);
|
|
250
|
-
const request = (seat) => classifierRuntime.completeSimple(classifierModel, { systemPrompt: classifierSystemPrompt, messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] }, {
|
|
251
|
-
signal,
|
|
252
|
-
...seat,
|
|
253
|
-
...(classifierAuth?.apiKey !== undefined ? { apiKey: classifierAuth.apiKey } : {}),
|
|
254
|
-
...(classifierAuth?.headers !== undefined ? { headers: classifierAuth.headers } : {}),
|
|
255
|
-
});
|
|
256
|
-
let response = await request(classifierSeat);
|
|
257
|
-
if (classifierSeat === classifierOffSeat && classifierReplyEmptyAtCap(response)) {
|
|
258
|
-
response = await request(classifierLowSeat);
|
|
214
|
+
candidates: classifierRungs.map((m) => m.id),
|
|
215
|
+
onClassified: classifierRoundObserver({ tracer: deps.tracer, onNotice: deps.onNotice, taskId: hostTaskId, seatModelId: classifierModel.id, ...(sessionId !== undefined ? { sessionId } : {}), ...(runId !== undefined ? { runId } : {}) }),
|
|
216
|
+
classify: async (input, signal, rung) => {
|
|
217
|
+
const rungModel = rung !== undefined ? classifierRungs[rung.index] : undefined;
|
|
218
|
+
if (rung === undefined || rungModel === undefined) {
|
|
219
|
+
throw new Error(`the auto-mode classifier was asked at ladder position ${JSON.stringify(rung?.index)}, which this arming did not build`);
|
|
220
|
+
}
|
|
221
|
+
let build = rung.index > 0 ? roundPrompt.get(input) : undefined;
|
|
222
|
+
if (build === undefined) {
|
|
223
|
+
build = (async () => {
|
|
224
|
+
const ctx = await session.buildContext();
|
|
225
|
+
const known = ctx.messages.filter((m) => !isSyntheticApiErrorMessage(m) && (m.role === "user" || m.role === "assistant" || m.role === "toolResult"));
|
|
226
|
+
return renderAutoModeWindow(known, am.window) + renderAutoModeAction(input);
|
|
227
|
+
})();
|
|
228
|
+
roundPrompt.set(input, build);
|
|
259
229
|
}
|
|
260
|
-
|
|
230
|
+
const userPrompt = await build.catch((e) => { throw autoModeRoundNotAsked(e); });
|
|
231
|
+
const classifierAuth = await spec.getApiKeyAndHeaders?.(rungModel);
|
|
232
|
+
const request = async (seat, suffix) => {
|
|
233
|
+
const response = await classifierRuntime.completeSimple(rungModel, { systemPrompt: classifierSystemPrompt, messages: [{ role: "user", content: userPrompt + suffix, timestamp: Date.now() }] }, {
|
|
234
|
+
signal,
|
|
235
|
+
...seat,
|
|
236
|
+
...(classifierAuth?.apiKey !== undefined ? { apiKey: classifierAuth.apiKey } : {}),
|
|
237
|
+
...(classifierAuth?.headers !== undefined ? { headers: classifierAuth.headers } : {}),
|
|
238
|
+
});
|
|
239
|
+
const failure = classifierReplyFailure(response);
|
|
240
|
+
if (failure !== undefined)
|
|
241
|
+
throw failure;
|
|
242
|
+
return response;
|
|
243
|
+
};
|
|
244
|
+
let response = await request(classifierRungSeat(rungModel), CLASSIFIER_ATTEMPT_SUFFIX.first);
|
|
245
|
+
if (classifierReplyAsksAgain(response) && signal?.aborted !== true)
|
|
246
|
+
response = await request(CLASSIFIER_THINK_SEAT, CLASSIFIER_ATTEMPT_SUFFIX.reask);
|
|
247
|
+
return classifierReplyVerdictText(response);
|
|
261
248
|
},
|
|
262
249
|
});
|
|
263
250
|
if (am.persistArming === true)
|
|
@@ -325,6 +312,7 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
325
312
|
parentCwd: taskRootFinal,
|
|
326
313
|
parentThinking: () => childThinkingSeat(undefined, deploymentSubagentThinking(runnerSelf.agentCatalog?.roles), harnessRef.current?.getThinkingLevel() ?? thinking).thinking,
|
|
327
314
|
parentReadFace: () => carrierReadFace(),
|
|
315
|
+
parentWriteFace: () => carrierWriteFace(),
|
|
328
316
|
parentReadDenyPatterns: () => {
|
|
329
317
|
const readDenyAdditionsNormalized = input.readDenyAdditionsNormalized();
|
|
330
318
|
return readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized : undefined;
|
|
@@ -25,6 +25,7 @@ import type { ThinkingLevel } from "../../internal/harness.js";
|
|
|
25
25
|
import { type MicroCompactMachine } from "../context-edit.js";
|
|
26
26
|
import { type LockedPreflight } from "../locked-config.js";
|
|
27
27
|
import { type ResolvedRole } from "../roles.js";
|
|
28
|
+
import { type ResolvedSkillListingBudget } from "../skill-listing-budget.js";
|
|
28
29
|
import type { SessionStore } from "../session.js";
|
|
29
30
|
import type { RunnerDeps, TaskLimits, TaskSpec } from "../types.js";
|
|
30
31
|
import { type UsageWindow } from "../usage-window-store.js";
|
|
@@ -115,7 +116,7 @@ export interface PrepareConfigDoorsInput {
|
|
|
115
116
|
/** borrowed-readonly — the caller's spec. NEVER mutated here: the per-task agents rebind returns a
|
|
116
117
|
* SHALLOW COPY on {@link PrepareConfigDoorsResult.spec} (only `tools` replaced). */
|
|
117
118
|
spec: TaskSpec;
|
|
118
|
-
/** borrowed-readonly — deployment seats. Read for:
|
|
119
|
+
/** borrowed-readonly — deployment seats. Read for: the two containment-face value screens, locked-config preflight,
|
|
119
120
|
* retention door, interaction-posture door (incl. `deps.onError` disclosure), usage windows,
|
|
120
121
|
* brain-call guardrail default, model/role maps. */
|
|
121
122
|
deps: RunnerDeps;
|
|
@@ -184,6 +185,11 @@ export interface PrepareConfigDoorsResult {
|
|
|
184
185
|
* mutated (or getter-backed) after the door must not present an unscreened value to the mark
|
|
185
186
|
* branch (the read-once posture). */
|
|
186
187
|
memoryDelegationEvidence: "static-face" | "attested-only";
|
|
188
|
+
/** owned — the lowered skills-listing budget seats (`TaskSpec.skillListingBudgetFraction` /
|
|
189
|
+
* `skillListingMaxDescChars`): the renderer's two numbers, resolved once against the resolved main
|
|
190
|
+
* model's window. Read at the door so a bad value refuses BEFORE session acquisition, and carried so
|
|
191
|
+
* the listing phase and the boundary renderer measure against the same resolution. */
|
|
192
|
+
skillListingBudget: ResolvedSkillListingBudget;
|
|
187
193
|
/** owned — the NORMALIZED memory-provenance mode: the deps seat read ONCE in
|
|
188
194
|
* the synchronous pre-await stretch, screened, absent folded to the `"carry"` default.
|
|
189
195
|
* The memory phase constructs every engine with THIS value — never a live deps re-read. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveBrainCallGuardrailMs } from "../../brain/timeout.js";
|
|
2
|
-
import {
|
|
2
|
+
import { assertContainmentFaceValue } from "../../tools/fs/index.js";
|
|
3
3
|
import { MICRO_COMPACT_MACHINES } from "../context-edit.js";
|
|
4
4
|
import { assertNoRetiredRunnerDeps } from "./retired-runner-deps.js";
|
|
5
5
|
import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
@@ -7,6 +7,8 @@ import { isModelPriced, malformedPricingField, modelCostToPricing } from "../pri
|
|
|
7
7
|
import { preflightLockedConfig } from "../locked-config.js";
|
|
8
8
|
import { assertRetentionCapability } from "../retention.js";
|
|
9
9
|
import { resolveModel, resolveTaskModel, roleModelIfSet } from "../roles.js";
|
|
10
|
+
import { resolveSkillListingBudget } from "../skill-listing-budget.js";
|
|
11
|
+
import { describeRejectedValue } from "../tool-search-setting.js";
|
|
10
12
|
import { applyToolModelGate, assertRestoreGatedToolsValue, modelIdTail } from "../tool-model-gate.js";
|
|
11
13
|
import { resolveUsageWindows } from "../usage-window-store.js";
|
|
12
14
|
import { deriveAskEffective, resolveAskSeamForm, resolveQuestionSeam } from "../wiring-manifest.js";
|
|
@@ -35,16 +37,6 @@ export function limitConfigError(code, message) {
|
|
|
35
37
|
e.code = code;
|
|
36
38
|
return e;
|
|
37
39
|
}
|
|
38
|
-
function describeRejectedValue(value) {
|
|
39
|
-
try {
|
|
40
|
-
const quoted = JSON.stringify(value);
|
|
41
|
-
if (quoted !== undefined)
|
|
42
|
-
return quoted;
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
}
|
|
46
|
-
return `a ${typeof value} value`;
|
|
47
|
-
}
|
|
48
40
|
export function resolveTaskLimits(limits) {
|
|
49
41
|
if (limits === undefined)
|
|
50
42
|
return undefined;
|
|
@@ -196,8 +188,10 @@ export function prepareConfigDoors(input) {
|
|
|
196
188
|
throw e;
|
|
197
189
|
}
|
|
198
190
|
}
|
|
199
|
-
|
|
200
|
-
|
|
191
|
+
assertContainmentFaceValue(spec.readFace, "read", "spec");
|
|
192
|
+
assertContainmentFaceValue(deps.readFace, "read", "deps");
|
|
193
|
+
assertContainmentFaceValue(spec.writeFace, "write", "spec");
|
|
194
|
+
assertContainmentFaceValue(deps.writeFace, "write", "deps");
|
|
201
195
|
const memoryDelegationEvidenceRaw = deps.memoryDelegationEvidence;
|
|
202
196
|
if (memoryDelegationEvidenceRaw !== undefined && memoryDelegationEvidenceRaw !== "static-face" && memoryDelegationEvidenceRaw !== "attested-only") {
|
|
203
197
|
const evidence = memoryDelegationEvidenceRaw;
|
|
@@ -414,6 +408,11 @@ export function prepareConfigDoors(input) {
|
|
|
414
408
|
if (gateDecision.survivors !== undefined) {
|
|
415
409
|
spec = { ...spec, tools: gateDecision.survivors };
|
|
416
410
|
}
|
|
411
|
+
const skillListingBudget = resolveSkillListingBudget({
|
|
412
|
+
fraction: spec.skillListingBudgetFraction,
|
|
413
|
+
maxDescChars: spec.skillListingMaxDescChars,
|
|
414
|
+
model,
|
|
415
|
+
});
|
|
417
416
|
const modelGate = Object.freeze({
|
|
418
417
|
removedByClass: gateDecision.removedByClass,
|
|
419
418
|
unknownClasses: gateDecision.unknownClasses,
|
|
@@ -437,6 +436,7 @@ export function prepareConfigDoors(input) {
|
|
|
437
436
|
fableMitigations,
|
|
438
437
|
modelGate,
|
|
439
438
|
memoryDelegationEvidence,
|
|
439
|
+
skillListingBudget,
|
|
440
440
|
memoryProvenance,
|
|
441
441
|
memoryCapturePolicy,
|
|
442
442
|
usageWindows,
|
|
@@ -5,11 +5,10 @@ import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
|
5
5
|
import type { AnnounceOnceSink, ToolFaceSnapshot } from "./contracts.js";
|
|
6
6
|
import { RosterBuilder } from "../tool-roster.js";
|
|
7
7
|
export interface PrepareDeferClassifyInput {
|
|
8
|
-
/** borrowed-readonly — the REBOUND spec (`spec′`); only `tools` is read (the
|
|
9
|
-
* classifier judges: names for the full-schema filter, specs for the `defer` declarations). */
|
|
8
|
+
/** borrowed-readonly — the REBOUND spec (`spec′`); only `tools` is read (names for the full-schema filter, specs for the `defer` declarations). */
|
|
10
9
|
spec: Pick<TaskSpec, "tools" | "excludeAllTools">;
|
|
11
|
-
/** borrowed-readonly —
|
|
12
|
-
deps: Pick<RunnerDeps, "deferMode">;
|
|
10
|
+
/** borrowed-readonly — deps; `deferMode` (candidate widening) and `toolSearch` (rule ②'s gate) are the only seats read. */
|
|
11
|
+
deps: Pick<RunnerDeps, "deferMode" | "toolSearch">;
|
|
13
12
|
/** borrowed-mutable — the shared mount array (later refs alias it; in-place contract, never
|
|
14
13
|
* re-created). Mutated here, in order: `splice` of every excluded name; element REPLACEMENT with a
|
|
15
14
|
* shallow copy for the classic-profile description swap (the caller's ToolSpec object is never
|
|
@@ -17,21 +16,17 @@ export interface PrepareDeferClassifyInput {
|
|
|
17
16
|
* (element replacement with the wrapped object), the disclosure mount, the MCP refresh re-splice. Since
|
|
18
17
|
* Every one of those writes is a builder verb (`unmountWhere` / `replaceAt`). */
|
|
19
18
|
roster: RosterBuilder;
|
|
20
|
-
/** borrowed-readonly — the frozen task-start tool face: `exclude` (the valve), `defer` (operator
|
|
21
|
-
* defers, exact wire names), `alwaysLoad` (the inline pins). */
|
|
19
|
+
/** borrowed-readonly — the frozen task-start tool face: `exclude` (the valve), `defer` (operator defers, exact wire names), `alwaysLoad` (the pins). */
|
|
22
20
|
toolFaceSnapshot: Pick<ToolFaceSnapshot, "exclude" | "defer" | "alwaysLoad">;
|
|
23
|
-
/** borrowed-readonly — whether a real execution env is mounted (the full-shell invariant runs only
|
|
24
|
-
* where a shell could be on the roster). */
|
|
21
|
+
/** borrowed-readonly — whether a real execution env is mounted (the full-shell invariant runs only where a shell could be on the roster). */
|
|
25
22
|
handsEnabled: boolean;
|
|
26
|
-
/** borrowed-readonly — the spec-time precomputation the invariant checks the post-exclusion roster
|
|
27
|
-
* against: a mismatch is an engine bug, thrown. */
|
|
23
|
+
/** borrowed-readonly — the spec-time precomputation the invariant checks the post-exclusion roster against: a mismatch is an engine bug, thrown. */
|
|
28
24
|
fullShellReachable: boolean;
|
|
29
25
|
/** borrowed-readonly — the resolved prompt profile (`classic` swaps in `descriptionClassic`). */
|
|
30
26
|
promptProfile: "simple" | "classic";
|
|
31
27
|
/** borrowed-readonly — the resolved model (the deferral gate's threshold reads its context window). */
|
|
32
28
|
model: Model;
|
|
33
|
-
/** borrowed-readonly — the materialized MCP roster; only `tools` is read (protocol names
|
|
34
|
-
* remote-roster arm; `mcpAlwaysLoad` self-declarations, losing to an explicit operator defer). */
|
|
29
|
+
/** borrowed-readonly — the materialized MCP roster; only `tools` is read (protocol names; `mcpAlwaysLoad` self-declarations lose to an operator defer). */
|
|
35
30
|
mcp: Pick<MaterializedMcp, "tools">;
|
|
36
31
|
/** borrowed-readonly — the materialized A2A roster; only `tools` is read (protocol names). */
|
|
37
32
|
a2a: Pick<MaterializedA2a, "tools">;
|
|
@@ -39,15 +34,12 @@ export interface PrepareDeferClassifyInput {
|
|
|
39
34
|
sharedMemoryPairMounted: boolean;
|
|
40
35
|
/** borrowed-readonly — whether the engine-memory pair mounted (project-context phase). */
|
|
41
36
|
memoryEnginePairMounted: boolean;
|
|
42
|
-
/** borrowed-readonly — the memory block as the project-context phase left it
|
|
43
|
-
*
|
|
44
|
-
* {@link PrepareDeferClassifyResult.memoryBlock}; the input value itself is never mutated. */
|
|
37
|
+
/** borrowed-readonly — the memory block as the project-context phase left it; the engine pair's retraction strips the recall paragraph and returns the
|
|
38
|
+
* stripped value as {@link PrepareDeferClassifyResult.memoryBlock}. The input is never mutated. */
|
|
45
39
|
memoryBlock: string | undefined;
|
|
46
|
-
/** borrowed-readonly — the exact recall-discipline segment the memory phase composed (the strip
|
|
47
|
-
* removes THIS string, never a re-composition). */
|
|
40
|
+
/** borrowed-readonly — the exact recall-discipline segment the memory phase composed (the strip removes THIS string, never a re-composition). */
|
|
48
41
|
memoryRecallSegment: string | undefined;
|
|
49
|
-
/** borrowed-readonly — the once-per-session ledger's deduplicated operator sink (a retraction is
|
|
50
|
-
* session-level fact, announced once). */
|
|
42
|
+
/** borrowed-readonly — the once-per-session ledger's deduplicated operator sink (a retraction is announced once per session). */
|
|
51
43
|
onceLedger: AnnounceOnceSink;
|
|
52
44
|
/** borrowed-readonly — the acquired session's id (operator-line context). */
|
|
53
45
|
sessionId: string;
|
|
@@ -60,6 +52,8 @@ export interface PrepareDeferClassifyResult {
|
|
|
60
52
|
/** owned — the memory block after the engine pair's retraction strip (unchanged when no retraction
|
|
61
53
|
* ran). The driver binds it under the name the prompt assembly reads. */
|
|
62
54
|
memoryBlock: string | undefined;
|
|
55
|
+
/** owned — the gate policy this classification was MEASURED under; the census reports it from here, never a second reading of the seat. */
|
|
56
|
+
toolSearch: import("../tool-search-setting.js").ResolvedToolSearch;
|
|
63
57
|
}
|
|
64
58
|
/** The M11 phase body — prepareTask's tool-face fold + deferred classification, verbatim (module header). */
|
|
65
59
|
export declare function prepareDeferClassify(input: PrepareDeferClassifyInput): PrepareDeferClassifyResult;
|
|
@@ -4,8 +4,9 @@ import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
|
4
4
|
import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
|
|
5
5
|
import { SHARED_MEMORY_TOOL_NAMES } from "../shared-memory/types.js";
|
|
6
6
|
import { protocolOf } from "../protocol-table.js";
|
|
7
|
-
import {
|
|
7
|
+
import { classifyDeferredWithGate } from "./tool-defer-gate.js";
|
|
8
8
|
import { TOOL_SEARCH_NAME } from "./tool-disclosure.js";
|
|
9
|
+
import { resolveToolSearch, toolSearchSettingOf } from "../tool-search-setting.js";
|
|
9
10
|
import { RosterBuilder } from "../tool-roster.js";
|
|
10
11
|
function explicitlyDeferredMemoryTrio(mounted, roster, callerDeferNames) {
|
|
11
12
|
return mounted ? MEMORY_ENGINE_TOOL_NAMES.filter((n) => roster.some((t) => t.name === n) && (callerDeferNames ?? []).includes(n)) : [];
|
|
@@ -45,13 +46,16 @@ export function prepareDeferClassify(input) {
|
|
|
45
46
|
const mcpAlwaysLoadNames = mcp.tools
|
|
46
47
|
.filter((t) => t.mcpAlwaysLoad === true && !(toolFaceSnapshot.defer ?? []).includes(t.name))
|
|
47
48
|
.map((t) => t.name);
|
|
49
|
+
const resolvedToolSearch = resolveToolSearch(deps.toolSearch);
|
|
50
|
+
const toolSearchSeat = toolSearchSettingOf(resolvedToolSearch);
|
|
48
51
|
const classifyDeferredOverFace = (face, builtinDeferNames) => {
|
|
49
52
|
const mounted = new Set(face.map((t) => t.name));
|
|
50
|
-
const
|
|
53
|
+
const classified = classifyDeferredWithGate({
|
|
51
54
|
specs: spec.tools ?? [],
|
|
52
55
|
protocolToolNames,
|
|
53
56
|
fullTools: face,
|
|
54
57
|
deferMode: deps.deferMode,
|
|
58
|
+
toolSearch: toolSearchSeat,
|
|
55
59
|
model,
|
|
56
60
|
callerDeferNames: (toolFaceSnapshot.defer ?? []).filter((n) => mounted.has(n)),
|
|
57
61
|
builtinDeferNames: builtinDeferNames.filter((n) => mounted.has(n)),
|
|
@@ -61,6 +65,7 @@ export function prepareDeferClassify(input) {
|
|
|
61
65
|
...mcpAlwaysLoadNames,
|
|
62
66
|
],
|
|
63
67
|
});
|
|
68
|
+
const deferredSet = classified.deferred;
|
|
64
69
|
for (const n of [...deferredSet])
|
|
65
70
|
if (!mounted.has(n))
|
|
66
71
|
deferredSet.delete(n);
|
|
@@ -105,5 +110,5 @@ export function prepareDeferClassify(input) {
|
|
|
105
110
|
else {
|
|
106
111
|
deferred = classifyDeferredOverFace(tools, []);
|
|
107
112
|
}
|
|
108
|
-
return { deferred, memoryBlock };
|
|
113
|
+
return { deferred, memoryBlock, toolSearch: resolvedToolSearch };
|
|
109
114
|
}
|
|
@@ -28,12 +28,38 @@ import type { AutoModeDecider, AutoModeDenialTracker } from "../auto-mode.js";
|
|
|
28
28
|
import { type ComplianceCapability } from "../compliance.js";
|
|
29
29
|
import { type HookEnvCapabilities, type HookInvocationIdentity, type Hooks } from "../hooks.js";
|
|
30
30
|
import type { ToolPolicy } from "../tool-policy.js";
|
|
31
|
+
import { type GateOutcome } from "../gate-outcome.js";
|
|
31
32
|
import type { RunnerDeps, TaskSpec, ToolEffect } from "../types.js";
|
|
32
33
|
import type { CwdRef } from "../../tools/fs/fs-shared.js";
|
|
33
34
|
import type { AskLane, IrreversibilityTier, ParkAsk, Prepared, ReversibilityProbes } from "./contracts.js";
|
|
34
35
|
import type { StopForDenialLimit } from "./denial-limit-arms.js";
|
|
35
36
|
import type { PermissionRuleLanes } from "./permission-rule-lanes.js";
|
|
36
37
|
import { type ToolRosterDeltaSeat } from "../tool-roster.js";
|
|
38
|
+
/**
|
|
39
|
+
* The parent-thread human-rejection boundary — judged ONCE here, from the pass's own record (CC parity:
|
|
40
|
+
* the reference CLI's reject path aborts exactly when there is no feedback and the run is not a
|
|
41
|
+
* subagent; a rejection WITH the decider's note, and every delegated child — forks included — keep the
|
|
42
|
+
* continue / adapt-or-report posture): the final block IS a person's refusal (`deniedBy: ask_resolution`
|
|
43
|
+
* and a `human_refused` settlement — not a later fold layer's deny that merely followed a human
|
|
44
|
+
* interaction), the refusal carried NO note (`settlement.note` absent — a fact composed at the refusal,
|
|
45
|
+
* never re-derived from message text), and the run is not a delegated child (the raw trusted delegation
|
|
46
|
+
* facet — the same fact that selects the refusal text's posture, so the boundary and the words the model
|
|
47
|
+
* was told always agree). Policy/hook/classifier denies and window/abort settlements never satisfy it.
|
|
48
|
+
*
|
|
49
|
+
* Returns the loop directive that settles every never-started same-batch sibling: honest
|
|
50
|
+
* known-not-executed wording plus the machine mark (`error`/`code` twin — the wire errorCode lift
|
|
51
|
+
* reads `details.code`; `details.error` is the in-band mark result consumers grep) naming the
|
|
52
|
+
* rejected call. `undefined` = no boundary (the block stands alone, current behavior).
|
|
53
|
+
*/
|
|
54
|
+
export declare function maybeHumanRejectionHalt(input: {
|
|
55
|
+
gate: GateOutcome | undefined;
|
|
56
|
+
isDelegatedChild: boolean;
|
|
57
|
+
toolName: string;
|
|
58
|
+
toolCallId: string;
|
|
59
|
+
}): {
|
|
60
|
+
reason: string;
|
|
61
|
+
details: Record<string, unknown>;
|
|
62
|
+
} | undefined;
|
|
37
63
|
export interface PrepareGateStationsInput {
|
|
38
64
|
/** borrowed-readonly — the in-stream ask lane, or undefined when the gate machinery is inactive (then no `tool_call`
|
|
39
65
|
* station is built). Read: `adjudicate`, `resolveAskBound`, `notifyPermissionDenied`, `notifyHookError`. */
|
|
@@ -23,7 +23,7 @@ function screenGateResult(result) {
|
|
|
23
23
|
}
|
|
24
24
|
return defects.length > 0 ? { defects } : { gate, defects };
|
|
25
25
|
}
|
|
26
|
-
function maybeHumanRejectionHalt(input) {
|
|
26
|
+
export function maybeHumanRejectionHalt(input) {
|
|
27
27
|
const d = input.gate?.disposition;
|
|
28
28
|
const s = input.gate?.settlement;
|
|
29
29
|
const bare = d?.kind === "denied" && d.deniedBy === "ask_resolution" && s?.kind === "human_refused" && s.note === undefined;
|