@sema-agent/core 5.56.0 → 5.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +13 -2
- package/dist/agents/send-message-tool.js +34 -12
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +15 -6
- package/dist/agents/team.js +1 -0
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/anthropic.js +15 -5
- package/dist/brain/circuit-breaker.js +2 -1
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/degrading.js +4 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/failover.js +16 -1
- package/dist/brain/open-responses.js +15 -5
- package/dist/brain/openai.js +16 -5
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/request-params.d.ts +30 -27
- package/dist/brain/request-params.js +1 -7
- package/dist/brain/route-adjudicator.d.ts +190 -0
- package/dist/brain/route-adjudicator.js +189 -0
- package/dist/brain/route-conformance.d.ts +55 -0
- package/dist/brain/route-conformance.js +136 -0
- package/dist/brain/routing.js +8 -3
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/mcp.js +4 -4
- package/dist/core/memory-engine/consolidation-driver.d.ts +207 -0
- package/dist/core/memory-engine/consolidation-driver.js +378 -0
- package/dist/core/memory-engine/consolidation.d.ts +46 -2
- package/dist/core/memory-engine/consolidation.js +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +62 -8
- package/dist/core/memory-engine/engine.js +40 -4
- package/dist/core/memory-engine/file-backend.d.ts +1 -1
- package/dist/core/memory-engine/index.d.ts +4 -2
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +230 -36
- package/dist/core/permission-rule-consent.js +258 -54
- package/dist/core/permission-rule-model.d.ts +295 -97
- package/dist/core/permission-rule-model.js +132 -41
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +54 -18
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +15 -12
- package/dist/core/runner/runtask.js +48 -0
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +10 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +14 -7
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +55 -28
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +155 -70
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/agent-harness.js +26 -1
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +15 -11
- package/dist/engine/llm/types.d.ts +79 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -2
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +10 -10
- package/dist/prompts/default.js +2 -0
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +6 -2
- package/dist/scenarios/scenario-registry.js +4 -2
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/index.js +8 -1
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/scheduler-tools.js +28 -6
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +19 -4
- package/dist/tools/web.js +8 -2
- package/dist/tools/worktree.d.ts +5 -5
- package/dist/tools/worktree.js +2 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +74 -3
|
@@ -77,7 +77,7 @@ export declare function classifyDeferred(opts: {
|
|
|
77
77
|
fullTools: ReadonlyArray<ToolFingerprintInput>;
|
|
78
78
|
deferMode?: "auto";
|
|
79
79
|
model: Model;
|
|
80
|
-
/**
|
|
80
|
+
/** TaskSpec.deferTools — defer ALREADY-MOUNTED tools by wire name (built-ins included;
|
|
81
81
|
* `ToolSpec.defer` only reaches caller specs). Caller pre-filters to mounted names. */
|
|
82
82
|
deferNames?: ReadonlyArray<string>;
|
|
83
83
|
/** RB-400-a — inline-pin names (`TaskSpec.alwaysLoadTools` + the MCP tools whose server declared
|
|
@@ -253,7 +253,7 @@ export declare function createToolSearchTool(opts: {
|
|
|
253
253
|
* the listing text here and it rides THIS search's own result content — tail of the log, cache
|
|
254
254
|
* prefix untouched, same channel the activation announcement already uses. */
|
|
255
255
|
listingRide?: (newlyActivated: readonly string[]) => string | undefined;
|
|
256
|
-
/**
|
|
256
|
+
/** The names callable DIRECTLY right now (mounted non-deferred + activated),
|
|
257
257
|
* computed at call time (setTools swaps mutate the surface). Lets the miss note tell the model
|
|
258
258
|
* "Workflow is already available — call it" instead of a generic not-found that reads as absence
|
|
259
259
|
* (observed: the model treated the miss as unavailability and only recovered by guessing). */
|
|
@@ -166,7 +166,7 @@ export interface AttachmentState {
|
|
|
166
166
|
skillsListingStarved?: boolean;
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
|
-
*
|
|
169
|
+
* A1-R — the date_change lane's OWN state, deliberately NOT an
|
|
170
170
|
* {@link AttachmentState} member: allocating that for a date-only run would activate the cadence
|
|
171
171
|
* content scan + projection reducers on every non-opted run (the reopen's exact finding). Two
|
|
172
172
|
* fields, zero reducers. `announcedDate` starts at the leg's frozen prefix date; the RUN LOOP
|
|
@@ -185,7 +185,7 @@ export interface DateChangeState {
|
|
|
185
185
|
* (`ProjectMemoryLoad.instructionSources` — what the model is already seeing) and the RUN LOOP
|
|
186
186
|
* commits it via {@link commitInstructionsChange} when it actually appends the frame (the producer
|
|
187
187
|
* below is pure). The frame rides ABOVE the 8KB bundle cap as a fixed ≤{@link INSTRUCTIONS_CHANGE_BYTE_CAP}
|
|
188
|
-
* item — no clipping face exists, so commit-at-append is sound (the
|
|
188
|
+
* item — no clipping face exists, so commit-at-append is sound (the A1-R argument verbatim).
|
|
189
189
|
* `null` value = "announced as removed" (a reappearing file re-announces by hash inequality).
|
|
190
190
|
*/
|
|
191
191
|
export interface InstructionsChangeState {
|
|
@@ -475,10 +475,10 @@ export declare function renderToolSearchUsageReminder(undiscovered: readonly str
|
|
|
475
475
|
* float accumulator; no rounding anywhere in QFm or the renderer), kept verbatim: sema's inputs come
|
|
476
476
|
* from integer micro-USD ÷ 1e6, so they render with ≤6 decimals by construction.
|
|
477
477
|
*/
|
|
478
|
-
/**
|
|
478
|
+
/** A1 — CC messages.ts:4162 verbatim shape (de-branded is a no-op here: the text is neutral). */
|
|
479
479
|
export declare function renderDateChange(newDate: string): string;
|
|
480
480
|
/**
|
|
481
|
-
*
|
|
481
|
+
* A1-R — the date_change producer (CC attachments.ts:1400-1443 parity): the system-prefix
|
|
482
482
|
* date is FROZEN for the leg (upstream: "cached for the duration of the conversation" — re-rendering
|
|
483
483
|
* the prefix at midnight costs ~920K effective tokens per overnight session, upstream's own comment);
|
|
484
484
|
* when the boundary-time LOCAL date walks away from the last announced one, the model is told at the
|
|
@@ -625,7 +625,7 @@ export declare const AMBIENT_CONTEXT_NOTE = "This is ambient context \u2014 do n
|
|
|
625
625
|
* AND the run loop's resume transcript probe (MED-3②: "was the listing ever delivered?"). */
|
|
626
626
|
export declare function agentListingInitialHeader(toolName: string): string;
|
|
627
627
|
/**
|
|
628
|
-
* [
|
|
628
|
+
* [session-dedup] Rebuild the EXACT announced name-set by replaying every listing
|
|
629
629
|
* frame in a transcript, in order: an initial frame RESETS the set to its names, a delta frame ADDS,
|
|
630
630
|
* a removal frame DELETES. Header-presence alone is NOT a safe seed (it proves "announced once", not
|
|
631
631
|
* WHAT was announced — seeding the current entries would swallow the A→A+B delta and removal-to-zero
|
|
@@ -684,12 +684,12 @@ export declare function agentListingDeltaHeader(toolName: string): string;
|
|
|
684
684
|
*/
|
|
685
685
|
export declare function renderAgentListingDelta(state: AttachmentState, entries: ReadonlyArray<AgentListingEntry>, toolName: string, models?: readonly string[]): string | undefined;
|
|
686
686
|
/** [c209-C] R2 C7 — the Q4 catalog line, single-sourced for the initial frame's tail AND the
|
|
687
|
-
* drift re-announce arm so the two can never diverge byte-wise. [c209-C]
|
|
687
|
+
* drift re-announce arm so the two can never diverge byte-wise. [c209-C] 收口 C7 补口: an
|
|
688
688
|
* EMPTY catalog renders an honest "(none)" — reachable only from the DRIFT arm (a known announced
|
|
689
689
|
* catalog shrank to nothing; the initial frame still omits the line when there is nothing to offer). */
|
|
690
690
|
/** Single-sourced carrier prefix of the model-catalog line (renderer + replay parser). */
|
|
691
691
|
export declare const MODELS_AVAILABLE_PREFIX = "Models available for the 'model' parameter: ";
|
|
692
|
-
/** [
|
|
692
|
+
/** [] Replay the ANNOUNCED model catalog from stamped transcript texts — the last
|
|
693
693
|
* carried "Models available…" line wins (the line is re-carried in full on every drift, [c209-C]
|
|
694
694
|
* C7). Undefined = the catalog was never carried (unknowable — the drift compare stays silent,
|
|
695
695
|
* same conservative arm as an old checkpoint). */
|
|
@@ -734,7 +734,7 @@ export declare function commitSkillsListing(state: AttachmentState, entries: Rea
|
|
|
734
734
|
* bundle byte cap ({@link ATTACHMENT_BYTE_CAP}) is a per-frame structural backstop on the delta lane
|
|
735
735
|
* and does not exist AT ALL on the stable system-prompt lane, so without this a single server could
|
|
736
736
|
* pin an arbitrarily large blob into the cached prompt prefix for the whole task (and, on the delta
|
|
737
|
-
* lane, wedge the frame permanently against the 8KB cap — the
|
|
737
|
+
* lane, wedge the frame permanently against the 8KB cap — the failure shape).
|
|
738
738
|
* Sized at the delta lane's own order of magnitude (the 8KB frame budget), leaving fence + header
|
|
739
739
|
* room under the bundle cap once the "…" truncation marker lands.
|
|
740
740
|
*/
|
|
@@ -802,18 +802,18 @@ export declare function renderMcpInstructionsDelta(added: ReadonlyArray<{
|
|
|
802
802
|
* loop's intact-survival consumption check (tools_delta discipline).
|
|
803
803
|
*/
|
|
804
804
|
export declare function renderMcpDroppedTools(entries: ReadonlyArray<McpDroppedTool>): string;
|
|
805
|
-
/**
|
|
805
|
+
/** per-boundary byte bound for one mcp_dropped_tools frame — half the bundle cap, so
|
|
806
806
|
* the batch can never monopolize the boundary against the listing family/changed_files. */
|
|
807
807
|
export declare const MCP_DROPPED_BATCH_MAX_BYTES = 4096;
|
|
808
808
|
/**
|
|
809
|
-
*
|
|
809
|
+
* (medium) — bounded-batch selection for the dropped-tools announce. An UNBOUNDED
|
|
810
810
|
* render larger than the 8KB bundle cap gets prefix-CLIPPED by capAttachments; the intact-survival
|
|
811
811
|
* drain predicate then never matches, the full array is retained, and every later boundary re-renders
|
|
812
812
|
* and re-clips the identical prefix forever (tail entries never disclosed, permanent cap churn).
|
|
813
813
|
* Selecting the longest prefix of COMPLETE entries whose render fits {@link MCP_DROPPED_BATCH_MAX_BYTES}
|
|
814
814
|
* (always ≥1) restores monotonic drainage: the run loop splices exactly the delivered batch, the
|
|
815
815
|
* tail rides later boundaries. Pure/deterministic so the drain predicate can re-derive the exact
|
|
816
|
-
* snapshot.
|
|
816
|
+
* snapshot. the ≥1 floor is SAFE only because entries are bounded at the mcp.ts
|
|
817
817
|
* producer (tool ≤160 cps, reason ≤240 cps, both single-lined) — one rendered entry is always a
|
|
818
818
|
* few hundred bytes, far under both this bound and the 8KB bundle cap, so the single-entry frame
|
|
819
819
|
* can never be cap-clipped into a permanent re-render wedge.
|
package/dist/core/scheduler.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* core 薄壳裁定:core 只出接口 + 工具壳 + `hasScheduler` 门控;**持久化存储 / cron 时钟 / idle 触发 / 起新 task 全在
|
|
11
11
|
* backend(daemon)**——core 是 request-driven 不常驻,绝不假装调度器。NodeExecutionEnv 不自带 daemon(不同于
|
|
12
|
-
* background-shell 自带 spawn),而是**委托一个注入的 backend
|
|
12
|
+
* background-shell 自带 spawn),而是**委托一个注入的 backend**(由一个 shell daemon 实现本接口)。
|
|
13
13
|
*/
|
|
14
14
|
import type { ExecutionEnv, Result } from "../internal/harness-types.js";
|
|
15
15
|
/** 一个已排未来意图的句柄。**backend-local、durable(daemon 持久化、重启存活)、对调用方不透明** —— 绝不暴露可枚举的 raw id。 */
|
|
@@ -114,11 +114,11 @@ export interface ScheduledTaskSummary {
|
|
|
114
114
|
* wakeup(cron/task 意图不受 stop 影响——CC 206 D9 语义)。老 backend 不回 = undefined(工具壳以
|
|
115
115
|
* label 兜底过滤)。 */
|
|
116
116
|
mode?: "task" | "session-wakeup";
|
|
117
|
-
/** [c209-D2]
|
|
117
|
+
/** [c209-D2]:生命周期层级回显({@link ScheduledIntent.lifetime})——缺了它,任务创建后就再无
|
|
118
118
|
* 公开面能辨认自己是会话级还是持久级(CronCreate 的即时 details 是唯一一瞥)。老 backend 不回 =
|
|
119
119
|
* undefined(层级未知,按既有 durable 直觉读)。 */
|
|
120
120
|
lifetime?: "durable" | "session";
|
|
121
|
-
/** [c209-D2]
|
|
121
|
+
/** [c209-D2]:one-shot cron 回显({@link ScheduledIntent.recurring});undefined = 老 backend
|
|
122
122
|
* 或非 cron 意图。 */
|
|
123
123
|
recurring?: boolean;
|
|
124
124
|
}
|
|
@@ -143,14 +143,19 @@ export interface SchedulerCapability {
|
|
|
143
143
|
* reap)。缺省 undefined/false = 不支持:工具壳收到 session 语义调用(CC 形 `durable` 缺省 false)时
|
|
144
144
|
* 诚实拒绝并引导 `durable: true`——**绝不静默落成永生任务**。声明 `true` 的 backend MUST 实现 session
|
|
145
145
|
* intent 的 reap 消费契约(见 {@link ScheduledIntent.lifetime} 注释)。
|
|
146
|
-
*
|
|
146
|
+
* 🔴(TOCTOU 契约条款):本能力位 MUST 在 backend **实例生命周期内不可变**(`readonly` 快照,
|
|
147
147
|
* 不得热翻)——工具壳的门控读与 `schedule()` 是两次操作,中途翻位会让 session intent 落到不会 reap 的
|
|
148
148
|
* backend 上。防线双置:声明面不可变 + `schedule()` 实现 MUST 自行拒绝它无法履行 reap 契约的
|
|
149
149
|
* `lifetime:"session"` intent(fail-closed 兜底,不依赖工具壳的先行探测)。
|
|
150
|
+
*
|
|
151
|
+
* 「诚实拒绝」条款的适用边界:它约束**携带 session 语义字段的调用**(CronCreate 的 `durable` 形)。
|
|
152
|
+
* 一个没有 durable 逃生口的工具(ScheduleWakeup 形)对不支持位的 backend 走的是另一臂——发送
|
|
153
|
+
* 历史 durable intent 并在回执与工具描述上**披露**该 wakeup 不随会话终结(披露≠静默;拒绝会在
|
|
154
|
+
* 零收益下拿掉该宿主的整只工具)。该臂为既裁形(capability 位 opt-out 裁定),非本条款的违例。
|
|
150
155
|
*/
|
|
151
156
|
readonly supportsSessionLifetime?: boolean;
|
|
152
157
|
/**
|
|
153
|
-
* TB
|
|
158
|
+
* TB 裁决 — 宿主是否有会兑现 `mode:"session-wakeup"` intent 的常驻唤醒腿。
|
|
154
159
|
* **opt-out 方向(与 supportsSessionLifetime 的 fail-closed 缺省相反,有意)**:session-wakeup
|
|
155
160
|
* 是既有工作语义(daemon 宿主已在兑现),缺省关断=误伤现网——缺省/undefined=支持;headless 单发
|
|
156
161
|
* 宿主(如 `-p` print 路径:零 daemon,进程终答即退)**显式声明 false** ⇒ 工具壳对 ScheduleWakeup
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* This lives in `src/core/` — NOT `src/vendor/` — on purpose. It is OUR security invariant (D1 is a first-party
|
|
10
10
|
* edit, not openclaw upstream), shared by the (currently-vendored) {@link NodeExecutionEnv} AND a downstream
|
|
11
|
-
* adapter (service host adapter
|
|
11
|
+
* adapter (service host adapter). Keeping the single source of the secret PATTERN here means:
|
|
12
12
|
* 1. A consumer imports it instead of mirroring a regex that would silently DRIFT when the pattern is extended.
|
|
13
13
|
* 2. The public export points at a STABLE first-party path that SURVIVES the planned de-vendoring refactor —
|
|
14
14
|
* when NodeExecutionEnv is naturalized out of `src/vendor/`, this module does not move and nothing rebinds.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ExecutionEnv } from "../internal/harness-types.js";
|
|
2
2
|
import type { ToolPolicy } from "./tool-policy.js";
|
|
3
3
|
/**
|
|
4
|
-
* RECOMMENDED default pattern set for {@link createSensitivePathPolicy} (
|
|
4
|
+
* RECOMMENDED default pattern set for {@link createSensitivePathPolicy} (additive export).
|
|
5
5
|
* NO upstream verbatim anchor exists (cc-anchors/2.1.209 carries no sensitive/dangerous file-pattern
|
|
6
6
|
* material), so this is an ENGINEERING-CONSENSUS set — each line states its tradeoff. The factory's
|
|
7
7
|
* default behavior is unchanged (no implicit default list; wiring this set is the caller's opt-in:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* task-time {@link import("./tool-policy.js").ToolPolicy} (see {@link import("./runner/session-rule-policy.js").createSessionRulePolicy}).
|
|
4
4
|
*
|
|
5
5
|
* Why core-owned (not a parallel service store): the rules must be ENFORCED by the same policy fold that runs
|
|
6
|
-
* every tool call, so storage and enforcement can't drift (the
|
|
6
|
+
* every tool call, so storage and enforcement can't drift (the capability-token invariant). core defines
|
|
7
7
|
* the seam + an InMemory default; a deployment supplies a DURABLE cross-replica backend (its CAS-rev semantics
|
|
8
8
|
* must match this InMemory one byte-for-byte — a cross-backend equivalence test is the contract).
|
|
9
9
|
*
|
|
@@ -68,7 +68,7 @@ export interface SessionPolicyStore {
|
|
|
68
68
|
getRules(sessionId: string, principal?: string): Promise<StoredSessionRules | null>;
|
|
69
69
|
putRules(sessionId: string, principal: string | undefined, rules: SessionPermissionRules, opts?: PutRulesOptions): Promise<StoredSessionRules>;
|
|
70
70
|
/**
|
|
71
|
-
* 2c session-sync
|
|
71
|
+
* 2c session-sync: every (principal, rules) record for `sessionId` across ALL principals — `getRules`
|
|
72
72
|
* is per-(sessionId, principal), but a cross-backend session EXPORT must bundle the WHOLE session's policy.
|
|
73
73
|
* The importer replays each via `putRules(sessionId, record.principal, record.rules)`. Optional — a backend
|
|
74
74
|
* that supports cross-backend policy export implements it (local backend uses the in-memory/file impl).
|
|
@@ -20,7 +20,7 @@ import type { ToolEffect } from "./types.js";
|
|
|
20
20
|
* decision to the model under its verification discipline.
|
|
21
21
|
* - Use the tool's {@link ToolEffect} to tune the message: `read` carries no risk at all; `idempotent`
|
|
22
22
|
* is replayable (re-issuing converges the state, but the interrupted attempt may have partially
|
|
23
|
-
* landed — RB-221
|
|
23
|
+
* landed — RB-221); `write` (and unknown tools, conservatively) must be verified/confirmed
|
|
24
24
|
* before repeating.
|
|
25
25
|
*
|
|
26
26
|
* This runs on `acquire` of a resumed session, before the next turn starts. New/empty sessions and
|
|
@@ -31,7 +31,7 @@ export interface OrphanToolCall {
|
|
|
31
31
|
toolCallId: string;
|
|
32
32
|
toolName: string;
|
|
33
33
|
/**
|
|
34
|
-
* RB-398-a part 2
|
|
34
|
+
* RB-398-a part 2: which half of the pair is missing.
|
|
35
35
|
* - absent (the historical shape) = a **call-orphan**: an assistant `toolCall` with no matching
|
|
36
36
|
* `toolResult` — the reconcile-actionable kind ({@link reconcileInterruptedSession} closes it
|
|
37
37
|
* with a synthetic interrupted result).
|
|
@@ -95,14 +95,14 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
95
95
|
private owners;
|
|
96
96
|
/** In-flight acquisitions keyed by id, so concurrent acquire(sameId) share one session. */
|
|
97
97
|
private pending;
|
|
98
|
-
/** Subagent transcript persistence
|
|
98
|
+
/** Subagent transcript persistence — placed ids whose durable deletion FAILED: the
|
|
99
99
|
* placed fact for the retry lives HERE, not on a retained cache entry, because the repo may have
|
|
100
100
|
* torn down the shared session authority before its removal failed (the File repo closes the
|
|
101
101
|
* append fd pre-rmSync) — a retained entry would serve a session whose log is closed while the
|
|
102
102
|
* file still exists (append → log_closed, transcript revival broken until restart). The entry is
|
|
103
103
|
* dropped instead, so a re-acquire replays a FRESH authority from disk; success clears the row. */
|
|
104
104
|
private pendingPlacedDeletes;
|
|
105
|
-
/** Subagent transcript persistence
|
|
105
|
+
/** Subagent transcript persistence — placed deletions IN FLIGHT: acquire awaits the
|
|
106
106
|
* settlement before resolving the id, because the repo's delete tears down the shared session
|
|
107
107
|
* authority mid-flight — an acquire racing the await window could capture (or rebuild and then
|
|
108
108
|
* lose) an authority the delete is about to close, and the caller would hold a session whose
|
|
@@ -126,7 +126,7 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
126
126
|
* (the trusted-internals form; the creating call and its dedup/retry re-acquires stay legal, and
|
|
127
127
|
* placement immutability means the argument can never REWRITE anything — the persisted tuple wins).
|
|
128
128
|
*
|
|
129
|
-
* …and the MIRROR direction (
|
|
129
|
+
* …and the MIRROR direction (the pre-claim SQUAT race): the child session id is
|
|
130
130
|
* published on the spawn frame BEFORE the child's prepare creates the session, so a concurrent
|
|
131
131
|
* claim-form acquire could win first creation and hand the trusted placement caller an ORDINARY
|
|
132
132
|
* session — host-listable, never really-deleted, the declared full tier falsified in silence. On
|
package/dist/core/session.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ export interface AcquiredSession {
|
|
|
58
58
|
* Named `*StoreSummary` (not the bare `SessionSummary` an earlier version used) because that name collided
|
|
59
59
|
* with an unrelated, differently-shaped `SessionSummary` downstream (the SDK's wire GET /v1/sessions row) —
|
|
60
60
|
* same name, two shapes, the exact "同名异形" pattern a cross-repo cleanup was independently eradicating
|
|
61
|
-
* elsewhere
|
|
61
|
+
* elsewhere. This type is this store interface's own projection, never itself
|
|
62
62
|
* serialized onto the wire — a service backend re-projects/renames its fields (`lastTaskId` → `lastRunId`)
|
|
63
63
|
* when building the actual wire response.
|
|
64
64
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** shutdown forensics — opt-in (`SEMA_DEBUG_SHUTDOWN=1`) stderr trace of every
|
|
2
2
|
* teardown kill/reap action. stderr lands in the host's engine log, so a "who killed my process"
|
|
3
3
|
* hunt no longer dead-ends at the drain marker with zero shutdown-phase evidence (test-line pain,
|
|
4
|
-
* three times
|
|
4
|
+
* three times — the reap lane was the blind spot of the first cut).
|
|
5
5
|
* Zero default noise. Single source: the exec env's kill paths AND the task registry's reap paths
|
|
6
6
|
* ride this one function, so the flag can never half-cover the kill surface again. */
|
|
7
7
|
export declare function shutdownDebug(msg: string, extra?: Record<string, unknown>): void;
|
|
@@ -9,7 +9,7 @@ export interface SideQueryToolDef {
|
|
|
9
9
|
parameters: Tool["parameters"];
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* The side-query INPUT message union
|
|
12
|
+
* The side-query INPUT message union — REQUEST shapes, not transcript entries. Each
|
|
13
13
|
* role keeps only what the brain wire actually consumes; the assistant arm drops the response
|
|
14
14
|
* metadata (`api`/`provider`/`model`/`usage`/`stopReason`) a transcript entry carries — requiring
|
|
15
15
|
* those would force callers to FABRICATE attribution, the exact shape-forging this verb exists to
|
|
@@ -57,11 +57,18 @@ export interface SideQuerySpec {
|
|
|
57
57
|
/**
|
|
58
58
|
* Per-model auth — MIRRORS {@link TaskSpec.getApiKeyAndHeaders} (same signature, resolved per
|
|
59
59
|
* call against the RESOLVED model, exactly like the task path's per-call hook). The brain
|
|
60
|
-
* contract is
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
60
|
+
* contract is the route pairing law (route-adjudicator.ts): a per-model credential (this hook,
|
|
61
|
+
* or an auth header on `Model.headers`) always rides; the deployment credential rides only where
|
|
62
|
+
* its pairing is verifiable-or-unpinned — a declared `config.baseUrl` with an off-root model is
|
|
63
|
+
* refused (`route.credential_mismatch` / `route.credential_missing`), never silently followed.
|
|
64
|
+
* Historically the fallback was unconditional (`options.apiKey ?? config.apiKey`, with a model's
|
|
65
|
+
* own `baseUrl` outranking the brain's), so a side query routed to a model carrying its own
|
|
66
|
+
* `baseUrl` + per-model key sent the GATEWAY key to the per-model (possibly external) URL — the
|
|
67
|
+
* credential leak the pairing law now stops. Absent seat ⇒ no options are minted (byte-identical
|
|
68
|
+
* to before): on an UNDECLARED root the construction-time credential still applies (the
|
|
69
|
+
* quick-start posture), while a declared-root brain + off-root model hard-fails the side query
|
|
70
|
+
* with the loud refusal (`stopReason: "error"`) instead of leaking — there is no primary model
|
|
71
|
+
* for a side query to fall back to.
|
|
65
72
|
*/
|
|
66
73
|
getApiKeyAndHeaders?: TaskSpec["getApiKeyAndHeaders"];
|
|
67
74
|
signal?: AbortSignal;
|
|
@@ -78,7 +85,7 @@ export interface SideQueryResult {
|
|
|
78
85
|
/** The RESOLVED pool model id the query was ROUTED to (the caller's ref resolved). See
|
|
79
86
|
* `servedModel` for the model that actually answered. */
|
|
80
87
|
model: string;
|
|
81
|
-
/** The model that ACTUALLY served the reply (
|
|
88
|
+
/** The model that ACTUALLY served the reply (a degrading-brain deployment may fall
|
|
82
89
|
* back mid-query — billing/quality attribution must follow the real server, not the routing
|
|
83
90
|
* intent). Equals `model` when no degradation occurred. */
|
|
84
91
|
servedModel: string;
|
|
@@ -136,7 +136,7 @@ export declare function snapshotFrozenPaths(resolvedPaths: string[]): Map<string
|
|
|
136
136
|
* Restore any frozen file whose on-disk bytes differ from the snapshot (belt for `echo > test/x`-style
|
|
137
137
|
* bash writes the Write/Edit deny policy cannot see — fable-MIN2). Returns the number of files restored.
|
|
138
138
|
*
|
|
139
|
-
* Symlink-safe (
|
|
139
|
+
* Symlink-safe (实现审 B2): a tampered entry that is no longer a regular file (the model swapped
|
|
140
140
|
* it for a symlink pointing outside the root) is REMOVED first — the snapshot bytes are then written to
|
|
141
141
|
* a fresh regular file, never THROUGH a link. When `rootDir` is given, the parent directory's physical
|
|
142
142
|
* path is containment-checked too (a symlinked PARENT dir would also carry the write outside); an entry
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* already consumes in production). vitest-free BY CONTRACT: the kits run under any harness — a
|
|
5
5
|
* vitest binding passes `(name, fn) => { it(name, fn); }`, a bare script passes nothing and gets
|
|
6
6
|
* the sequential default — so a third-party store implementor needs NO test framework to verify
|
|
7
|
-
* their backend (
|
|
7
|
+
* their backend (shell/client-core run self-written runners).
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Labels + schedules one contract case. May return a promise (collected and awaited by the kit's
|
|
11
11
|
* final `Promise.all`) or register the case with a harness and return void (vitest `it`).
|
|
12
12
|
*
|
|
13
|
-
* ⚠️ Binding note (
|
|
13
|
+
* ⚠️ Binding note (inherited from workflowRunStoreContract): cases are REGISTERED
|
|
14
14
|
* eagerly — an async runner that starts work immediately will interleave cases. Every case builds
|
|
15
15
|
* its own fresh store via `make()`, so interleaving is safe UNLESS your binding's stores share
|
|
16
16
|
* state (e.g. SQL twins on one table); such bindings must serialize inside `runAssertion`.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* design/159 S1 — the contract kit's version-lockstep constant (
|
|
2
|
+
* design/159 S1 — the contract kit's version-lockstep constant (a downstream consumer requirement).
|
|
3
3
|
*
|
|
4
4
|
* The store-contract kit ships INSIDE `@sema-agent/core` and evolves in lockstep with the engine —
|
|
5
5
|
* an assertion added because an engine release changed a store's semantics is only meaningful
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
17
|
* A third party running an old kit against a new engine (or the reverse) would otherwise get a
|
|
18
|
-
* silent false-green
|
|
18
|
+
* silent false-green — e.g. a pre-2.2.0 kit has no idempotent-reopen entry, so a
|
|
19
19
|
* wiping SessionRepo passes it. Compare this constant against the `@sema-agent/core` version you
|
|
20
20
|
* actually resolved (read the installed package.json — the lock file can pin something older than
|
|
21
21
|
* what your manifest says).
|
|
@@ -9,7 +9,7 @@ import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
|
9
9
|
* 后端,于是没进 harness 的那个后端反复独立漂移 ——
|
|
10
10
|
* - RB-86:`stores/cc/mailbox-store.ts` 注释自陈 "the contract both bundled backends already
|
|
11
11
|
* honor, missing only here"(空箱 claimLease 不返回 null,还装上幽灵租约);
|
|
12
|
-
* - MB1
|
|
12
|
+
* - MB1:CC 后端的 `ack` 根本不查 lease 表,注释自陈 "worse than the other two
|
|
13
13
|
* backends' pre-fix bug"。
|
|
14
14
|
* 两次漏的都是同一个后端。修法不是再补一次点,而是把契约本身变成全后端共跑的资产 —— design/159
|
|
15
15
|
* 再进一步:第三方后端也拿得到同一份资产。
|
|
@@ -167,7 +167,7 @@ export async function mailboxAckOwnershipContract(mk, runAssertion) {
|
|
|
167
167
|
export async function mailboxBundledOnlyContract(mk, runAssertion) {
|
|
168
168
|
const { run: runRaw, settle } = beginContract(runAssertion);
|
|
169
169
|
const run = (name, fn) => runRaw(name, () => withStores(mk, fn));
|
|
170
|
-
run("RB-251
|
|
170
|
+
run("RB-251:handle 含 NUL 被两个后端一致拒绝,且不得跨 (scope,handle) 串箱", async (make) => {
|
|
171
171
|
const s = make();
|
|
172
172
|
const NUL = String.fromCharCode(0);
|
|
173
173
|
await assert.rejects(s.append("s", `a${NUL}b`, msg("secret")));
|
|
@@ -55,7 +55,7 @@ export interface TaskNotificationPayload {
|
|
|
55
55
|
* to default copy. */
|
|
56
56
|
stoppedBy?: "user" | "parent" | "system" | (string & {});
|
|
57
57
|
summary: string;
|
|
58
|
-
/** RB-386①
|
|
58
|
+
/** RB-386① — the failure reason DIGEST on a `status:"failed"` terminal notification
|
|
59
59
|
* (background_agent lanes): the same bounded text the settle stored as the registry row's `error`
|
|
60
60
|
* (the completed frame carries the full `result`; the failed frame used to carry NOTHING machine-
|
|
61
61
|
* readable — consumers had to parse the summary prose, which pre-fix didn't even include the
|
|
@@ -78,7 +78,7 @@ export interface TaskNotificationPayload {
|
|
|
78
78
|
partial?: boolean;
|
|
79
79
|
output_file?: string;
|
|
80
80
|
usage?: unknown;
|
|
81
|
-
/**
|
|
81
|
+
/** CC `<diagnostics>` parity: ENGINE-MINTED teaching text for the "result is empty/unexpected —
|
|
82
82
|
* now what" moment (per-agent read route / journal coordinate / resume command). Producers must mint it
|
|
83
83
|
* from engine values only (ids, store locators) — never from model-influenceable text. */
|
|
84
84
|
diagnostics?: string;
|
|
@@ -98,7 +98,7 @@ export interface TaskNotificationPayload {
|
|
|
98
98
|
* preconditions, so the claim and the next SendMessage agree. Lets the parent decide
|
|
99
99
|
* continue-vs-restart without trial-and-error. Background-agent lane only. */
|
|
100
100
|
resumable?: boolean;
|
|
101
|
-
/**
|
|
101
|
+
/** A cross-channel correlation key for
|
|
102
102
|
* ONE completion event. The same task's completion fans out across several independent read faces
|
|
103
103
|
* today (this live notification frame, a durable inbox entry, and the `TaskOutput` poll projection)
|
|
104
104
|
* — a consumer previously had to reconstruct "are these the same completion?" from weaker signals
|
|
@@ -107,7 +107,7 @@ export interface TaskNotificationPayload {
|
|
|
107
107
|
* {@link "./task-registry.js".UnifiedTaskOutput.completionId} for the shared contract (open-shape
|
|
108
108
|
* `string`, absent until terminal settle, absent on a pre-P1-3 core build). Deliberately ABSENT on
|
|
109
109
|
* the `"external"` lane (`TaskStream.notify()`) — that lane has its own caller-supplied `seq`
|
|
110
|
-
* correlation key (
|
|
110
|
+
* correlation key (confirmed posture) and no registry-side settle point to
|
|
111
111
|
* mint this from; core-minting one there would create two competing correlation keys on the same
|
|
112
112
|
* frame. */
|
|
113
113
|
completionId?: string;
|
|
@@ -174,7 +174,7 @@ export interface SystemInjection<TPayload = unknown> {
|
|
|
174
174
|
priority: SystemInjectionPriority;
|
|
175
175
|
dedupKey: string;
|
|
176
176
|
payload: TPayload;
|
|
177
|
-
/** S2b
|
|
177
|
+
/** S2b' — resolved with the ACTUAL injection outcome by the runner's subscribe
|
|
178
178
|
* listener: "queued" once the boundary steer accepted, "parked" when the idle tail-race (or the
|
|
179
179
|
* engine-note backlog cap) rejected and the payload was pended per session. Absent =
|
|
180
180
|
* fire-and-forget producer (no receipt to honor). */
|
|
@@ -16,7 +16,7 @@ export declare function ensureDurableHeartbeatLane(core: DurableAgentCore): void
|
|
|
16
16
|
/** design/151 S1a — enqueue one durable-row write (see {@link DurableAgentLane} for the lane
|
|
17
17
|
* contract). `patch` is captured at CALL time (the settle-site values), applied in chain order.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
19
|
+
* hardening — failure taxonomy, decided by EVIDENCE not by exception class:
|
|
20
20
|
* - thrown store errors get a bounded in-lane retry (a transient outage must not permanently
|
|
21
21
|
* strand a terminal write — the settle is often the row's LAST write);
|
|
22
22
|
* - `already_exists` on a put and a lost CAS both trigger a read-back writerId check first: an
|
|
@@ -27,9 +27,9 @@ export declare function ensureDurableHeartbeatLane(core: DurableAgentCore): void
|
|
|
27
27
|
export declare function durableAgentWriteLane(handle: BackgroundAgentTaskHandle, patch: Partial<BackgroundAgentRecord>, clear?: readonly (keyof BackgroundAgentRecord)[]): void;
|
|
28
28
|
/** design/151 S1b — is this row's durable lane ARMED (store wired at registration, not contaminated)?
|
|
29
29
|
* Observability/test face. ⚠️ NOT the lifecycle-flip key: arming says a row was ATTEMPTED, not
|
|
30
|
-
* that it EXISTS — release anchors gate on {@link durableAgentRowProbe}
|
|
30
|
+
* that it EXISTS — release anchors gate on {@link durableAgentRowProbe}. */
|
|
31
31
|
export declare function durableAgentArmedLane(core: DurableAgentCore, id: string): boolean;
|
|
32
|
-
/** design/151 S1b
|
|
32
|
+
/** design/151 S1b — the AWAITABLE lifecycle-flip key. Returns undefined when no
|
|
33
33
|
* lane was armed; otherwise a probe CLOSURE over the HANDLE (outlives its eviction from the map —
|
|
34
34
|
* retain-ledger TTL arms fire hours after terminal GC) that flushes the queued writes and answers
|
|
35
35
|
* whether a durable row actually EXISTS right now (initial put confirmed, not contaminated). A store
|
|
@@ -53,23 +53,23 @@ export declare function durableAgentRowProbeLane(core: DurableAgentCore, id: str
|
|
|
53
53
|
export declare function beginDurableClaimLane(core: DurableAgentCore, id: string): boolean;
|
|
54
54
|
/** Close the {@link beginDurableClaim} window (idempotent). */
|
|
55
55
|
export declare function endDurableClaimLane(core: DurableAgentCore, id: string): void;
|
|
56
|
-
/** design/151 §3.1 MED-7
|
|
56
|
+
/** design/151 §3.1 MED-7 — the BLESSED retention path: the joint reap that drops a
|
|
57
57
|
* doomed row under its rev guard and THEN releases its transcript session (raw `store.reap`
|
|
58
58
|
* strands transcripts — its contract says so). Policy semantics mirror the store sweep (double
|
|
59
59
|
* bound + stale-running flip; running rows are never deleted).
|
|
60
60
|
*
|
|
61
|
-
*
|
|
61
|
+
* ORDER: conditional DELETE first, release only after the delete WINS. The
|
|
62
62
|
* reverse (release→delete) destroyed a live transcript whenever a concurrent writer revived the
|
|
63
63
|
* row between the release and the losing CAS (stale-flip heal / retained-session revive: row
|
|
64
64
|
* back to running, session already gone). Failure economics of this order: a crash (or release
|
|
65
65
|
* throw) after the winning delete LEAKS the session to the deployment's session TTL sweep —
|
|
66
66
|
* recoverable — instead of stranding a live transcript — not. The release must therefore treat
|
|
67
|
-
* a missing/already-released id as a no-op (idempotent
|
|
67
|
+
* a missing/already-released id as a no-op (idempotent — a release that throws on
|
|
68
68
|
* not_found merely forfeits this bookkeeping, the TTL sweep still owns the orphan). An
|
|
69
69
|
* IN-PROCESS handle running again gates the row out entirely (a revive flips memory before its
|
|
70
70
|
* durable write flushes). `sessions` is structural (unpin/release) so any SessionStore fits
|
|
71
71
|
* without an import cycle.
|
|
72
|
-
* ⚠️
|
|
72
|
+
* ⚠️ Review note: passing `sessions` DECLARES that its `release` truly ends the
|
|
73
73
|
* transcript's addressability (durable deletion or an equivalent lifecycle handoff). A face
|
|
74
74
|
* whose release only clears in-memory state must NOT be passed — omit `sessions` instead
|
|
75
75
|
* (fail-closed: rows are kept and counted in `skippedNoSessions`, and the deployment's own
|
|
@@ -115,7 +115,7 @@ export declare function reapDurableAgentsLane(core: DurableAgentCore, scope: str
|
|
|
115
115
|
skippedNoSessions: number;
|
|
116
116
|
orphanPlacedReleased: number;
|
|
117
117
|
}>;
|
|
118
|
-
/**
|
|
118
|
+
/** after a probe-false RELEASE the row must stop claiming a transcript:
|
|
119
119
|
* the heartbeat's F-1 arm keeps re-driving a flush-failed lane, so a later successful flush
|
|
120
120
|
* would otherwise persist a row whose sessionId points at the session the caller just released.
|
|
121
121
|
* Clearing the anchor makes the eventual row honest: state/result survive, transcript does not. */
|
|
@@ -163,7 +163,7 @@ export declare function parkBackgroundAgentLane(core: DurableAgentCore, id: stri
|
|
|
163
163
|
resolveStop?: () => Promise<boolean>;
|
|
164
164
|
}): "parked" | undefined;
|
|
165
165
|
/**
|
|
166
|
-
* design/153 §7.1 (件1
|
|
166
|
+
* design/153 §7.1 (件1 split-brain fence) — the registry-aware reconciliation entry an
|
|
167
167
|
* IN-PROCESS deployment calls on its retention cadence. Two halves, one call:
|
|
168
168
|
* 1. LIVE half: this instance's own parked handles are probed against their checkpoint and, on
|
|
169
169
|
* expired/missing/DECIDED-ELSEWHERE, settled failed THROUGH the handle (poll/stop/durable row
|
|
@@ -234,7 +234,7 @@ export declare function rollbackParkedClaimLane(core: DurableAgentCore, stores:
|
|
|
234
234
|
checkpointStore: Pick<import("./checkpoint-store.js").CheckpointStore, "get">;
|
|
235
235
|
}, ticket: ParkedClaimTicket): Promise<"rolled_back" | "failed" | "lost" | "retry">;
|
|
236
236
|
/**
|
|
237
|
-
* design/153 §7.2d (件3c
|
|
237
|
+
* design/153 §7.2d (件3c 3c H-1) — the CONSUME FLIP, SERIALIZED THROUGH THE DURABLE LANE:
|
|
238
238
|
* the guarded parked→running store CAS runs INSIDE the lane chain (ordered after every seeded
|
|
239
239
|
* write — the session-bind CAS included), so no in-flight lane write can race it, CAS-fail on the
|
|
240
240
|
* flip's rev bump, read the new epoch as foreign, and contaminate the lane (which would permanently
|
|
@@ -315,7 +315,7 @@ export declare function resolveBackgroundAgentByNameLane(core: DurableAgentCore,
|
|
|
315
315
|
status: "not_found";
|
|
316
316
|
suggestion?: string;
|
|
317
317
|
};
|
|
318
|
-
/** S2b
|
|
318
|
+
/** S2b': flip the park-redeemability bit AFTER retention is actually secured
|
|
319
319
|
* (tryRetainChild success) — registration happens before the retain attempt, and session-scope
|
|
320
320
|
* alone does NOT retain the child session, so declaring at register time acknowledged parks that
|
|
321
321
|
* a capacity/pin failure (or plain session-scope) could never drain. No-op on unknown ids. */
|
|
@@ -413,7 +413,7 @@ export declare function noteBackgroundAgentActivityLane(core: DurableAgentCore,
|
|
|
413
413
|
* aborted. Returns how many rows were collected.
|
|
414
414
|
*/
|
|
415
415
|
export declare function reapStaleSessionBackgroundAgentsLane(core: DurableAgentCore, staleMs: number, now?: number, onTerminal?: (note: () => void) => void): number;
|
|
416
|
-
/** S2b
|
|
416
|
+
/** S2b — retention is REVOCABLE: every retain-ledger eviction path (TTL / LRU / abandon /
|
|
417
417
|
* parent-teardown disposeAll) runs the entry's release closure, and the spawner wraps that closure
|
|
418
418
|
* to call this — so a park can never be acknowledged against a continuation that was already
|
|
419
419
|
* released (the write-once bit was a lie window during parent teardown). */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TaskNotificationPayload } from "./task-notification.js";
|
|
2
2
|
import { type RegistryCore, type RegisterMonitorInput, type MonitorTaskHandle, type UnifiedTaskResult } from "./task-registry-shared.js";
|
|
3
3
|
export declare function registerMonitorLane(core: RegistryCore, input: RegisterMonitorInput): string;
|
|
4
|
-
/** RB-239
|
|
4
|
+
/** RB-239: ONE absorption arithmetic for a monitor poll — env-side-loss accounting
|
|
5
5
|
* (RB-238), the spool roll (registry memory bound) and the completed-line split — shared by the
|
|
6
6
|
* watcher tick and the stop-time final drain. A hand-copied twin in stopMonitor is how half-fixes
|
|
7
7
|
* happen: any change to the roll/line rules must reach both consumers through this method. Returns
|