@sema-agent/core 7.2.0 → 7.3.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/agents/cross-session-envelope.d.ts +7 -0
  3. package/dist/agents/cross-session-envelope.js +4 -0
  4. package/dist/agents/list-agents-tool.d.ts +55 -0
  5. package/dist/agents/list-agents-tool.js +94 -0
  6. package/dist/agents/peer-admission.d.ts +17 -1
  7. package/dist/agents/peer-admission.js +19 -2
  8. package/dist/agents/peer-directory.d.ts +208 -0
  9. package/dist/agents/peer-directory.js +272 -0
  10. package/dist/agents/peer-session-drain.d.ts +159 -0
  11. package/dist/agents/peer-session-drain.js +245 -0
  12. package/dist/agents/send-message-tool.d.ts +31 -0
  13. package/dist/agents/send-message-tool.js +145 -4
  14. package/dist/agents/subagent-steps.d.ts +11 -0
  15. package/dist/agents/subagent-steps.js +27 -4
  16. package/dist/core/auto-mode-arming.d.ts +11 -0
  17. package/dist/core/auto-mode-arming.js +7 -1
  18. package/dist/core/auto-mode-prompt.d.ts +5 -0
  19. package/dist/core/auto-mode-prompt.js +2 -1
  20. package/dist/core/auto-mode-rebuild.d.ts +2 -1
  21. package/dist/core/auto-mode-rebuild.js +2 -0
  22. package/dist/core/checkpoint-store.d.ts +14 -0
  23. package/dist/core/checkpoint-store.js +4 -3
  24. package/dist/core/governance-codes.d.ts +1 -1
  25. package/dist/core/governance-codes.js +6 -0
  26. package/dist/core/mailbox-store.d.ts +89 -2
  27. package/dist/core/mailbox-store.js +77 -2
  28. package/dist/core/permission-rule-model.d.ts +9 -0
  29. package/dist/core/permission-rule-model.js +4 -1
  30. package/dist/core/runner/prepare-task.d.ts +20 -0
  31. package/dist/core/runner/prepare-task.js +137 -37
  32. package/dist/core/runner/runtask.js +3 -2
  33. package/dist/core/runner/tool-output-projection.js +1 -0
  34. package/dist/core/store-contracts/mailbox-store-contract.d.ts +23 -0
  35. package/dist/core/store-contracts/mailbox-store-contract.js +157 -1
  36. package/dist/core/task-notification.d.ts +38 -9
  37. package/dist/core/task-notification.js +8 -2
  38. package/dist/core/types.d.ts +132 -21
  39. package/dist/core/wiring-manifest.d.ts +21 -0
  40. package/dist/core/wiring-manifest.js +1 -0
  41. package/dist/index.d.ts +9 -3
  42. package/dist/index.js +9 -3
  43. package/dist/stores/cc/mailbox-store.d.ts +1 -1
  44. package/dist/stores/cc/mailbox-store.js +13 -0
  45. package/dist/stores/file/adoption/marker.d.ts +1 -1
  46. package/dist/stores/file/mailbox-store.d.ts +57 -0
  47. package/dist/stores/file/mailbox-store.js +369 -18
  48. package/package.json +1 -1
  49. package/test/export-surface.snapshot.json +109 -1
@@ -155,23 +155,45 @@ export interface TaskNotificationPayload {
155
155
  body: string;
156
156
  };
157
157
  /**
158
- * design/385 §1.4 d1 — the engine-minted PROVENANCE side record of an agent-message frame, a typed
159
- * key (never model text) so a host can attribute and correlate the injection on the wire:
160
- * `kind` names the lane, `from` is the sender label the frame's attribute spells, `taskId` the
161
- * sender's run/agent id, `seq` the producer's per-frame counter (= this payload's `seq`),
162
- * `agentType` the sender's resolved agent type when the producer knows it. Present exactly when
163
- * {@link agentMessage} is.
158
+ * design/385 §4.1 — the CROSS-SESSION carrier (a peer session's message drained from this session's
159
+ * own box). Its PRESENCE is the render discriminator: the model reads a top-level
160
+ * `<cross-session-message from="…" …>` envelope (design/385 §4.2 model-face codec from-session /
161
+ * from-name / from-mode / from-scope as the typed record carried them; the hop chain never appears)
162
+ * followed by the cross-session discipline block, never a `<task-notification>` shell. The
163
+ * attributes are a PROJECTION of the store record's typed `peerMeta` — the text is presentation,
164
+ * the typed side record ({@link _sema_provenance}) is the authority. Minted ONLY by the engine's
165
+ * session-box drain; an external `notify()` cannot wear it.
166
+ */
167
+ crossSessionMessage?: import("../agents/cross-session-envelope.js").CrossSessionEnvelopeFields & {
168
+ body: string;
169
+ };
170
+ /**
171
+ * design/385 §1.4 d1 / §4.1 — the engine-minted PROVENANCE side record of an engine-injected peer
172
+ * frame, a typed key (never model text) so a host can attribute and correlate the injection on the
173
+ * wire. Present exactly when {@link agentMessage} OR {@link crossSessionMessage} is — one record
174
+ * per carrier, `kind` naming which. Its fields are read per `kind` (see {@link SemaProvenance}):
175
+ * on the agent-message lane `from` is the sender label the frame's attribute spells, `taskId` the
176
+ * sender's run/agent id, `seq` the producer's per-frame counter (= this payload's `seq`) and
177
+ * `agentType` the sender's resolved agent type when the producer knows it; on the cross-session
178
+ * lane `from` is the sender's ADDRESS, `taskId` the recipient's own box handle, `seq` the box seq,
179
+ * and the typed peer record rides in `peerMeta`.
164
180
  */
165
181
  _sema_provenance?: SemaProvenance;
166
182
  }
167
- /** design/385 §1.4 d1 — see {@link TaskNotificationPayload._sema_provenance}. `kind` is a closed set
168
- * with one member today; a future lane adds a member, never a second key. */
183
+ /** design/385 §1.4 d1 / §4.1 — see {@link TaskNotificationPayload._sema_provenance}. `kind` is a
184
+ * closed set of the two engine lanes that mint the record; a future lane adds a member, never a
185
+ * second key. */
169
186
  export interface SemaProvenance {
170
- kind: "agent_message";
187
+ /** `agent_message` = the same-process uplink (§1.4 d1); `cross_session_message` = the session-box
188
+ * drain (§4.1) — `from` is then the sender's ADDRESS, `taskId` the recipient's own box handle,
189
+ * `seq` the box seq, and the typed peer record rides in `peerMeta`. */
190
+ kind: "agent_message" | "cross_session_message";
171
191
  from: string;
172
192
  taskId: string;
173
193
  seq: number;
174
194
  agentType?: string;
195
+ /** cross_session_message only — the store record's typed peer metadata, verbatim (authority). */
196
+ peerMeta?: import("./mailbox-store.js").MailboxPeerMeta;
175
197
  }
176
198
  /**
177
199
  * design/144 §2 — the caller-facing input of `TaskStream.notify()`: a STRUCTURED external event to inject
@@ -278,6 +300,13 @@ export declare function renderAgentMessageFrame(frame: {
278
300
  from: string;
279
301
  body: string;
280
302
  }): string;
303
+ /**
304
+ * design/385 §4.1 — render a drained peer-session message as the model-face envelope (the §4.2
305
+ * codec: canonical attribute order, neutralized body) followed by the cross-session discipline block
306
+ * OUTSIDE the envelope. Distinct from {@link renderAgentMessageFrame}: another lane, another trust
307
+ * level, another block — sharing either would blur the classifier's lane judgment.
308
+ */
309
+ export declare function renderCrossSessionMessageFrame(frame: NonNullable<TaskNotificationPayload["crossSessionMessage"]>): string;
281
310
  export declare function renderTaskNotificationXml(n: TaskNotificationPayload): string;
282
311
  /**
283
312
  * The BETWEEN-TURNS pending lane. A task notification born while NO turn is
@@ -1,6 +1,6 @@
1
1
  import { escapeEnvelopeTag, inlineUntrusted, sanitizeUntrustedText } from "./untrusted-text.js";
2
2
  import { PEER_MESSAGE_NOTICE } from "../agents/peer-admission.js";
3
- import { neutralizePeerBody } from "../agents/cross-session-envelope.js";
3
+ import { buildCrossSessionEnvelope, CROSS_SESSION_MESSAGE_NOTICE, neutralizePeerBody } from "../agents/cross-session-envelope.js";
4
4
  export const SYSTEM_INJECTION_PRIORITIES = ["now", "next", "later"];
5
5
  export function isSystemInjectionPriority(value) {
6
6
  return typeof value === "string" && SYSTEM_INJECTION_PRIORITIES.includes(value);
@@ -53,9 +53,15 @@ export function renderAgentMessageFrame(frame) {
53
53
  const body = escapeEnvelopeTag(AGENT_MESSAGE_TAG, neutralizePeerBody(frame.body));
54
54
  return `<${AGENT_MESSAGE_TAG} from="${attrEscape(frame.from)}">\n${body}\n</${AGENT_MESSAGE_TAG}>\n\n${PEER_MESSAGE_NOTICE}`;
55
55
  }
56
+ export function renderCrossSessionMessageFrame(frame) {
57
+ const { body, ...fields } = frame;
58
+ return `${buildCrossSessionEnvelope(fields, body)}\n\n${CROSS_SESSION_MESSAGE_NOTICE}`;
59
+ }
56
60
  export function renderTaskNotificationXml(n) {
57
61
  if (n.agentMessage !== undefined)
58
62
  return renderAgentMessageFrame(n.agentMessage);
63
+ if (n.crossSessionMessage !== undefined)
64
+ return renderCrossSessionMessageFrame(n.crossSessionMessage);
59
65
  const usage = n.usage === undefined
60
66
  ? undefined
61
67
  : (() => {
@@ -211,7 +217,7 @@ export function discloseDroppedPending(drained) {
211
217
  if (dropped === undefined || disclosed.has(lane))
212
218
  return [n];
213
219
  disclosed.add(lane);
214
- if (n.agentMessage !== undefined) {
220
+ if (n.agentMessage !== undefined || n.crossSessionMessage !== undefined) {
215
221
  const line = {
216
222
  task_id: n.task_id,
217
223
  task_type: n.task_type,
@@ -1032,7 +1032,8 @@ export interface ToolExecuteContext {
1032
1032
  } | undefined;
1033
1033
  /**
1034
1034
  * RB-201 FO-3 (form-one audit, CC 220 `Ipd`/`ein` parity) — the auto-mode classifier decider ARMED
1035
- * for THIS task (`RuntimeCaps.autoMode === true` AND `RunnerDeps.autoMode` both present; the same
1035
+ * for THIS task (auto-mode intent `RunnerDeps.autoMode` present `RuntimeCaps.autoMode !== false`
1036
+ * — see {@link TaskSpec.autoModeRequested}; the same
1036
1037
  * instance `runToolGate`'s per-call ask review already consults, carrying its own live breaker
1037
1038
  * state — not a fresh one built from raw config). Runner-filled, trusted, undefined when auto-mode
1038
1039
  * is not armed or the tool runs outside a Runner task.
@@ -2608,6 +2609,35 @@ export interface TaskSpec {
2608
2609
  * pending call itself runs once, having been adjudicated). Re-pass the same value the original task used.
2609
2610
  */
2610
2611
  shellGate?: "off" | "always" | "classify";
2612
+ /**
2613
+ * The caller's AUTO-MODE INTENT for this task — the "user turned auto on" half of the classifier
2614
+ * arming (CC 2.1.250 polarity: auto mode is something the USER enables at the permission-mode
2615
+ * seat, and something an ORGANIZATION may only DENY; it is never something an organization grants
2616
+ * on a user's behalf). The engine arms its per-run classifier only when ALL THREE hold:
2617
+ * - this seat is `true` (intent),
2618
+ * - {@link RunnerDeps.autoMode} is present (the deployment is classifier-capable — the trust gate;
2619
+ * classifier RULES still enter ONLY through that face, never through this seat), and
2620
+ * - {@link RuntimeCaps.autoMode} is not `false` (the per-principal DENY bit; ABSENT is NOT a denial).
2621
+ *
2622
+ * **Ownership** — same split as {@link shellGate}: the service layer TRANSLATES the effective
2623
+ * permission mode into this seat (at the same point it translates the mode into `shellGate`);
2624
+ * core only CONSUMES it. Absent ⇒ not an auto-mode task (byte-identical to the pre-seat shape:
2625
+ * asks flow the original chain). Only the literal `true` is a value here: any other present value
2626
+ * (`false`, `"true"`, `1`) is refused at the door (`config.auto_mode_requested_invalid`) rather than
2627
+ * read as either polarity — a marshalled string must never silently arm, or silently disarm, a
2628
+ * classifier.
2629
+ *
2630
+ * **Inheritance**: the intent is session-wide, like a permission mode — an engine-spawned child of
2631
+ * an auto-mode task inherits it through the trusted constraint chain
2632
+ * (`InheritedGate.autoModeRequested`), never through a model-authored argument; the child's own
2633
+ * deny bit and deployment face are still evaluated for the child. **On resume:** the intent the
2634
+ * suspend leg resolved (this seat, or the bit its chain carried) is recorded on the checkpoint's
2635
+ * data half (`CheckpointState.inheritedGate.autoModeRequested`) and read back as one more intent
2636
+ * source, so a redemption in another process arms as the suspend leg did without re-passing the
2637
+ * seat; re-passing it is still honoured (the sources fold by OR). Intent only — the resuming
2638
+ * deployment's face and the resuming principal's deny bit are judged afresh on every leg.
2639
+ */
2640
+ autoModeRequested?: true;
2611
2641
  /** Task-scoped MCP servers, materialized into tools then disposed. */
2612
2642
  mcp?: McpServerSpec[];
2613
2643
  /** Task-scoped A2A peers (remote agents), whose advertised skills mount as `a2a__<peer>__<skill>`
@@ -5248,9 +5278,16 @@ export interface WorkflowGovernanceBaseline {
5248
5278
  /**
5249
5279
  * design/99 §K — the per-principal runtime ENTITLEMENTS the engine enforces server-side, resolved by a
5250
5280
  * deployment via {@link RunnerDeps.runtimeCapsResolver} from center's `GET /api/config/effective?principal=`.
5251
- * Every field is TIGHTEN-ONLY (a cap only ever DENIES or FORCES; `undefined` = no per-principal restriction).
5252
- * Only the two caps the ENGINE can enforce live here; `allowUltracode`/`allowBypassPermissions` are
5253
- * shell-UX / service-settings-layer concerns (see {@link RunnerDeps.runtimeCapsResolver}).
5281
+ * Every field is TIGHTEN-ONLY (a cap only ever DENIES or FORCES) but the family carries THREE
5282
+ * polarities, and "absent" does not read the same on each:
5283
+ * · DENY-shaped, `false` denies / absent is no restriction: {@link allowWorkflows}, {@link allowFork},
5284
+ * {@link autoMode} (the per-principal deny bit of a user-enabled mode), {@link allowMemoryOptOut}
5285
+ * (the one member whose resolver-FAULT degrade is allow, on the privacy axis);
5286
+ * · GRANT-shaped, `=== true` opts in / absent is OFF: {@link allowObservers};
5287
+ * · FORCE-shaped, `true` mandates / absent is the caller's opt-in default: {@link forceDurableGate}
5288
+ * (binds only where a checkpoint store is wired; announced `config.durable_gate_unavailable` where none is).
5289
+ * These six are the caps the ENGINE enforces; `allowUltracode`/`allowBypassPermissions` are shell-UX /
5290
+ * service-settings-layer concerns (see {@link RunnerDeps.runtimeCapsResolver}).
5254
5291
  */
5255
5292
  export interface RuntimeCaps {
5256
5293
  /** `false` DENIES workflow self-orchestration for this principal server-side — even on a deployment that is
@@ -5279,18 +5316,29 @@ export interface RuntimeCaps {
5279
5316
  /** `true` FORCES this principal's run onto the durable-approval path: the engine synthesizes a
5280
5317
  * `durableApproval{scope: principal}` so a policy `ask` suspends to the wire (a per-tool CC-faithful gate)
5281
5318
  * even when the caller did not opt in — center's fleet-wide "interactive runs gate" mandate. A
5282
- * caller-supplied `TaskSpec.durableApproval` always wins (it may carry a tighter scope/ttl). */
5319
+ * caller-supplied `TaskSpec.durableApproval` always wins (it may carry a tighter scope/ttl).
5320
+ * The mandate binds only where a {@link RunnerDeps.checkpointStore} is wired — the park facility it
5321
+ * forces the run onto. On a store-less deployment it has no facility: the leg announces
5322
+ * `config.durable_gate_unavailable` once (before its first ask), every ask resolves on the live chain
5323
+ * (a live approver / question face in-stream, or the fail-closed deny with none), no durable record
5324
+ * is written, and a live question face is consulted rather than vetoed (a mandate that cannot park
5325
+ * must not demote a reachable person into the model answering for them). */
5283
5326
  forceDurableGate?: boolean;
5284
5327
  /**
5285
- * design/143 批2 (CC 2.1.207 auto mode): route a surviving permission `ask` to the
5286
- * small-model security CLASSIFIER before any human/durable resolution (allow run; block deny
5287
- * `source:"classifier"`; classifier failure FAIL-CLOSED back to the original ask chain).
5288
- * **POLARITY: `=== true` EXPLICIT opt-in, default OFF** (same as {@link allowObservers} — auto mode
5289
- * hands a model the ask-resolution power for this principal's session; that is never implied).
5290
- * Arming ALSO requires the deployment to be classifier-capable ({@link RunnerDeps.autoMode} the
5291
- * trust gate lives there: classifier RULES enter only through the deployment assembly face, never a
5292
- * repo-controlled plane; the CC 2.1.207 three-source invariant). `true` on an incapable
5293
- * deployment resolves to a no-op (asks flow the original chain; no warn the gate, not a mistake).
5328
+ * The per-principal auto-mode DENY bit (CC 2.1.250 polarity the mirror of the settings-plane
5329
+ * `permissions.disableAutoMode` ratchet: an organization may only take auto mode AWAY; it is the
5330
+ * USER who turns it on, at the task's intent seat {@link TaskSpec.autoModeRequested}).
5331
+ *
5332
+ * **POLARITY: `=== false` DENIES; ABSENT IS NOT A DENIAL.** This is the family's deny-shaped
5333
+ * member (like {@link allowWorkflows} / {@link allowFork}), NOT a grant-shaped one like
5334
+ * {@link allowObservers}: a deployment with no entitlement source at all resolves `undefined` here
5335
+ * and still arms on intent + capability. `true` is accepted and means the same as absent (no
5336
+ * per-principal restriction) it is not a grant, and it cannot arm a task whose intent seat is
5337
+ * unset. The arming itself: intent ∧ {@link RunnerDeps.autoMode} present ∧ this bit not `false`
5338
+ * (allow → run; block → deny `source:"classifier"`; classifier failure → FAIL-CLOSED back to the
5339
+ * original ask chain). The trust gate is unchanged: classifier RULES enter only through the
5340
+ * deployment assembly face, never a repo-controlled plane (the CC 2.1.207 three-source invariant).
5341
+ * A denial resolves to a no-op (asks flow the original chain; no warn — the gate, not a mistake).
5294
5342
  */
5295
5343
  autoMode?: boolean;
5296
5344
  /**
@@ -5770,6 +5818,23 @@ export interface EngineNotice {
5770
5818
  * `onNotice` sink per value (console arm once per process) instead of lying in wait; where the
5771
5819
  * value IS in force the prepare refuses with the same code as `TaskResult.errorCode` (one
5772
5820
  * fact, one code, two loudness dialects); `detail: { raw }`.
5821
+ * - `"config.durable_gate_unavailable"` — the per-principal `forceDurableGate` entitlement is in
5822
+ * force on a leg whose deployment wired NO checkpoint store. The entitlement is a mandate
5823
+ * ("every interactive ask of this principal gates durably"), and a mandate with no park
5824
+ * facility cannot be honored: no ask of the leg can suspend, so each one resolves on the LIVE
5825
+ * chain — a live approver / question face answers in-stream, and with none the ask is denied
5826
+ * fail-closed — and NO durable approval record is written. The ask routing itself is not
5827
+ * changed by the notice (a store-less leg never could park); the notice is the loud half of a
5828
+ * posture that used to degrade silently, disclosed before the first ask of the leg. Audience
5829
+ * `"user"` (the person whose asks will not be recorded is entitled to that; the operator hears
5830
+ * it through the sink as always). Once per prepared task leg — a resume or a delegated child
5831
+ * is its own leg and says so again; `detail: { sessionId, runId, principal?, cause, liveApprover,
5832
+ * liveQuestionFace }` — `cause` is `"no_deployment_store"` (the deployment wired none) or
5833
+ * `"task_store_null"` (`TaskSpec.checkpointStore: null`, the per-run off switch, on a leg
5834
+ * whose deployment may well have a store: the fix is the task's); `liveApprover` /
5835
+ * `liveQuestionFace`: whether a live seat will EFFECTIVELY answer the leg's permission asks /
5836
+ * questions in-stream (a delegated child under an inherited content mandate reads `false`
5837
+ * even with a face wired — the marker withholds the question), or the fail-closed deny will.
5773
5838
  *
5774
5839
  * - `"task.user_steer_undrained"` / `"task.user_followup_undrained"` (#259) — user steers /
5775
5840
  * follow-ups whose receipts said "queued" were still in their queue at agent_end: the run
@@ -6021,6 +6086,24 @@ export interface EngineNotice {
6021
6086
  * disposition table with the error dispositions. The loser MUST NOT retry into the winner's
6022
6087
  * account. A consumer diffing its own table against the catalog must not add a row for it.
6023
6088
  *
6089
+ * - `"config.peer_lane_unmounted"` (design/385 §1.2⑥) — `RunnerDeps.peerDirectory` is wired but
6090
+ * the cross-session lane could not mount on this leg: no `mailboxStore`, or one that does not
6091
+ * declare `crossProcessSafe: true` (several terminals would share one session box on luck). The
6092
+ * seat is inert for the run (no ListAgents, peer addresses refuse with the same reason). Once per
6093
+ * prepared leg; `detail: { reason, code, mailboxWired, sessionId, runId }`. Audience `"operator"`
6094
+ * (a wiring fact; the fix is the deployment's).
6095
+ * - `"peer.inbound_disposition"` (design/385 §1.2④ / §4.6) — a message parked in THIS session's
6096
+ * own box was settled at the drain WITHOUT reaching the model. `detail.disposition` is the arm:
6097
+ * `"refused"` (this session's `crossSessionInbound` setting, or a record whose typed fields
6098
+ * cannot be rendered canonically), `"admission_refused"` (the drain-stage admission re-check:
6099
+ * duplicate / hop loop / runaway — `cause` names it), `"notice_unrouted"` (a notice-kind record
6100
+ * — idle/delivery notice — met a build with no notice face: settled without delivery, never
6101
+ * ridden through the peer-message envelope), or `"held"` (mode parity held it; the
6102
+ * held-message review face is not mounted in this build, so the message STAYS PARKED and the
6103
+ * drain stops at it — disclosed once per seq per leg). `detail: { disposition, cause, seq, box,
6104
+ * fromSession?, sessionId, runId }`. Audience `"user"`: the session's user is the one who did
6105
+ * not receive it.
6106
+ *
6024
6107
  * - `"delegation.transcript_integrity"` (subagent transcript persistence) — a durable agent row
6025
6108
  * with a BOUND transcript sessionId met a session store that attests `not_found` for it: the
6026
6109
  * deployment's declared transcript durability is being contradicted by reality. Announced at
@@ -6661,11 +6744,15 @@ export interface RunnerDeps {
6661
6744
  * resolver, or an unset cap) = NO per-principal restriction (TIGHTEN-ONLY: a cap can only ever DENY or
6662
6745
  * FORCE; absence falls back to the deployment-level default). Symmetric with {@link sessionPolicyStore}.
6663
6746
  *
6664
- * core enforces only the caps it CAN enforce in the engine: `allowWorkflows` (the third stage of the
6665
- * workflows gate — task opt-in ∧ deployment capability ∧ this) and `forceDurableGate` (forces a run onto
6666
- * the durable-approval path so a policy `ask` suspends to the wire). `allowUltracode` is a shell/UX concern
6667
- * (reasoning-tier, not a core primitive); `allowBypassPermissions` is enforced at the service settings-
6668
- * resolution layer (the engine sees only a resolved policy, never a "this allow came from bypass" signal).
6747
+ * core enforces the six caps it CAN enforce in the engine (polarity per member on {@link RuntimeCaps}):
6748
+ * `allowWorkflows` (the third stage of the workflows gate — task opt-in ∧ deployment capability ∧ this),
6749
+ * `allowFork` (the Agent-fork route), `allowObservers` (explicit opt-in for observer auto-spawn),
6750
+ * `autoMode` (the per-principal deny bit of the user-enabled auto mode), `allowMemoryOptOut` (may this
6751
+ * principal declare a capture opt-out), and `forceDurableGate` (forces a run onto the durable-approval
6752
+ * path so a policy `ask` suspends to the wire — where a checkpoint store is wired; a store-less leg
6753
+ * announces `config.durable_gate_unavailable`). `allowUltracode` is a shell/UX concern (reasoning-tier,
6754
+ * not a core primitive); `allowBypassPermissions` is enforced at the service settings-resolution layer
6755
+ * (the engine sees only a resolved policy, never a "this allow came from bypass" signal).
6669
6756
  */
6670
6757
  runtimeCapsResolver?: (principal: string | undefined) => RuntimeCaps | undefined | Promise<RuntimeCaps | undefined>;
6671
6758
  /**
@@ -6734,8 +6821,10 @@ export interface RunnerDeps {
6734
6821
  retentionPolicy?: import("./retention.js").RetentionPolicy;
6735
6822
  /**
6736
6823
  * design/143 批2b — the auto-mode classifier's DEPLOYMENT assembly face. This is the
6737
- * capability half of the arming AND-gate: a run arms auto mode only when the per-principal
6738
- * entitlement grants it ({@link RuntimeCaps.autoMode}` === true`) AND this face is present.
6824
+ * CAPABILITY arm of the three-arm arming: a run arms auto mode only when the task carries the
6825
+ * auto-mode INTENT ({@link TaskSpec.autoModeRequested}, or the same bit inherited on the chain by an
6826
+ * engine-spawned child) AND this face is present AND the per-principal DENY bit is not set
6827
+ * ({@link RuntimeCaps.autoMode}` !== false` — absent is not a denial).
6739
6828
  *
6740
6829
  * 🔐 Trust gate (the CC 2.1.207 three-source invariant): classifier RULES enter EXCLUSIVELY
6741
6830
  * here — a deployment-constructed object, never a `TaskSpec` field, never a repo-file plane. The
@@ -6901,6 +6990,28 @@ export interface RunnerDeps {
6901
6990
  * absent means the default table, not "guard off". Threaded into the auto-mounted SendMessage as
6902
6991
  * `SendMessageToolOptions.admission`; read per call (a value change governs the next message). */
6903
6992
  peerAdmission?: Partial<import("../agents/peer-admission.js").PeerAdmissionConfig>;
6993
+ /**
6994
+ * design/385 §2.1 / §5.1 — the peer-session DIRECTORY: the discovery truth of the cross-session
6995
+ * lane (other sessions of this engine for the same user). A HOST implements the contract (cli: the
6996
+ * pid-keyed registration files; server: its session table) and writes the rows; the engine only
6997
+ * reads them. Seat semantics = the mailbox seat's: NO seat, NO lane — every face stays byte-identical
6998
+ * to a pre-385 build. With the seat wired the engine (a) mounts `ListAgents` (alias `ListPeers`),
6999
+ * (b) opens SendMessage's `session.<id>` address arm and its last `name [ref]` rung, (c) drains this
7000
+ * session's own `session.<sessionId>` box at every turn boundary (the mailbox contract's third
7001
+ * consumption chain), and (d) splices the cross-session rule into the auto-mode classifier slot.
7002
+ * HARD PRECONDITION (design/385 §1.2⑥): `mailboxStore` must be wired AND declare
7003
+ * `crossProcessSafe: true`; otherwise the lane is REFUSED at prepare with a named
7004
+ * `config.peer_lane_unmounted` notice (never mounted on luck), and the seat is inert for that run.
7005
+ */
7006
+ peerDirectory?: import("../agents/peer-directory.js").PeerDirectory;
7007
+ /**
7008
+ * design/385 §4.4 — this deployment's `crossSessionInbound` setting LAYERS for the drain-point
7009
+ * judgment (managed / user / repo, resolved by `resolveCrossSessionInboundSetting` — explicit value
7010
+ * wins, unset ⇒ mode parity, an unrecognized value forces `hold` loudly). Read at every drain, so a
7011
+ * host that re-reads its settings files hands the current layers through a getter. Absent = unset
7012
+ * everywhere (mode parity, the CC default). Inert without {@link peerDirectory}.
7013
+ */
7014
+ crossSessionInbound?: import("../agents/cross-session-judge.js").CrossSessionInboundSettingLayers | (() => import("../agents/cross-session-judge.js").CrossSessionInboundSettingLayers);
6904
7015
  /**
6905
7016
  * design/164 件五 — DEPLOYMENT-level usage governance: allowances that span TASKS, evaluated per
6906
7017
  * principal (or once for the whole deployment when a task declares none). A different axis from
@@ -175,6 +175,21 @@ export interface WiringManifest {
175
175
  memoryAdmission: boolean;
176
176
  retention: boolean;
177
177
  };
178
+ /**
179
+ * EFFECTIVE half only, present iff the model gate trimmed a default-mounted tool from THIS run's
180
+ * roster: the per-session READ face of the same fact `config.tool_model_gate_removed` announces on
181
+ * the operator sink (one notice per sink, not per session — a client that needs "which default tools
182
+ * did MY session lose" reads it here). `class` = the gate class the table keyed the trim on, `removed`
183
+ * = the wire names not mounted, `restore` = the three valves in one sentence. Minted from the SAME
184
+ * gate decision the notice reads (one source, projected twice); absent = no trim on this run. A gate
185
+ * table with several classes trimming at once reports the FIRST class here and every removed name
186
+ * across classes in `removed` (the notice keeps its per-class lines).
187
+ */
188
+ modelGate?: {
189
+ class: string;
190
+ removed: readonly string[];
191
+ restore: string;
192
+ };
178
193
  /** EFFECTIVE half only — a short, non-sensitive fingerprint (sha256 prefix over the canonical
179
194
  * JSON of this manifest's own resolved facts; every field here is an enum/boolean/count, no
180
195
  * secrets) so an operator can correlate legs that ran under the same resolved assembly. */
@@ -231,6 +246,12 @@ export interface WiringFacts {
231
246
  complianceWired: boolean;
232
247
  memoryAdmissionWired: boolean;
233
248
  retentionPolicyWired: boolean;
249
+ /** Effective half only — see {@link WiringManifest.modelGate}; the static half has no roster to trim. */
250
+ modelGate?: {
251
+ class: string;
252
+ removed: readonly string[];
253
+ restore: string;
254
+ };
234
255
  }
235
256
  /** Named view of the deps seats the static half reads (a `Pick` of the real {@link RunnerDeps} —
236
257
  * single-source shapes, no parallel hand-copied interface). */
@@ -117,6 +117,7 @@ export function deriveWiringManifest(facts) {
117
117
  memoryAdmission: facts.memoryAdmissionWired,
118
118
  retention: facts.retentionPolicyWired,
119
119
  },
120
+ ...(facts.half === "effective" && facts.modelGate !== undefined ? { modelGate: { class: facts.modelGate.class, removed: [...facts.modelGate.removed], restore: facts.modelGate.restore } } : {}),
120
121
  };
121
122
  if (facts.half === "effective") {
122
123
  const { leg: _leg, ...assembly } = manifest;
package/dist/index.d.ts CHANGED
@@ -125,7 +125,7 @@ export { type StoreDurability } from "./core/checkpoint-store.js";
125
125
  export { type StoreFidelity } from "./core/checkpoint-store.js";
126
126
  export { projectHumanInput, buildHumanInputEvent, type HumanInputSource, type HumanInputFrame, type HumanInputEvent, type HumanInputDelivery, } from "./core/human-input-projection.js";
127
127
  export { TaskRegistry, defaultTaskRegistry, createTaskOutputTool, createTaskStopTool, type SemaTaskType, type SemaTaskStatus, type SemaTaskHandle, type ParkedClaimTicket, type TaskAccess, type UnifiedTaskOutput, type TaskRetrievalStatus, type StopSource, type RegisterMonitorInput, type MonitorTimers, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE, canAccessWorkflowRun, DURABLE_AGENT_HANDLE_RE, } from "./core/task-registry.js";
128
- export { InMemoryMailboxStore, type MailboxStore, type MailboxMessage, type MailboxLease, MailboxStoreError, MAILBOX_TOMBSTONED_RECIPIENT_CODE, } from "./core/mailbox-store.js";
128
+ export { InMemoryMailboxStore, type MailboxStore, type MailboxMessage, type MailboxLease, MailboxStoreError, type MailboxStoreErrorCode, MAILBOX_TOMBSTONED_RECIPIENT_CODE, type MailboxAppendMessage, type MailboxPeerMeta, type MailboxPeerFromMode, type MailboxPeerRecordKind, MAILBOX_PEER_FROM_MODES, MAILBOX_PEER_RECORD_KINDS, MAILBOX_INVALID_PEER_META_CODE, MAILBOX_CROSS_PROCESS_UNSAFE_CODE, readMailboxPeerMeta, mailboxCrossProcessMountVerdict, type MailboxCrossProcessVerdict, } from "./core/mailbox-store.js";
129
129
  export { FileMailboxStore, type FileMailboxStoreOptions } from "./stores/file/mailbox-store.js";
130
130
  export { createFileTaskListStore } from "./stores/file/task-list-store.js";
131
131
  export { createCcFileTaskListStore } from "./stores/cc/task-list-store.js";
@@ -166,7 +166,7 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
166
166
  * and nothing more. Removal is exported without ceremony, because narrowing on a user's behalf is
167
167
  * allowed and widening is not.
168
168
  */
169
- export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
169
+ export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
170
170
  export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryPermissionRuleStore, EMPTY_RULE_STORE, type PermissionRuleStore, type PermissionRuleStoreProvider, type StoredAllowRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritablePermissionRuleStore, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
171
171
  export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, type PermissionRuleSyncTransport, type PermissionRuleSyncResult, type RuleSyncRequestBody, type RuleSyncResponseBody, } from "./core/permission-rule-sync.js";
172
172
  export { InMemorySessionRuleOverlay, type SessionRuleOverlay, type SessionRuleOverlayAdd, type SessionRuleOverlayApplyResult, } from "./core/permission-rule-session.js";
@@ -232,7 +232,7 @@ export { sessionRepoContract } from "./core/store-contracts/session-repo-contrac
232
232
  export { toolResultStoreContract } from "./core/store-contracts/tool-result-store-contract.js";
233
233
  export { fileHistoryStoreContract } from "./core/store-contracts/file-history-store-contract.js";
234
234
  export { permissionRuleSyncContract, type PermissionRuleSyncContractHooks } from "./core/store-contracts/permission-rule-sync-contract.js";
235
- export { MAILBOX_CONTRACT_SCOPE, mailboxStoreContract, mailboxAckOwnershipContract, mailboxBundledOnlyContract, mailboxTombstonedRecipientContract, type MailboxTombstonedRecipientContractHooks, } from "./core/store-contracts/mailbox-store-contract.js";
235
+ export { MAILBOX_CONTRACT_SCOPE, mailboxStoreContract, mailboxAckOwnershipContract, mailboxBundledOnlyContract, mailboxTombstonedRecipientContract, type MailboxTombstonedRecipientContractHooks, mailboxCrossProcessContract, type MailboxCrossProcessContractHooks, } from "./core/store-contracts/mailbox-store-contract.js";
236
236
  export { BACKGROUND_AGENT_CONTRACT_SCOPE, backgroundAgentStoreContract, backgroundAgentStoreScopesContract, } from "./core/store-contracts/background-agent-store-contract.js";
237
237
  export { type BackgroundAgentStore, type BackgroundAgentRecord, type BackgroundAgentRowSummary, type BackgroundAgentUsage, canAccessAgentRecord, STALE_RUNNING_REAP_ATTRIBUTION, BackgroundAgentStoreError, InMemoryBackgroundAgentStore, reconcileParkedAgents, queryBackgroundAgents, type BackgroundAgentQuery, } from "./core/background-agent-store.js";
238
238
  export { serveDurableAgentRowLane, buildAgentPollDetails, type AgentPollDetailsInput, } from "./core/task-registry-agent.js";
@@ -255,6 +255,12 @@ export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerA
255
255
  export { CROSS_SESSION_MESSAGE_TAG, CROSS_SESSION_MESSAGE_NOTICE, PERMISSION_MODE_CLASSES, isPermissionModeClass, CrossSessionCodecError, PEER_HOP_TOKEN_HEX, PEER_HOP_CHAIN_CARRY_WINDOW, encodePeerAddress, isCanonicalPeerAddress, encodeScopeAttribute, decodeScopeAttribute, canonicalPeerDisplayName, buildCrossSessionEnvelope, parseCrossSessionEnvelope, clampHopChain, encodeCcPeerFrame, decodeCcPeerFrame, type PermissionModeClass, type CrossSessionEnvelopeFields, type CrossSessionEnvelopeParse, type CrossSessionEnvelopeRefusal, type CcPeerFrameFields, type CcPeerFrameParse, } from "./agents/cross-session-envelope.js";
256
256
  export { CROSS_SESSION_INBOUND_SETTINGS, isCrossSessionInboundSetting, resolveCrossSessionInboundSetting, CROSS_SESSION_HOLD_CAUSES, describeCrossSessionHoldCause, judgeCrossSessionInbound, foldPermissionModeClass, PEER_SEND_VERDICT_CODES, peerSendVerdictSeverity, type CrossSessionInboundSetting, type CrossSessionSettingSource, type CrossSessionInboundSettingLayers, type ResolvedCrossSessionInboundSetting, type CrossSessionHoldCause, type CrossSessionInboundVerdict, type CrossSessionInboundInput, type PeerSendVerdictCode, type PeerSendVerdict, } from "./agents/cross-session-judge.js";
257
257
  export { PEER_REF_MIN, PEER_REF_MAX, PEER_REF_RE, mintPeerRef, formatPeerNameRef, parsePeerNameRef, normalizePeerName, PEER_ADDRESS_PREFIXES, reservedPeerNameReason, type PeerRefEntry, } from "./agents/cross-session-ref.js";
258
+ export { PEER_SESSION_RECORD_SCHEMA_VERSION, PEER_SESSION_RECORD_MAX_BYTES, SESSION_BOX_PREFIX, peerSessionBoxHandle, isPeerSessionId, PEER_SESSION_ID_GRAMMAR, parsePeerSessionAddress, readPeerSessionRecord, defaultPeerLivenessProbe, isPeerSessionProcessAlive, mintPeerSessionCandidates, resolvePeerSessions, createInMemoryPeerDirectory, vetPeerRegistryDirectory, judgePeerRecordFile, type PeerSessionRecord, type PeerSessionLiveness, type PeerSessionTempo, type PeerSessionRecordRefusal, type PeerSessionRecordRead, type PeerLivenessProbe, type PeerDirectory, type PeerDirectoryAccess, type PeerSessionCandidate, type PeerSessionResolution, type InMemoryPeerDirectory, type PeerRegistryDirectoryRefusal, type PeerRegistryDirectoryVerdict, } from "./agents/peer-directory.js";
259
+ export { createListAgentsTool, LIST_AGENTS_TOOL_NAME, LIST_AGENTS_TOOL_ALIAS, LIST_AGENTS_MAX_RESULT_CHARS, type ListAgentsToolOptions, type ListAgentsRow } from "./agents/list-agents-tool.js";
260
+ export { CROSS_SESSION_CLASSIFIER_RULE } from "./agents/cross-session-envelope.js";
261
+ export { PEER_SESSION_ID_UNGRAMMATICAL_CODE, type PeerLaneMountVerdict } from "./agents/peer-session-drain.js";
262
+ export { renderCrossSessionMessageFrame } from "./core/task-notification.js";
263
+ export { type PeerAdmissionStage } from "./agents/peer-admission.js";
258
264
  export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, type AgentTranscriptToolOptions, } from "./agents/agent-transcript-tool.js";
259
265
  export { defineAgent } from "./agents/agent-definition.js";
260
266
  export { builtinAgentDefinitions, BUILTIN_READONLY_DENY_TOOLS, EXPLORE_WHEN_TO_USE, EXPLORE_WHEN_TO_USE_LEAN, PLAN_WHEN_TO_USE, EXPLORE_SYSTEM_PROMPT, PLAN_SYSTEM_PROMPT, } from "./agents/builtin-agents.js";
package/dist/index.js CHANGED
@@ -102,7 +102,7 @@ export {} from "./core/checkpoint-store.js";
102
102
  export {} from "./core/checkpoint-store.js";
103
103
  export { projectHumanInput, buildHumanInputEvent, } from "./core/human-input-projection.js";
104
104
  export { TaskRegistry, defaultTaskRegistry, createTaskOutputTool, createTaskStopTool, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE, canAccessWorkflowRun, DURABLE_AGENT_HANDLE_RE, } from "./core/task-registry.js";
105
- export { InMemoryMailboxStore, MailboxStoreError, MAILBOX_TOMBSTONED_RECIPIENT_CODE, } from "./core/mailbox-store.js";
105
+ export { InMemoryMailboxStore, MailboxStoreError, MAILBOX_TOMBSTONED_RECIPIENT_CODE, MAILBOX_PEER_FROM_MODES, MAILBOX_PEER_RECORD_KINDS, MAILBOX_INVALID_PEER_META_CODE, MAILBOX_CROSS_PROCESS_UNSAFE_CODE, readMailboxPeerMeta, mailboxCrossProcessMountVerdict, } from "./core/mailbox-store.js";
106
106
  export { FileMailboxStore } from "./stores/file/mailbox-store.js";
107
107
  export { createFileTaskListStore } from "./stores/file/task-list-store.js";
108
108
  export { createCcFileTaskListStore } from "./stores/cc/task-list-store.js";
@@ -126,7 +126,7 @@ export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/au
126
126
  export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
127
127
  export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
128
128
  export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
129
- export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
129
+ export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
130
130
  export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryPermissionRuleStore, EMPTY_RULE_STORE, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
131
131
  export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
132
132
  export { InMemorySessionRuleOverlay, } from "./core/permission-rule-session.js";
@@ -191,7 +191,7 @@ export { sessionRepoContract } from "./core/store-contracts/session-repo-contrac
191
191
  export { toolResultStoreContract } from "./core/store-contracts/tool-result-store-contract.js";
192
192
  export { fileHistoryStoreContract } from "./core/store-contracts/file-history-store-contract.js";
193
193
  export { permissionRuleSyncContract } from "./core/store-contracts/permission-rule-sync-contract.js";
194
- export { MAILBOX_CONTRACT_SCOPE, mailboxStoreContract, mailboxAckOwnershipContract, mailboxBundledOnlyContract, mailboxTombstonedRecipientContract, } from "./core/store-contracts/mailbox-store-contract.js";
194
+ export { MAILBOX_CONTRACT_SCOPE, mailboxStoreContract, mailboxAckOwnershipContract, mailboxBundledOnlyContract, mailboxTombstonedRecipientContract, mailboxCrossProcessContract, } from "./core/store-contracts/mailbox-store-contract.js";
195
195
  export { BACKGROUND_AGENT_CONTRACT_SCOPE, backgroundAgentStoreContract, backgroundAgentStoreScopesContract, } from "./core/store-contracts/background-agent-store-contract.js";
196
196
  export { canAccessAgentRecord, STALE_RUNNING_REAP_ATTRIBUTION, BackgroundAgentStoreError, InMemoryBackgroundAgentStore, reconcileParkedAgents, queryBackgroundAgents, } from "./core/background-agent-store.js";
197
197
  export { serveDurableAgentRowLane, buildAgentPollDetails, } from "./core/task-registry-agent.js";
@@ -212,6 +212,12 @@ export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerA
212
212
  export { CROSS_SESSION_MESSAGE_TAG, CROSS_SESSION_MESSAGE_NOTICE, PERMISSION_MODE_CLASSES, isPermissionModeClass, CrossSessionCodecError, PEER_HOP_TOKEN_HEX, PEER_HOP_CHAIN_CARRY_WINDOW, encodePeerAddress, isCanonicalPeerAddress, encodeScopeAttribute, decodeScopeAttribute, canonicalPeerDisplayName, buildCrossSessionEnvelope, parseCrossSessionEnvelope, clampHopChain, encodeCcPeerFrame, decodeCcPeerFrame, } from "./agents/cross-session-envelope.js";
213
213
  export { CROSS_SESSION_INBOUND_SETTINGS, isCrossSessionInboundSetting, resolveCrossSessionInboundSetting, CROSS_SESSION_HOLD_CAUSES, describeCrossSessionHoldCause, judgeCrossSessionInbound, foldPermissionModeClass, PEER_SEND_VERDICT_CODES, peerSendVerdictSeverity, } from "./agents/cross-session-judge.js";
214
214
  export { PEER_REF_MIN, PEER_REF_MAX, PEER_REF_RE, mintPeerRef, formatPeerNameRef, parsePeerNameRef, normalizePeerName, PEER_ADDRESS_PREFIXES, reservedPeerNameReason, } from "./agents/cross-session-ref.js";
215
+ export { PEER_SESSION_RECORD_SCHEMA_VERSION, PEER_SESSION_RECORD_MAX_BYTES, SESSION_BOX_PREFIX, peerSessionBoxHandle, isPeerSessionId, PEER_SESSION_ID_GRAMMAR, parsePeerSessionAddress, readPeerSessionRecord, defaultPeerLivenessProbe, isPeerSessionProcessAlive, mintPeerSessionCandidates, resolvePeerSessions, createInMemoryPeerDirectory, vetPeerRegistryDirectory, judgePeerRecordFile, } from "./agents/peer-directory.js";
216
+ export { createListAgentsTool, LIST_AGENTS_TOOL_NAME, LIST_AGENTS_TOOL_ALIAS, LIST_AGENTS_MAX_RESULT_CHARS } from "./agents/list-agents-tool.js";
217
+ export { CROSS_SESSION_CLASSIFIER_RULE } from "./agents/cross-session-envelope.js";
218
+ export { PEER_SESSION_ID_UNGRAMMATICAL_CODE } from "./agents/peer-session-drain.js";
219
+ export { renderCrossSessionMessageFrame } from "./core/task-notification.js";
220
+ export {} from "./agents/peer-admission.js";
215
221
  export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, } from "./agents/agent-transcript-tool.js";
216
222
  export { defineAgent } from "./agents/agent-definition.js";
217
223
  export { builtinAgentDefinitions, BUILTIN_READONLY_DENY_TOOLS, EXPLORE_WHEN_TO_USE, EXPLORE_WHEN_TO_USE_LEAN, PLAN_WHEN_TO_USE, EXPLORE_SYSTEM_PROMPT, PLAN_SYSTEM_PROMPT, } from "./agents/builtin-agents.js";
@@ -1,4 +1,4 @@
1
- import type { MailboxStore } from "../../core/mailbox-store.js";
1
+ import { type MailboxStore } from "../../core/mailbox-store.js";
2
2
  /** CC's path-component sanitize rule (README §一 Jeo/UJt): non-alphanumerics → "-", lowercased. */
3
3
  export declare function sanitizeCcAgentName(name: string): string;
4
4
  export interface CcFileMailboxStoreOptions {
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync, readFileSync, rmSync, readdirSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
  import { randomUUID } from "node:crypto";
4
+ import { readMailboxPeerMeta } from "../../core/mailbox-store.js";
4
5
  import { atomicWriteFile, canonicalStoreKey } from "../file/fs-atomic.js";
5
6
  import { withCcLock } from "./lockfile.js";
6
7
  const INBOX_FILE_EXT = ".json";
@@ -94,6 +95,15 @@ export function createCcFileMailboxStore(opts) {
94
95
  note(path, `${dropped} malformed inbox entries skipped (first: ${firstReason})`);
95
96
  return kept;
96
97
  };
98
+ const readBackPeerMeta = (raw) => {
99
+ try {
100
+ const meta = readMailboxPeerMeta(raw);
101
+ return meta === undefined ? {} : { peerMeta: meta };
102
+ }
103
+ catch {
104
+ return {};
105
+ }
106
+ };
97
107
  const saveBox = (path, box) => {
98
108
  atomicWriteFile(inboxDir, path, JSON.stringify(box, null, 2));
99
109
  };
@@ -136,6 +146,7 @@ export function createCcFileMailboxStore(opts) {
136
146
  return {
137
147
  append: (scope, handle, msg) => {
138
148
  requireDefaultScope(scope);
149
+ const peerMeta = readMailboxPeerMeta(msg.peerMeta);
139
150
  mkdirSync(inboxDir, { recursive: true });
140
151
  const path = inboxPath(handle);
141
152
  const notes = deferredNotes();
@@ -150,6 +161,7 @@ export function createCcFileMailboxStore(opts) {
150
161
  msg_id: randomUUID(),
151
162
  read: false,
152
163
  ...(msg.hopChain !== undefined ? { hopChain: [...msg.hopChain] } : {}),
164
+ ...(peerMeta !== undefined ? { peerMeta } : {}),
153
165
  });
154
166
  saveBox(path, box);
155
167
  return box.length;
@@ -178,6 +190,7 @@ export function createCcFileMailboxStore(opts) {
178
190
  ...(Array.isArray(e.hopChain) && e.hopChain.every((h) => typeof h === "string")
179
191
  ? { hopChain: e.hopChain.filter((h) => typeof h === "string") }
180
192
  : {}),
193
+ ...readBackPeerMeta(e.peerMeta),
181
194
  }));
182
195
  if (pending.length === 0)
183
196
  return Promise.resolve(null);
@@ -209,7 +209,7 @@ export declare function writeRootAdoptionFile(root: string, content: RootAdoptio
209
209
  * and it is the ONLY thing this function does — it never reaches an object that already exists. So a
210
210
  * store instance constructed BEFORE the marker landed keeps writing for as long as it is held, in
211
211
  * ANOTHER OS process (cross-process sharing of one data dir is the file family's documented
212
- * UNSUPPORTED shape task-list F-14, mailbox RB-249) and, symmetrically, in THIS one (an independent
212
+ * UNSUPPORTED shape for the task-list store — F-14; the mailbox store is the exception since its per-box lock upgrade, see `stores/file/mailbox-store.ts`) and, symmetrically, in THIS one (an independent
213
213
  * store face built before the adoption started; the arc's `LOCK` acquisition excludes a live
214
214
  * `FileStorageBackend`, which is the only shape that takes that lock). Adoption adds no new promise on
215
215
  * either side of that seam — see the freeze note on `adoptLocalDataRoot` for the full division.