@sema-agent/core 7.5.0 → 7.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/core/auto-mode.d.ts +9 -0
  3. package/dist/core/auto-mode.js +11 -0
  4. package/dist/core/checkpoint-store.js +5 -1
  5. package/dist/core/protocol-table.d.ts +5 -0
  6. package/dist/core/protocol-table.js +1 -0
  7. package/dist/core/runner/abort-race.d.ts +41 -0
  8. package/dist/core/runner/abort-race.js +38 -0
  9. package/dist/core/runner/checkpoint-scope.d.ts +44 -0
  10. package/dist/core/runner/checkpoint-scope.js +7 -0
  11. package/dist/core/runner/compaction-call-options.d.ts +1 -1
  12. package/dist/core/runner/content-ask-bindings.d.ts +27 -0
  13. package/dist/core/runner/content-ask-bindings.js +1 -0
  14. package/dist/core/runner/contracts.d.ts +1990 -0
  15. package/dist/core/runner/contracts.js +1 -0
  16. package/dist/core/runner/denial-limit-arms.d.ts +24 -1
  17. package/dist/core/runner/denial-limit-arms.js +21 -0
  18. package/dist/core/runner/derived-route-fallback.d.ts +34 -0
  19. package/dist/core/runner/derived-route-fallback.js +16 -0
  20. package/dist/core/runner/inherited-ask-grants.d.ts +46 -0
  21. package/dist/core/runner/inherited-ask-grants.js +29 -0
  22. package/dist/core/runner/park-commit.d.ts +108 -0
  23. package/dist/core/runner/park-commit.js +32 -0
  24. package/dist/core/runner/{prepare-permission-rules.d.ts → permission-rule-lanes.d.ts} +109 -3
  25. package/dist/core/runner/{prepare-permission-rules.js → permission-rule-lanes.js} +47 -1
  26. package/dist/core/runner/prepare-acquire-reconcile.d.ts +1 -1
  27. package/dist/core/runner/prepare-ask-lane.d.ts +110 -0
  28. package/dist/core/runner/prepare-ask-lane.js +133 -0
  29. package/dist/core/runner/prepare-boundary-parks.d.ts +105 -0
  30. package/dist/core/runner/prepare-boundary-parks.js +169 -0
  31. package/dist/core/runner/prepare-caps-and-workflow.d.ts +170 -0
  32. package/dist/core/runner/prepare-caps-and-workflow.js +255 -0
  33. package/dist/core/runner/prepare-config-doors.d.ts +2 -10
  34. package/dist/core/runner/prepare-context-lane.d.ts +119 -0
  35. package/dist/core/runner/prepare-context-lane.js +230 -0
  36. package/dist/core/runner/prepare-defer-classify.d.ts +86 -0
  37. package/dist/core/runner/prepare-defer-classify.js +107 -0
  38. package/dist/core/runner/prepare-delegation-surface.d.ts +104 -0
  39. package/dist/core/runner/prepare-delegation-surface.js +144 -0
  40. package/dist/core/runner/prepare-execution-env.d.ts +54 -0
  41. package/dist/core/runner/prepare-execution-env.js +86 -0
  42. package/dist/core/runner/prepare-file-history.d.ts +95 -0
  43. package/dist/core/runner/prepare-file-history.js +383 -0
  44. package/dist/core/runner/prepare-gate-stations.d.ts +177 -0
  45. package/dist/core/runner/prepare-gate-stations.js +290 -0
  46. package/dist/core/runner/prepare-hands-readface.d.ts +9 -11
  47. package/dist/core/runner/prepare-hands-readface.js +1 -1
  48. package/dist/core/runner/prepare-inherited-gate.d.ts +268 -0
  49. package/dist/core/runner/prepare-inherited-gate.js +266 -0
  50. package/dist/core/runner/prepare-listings.d.ts +77 -0
  51. package/dist/core/runner/prepare-listings.js +76 -0
  52. package/dist/core/runner/prepare-lsp.d.ts +55 -0
  53. package/dist/core/runner/prepare-lsp.js +27 -0
  54. package/dist/core/runner/prepare-memory-engine-session.d.ts +84 -0
  55. package/dist/core/runner/prepare-memory-engine-session.js +233 -0
  56. package/dist/core/runner/prepare-memory.d.ts +1 -1
  57. package/dist/core/runner/prepare-offload-wrappers.d.ts +62 -0
  58. package/dist/core/runner/prepare-offload-wrappers.js +45 -0
  59. package/dist/core/runner/prepare-park-ask.d.ts +164 -0
  60. package/dist/core/runner/prepare-park-ask.js +377 -0
  61. package/dist/core/runner/prepare-policy-chain.d.ts +208 -0
  62. package/dist/core/runner/prepare-policy-chain.js +584 -0
  63. package/dist/core/runner/prepare-project-context.d.ts +119 -0
  64. package/dist/core/runner/prepare-project-context.js +148 -0
  65. package/dist/core/runner/prepare-prompt-assembly.d.ts +95 -0
  66. package/dist/core/runner/prepare-prompt-assembly.js +162 -0
  67. package/dist/core/runner/prepare-prompt-inputs.d.ts +119 -0
  68. package/dist/core/runner/prepare-prompt-inputs.js +141 -0
  69. package/dist/core/runner/prepare-protocol-tools.d.ts +91 -0
  70. package/dist/core/runner/prepare-protocol-tools.js +179 -0
  71. package/dist/core/runner/prepare-question-face.d.ts +101 -0
  72. package/dist/core/runner/prepare-question-face.js +84 -0
  73. package/dist/core/runner/prepare-run-refs.d.ts +89 -0
  74. package/dist/core/runner/prepare-run-refs.js +39 -0
  75. package/dist/core/runner/prepare-safety-scan.d.ts +3 -7
  76. package/dist/core/runner/prepare-safety-scan.js +1 -2
  77. package/dist/core/runner/prepare-suspend-saga.d.ts +170 -0
  78. package/dist/core/runner/prepare-suspend-saga.js +308 -0
  79. package/dist/core/runner/prepare-task.d.ts +14 -1976
  80. package/dist/core/runner/prepare-task.js +182 -5162
  81. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +111 -0
  82. package/dist/core/runner/prepare-tool-disclosure-mount.js +219 -0
  83. package/dist/core/runner/prepare-turn-wiring.d.ts +154 -0
  84. package/dist/core/runner/prepare-turn-wiring.js +201 -0
  85. package/dist/core/runner/prepare-wiring-manifest.d.ts +192 -0
  86. package/dist/core/runner/prepare-wiring-manifest.js +247 -0
  87. package/dist/core/runner/prepare-workspace-restore.d.ts +3 -56
  88. package/dist/core/runner/prepare-workspace-restore.js +4 -38
  89. package/dist/core/runner/prompt-hash-salt.d.ts +1 -0
  90. package/dist/core/runner/prompt-hash-salt.js +2 -0
  91. package/dist/core/runner/remote-env-retry.d.ts +29 -0
  92. package/dist/core/runner/remote-env-retry.js +16 -0
  93. package/dist/core/runner/rollback-stack.d.ts +32 -0
  94. package/dist/core/runner/rollback-stack.js +30 -0
  95. package/dist/core/runner/runtask.js +1 -1
  96. package/dist/core/runner/workspace-path.d.ts +33 -0
  97. package/dist/core/runner/workspace-path.js +22 -0
  98. package/dist/core/session.d.ts +12 -0
  99. package/dist/core/session.js +3 -0
  100. package/dist/core/tool-policy.d.ts +16 -0
  101. package/dist/core/tool-policy.js +3 -0
  102. package/dist/core/types.d.ts +2 -2
  103. package/dist/core/write-protect.js +3 -2
  104. package/package.json +6 -2
  105. /package/dist/core/runner/{prepare-announce-once.d.ts → announce-once-ledger.d.ts} +0 -0
  106. /package/dist/core/runner/{prepare-announce-once.js → announce-once-ledger.js} +0 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * design/390 §1.2 M4 — prepareTask's CAPS-AND-WORKFLOW phase, verbatim from the driver: the caller-tool roster
3
+ * map (the defineTool-product branch and the rich-ctx wrap through the large-result wrapper), the ReportBlocked /
4
+ * ReportFindings / plan-pair mounts, the per-principal runtime caps resolve with its fail-closed degrade and value
5
+ * screen, the compliance posture veto with its two refusal codes, the fork verdict and the observers grant, the
6
+ * auto-mode arming (classifier model, lane rule, decider + denial tracker + persisted recipe) with its manifest
7
+ * reason, the self-orchestration gate with its governance note, and the Workflow mount with its size-guideline
8
+ * seat. The three arming helpers and the parent-capture-state join moved with the segment (only this phase calls
9
+ * them). The interface is the dependency list the segment had implicitly (design/238 R-1).
10
+ *
11
+ * ASYNC PHASE: the segment awaits the two resolvers, the classifier route pre-flight and the Workflow factory,
12
+ * exactly where the driver awaited them; the roster map and the synthetic mounts before the first of those awaits
13
+ * run synchronously as they did. Read-stability of the host handles for the call: {@link RunInternals}
14
+ * (`@contract prepare.deps-read-stable`).
15
+ *
16
+ * THE ROSTER IS MINTED HERE (`tools`): every later phase that mounts pushes into this same array — the writer table
17
+ * lives on {@link Prepared.tools} (design/238 R-3). LATE-BOUND SEATS: the Workflow mount's call-time getters read
18
+ * three facts later stations resolve (the memory session, the center adoption, the hands mount's deny additions);
19
+ * each enters as a getter on the Input and is read exactly where the driver's getter read the variable.
20
+ */
21
+ import type { AgentHarness, AgentTool, ThinkingLevel } from "../../internal/harness.js";
22
+ import type { Model } from "../../internal/llm.js";
23
+ import { forkGovernanceDenial } from "../../agents/subagent.js";
24
+ import type { PromptEpochArtifact } from "../../prompt-assembly/artifact.js";
25
+ import { createRunWorkflowTool } from "../../orchestration/run-workflow-tool.js";
26
+ import { type WorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
27
+ import { type AutoModeArmingRecipe } from "../auto-mode-arming.js";
28
+ import { type AutoModeDecider, type AutoModeDenialTracker } from "../auto-mode.js";
29
+ import { type ComplianceCapability } from "../compliance.js";
30
+ import type { LockedPreflight } from "../locked-config.js";
31
+ import type { StoredSession } from "../session.js";
32
+ import type { OnAsk } from "../tool-policy.js";
33
+ import type { RunnerDeps, RuntimeCaps, TaskEvent, TaskSpec, ToolExecuteContext } from "../types.js";
34
+ import type { AutoModeArmReason } from "../wiring-manifest.js";
35
+ import type { ReadFace } from "../../tools/fs/index.js";
36
+ import type { InheritedGate, Prepared, RunInternals, ToolFaceSnapshot } from "./contracts.js";
37
+ import { type BlockedRef } from "./synthetic-tools.js";
38
+ /** The runner the Workflow mount accepts — spelled as the factory's own option type so this phase names no runner
39
+ * module of its own (the narrow `RunnerSelfSeat` contract is a design decision still open; see the layering registry). */
40
+ type WorkflowMountRunner = Parameters<typeof createRunWorkflowTool>[0]["runner"];
41
+ export interface PrepareCapsAndWorkflowInput {
42
+ /** borrowed-readonly — the REBOUND spec, whole: the roster map reads `tools`; the mounts read `enableBlockedReport`,
43
+ * `enablePlanMode`, `interactiveTools`, `checkpointStore`; the caps/compliance stations read `principal`, `selfOrchestration`,
44
+ * `enableFork`, `getApiKeyAndHeaders`; the Workflow mount forwards `oneShot`, `handsReadOnly`, `interactiveTools`. The
45
+ * self-orchestration predicate takes the whole spec. Never mutated. */
46
+ spec: TaskSpec;
47
+ /** borrowed-readonly — the deployment seats, whole: `runtimeCapsResolver`, `compliancePostureResolver`, `onError`, `onNotice`,
48
+ * `autoMode`, `brain`, `models`, `checkpointStore` (the plan-pair face), and the Workflow mount's dozen deps (`workflowScriptRunner`,
49
+ * `workflowGovernanceBaseline`, `workflowRunStore`, `workflowJournalStore`, `workflowScriptStore`, `builtinWorkflows`,
50
+ * `onWorkflowAgentSpawn`, `workflowCompletionNotifier`, `workflowLimits`, `agents`, `builtinAgents`, `onBackgroundChildEvent`).
51
+ * The self-orchestration predicate takes the whole record. */
52
+ deps: RunnerDeps;
53
+ /** borrowed-readonly — the trusted spawn-side channel; the Workflow mount forwards `rootSessionId`, `placementRoot`,
54
+ * `onTaskNotification`, `workflowDepth`, and the capture-floor getter reads `memoryCaptureAncestors`. */
55
+ internals: Pick<RunInternals, "rootSessionId" | "placementRoot" | "onTaskNotification" | "workflowDepth" | "memoryCaptureAncestors"> | undefined;
56
+ /** borrowed-readonly — the acquired session; the classifier leg rebuilds its transcript window from `buildContext`. */
57
+ session: Pick<StoredSession, "buildContext">;
58
+ /** borrowed-readonly — the acquired session id (operator-line context, the refusal codes' phase record). */
59
+ sessionId: string;
60
+ /** borrowed-readonly — the run's invocation id (the classifier route pre-flight's notice names it). */
61
+ runId: string;
62
+ /** borrowed-readonly — the per-task identity the Workflow mount registers its children under. */
63
+ hostTaskId: string;
64
+ /** borrowed-readonly — the registry scope the Workflow mount registers in. */
65
+ taskScope: string;
66
+ /** borrowed-readonly — the SETTLED task root the Workflow mount hands its children as `parentCwd`. */
67
+ taskRootFinal: string;
68
+ /** borrowed-readonly — the run's resolved model: the classifier leg's fallback and the route pre-flight's primary. */
69
+ model: Model;
70
+ /** borrowed-readonly — the run's resolved thinking level, when one is (the Workflow mount's parentThinking fallback). */
71
+ thinking: ThinkingLevel | undefined;
72
+ /** borrowed-readonly — the frozen preflight; only `mcp` (the compliance veto's mcp_servers conflict check). */
73
+ lockedPreflight: Pick<LockedPreflight, "mcp">;
74
+ /** borrowed-mutable — the effect collection (`Prepared.toolEffects`). Writer here: ONE set, `Workflow → write`, at its mount.
75
+ * Every other writer is the safety scan (the seed) and the later mounts (see the roster table on `Prepared.tools`). */
76
+ toolEffects: Prepared["toolEffects"];
77
+ /** borrowed-readonly — the frozen tool-face snapshot the Workflow mount forwards (exclude / defer / alwaysLoad / restoreGated). */
78
+ toolFaceSnapshot: ToolFaceSnapshot;
79
+ /** borrowed-readonly — the resolved prompt profile (the Workflow mount's parentPromptProfile). */
80
+ promptProfile: ToolExecuteContext["promptProfile"];
81
+ /** borrowed-readonly — the resolved interaction posture (the Workflow mount's parentInteractionPosture; absent ⇒ no key). */
82
+ resolvedInteractionPosture: ToolExecuteContext["interactionPosture"];
83
+ /** borrowed-readonly — the harness seat; the Workflow mount's parentModel / parentThinking getters read it call-time. */
84
+ harnessRef: {
85
+ current?: AgentHarness;
86
+ };
87
+ /** borrowed-readonly — the FROZEN approver seat (the Workflow mount's parentOnAsk). */
88
+ frozenOnAsk: OnAsk | undefined;
89
+ /** borrowed-readonly — the ONE read-face carrier expression (the Workflow mount's parentReadFace getter calls it). */
90
+ carrierReadFace: () => ReadFace | undefined;
91
+ /** borrowed-readonly — the filtered display-forwarding wrapper (the Workflow mount's forwardEvent; absent ⇒ no key). */
92
+ forwardEvent: ((e: TaskEvent) => void) | undefined;
93
+ /** borrowed-readonly — the child-chain assembly (the Workflow mount's inheritedGateForChildren). */
94
+ inheritedGateForChildren: () => InheritedGate;
95
+ /** borrowed-readonly — the caller-tool ctx enrichment the roster map wraps every raw ToolSpec with. */
96
+ enrichSpecToolCtx: (ctx: ToolExecuteContext) => ToolExecuteContext;
97
+ /** borrowed-readonly — the large-result wrapper every roster entry passes through (per-tool policy honored inside). */
98
+ maybeOffload: (tool: AgentTool, perTool?: {
99
+ offload?: boolean;
100
+ offloadThresholdChars?: number;
101
+ }) => AgentTool;
102
+ /** borrowed-readonly — the plan-review primitive the ExitPlanMode tool calls. */
103
+ requestReview: (opts?: {
104
+ reason?: string;
105
+ }) => void;
106
+ /** borrowed-readonly — the plan-mode primitive the EnterPlanMode tool calls. */
107
+ enterPlanMode: () => void;
108
+ /** borrowed-readonly — the auto-mode INTENT (own seat ∨ chain ∨ checkpoint), the arming's first arm. */
109
+ autoModeIntent: boolean;
110
+ /** borrowed-readonly — the peer lane's mount verdict (the classifier's cross-session rule fills only while mounted). */
111
+ peerLaneActive: boolean;
112
+ /** borrowed-readonly — whether the BUILT-IN SendMessage is on this face (the lane rule's second term). */
113
+ peerSendMessageBuiltIn: boolean;
114
+ /** borrowed-readonly — the trusted Runner self-reference the Workflow mount executes children through; undefined when
115
+ * prepareTask runs standalone (then Workflow is simply not mounted). */
116
+ runnerSelf: WorkflowMountRunner | undefined;
117
+ /** borrowed-readonly — LATE-BOUND: the memory-engine session; the Workflow mount's capture-floor getter reads it at ITS call time. */
118
+ memoryEngineSession: () => Prepared["memoryEngineSession"];
119
+ /** borrowed-readonly — LATE-BOUND: the adopted center artifact; the Workflow mount's two center getters read it at THEIR call time. */
120
+ centerAdoption: () => {
121
+ artifact: PromptEpochArtifact;
122
+ sourceRevision?: string;
123
+ } | undefined;
124
+ /** borrowed-readonly — LATE-BOUND: the normalized deny additions; the Workflow mount's parentReadDenyPatterns getter reads it at call time. */
125
+ readDenyAdditionsNormalized: () => ReadonlyArray<{
126
+ pattern: string;
127
+ caseSensitive: boolean;
128
+ }>;
129
+ }
130
+ export interface PrepareCapsAndWorkflowResult {
131
+ /** owned — THE run's roster, minted here from the caller's tools; every later mount pushes into this same array
132
+ * (`Prepared.tools`, whose JSDoc carries the writer table). Writers here: the map that mints it, then the ReportBlocked,
133
+ * ReportFindings, ExitPlanMode, EnterPlanMode and Workflow pushes. */
134
+ tools: AgentTool[];
135
+ /** borrowed-mutable — the ReportBlocked tool's write seat (`Prepared.blockedRef`). Writer: the tool at run time; read at
136
+ * result assembly. */
137
+ blockedRef: BlockedRef;
138
+ /** owned — the per-principal entitlements as resolved (or the fail-closed degrade), undefined = no restriction. */
139
+ runtimeCaps: RuntimeCaps | undefined;
140
+ /** owned — whether the caps resolve FAULTED (throw or value screen) — never read off a coined explicit value. */
141
+ runtimeCapsFaulted: boolean;
142
+ /** owned — the compliance deny set (every capability under a resolver fault). */
143
+ complianceDenies: ReadonlySet<ComplianceCapability>;
144
+ /** owned — whether the compliance resolve faulted (the refusal code distinguishes it). */
145
+ complianceDegraded: boolean;
146
+ /** owned — the fork-governance verdict (present only when denied; the ctx reads it call-time). */
147
+ agentForkDenial: ReturnType<typeof forkGovernanceDenial>;
148
+ /** owned — the observers grant (`allowObservers === true`, explicit opt-in). */
149
+ observersActive: boolean;
150
+ /** owned — the arming outcome as a closed reason (the manifest's auto-mode face). */
151
+ autoModeArmReason: AutoModeArmReason;
152
+ /** owned — the armed classifier, or undefined when any arming arm failed. */
153
+ autoModeDecider: AutoModeDecider | undefined;
154
+ /** owned — the denial tracker built beside the decider (same face, same arming). */
155
+ autoModeDenialTracking: AutoModeDenialTracker | undefined;
156
+ /** owned — the serializable arming recipe (persistArming opt-in only). */
157
+ autoModeArming: AutoModeArmingRecipe | undefined;
158
+ /** owned — self-orchestration is ACTIVE for this leg (deployment ready ∧ not entitlement-denied); drives the prompt injection. */
159
+ selfOrchestrationActive: boolean;
160
+ /** owned — the Workflow tool is on the roster (the delegation surface's second door). */
161
+ workflowToolsActive: boolean;
162
+ /** owned — the mid-session size-guideline seat, armed with the Workflow mount (`Prepared.workflowSizeGuideline`). */
163
+ workflowSizeGuideline: {
164
+ legGuideline: WorkflowSizeGuideline;
165
+ current: () => WorkflowSizeGuideline;
166
+ } | undefined;
167
+ }
168
+ /** The M4 phase body — prepareTask's caps-and-workflow stretch, verbatim (see the module header). */
169
+ export declare function prepareCapsAndWorkflow(input: PrepareCapsAndWorkflowInput): Promise<PrepareCapsAndWorkflowResult>;
170
+ export {};
@@ -0,0 +1,255 @@
1
+ import { isSyntheticApiErrorMessage } from "../../internal/harness.js";
2
+ import { createHash } from "node:crypto";
3
+ import { forkGovernanceDenial } from "../../agents/subagent.js";
4
+ import { CROSS_SESSION_CLASSIFIER_RULE } from "../../agents/cross-session-envelope.js";
5
+ import { createRunWorkflowTool, RUN_WORKFLOW_TOOL_NAME } from "../../orchestration/run-workflow-tool.js";
6
+ import { isSelfOrchestrationActive } from "../../orchestration/workflow-script-runner.js";
7
+ import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
8
+ import { autoModeArmingRecipeOf } from "../auto-mode-arming.js";
9
+ import { buildAutoModePrompt, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
10
+ import { createAutoModeDecider, createAutoModeDenialTracker } from "../auto-mode.js";
11
+ import { resolveCheckpointStore } from "../checkpoint-store.js";
12
+ import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, resolveComplianceDenies } from "../compliance.js";
13
+ import { createPresentPlanTool, createEnterPlanModeTool } from "../present-plan-tool.js";
14
+ import { resolveTaskModel } from "../roles.js";
15
+ import { brainToRuntime } from "../runtime.js";
16
+ import { defaultTaskRegistry } from "../task-registry.js";
17
+ import { defineTool, isDefineToolProduct } from "../tools.js";
18
+ import { derivedRouteFallsBack } from "./derived-route-fallback.js";
19
+ import { REPORT_FINDINGS_TOOL_NAME, createReportBlockedTool, createReportFindingsTool } from "./synthetic-tools.js";
20
+ function assembleParentCaptureState(o, i, ctl, ancestors) {
21
+ const build = (optedOut, indeterminate) => ({
22
+ optedOut: optedOut === true,
23
+ indeterminate: indeterminate === true,
24
+ ...(ctl !== undefined ? { controlDir: ctl } : {}),
25
+ ancestors,
26
+ });
27
+ return o instanceof Promise || i instanceof Promise ? Promise.all([o, i]).then(([ov, iv]) => build(ov, iv)) : build(o, i);
28
+ }
29
+ function screenAutoModeCap(caps, onError, sessionId) {
30
+ if (caps === undefined)
31
+ return { caps, faulted: false };
32
+ if (typeof caps !== "object" || caps === null || Array.isArray(caps)) {
33
+ onError?.(new Error(`runtimeCapsResolver returned a non-record value (${JSON.stringify(caps)}) — read as a resolver fault: every per-principal capability is DENIED for this run (auto mode is not armed; asks flow the original chain). Return a RuntimeCaps object or undefined.`), { phase: "config", sessionId });
34
+ return { caps: { allowWorkflows: false, allowFork: false, autoMode: false }, faulted: true };
35
+ }
36
+ const record = caps;
37
+ if (record.autoMode === undefined || typeof record.autoMode === "boolean")
38
+ return { caps: record, faulted: false };
39
+ onError?.(new Error(`runtimeCapsResolver returned a non-boolean autoMode (${JSON.stringify(record.autoMode)}) — read as a resolver fault: auto mode is DENIED for this run (the classifier is not armed; asks flow the original chain). Return true, false, or omit the key.`), { phase: "config", sessionId });
40
+ return { caps: { ...record, autoMode: false }, faulted: true };
41
+ }
42
+ function mintPersistedArming(am, laneRule, classifierSystemPrompt, onError, sessionId) {
43
+ const arming = autoModeArmingRecipeOf(laneRule ? { ...am, crossSessionMessagesRule: true } : am, {
44
+ promptDigest: `apv1:${createHash("sha256").update(classifierSystemPrompt).digest("hex")}`,
45
+ });
46
+ if (arming === undefined) {
47
+ onError?.(new Error("RunnerDeps.autoMode.persistArming is set but the auto-mode face did not canonicalize into an arming recipe " +
48
+ "(a rule list carrying a non-string, or a non-finite/out-of-range timeoutMs / failureThreshold / window bound) — " +
49
+ "NO arming recipe is recorded on this run's parked constraint chain, and a cross-process redemption keeps the " +
50
+ "conservative behavior (the ancestor classifier answers unavailable and the inherited ask flows to a human)"), { phase: "config", sessionId });
51
+ }
52
+ return arming;
53
+ }
54
+ function autoModeArmReasonOf(intent, facePresent, capsAutoMode, capsFaulted) {
55
+ if (!intent)
56
+ return "no_intent";
57
+ if (!facePresent)
58
+ return "no_face";
59
+ if (capsAutoMode === false)
60
+ return capsFaulted ? "resolver_fault" : "denied";
61
+ return "armed";
62
+ }
63
+ export async function prepareCapsAndWorkflow(input) {
64
+ const { spec, deps, 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;
65
+ const tools = (spec.tools ?? []).map((t) => {
66
+ if (isDefineToolProduct(t)) {
67
+ return maybeOffload(t, t);
68
+ }
69
+ return maybeOffload(defineTool({
70
+ ...t,
71
+ execute: (args, ctx) => t.execute(args, enrichSpecToolCtx(ctx)),
72
+ }), t);
73
+ });
74
+ const blockedRef = {};
75
+ if (spec.enableBlockedReport !== false) {
76
+ tools.push(createReportBlockedTool(blockedRef));
77
+ }
78
+ if (!(spec.tools ?? []).some((t) => t.name === REPORT_FINDINGS_TOOL_NAME || t.aliases?.includes(REPORT_FINDINGS_TOOL_NAME))) {
79
+ tools.push(createReportFindingsTool());
80
+ }
81
+ if (spec.enablePlanMode === true && spec.interactiveTools !== false) {
82
+ const planReviewFace = resolveCheckpointStore(spec, deps) !== undefined;
83
+ if (spec.interactiveTools === true || planReviewFace) {
84
+ tools.push(defineTool(createPresentPlanTool(requestReview)));
85
+ if (planReviewFace) {
86
+ tools.push(defineTool(createEnterPlanModeTool(enterPlanMode)));
87
+ }
88
+ }
89
+ }
90
+ let runtimeCaps;
91
+ let runtimeCapsFaulted = false;
92
+ if (deps.runtimeCapsResolver) {
93
+ try {
94
+ runtimeCaps = (await deps.runtimeCapsResolver(spec.principal)) ?? undefined;
95
+ }
96
+ catch (err) {
97
+ deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
98
+ runtimeCaps = { allowWorkflows: false, allowFork: false, autoMode: false };
99
+ runtimeCapsFaulted = true;
100
+ }
101
+ const screened = screenAutoModeCap(runtimeCaps, deps.onError, sessionId);
102
+ runtimeCaps = screened.caps;
103
+ runtimeCapsFaulted ||= screened.faulted;
104
+ }
105
+ let complianceDenies = new Set();
106
+ let complianceDegraded = false;
107
+ if (deps.compliancePostureResolver) {
108
+ try {
109
+ const posture = (await deps.compliancePostureResolver(spec.principal)) ?? undefined;
110
+ if (posture !== undefined)
111
+ complianceDenies = resolveComplianceDenies(posture);
112
+ }
113
+ catch (err) {
114
+ deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
115
+ complianceDenies = new Set(COMPLIANCE_CAPABILITIES);
116
+ complianceDegraded = true;
117
+ }
118
+ const complianceRefuse = (capability, requested) => {
119
+ const e = new Error(`${requested} is denied for this principal by the compliance posture (capability "${capability}"` +
120
+ `${complianceDegraded ? "; the posture resolver is currently failing, so every managed capability is denied fail-closed" : ""}) — ` +
121
+ `the task is refused rather than silently narrowed.`);
122
+ e.code = complianceDegraded ? "config.compliance_required" : "config.compliance_denied";
123
+ throw e;
124
+ };
125
+ if (complianceDenies.has("mcp_servers") && lockedPreflight.mcp?.length) {
126
+ complianceRefuse("mcp_servers", "TaskSpec.mcp (MCP server materialization)");
127
+ }
128
+ if (complianceDenies.has("workflows") && spec.selfOrchestration === true) {
129
+ complianceRefuse("workflows", "TaskSpec.selfOrchestration (workflow self-orchestration)");
130
+ }
131
+ if (complianceDenies.has("web_fetch")) {
132
+ const webTool = (spec.tools ?? []).find((t) => t.name === WEB_FETCH_TOOL_NAME || (t.aliases ?? []).includes(WEB_FETCH_TOOL_NAME));
133
+ if (webTool !== undefined) {
134
+ complianceRefuse("web_fetch", `TaskSpec.tools["${webTool.name}"] (the WebFetch tool face)`);
135
+ }
136
+ }
137
+ }
138
+ const agentForkDenial = forkGovernanceDenial(spec.enableFork, runtimeCaps?.allowFork);
139
+ const observersActive = runtimeCaps?.allowObservers === true;
140
+ let autoModeDecider;
141
+ let autoModeDenialTracking;
142
+ let autoModeArming;
143
+ const autoModeArmReason = autoModeArmReasonOf(autoModeIntent, deps.autoMode !== undefined, runtimeCaps?.autoMode, runtimeCapsFaulted);
144
+ if (autoModeIntent && deps.autoMode !== undefined && runtimeCaps?.autoMode !== false) {
145
+ const am = deps.autoMode;
146
+ let classifierModel;
147
+ try {
148
+ classifierModel = resolveTaskModel({ modelRole: "classifier" }, deps).model;
149
+ }
150
+ catch {
151
+ classifierModel = model;
152
+ }
153
+ if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId })) {
154
+ classifierModel = model;
155
+ }
156
+ const classifierLaneRule = peerLaneActive && peerSendMessageBuiltIn;
157
+ const classifierSystemPrompt = buildAutoModePrompt(classifierLaneRule ? { ...am, crossSessionMessagesRule: CROSS_SESSION_CLASSIFIER_RULE } : am);
158
+ const classifierRuntime = brainToRuntime(deps.brain);
159
+ autoModeDenialTracking = createAutoModeDenialTracker(am.denialLimit);
160
+ autoModeDecider = createAutoModeDecider({
161
+ ...(am.timeoutMs !== undefined ? { timeoutMs: am.timeoutMs } : {}),
162
+ ...(am.failureThreshold !== undefined ? { failureThreshold: am.failureThreshold } : {}),
163
+ ...(am.onBreakerOpen !== undefined ? { onBreakerOpen: am.onBreakerOpen } : {}),
164
+ classify: async (input, signal) => {
165
+ const ctx = await session.buildContext();
166
+ const known = ctx.messages.filter((m) => !isSyntheticApiErrorMessage(m) &&
167
+ (m.role === "user" || m.role === "assistant" || m.role === "toolResult"));
168
+ const userPrompt = renderAutoModeWindow(known, am.window) + renderAutoModeAction(input);
169
+ const classifierAuth = await spec.getApiKeyAndHeaders?.(classifierModel);
170
+ const response = await classifierRuntime.completeSimple(classifierModel, { systemPrompt: classifierSystemPrompt, messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] }, {
171
+ signal,
172
+ ...(classifierAuth?.apiKey !== undefined ? { apiKey: classifierAuth.apiKey } : {}),
173
+ ...(classifierAuth?.headers !== undefined ? { headers: classifierAuth.headers } : {}),
174
+ });
175
+ return response.content
176
+ .filter((c) => c.type === "text")
177
+ .map((c) => c.text)
178
+ .join("");
179
+ },
180
+ });
181
+ if (am.persistArming === true)
182
+ autoModeArming = mintPersistedArming(am, classifierLaneRule, classifierSystemPrompt, deps.onError, sessionId);
183
+ }
184
+ const deploymentWorkflowReady = runnerSelf !== undefined && isSelfOrchestrationActive(spec, deps);
185
+ const selfOrchestrationActive = deploymentWorkflowReady && runtimeCaps?.allowWorkflows !== false;
186
+ if (deploymentWorkflowReady && runtimeCaps?.allowWorkflows === false) {
187
+ deps.onError?.(new Error(`self-orchestration DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowWorkflows=false ` +
188
+ `(per-principal entitlement governance, not a misconfiguration — the run_workflow tool is not mounted)`), { phase: "config", sessionId });
189
+ }
190
+ let workflowToolsActive = false;
191
+ let workflowSizeGuideline;
192
+ if (selfOrchestrationActive && runnerSelf && deps.workflowScriptRunner && deps.workflowGovernanceBaseline) {
193
+ workflowToolsActive = true;
194
+ const currentSizeGuideline = () => resolveWorkflowSizeGuideline(deps.workflowLimits?.sizeGuideline).size;
195
+ workflowSizeGuideline = { legGuideline: currentSizeGuideline(), current: currentSizeGuideline };
196
+ toolEffects.set(RUN_WORKFLOW_TOOL_NAME, "write");
197
+ tools.push(await createRunWorkflowTool({
198
+ runner: runnerSelf,
199
+ scriptRunner: deps.workflowScriptRunner,
200
+ governanceBaseline: deps.workflowGovernanceBaseline,
201
+ parentExcludeTools: toolFaceSnapshot.exclude,
202
+ parentDeferTools: toolFaceSnapshot.defer,
203
+ parentAlwaysLoadTools: toolFaceSnapshot.alwaysLoad,
204
+ ...(toolFaceSnapshot.restoreGated !== undefined ? { parentRestoreGatedTools: toolFaceSnapshot.restoreGated } : {}),
205
+ parentPromptProfile: promptProfile,
206
+ models: deps.models,
207
+ agents: deps.agents,
208
+ builtinAgents: deps.builtinAgents,
209
+ store: deps.workflowRunStore,
210
+ journalStore: deps.workflowJournalStore,
211
+ ...(deps.onBackgroundChildEvent ? { onBackgroundChildEvent: deps.onBackgroundChildEvent } : {}),
212
+ scriptStore: deps.workflowScriptStore,
213
+ builtinWorkflows: deps.builtinWorkflows,
214
+ onAgentSpawn: deps.onWorkflowAgentSpawn,
215
+ scope: taskScope,
216
+ notifier: deps.workflowCompletionNotifier,
217
+ originatingSessionId: sessionId,
218
+ rootSessionId: internals?.rootSessionId ?? sessionId, ...(internals?.placementRoot !== undefined ? { placementRoot: internals.placementRoot } : {}),
219
+ taskRegistry: defaultTaskRegistry,
220
+ taskNotification: internals?.onTaskNotification,
221
+ taskOwner: hostTaskId,
222
+ limits: deps.workflowLimits,
223
+ sourceTaskId: hostTaskId,
224
+ parentModel: () => harnessRef.current?.getModel(),
225
+ ...(spec.getApiKeyAndHeaders !== undefined ? { parentGetApiKeyAndHeaders: spec.getApiKeyAndHeaders } : {}),
226
+ ...(frozenOnAsk !== undefined ? { parentOnAsk: frozenOnAsk } : {}),
227
+ principal: spec.principal,
228
+ oneShot: spec.oneShot,
229
+ ...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
230
+ parentMemoryCaptureState: () => {
231
+ const memoryEngineSession = input.memoryEngineSession();
232
+ const ctl = memoryEngineSession?.engine.controlPlaneDir;
233
+ const co = memoryEngineSession?.captureOptOut;
234
+ return assembleParentCaptureState(co?.optedOut() ?? false, co?.indeterminate() ?? false, ctl, [...(internals?.memoryCaptureAncestors ?? []), { sessionId, ...(ctl !== undefined ? { controlDir: ctl } : {}) }]);
235
+ },
236
+ autoModeReview: () => (autoModeDecider !== undefined ? { decider: autoModeDecider } : undefined),
237
+ workflowDepth: internals?.workflowDepth,
238
+ parentCwd: taskRootFinal,
239
+ parentThinking: () => harnessRef.current?.getThinkingLevel() ?? thinking,
240
+ parentReadFace: () => carrierReadFace(),
241
+ parentReadDenyPatterns: () => {
242
+ const readDenyAdditionsNormalized = input.readDenyAdditionsNormalized();
243
+ return readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized : undefined;
244
+ },
245
+ ...(spec.handsReadOnly === true ? { parentHandsReadOnly: true } : {}), ...(spec.interactiveTools === false ? { parentInteractiveTools: false } : {}),
246
+ onNotice: deps.onNotice,
247
+ parentCheckpointStoreDisabled: spec.checkpointStore === null,
248
+ parentCenterArtifactDigest: () => input.centerAdoption()?.artifact.artifactDigest,
249
+ parentCenterSourceRevision: () => input.centerAdoption()?.sourceRevision,
250
+ ...(forwardEvent ? { forwardEvent } : {}),
251
+ inheritedGateForChildren,
252
+ }));
253
+ }
254
+ return { tools, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDecider, autoModeDenialTracking, autoModeArming, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline };
255
+ }
@@ -28,7 +28,7 @@ import { type ResolvedRole } from "../roles.js";
28
28
  import type { SessionStore } from "../session.js";
29
29
  import type { RunnerDeps, TaskLimits, TaskSpec } from "../types.js";
30
30
  import { type UsageWindow } from "../usage-window-store.js";
31
- import type { PrepareResume, RunInternals } from "./prepare-task.js";
31
+ import type { PrepareResume, RunInternals, ToolFaceSnapshot } from "./contracts.js";
32
32
  export declare function limitConfigError(code: string, message: string): Error & {
33
33
  code?: string;
34
34
  };
@@ -138,15 +138,7 @@ export interface PrepareConfigDoorsResult {
138
138
  /** owned — the frozen task-start snapshot of the caller's tool-face control arrays; the ONLY thing
139
139
  * later face reads consult (own-task filter, defer classify, delegation ctx). Frozen-immutable ⇒
140
140
  * shared by reference into tool execution ctxs. */
141
- toolFaceSnapshot: {
142
- exclude: readonly string[] | undefined;
143
- defer: readonly string[] | undefined;
144
- alwaysLoad: readonly string[] | undefined;
145
- /** design/277 — the model-gate restore selector ({@link TaskSpec.restoreGatedTools}), fourth
146
- * seat of the same frozen task-start snapshot: the gate decision and the delegation carrier
147
- * read THIS, never the live spec. */
148
- restoreGated: readonly string[] | true | undefined;
149
- };
141
+ toolFaceSnapshot: ToolFaceSnapshot;
150
142
  /** owned — the profile half of the RB-50 single decision point (model-independent by contract). */
151
143
  promptProfile: "simple" | "classic";
152
144
  /** owned — the administrator lock snapshot; the rest of prepare reads guarded slots through it. */
@@ -0,0 +1,119 @@
1
+ /**
2
+ * design/390 §1.2 M21 — prepareTask's CONTEXT-LANE phase, verbatim from the driver: the edit/guard budgets, the
3
+ * microCompact machine state with the trigger-window clamp's one loud outlet, the model's chars-per-token coordinate,
4
+ * and the `context` handler registered on the harness — heal → ledger replay → aggregate tool-result and media caps →
5
+ * frontier clear → the guard chain (arms A/B/C) → the git-frame guard → the orphan belt → the lossy-projection flag →
6
+ * the projection seat. The four module-level helpers only this lane called moved with it (the machine-state builder,
7
+ * the frontier-clear recorder, the observation-buffer flush, the guard chain with its two types). The interface is the
8
+ * dependency list the segment had implicitly (design/238 R-1).
9
+ *
10
+ * SYNCHRONOUS FUNCTION, SYNCHRONOUS CALL: the stretch has no await of its own (the handler it registers is async and
11
+ * runs per provider request), so the phase adds no yield between the gate stations before it and the turn wiring after
12
+ * it (design/390 §1.5). Read-stability of the host handles: {@link RunInternals} (`@contract prepare.deps-read-stable`).
13
+ *
14
+ * REGISTRATION SIDE EFFECT, OWNED: this phase registers the ONE `context` handler on the harness; the harness owns the
15
+ * listener for the run's life (it is never unregistered — the harness is per prepare). No other station registers on
16
+ * that hook.
17
+ */
18
+ import { type AgentHarness, type AgentMessage } from "../../internal/harness.js";
19
+ import type { Model } from "../../internal/llm.js";
20
+ import { type ContextEditMachine, type OccurrenceIndex } from "../context-edit.js";
21
+ import { type ToolResultStore } from "../tool-result-store.js";
22
+ import { type RunnerDeps } from "../types.js";
23
+ import type { Prepared, PreparedMicroCompact } from "./contracts.js";
24
+ import { type GitStatusLaneRef } from "./git-status-frame.js";
25
+ export interface PrepareContextLaneInput {
26
+ /** borrowed-readonly — the task model: the budgets, the trigger-window geometry and `charsPerToken` are read off it. */
27
+ model: Model;
28
+ /** borrowed-readonly — the deployment seats, whole: `onNotice` (the clamp outlet, the offload-loss announcement), `tracer`
29
+ * (the cap / clear / trim frames), `mediaByteCapBytes` and `onMediaStripped` (the media cap), `onError` (the belt line, the
30
+ * git-frame degrade) — the guard chain and the machine-state builder read through the whole record. */
31
+ deps: RunnerDeps;
32
+ /** borrowed-readonly — the acquired session id (the offload persist key; every disclosure's attribution). */
33
+ sessionId: string;
34
+ /** borrowed-readonly — the run's invocation id (the clamp notice's per-run claim). */
35
+ runId: string;
36
+ /** borrowed-readonly — the per-task identity (the trace frames' taskId). */
37
+ hostTaskId: string;
38
+ /** borrowed-readonly — the run's offload store, or undefined (the caps' and the machine's persist seat). */
39
+ offloadStore: ToolResultStore | undefined;
40
+ /** borrowed-readonly — the doors' RESOLVED microCompact knob (immutable values, never the deps bag). */
41
+ microCompactKnob: {
42
+ machine: "off" | ContextEditMachine;
43
+ clearOnRejection: boolean;
44
+ };
45
+ /** borrowed-mutable — the built harness. Writer here: `on("context", …)` — the ONE registration of the request-build
46
+ * handler (the harness owns the listener; nothing unregisters it). */
47
+ harness: AgentHarness;
48
+ /** borrowed-mutable — the turn's halt fact (`Prepared.batchHaltRef`). Writer here: the handler CLEARS it at every new
49
+ * provider request (a new request means the halted boundary was legitimately passed). The judgment site sets it. */
50
+ batchHaltRef: Prepared["batchHaltRef"];
51
+ /** borrowed-mutable — the git-status lane ref. Writers here: the git-frame guard's degrade latch (`overBudgetShrunk`) inside
52
+ * the handler; the prompt-inputs phase seeds it. */
53
+ gitStatusRef: GitStatusLaneRef;
54
+ /** borrowed-mutable — the per-request lossy-projection flag. Writer here: the handler re-derives it at every request
55
+ * build; the provider-seam recording shim reads it immediately after. */
56
+ requestLossyRef: {
57
+ current: boolean;
58
+ };
59
+ /** borrowed-mutable — the trim-pressure flag (`Prepared.trimPressureRef`). Writer here: the guard chain's trim arm sets
60
+ * `droppedMessages`; the run loop's boundary reads and clears it. */
61
+ trimPressureRef: {
62
+ droppedMessages: boolean;
63
+ };
64
+ }
65
+ export interface PrepareContextLaneResult {
66
+ /** owned — the per-run microCompact machine state (`Prepared.microCompact`): machine, MC-R flag, ledger, the projection
67
+ * and in-turn-compaction seats the handler and the runtask arms fill. */
68
+ microCompact: PreparedMicroCompact;
69
+ /** owned — the model's structural coefficient (`charsPerToken ?? DEFAULT`), the ONE coordinate the request-layer
70
+ * defenses here and the prompt-overhead term downstream share with the compaction trigger estimate. */
71
+ charsPerToken: number;
72
+ }
73
+ /** The M21 phase body — prepareTask's context-lane stretch, verbatim (see the module header). */
74
+ export declare function prepareContextLane(input: PrepareContextLaneInput): PrepareContextLaneResult;
75
+ /** See {@link runGuardChain}. */
76
+ export interface GuardChainArgs {
77
+ /** The post-frontier view the chain starts from. */
78
+ edited: AgentMessage[];
79
+ /** The pre-cap counterpart view (arm A's clearSource — RB-212 durable composition seat). */
80
+ replayed: AgentMessage[];
81
+ index: OccurrenceIndex;
82
+ microCompact: PreparedMicroCompact;
83
+ guardAt: number;
84
+ charsPerToken: number;
85
+ offloadStore: import("../tool-result-store.js").ToolResultStore | undefined;
86
+ sessionId: string;
87
+ taskId: string;
88
+ deps: RunnerDeps;
89
+ trimPressureRef: {
90
+ droppedMessages: boolean;
91
+ };
92
+ recheck: boolean | undefined;
93
+ signal: AbortSignal | undefined;
94
+ /** The r7 per-request observation buffer — the chain DROPS it on its early returns (a discarded
95
+ * provisional projection must not narrate itself). */
96
+ pendingProjectionObservations: Array<() => void>;
97
+ }
98
+ export type GuardChainOutcome = {
99
+ earlyReturn: {
100
+ messages: AgentMessage[];
101
+ adoptSessionRebuild?: boolean;
102
+ };
103
+ } | {
104
+ working: AgentMessage[];
105
+ trimmed: AgentMessage[];
106
+ trimDroppedMessages: boolean;
107
+ };
108
+ /**
109
+ * design/374 slice 3 — the GUARD CHAIN over one request build (D-7 case-ii transfer table),
110
+ * module-level per the design/238 body-span bank. design/123 D3: the chain reads the anchored
111
+ * coordinate re-estimated on the EDITED array (pre-anchor clears don't lower it — deliberately;
112
+ * trimToBudget doc). The opt-out machine = the pre-374 backstop order byte-identical
113
+ * (trim as the ordinary second line); otherwise arm A (blocking machine run, only when the
114
+ * frontier pass is off) → arm B (in-turn forced compaction behind the adopt seam) → arm C (trim,
115
+ * the disaster-only last resort and this chain's sole `context.trim` emitter). Returns either the
116
+ * post-chain view for the pipeline tail, or an EARLY hook result the context handler must return
117
+ * verbatim (arm-B adoption / the r8 dead-turn stand-down).
118
+ */
119
+ export declare function runGuardChain(args: GuardChainArgs): Promise<GuardChainOutcome>;