@sema-agent/core 7.51.2 → 7.52.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 +504 -2
- package/dist/agents/agent-transcript-tool.d.ts +1 -1
- package/dist/agents/cascade.js +4 -0
- package/dist/agents/cumulative-stats.d.ts +3 -0
- package/dist/agents/cumulative-stats.js +3 -0
- package/dist/agents/list-agents-tool.d.ts +1 -1
- package/dist/agents/read-inbox-tool.d.ts +1 -1
- package/dist/agents/repair-loop.js +4 -0
- package/dist/agents/send-message-tool.d.ts +11 -16
- package/dist/agents/send-message-tool.js +11 -13
- package/dist/agents/subagent.js +6 -4
- package/dist/agents/tool-filter.d.ts +40 -13
- package/dist/agents/tool-filter.js +28 -14
- package/dist/bench/metrics.d.ts +1 -0
- package/dist/brain/anthropic.js +16 -12
- package/dist/brain/model-presets.d.ts +4 -5
- package/dist/brain/model-presets.js +4 -4
- package/dist/brain/open-responses.js +16 -12
- package/dist/brain/openai.js +16 -12
- package/dist/brain/request-params.d.ts +12 -33
- package/dist/brain/request-params.js +5 -2
- package/dist/brain/request-route.d.ts +9 -8
- package/dist/brain/request-route.js +1 -0
- package/dist/brain/route-adjudicator.d.ts +117 -47
- package/dist/brain/route-adjudicator.js +171 -42
- package/dist/brain/route-conformance.js +2 -2
- package/dist/brain/status-sink.d.ts +18 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/core/allow-entry.d.ts +40 -8
- package/dist/core/allow-entry.js +23 -16
- package/dist/core/auto-compaction.d.ts +23 -20
- package/dist/core/auto-compaction.js +37 -16
- package/dist/core/auto-promote.d.ts +2 -1
- package/dist/core/auto-promote.js +2 -2
- package/dist/core/caller-tool-name.d.ts +9 -0
- package/dist/core/caller-tool-name.js +13 -0
- package/dist/core/checkpoint-requirements.d.ts +7 -1
- package/dist/core/checkpoint-requirements.js +2 -0
- package/dist/core/checkpoint-store.d.ts +36 -12
- package/dist/core/checkpoint-store.js +1 -1
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +2 -1
- package/dist/core/credential-vocabulary.d.ts +33 -8
- package/dist/core/credential-vocabulary.js +32 -7
- package/dist/core/decision-receipt.d.ts +2 -2
- package/dist/core/delegation-frames.d.ts +9 -2
- package/dist/core/delegation-name.d.ts +18 -0
- package/dist/core/delegation-name.js +47 -0
- package/dist/core/engine-capabilities.d.ts +8 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +36 -19
- package/dist/core/frontmatter-fence.d.ts +10 -0
- package/dist/core/frontmatter-fence.js +6 -0
- package/dist/core/gate-fold.js +5 -23
- package/dist/core/gate-lanes.js +356 -270
- package/dist/core/governance-codes.d.ts +9 -4
- package/dist/core/governance-codes.js +9 -3
- package/dist/core/hooks.d.ts +276 -734
- package/dist/core/hooks.js +97 -192
- package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
- package/dist/{tools/fs → core}/image-admission.js +24 -6
- package/dist/core/mcp-connection-pool.d.ts +4 -1
- package/dist/core/mcp-connection-pool.js +7 -2
- package/dist/core/mcp-probe.d.ts +12 -9
- package/dist/core/mcp-probe.js +2 -2
- package/dist/core/mcp-server-spec.d.ts +16 -0
- package/dist/core/mcp.d.ts +11 -7
- package/dist/core/mcp.js +11 -5
- package/dist/core/memory-engine/data-plane.js +5 -1
- package/dist/core/memory-engine/distiller.js +16 -2
- package/dist/core/memory-engine/engine.d.ts +8 -11
- package/dist/core/memory-engine/engine.js +9 -5
- package/dist/core/memory-engine/frontmatter.d.ts +6 -0
- package/dist/core/memory-engine/frontmatter.js +19 -16
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/mode-policy.d.ts +4 -0
- package/dist/core/mode-policy.js +7 -5
- package/dist/core/model-seat.d.ts +4 -1
- package/dist/core/mods/dollar.d.ts +109 -0
- package/dist/core/mods/dollar.js +154 -0
- package/dist/core/mods/host.d.ts +23 -0
- package/dist/core/mods/host.js +21 -0
- package/dist/core/mods/kernel/budget.d.ts +43 -0
- package/dist/core/mods/kernel/budget.js +83 -0
- package/dist/core/mods/kernel/dispatch.d.ts +100 -0
- package/dist/core/mods/kernel/dispatch.js +701 -0
- package/dist/core/mods/kernel/events.d.ts +242 -0
- package/dist/core/mods/kernel/events.js +210 -0
- package/dist/core/mods/kernel/index.d.ts +6 -0
- package/dist/core/mods/kernel/index.js +5 -0
- package/dist/core/mods/kernel/receive.d.ts +65 -0
- package/dist/core/mods/kernel/receive.js +123 -0
- package/dist/core/mods/kernel/registration.d.ts +131 -0
- package/dist/core/mods/kernel/registration.js +102 -0
- package/dist/core/mods/kernel/site-rules.d.ts +84 -0
- package/dist/core/mods/kernel/site-rules.js +104 -0
- package/dist/core/mods/stations.d.ts +350 -0
- package/dist/core/mods/stations.js +444 -0
- package/dist/core/own-property-receipt.js +11 -23
- package/dist/core/parent-spec-seat.d.ts +18 -7
- package/dist/core/parent-spec-seat.js +6 -2
- package/dist/core/path-identity.js +2 -1
- package/dist/core/permission-rule-syntax.d.ts +15 -0
- package/dist/core/permission-rule-syntax.js +24 -16
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +26 -15
- package/dist/core/prompt-section-seat.d.ts +15 -27
- package/dist/core/prompt-section-seat.js +73 -40
- package/dist/core/protocol-http-auth.d.ts +3 -1
- package/dist/core/protocol-http-auth.js +2 -0
- package/dist/core/reminder-mint.d.ts +2 -2
- package/dist/core/remote-env.d.ts +24 -12
- package/dist/core/remote-env.js +1 -0
- package/dist/core/resume-startup-cause.d.ts +16 -1
- package/dist/core/resume-startup-cause.js +4 -1
- package/dist/core/retired-keys.d.ts +4 -0
- package/dist/core/retired-keys.js +3 -0
- package/dist/core/runner/announce-once-ledger.d.ts +31 -1
- package/dist/core/runner/announce-once-ledger.js +22 -0
- package/dist/core/runner/assemble-result.d.ts +9 -0
- package/dist/core/runner/assemble-result.js +3 -1
- package/dist/core/runner/call-hook-stations.d.ts +23 -27
- package/dist/core/runner/call-hook-stations.js +58 -42
- package/dist/core/runner/caller-stop-gate.d.ts +25 -0
- package/dist/core/runner/caller-stop-gate.js +7 -0
- package/dist/core/runner/compaction-seams.d.ts +8 -22
- package/dist/core/runner/compaction-seams.js +28 -53
- package/dist/core/runner/construction-doors.js +11 -1
- package/dist/core/runner/contracts.d.ts +85 -83
- package/dist/core/runner/credential-origin-seat.d.ts +2 -0
- package/dist/core/runner/credential-origin-seat.js +19 -0
- package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
- package/dist/core/runner/gate-exit.d.ts +47 -36
- package/dist/core/runner/gate-exit.js +8 -2
- package/dist/core/runner/image.js +1 -2
- package/dist/core/runner/inline-image.js +1 -1
- package/dist/core/runner/notice-seat-input.d.ts +11 -0
- package/dist/core/runner/notice-seat-input.js +1 -0
- package/dist/core/runner/person-path-rows.js +1 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
- package/dist/core/runner/prepare-ask-lane.js +6 -15
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
- package/dist/core/runner/prepare-config-doors.d.ts +5 -0
- package/dist/core/runner/prepare-config-doors.js +9 -0
- package/dist/core/runner/prepare-defer-classify.js +3 -4
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
- package/dist/core/runner/prepare-gate-stations.js +11 -10
- package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
- package/dist/core/runner/prepare-inherited-gate.js +8 -21
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +10 -14
- package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
- package/dist/core/runner/prepare-policy-chain.js +95 -100
- package/dist/core/runner/prepare-project-context.js +7 -10
- package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
- package/dist/core/runner/prepare-prompt-assembly.js +134 -101
- package/dist/core/runner/prepare-prompt-inputs.d.ts +18 -19
- package/dist/core/runner/prepare-prompt-inputs.js +5 -7
- package/dist/core/runner/prepare-protocol-tools.d.ts +6 -4
- package/dist/core/runner/prepare-protocol-tools.js +2 -2
- package/dist/core/runner/prepare-safety-scan.js +6 -10
- package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
- package/dist/core/runner/prepare-suspend-saga.js +7 -5
- package/dist/core/runner/prepare-task.js +33 -15
- package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
- package/dist/core/runner/prepare-turn-wiring.js +29 -27
- package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -6
- package/dist/core/runner/prepare-wiring-manifest.js +7 -7
- package/dist/core/runner/resume-apply.d.ts +5 -2
- package/dist/core/runner/resume-apply.js +24 -42
- package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
- package/dist/core/runner/resume-checkpoint-screen.js +9 -1
- package/dist/core/runner/resume-preflight.js +38 -16
- package/dist/core/runner/retired-runner-deps.js +3 -1
- package/dist/core/runner/run-brain-sinks.d.ts +3 -2
- package/dist/core/runner/run-brain-sinks.js +5 -1
- package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
- package/dist/core/runner/run-compaction-machinery.js +7 -33
- package/dist/core/runner/run-harness-handlers.js +4 -2
- package/dist/core/runner/run-identity-wiring.d.ts +3 -1
- package/dist/core/runner/run-identity-wiring.js +3 -2
- package/dist/core/runner/run-leg.js +62 -84
- package/dist/core/runner/run-notification-lane.js +1 -0
- package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
- package/dist/core/runner/run-recovery-lanes.js +11 -10
- package/dist/core/runner/run-settle-and-teardown.js +9 -28
- package/dist/core/runner/run-stop-and-final-verify.js +18 -25
- package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
- package/dist/core/runner/run-terminal-adoption.js +33 -22
- package/dist/core/runner/run-tool-mount-facts.js +5 -3
- package/dist/core/runner/run-turn-boundary.js +23 -34
- package/dist/core/runner/runtask.d.ts +6 -7
- package/dist/core/runner/runtask.js +14 -72
- package/dist/core/runner/session-rule-policy.d.ts +5 -5
- package/dist/core/runner/session-rule-policy.js +13 -8
- package/dist/core/runner/side-call-account.d.ts +68 -0
- package/dist/core/runner/side-call-account.js +61 -0
- package/dist/core/runner/stream-halt-verbs.js +12 -17
- package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
- package/dist/core/runner/stream-steer-verb.d.ts +1 -1
- package/dist/core/runner/stream-steer-verb.js +20 -38
- package/dist/core/runner/sub-agent-deny-lists.d.ts +121 -22
- package/dist/core/runner/sub-agent-deny-lists.js +228 -71
- package/dist/core/runner/tool-end-body.d.ts +5 -6
- package/dist/core/runner/tool-end-body.js +6 -4
- package/dist/core/runner/tool-not-executed.d.ts +15 -0
- package/dist/core/runner/tool-not-executed.js +30 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -7
- package/dist/core/runner/tool-occurrence.js +5 -5
- package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
- package/dist/core/runner-deps.d.ts +20 -28
- package/dist/core/safety-merge-corpus.js +18 -2
- package/dist/core/secret-env.d.ts +88 -20
- package/dist/core/secret-env.js +192 -38
- package/dist/core/session-policy-store.d.ts +52 -16
- package/dist/core/session-policy-store.js +118 -28
- package/dist/core/session-reconcile.d.ts +4 -0
- package/dist/core/session-reconcile.js +2 -1
- package/dist/core/shell-read-silence.js +3 -32
- package/dist/core/side-query.d.ts +5 -3
- package/dist/core/skill-grant.d.ts +3 -2
- package/dist/core/skill-grant.js +17 -9
- package/dist/core/skills-directory.d.ts +31 -11
- package/dist/core/skills-directory.js +655 -104
- package/dist/core/task-event.d.ts +13 -3
- package/dist/core/task-result.d.ts +8 -0
- package/dist/core/task-spec.d.ts +20 -19
- package/dist/core/task-stream.d.ts +14 -4
- package/dist/core/tighten-task-spec.d.ts +4 -3
- package/dist/core/tighten-task-spec.js +2 -4
- package/dist/core/tool-check-reading.d.ts +74 -0
- package/dist/core/tool-check-reading.js +80 -0
- package/dist/core/tool-policy.d.ts +59 -18
- package/dist/core/tool-policy.js +77 -12
- package/dist/core/tool-registry.d.ts +20 -0
- package/dist/core/tool-registry.js +4 -0
- package/dist/core/tool-spec.d.ts +10 -6
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +51 -32
- package/dist/core/unc-spelling.d.ts +10 -0
- package/dist/core/unc-spelling.js +3 -0
- package/dist/core/untrusted-egress.d.ts +8 -0
- package/dist/core/untrusted-egress.js +4 -1
- package/dist/core/user-attachment.d.ts +12 -2
- package/dist/core/user-attachment.js +17 -2
- package/dist/core/wiring-manifest.d.ts +14 -13
- package/dist/core/wiring-manifest.js +2 -2
- package/dist/engine/compaction/utils.js +1 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
- package/dist/engine/execution-env/symlink-chain.js +1 -1
- package/dist/engine/harness/agent-harness.d.ts +1 -1
- package/dist/engine/harness/agent-harness.js +3 -3
- package/dist/engine/harness/types.d.ts +17 -16
- package/dist/engine/harness/types.js +7 -1
- package/dist/engine/llm/types.d.ts +12 -7
- package/dist/engine/loop/agent-loop.js +1 -1
- package/dist/engine/loop/types.d.ts +1 -1
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.js +3 -10
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/engine/session/session.js +4 -4
- package/dist/index.d.ts +20 -16
- package/dist/index.js +13 -11
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/orchestration/run-spec.d.ts +4 -6
- package/dist/orchestration/run-spec.js +39 -63
- package/dist/orchestration/run-workflow-tool.js +1 -2
- package/dist/orchestration/workflow.d.ts +11 -3
- package/dist/orchestration/workflow.js +11 -2
- package/dist/prompt-assembly/artifact-store.d.ts +37 -56
- package/dist/prompt-assembly/artifact-store.js +31 -49
- package/dist/prompt-assembly/artifact.d.ts +89 -76
- package/dist/prompt-assembly/artifact.js +167 -146
- package/dist/prompt-assembly/assemble.d.ts +34 -29
- package/dist/prompt-assembly/assemble.js +33 -220
- package/dist/prompt-assembly/bands.d.ts +20 -0
- package/dist/prompt-assembly/bands.js +18 -0
- package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
- package/dist/prompt-assembly/catalog/constitution.js +69 -0
- package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
- package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
- package/dist/prompt-assembly/catalog/index.d.ts +11 -0
- package/dist/prompt-assembly/catalog/index.js +59 -0
- package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
- package/dist/prompt-assembly/catalog/modes.js +137 -0
- package/dist/prompt-assembly/catalog/role.d.ts +10 -0
- package/dist/prompt-assembly/catalog/role.js +157 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +124 -0
- package/dist/prompt-assembly/catalog/schema.js +25 -0
- package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
- package/dist/prompt-assembly/catalog/sections.js +98 -0
- package/dist/prompt-assembly/catalog/team.d.ts +4 -0
- package/dist/prompt-assembly/catalog/team.js +258 -0
- package/dist/prompt-assembly/composer.d.ts +24 -28
- package/dist/prompt-assembly/composer.js +124 -46
- package/dist/prompt-assembly/epoch.d.ts +89 -79
- package/dist/prompt-assembly/epoch.js +115 -142
- package/dist/prompt-assembly/explain.d.ts +58 -34
- package/dist/prompt-assembly/explain.js +21 -24
- package/dist/prompt-assembly/overlay.d.ts +127 -0
- package/dist/prompt-assembly/overlay.js +301 -0
- package/dist/prompt-assembly/renderers.d.ts +21 -0
- package/dist/prompt-assembly/renderers.js +39 -0
- package/dist/prompt-assembly/section-usage.d.ts +3 -3
- package/dist/prompt-assembly/section-usage.js +1 -1
- package/dist/prompt-assembly/select.d.ts +56 -0
- package/dist/prompt-assembly/select.js +69 -0
- package/dist/prompt-assembly/sugar.d.ts +31 -0
- package/dist/prompt-assembly/sugar.js +20 -0
- package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
- package/dist/prompt-assembly/types.d.ts +45 -148
- package/dist/prompts/coordinator.d.ts +2 -21
- package/dist/prompts/coordinator.js +3 -255
- package/dist/prompts/cowork.d.ts +27 -16
- package/dist/prompts/cowork.js +2 -23
- package/dist/prompts/default.d.ts +38 -500
- package/dist/prompts/default.js +20 -285
- package/dist/prompts/supervisor.d.ts +6 -71
- package/dist/prompts/supervisor.js +6 -117
- package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
- package/dist/tools/fs/dir-entries.d.ts +4 -2
- package/dist/tools/fs/dir-entries.js +16 -4
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +22 -11
- package/dist/tools/fs/fs-pdf.js +17 -13
- package/dist/tools/fs/fs-read.js +4 -3
- package/dist/tools/fs/fs-shared.d.ts +1 -10
- package/dist/tools/fs/fs-shared.js +3 -4
- package/dist/tools/fs/fs-write.js +2 -1
- package/dist/tools/fs/notebook.js +1 -1
- package/dist/tools/fs/pdf.d.ts +20 -10
- package/dist/tools/fs/pdf.js +19 -10
- package/dist/tools/fs/program-read-model.d.ts +68 -8
- package/dist/tools/fs/program-read-model.js +112 -33
- package/dist/tools/fs/program-read-model.rows.js +30 -10
- package/dist/tools/fs/read-deny-home.d.ts +25 -9
- package/dist/tools/fs/read-deny-home.js +28 -27
- package/dist/tools/fs/read-deny.d.ts +41 -11
- package/dist/tools/fs/read-deny.js +51 -5
- package/dist/tools/fs/safety.d.ts +4 -26
- package/dist/tools/fs/safety.js +10 -32
- package/dist/tools/fs/search.js +15 -10
- package/dist/tools/fs/shell-read-argv.d.ts +3 -2
- package/dist/tools/fs/shell-read-argv.js +118 -38
- package/dist/tools/fs/shell-read-establish.d.ts +5 -5
- package/dist/tools/fs/shell-read-establish.js +11 -61
- package/dist/tools/fs/shell-read-identity.js +6 -3
- package/dist/tools/fs/shell-read-judge.d.ts +13 -15
- package/dist/tools/fs/shell-read-judge.js +18 -4
- package/dist/tools/fs/shell-read-plan.d.ts +2 -2
- package/dist/tools/web.js +1 -1
- package/package.json +13 -1
- package/test/export-surface.snapshot.json +242 -99
- package/wire-changes/core@7.52.0.json +5859 -0
- package/dist/core/hook-seats.d.ts +0 -66
- package/dist/core/hook-seats.js +0 -37
- package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
- package/dist/prompt-assembly/packs/sema-default.js +0 -147
- package/dist/prompts/simple-sections.d.ts +0 -58
- package/dist/prompts/simple-sections.js +0 -43
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
* (green→`spec.not_red`、error→`spec.oracle_error`,均 fail-loud);捕获 baseline 计数。
|
|
9
9
|
* 2. frozen deny policy 经 {@link combinePolicies} 合入部署基线(deny 短路不可被顶);绝不裸赋顶掉
|
|
10
10
|
* `taskSpec.toolPolicy`(TRAP #1)。
|
|
11
|
-
* 3.
|
|
12
|
-
*
|
|
13
|
-
* (不吞其否决权);error ⇒ block 一次并注明 oracle 基础设施故障,**连续 2 次 error 放弃把关**走终态
|
|
14
|
-
* 判定(防 oracle 自坏死循环)。其它 hook 槽原样透传。
|
|
11
|
+
* 3. stop gate = 任务座位上的一条注册(在调用方注册之前):red ⇒ block(失败尾部经 `delimitUntrusted` 围栏);green ⇒
|
|
12
|
+
* `next(e)` 交下游;error ⇒ block 一次,**连续 2 次 error 放弃把关**走终态判定。
|
|
15
13
|
* 4. 收口:终态亲跑 oracle = 最终判定;`emitTaskOutcome`(mechanical):`oracleHadRedRun` = 任一
|
|
16
14
|
* 「真跑过且判 red」的观察(preflight ∨ stop-gate ∨ 终态;error 永不置位)。durable pause
|
|
17
15
|
* (suspended/needs_review)非终态,不发射(同 goal.ts 先例:无半事实、resume 不重复计数)。
|
|
@@ -34,8 +32,8 @@ import { type OracleBaseline, type OracleGateResult, type OracleVerdict, type Sp
|
|
|
34
32
|
export interface RunSpecOptions {
|
|
35
33
|
/** Workcopy root — the containment root for frozenPaths, oracle cwd, and `spec.path` resolution. */
|
|
36
34
|
rootDir: string;
|
|
37
|
-
/** Per-run base spec (model/tools/toolPolicy/
|
|
38
|
-
* spec framing); `toolPolicy` and `
|
|
35
|
+
/** Per-run base spec (model/tools/toolPolicy/mods/limits/…). `objective` is owned by runSpec (the
|
|
36
|
+
* spec framing); `toolPolicy` and `mods` are COMPOSED with runSpec's, never replaced. */
|
|
39
37
|
taskSpec: Omit<TaskSpec, "objective">;
|
|
40
38
|
/** Receives the oracle gates' once-per-process `config.secret_env_scrubbed` notice (`runOracle`'s `onNotice`);
|
|
41
39
|
* absent ⇒ the console line. */
|
|
@@ -9,6 +9,8 @@ import { writeTargetPath } from "../tools/fs/safety.js";
|
|
|
9
9
|
import { callTargetViewsOf } from "../core/effective-path-target.js";
|
|
10
10
|
import { captureBaseline, resolveFrozenPaths, restoreFrozenPaths, runOracle, snapshotFrozenPaths, specError, } from "../core/spec-contract.js";
|
|
11
11
|
import { isProtectedWrite } from "../core/tool-registry.js";
|
|
12
|
+
const RUN_SPEC_ORACLE_GATE = "run-spec-oracle-gate";
|
|
13
|
+
const RUN_SPEC_ORACLE_GATE_BUDGET_MS = 600_000;
|
|
12
14
|
const CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
|
|
13
15
|
const pathKey = (p) => {
|
|
14
16
|
let n = p.replace(/\\/g, "/");
|
|
@@ -100,81 +102,55 @@ export async function runSpec(runner, contract, opts) {
|
|
|
100
102
|
const frozenPolicy = frozenDenyPolicy(rootDir, frozenResolved);
|
|
101
103
|
const policies = [deployBaseline?.toolPolicy, opts.taskSpec.toolPolicy, frozenPolicy].filter((p) => p !== undefined);
|
|
102
104
|
const toolPolicy = policies.length === 1 ? policies[0] : combinePolicies(...policies);
|
|
103
|
-
const userHooks = opts.taskSpec.hooks && deployBaseline?.hooks
|
|
104
|
-
? {
|
|
105
|
-
preToolUse: (opts.taskSpec.hooks.preToolUse ?? deployBaseline.hooks.preToolUse)?.bind(opts.taskSpec.hooks.preToolUse ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
106
|
-
...((opts.taskSpec.hooks.preToolUse ? opts.taskSpec.hooks : deployBaseline.hooks).preToolUseObservational === true
|
|
107
|
-
? { preToolUseObservational: true }
|
|
108
|
-
: {}),
|
|
109
|
-
postToolUse: (opts.taskSpec.hooks.postToolUse ?? deployBaseline.hooks.postToolUse)?.bind(opts.taskSpec.hooks.postToolUse ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
110
|
-
userPromptSubmit: (opts.taskSpec.hooks.userPromptSubmit ?? deployBaseline.hooks.userPromptSubmit)?.bind(opts.taskSpec.hooks.userPromptSubmit ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
111
|
-
stop: (opts.taskSpec.hooks.stop ?? deployBaseline.hooks.stop)?.bind(opts.taskSpec.hooks.stop ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
112
|
-
postToolUseFailure: (opts.taskSpec.hooks.postToolUseFailure ?? deployBaseline.hooks.postToolUseFailure)?.bind(opts.taskSpec.hooks.postToolUseFailure ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
113
|
-
postToolBatch: (opts.taskSpec.hooks.postToolBatch ?? deployBaseline.hooks.postToolBatch)?.bind(opts.taskSpec.hooks.postToolBatch ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
114
|
-
preCompact: (opts.taskSpec.hooks.preCompact ?? deployBaseline.hooks.preCompact)?.bind(opts.taskSpec.hooks.preCompact ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
115
|
-
postCompact: (opts.taskSpec.hooks.postCompact ?? deployBaseline.hooks.postCompact)?.bind(opts.taskSpec.hooks.postCompact ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
116
|
-
stopFailure: (opts.taskSpec.hooks.stopFailure ?? deployBaseline.hooks.stopFailure)?.bind(opts.taskSpec.hooks.stopFailure ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
117
|
-
permissionDenied: (opts.taskSpec.hooks.permissionDenied ?? deployBaseline.hooks.permissionDenied)?.bind(opts.taskSpec.hooks.permissionDenied ? opts.taskSpec.hooks : deployBaseline.hooks),
|
|
118
|
-
...((opts.taskSpec.hooks.timeoutMs ?? deployBaseline.hooks.timeoutMs) !== undefined
|
|
119
|
-
? { timeoutMs: opts.taskSpec.hooks.timeoutMs ?? deployBaseline.hooks.timeoutMs }
|
|
120
|
-
: {}),
|
|
121
|
-
}
|
|
122
|
-
: (opts.taskSpec.hooks ?? deployBaseline?.hooks);
|
|
123
105
|
let guardRestores = 0;
|
|
124
106
|
let consecutiveOracleErrors = 0;
|
|
125
107
|
let gateAbandoned = false;
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const report = await runOracle(contract.oracle, rootDir, { baseline, ...(gateSignal !== undefined ? { signal: gateSignal } : {}), ...noticeSeat });
|
|
143
|
-
if (ctx.signal?.aborted === true)
|
|
144
|
-
return undefined;
|
|
145
|
-
oracleRuns++;
|
|
146
|
-
if (report.verdict === "red") {
|
|
147
|
-
oracleHadRedRun = true;
|
|
148
|
-
oracleRedRuns++;
|
|
149
|
-
stopGateBlocks++;
|
|
150
|
-
consecutiveOracleErrors = 0;
|
|
151
|
-
return { block: redFeedback(report.gates) };
|
|
152
|
-
}
|
|
153
|
-
if (report.verdict === "error") {
|
|
154
|
-
consecutiveOracleErrors++;
|
|
155
|
-
if (consecutiveOracleErrors < 2) {
|
|
156
|
-
const broken = report.gates.filter((g) => g.verdict === "error");
|
|
108
|
+
const oracleGate = {
|
|
109
|
+
name: RUN_SPEC_ORACLE_GATE,
|
|
110
|
+
uses: { events: ["classic.Stop"], calls: [] },
|
|
111
|
+
budgetMs: RUN_SPEC_ORACLE_GATE_BUDGET_MS,
|
|
112
|
+
register(on) {
|
|
113
|
+
on("classic.Stop", async (_$, e, next) => {
|
|
114
|
+
guardRestores += restoreFrozenPaths(snapshot, rootDir);
|
|
115
|
+
if (!gateAbandoned) {
|
|
116
|
+
const gateSignal = opts.taskSpec.signal !== undefined ? AbortSignal.any([next.signal, opts.taskSpec.signal]) : next.signal;
|
|
117
|
+
const report = await runOracle(contract.oracle, rootDir, { baseline, signal: gateSignal, ...noticeSeat });
|
|
118
|
+
if (next.signal.aborted)
|
|
119
|
+
return {};
|
|
120
|
+
oracleRuns++;
|
|
121
|
+
if (report.verdict === "red") {
|
|
122
|
+
oracleHadRedRun = true;
|
|
123
|
+
oracleRedRuns++;
|
|
157
124
|
stopGateBlocks++;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
125
|
+
consecutiveOracleErrors = 0;
|
|
126
|
+
return { block: redFeedback(report.gates) };
|
|
127
|
+
}
|
|
128
|
+
if (report.verdict === "error") {
|
|
129
|
+
consecutiveOracleErrors++;
|
|
130
|
+
if (consecutiveOracleErrors < 2) {
|
|
131
|
+
const broken = report.gates.filter((g) => g.verdict === "error");
|
|
132
|
+
stopGateBlocks++;
|
|
133
|
+
return {
|
|
134
|
+
block: `The verification oracle itself FAILED TO RUN (${broken.map((g) => `gate "${g.name}": ${g.reason}`).join("; ")}). ` +
|
|
135
|
+
`This is an infrastructure error, not a test failure — you may have broken the build/test environment. ` +
|
|
136
|
+
`Restore it so the oracle can run.`,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
gateAbandoned = true;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
consecutiveOracleErrors = 0;
|
|
163
143
|
}
|
|
164
|
-
gateAbandoned = true;
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
consecutiveOracleErrors = 0;
|
|
168
144
|
}
|
|
169
|
-
|
|
170
|
-
|
|
145
|
+
return next(e);
|
|
146
|
+
});
|
|
171
147
|
},
|
|
172
148
|
};
|
|
173
149
|
const result = await runner.runTask({
|
|
174
150
|
...opts.taskSpec,
|
|
175
151
|
objective: buildObjective(specText, contract),
|
|
176
152
|
toolPolicy,
|
|
177
|
-
|
|
153
|
+
mods: [oracleGate, ...(opts.taskSpec.mods ?? [])],
|
|
178
154
|
});
|
|
179
155
|
guardRestores += restoreFrozenPaths(snapshot, rootDir);
|
|
180
156
|
const final = await runOracle(contract.oracle, rootDir, { baseline, ...noticeSeat });
|
|
@@ -539,9 +539,8 @@ async function mountRunWorkflowTool(d) {
|
|
|
539
539
|
...((ctx.inheritedGateForChildren ?? d.inheritedGateForChildren) !== undefined
|
|
540
540
|
? { inheritedGate: (ctx.inheritedGateForChildren ?? d.inheritedGateForChildren)() }
|
|
541
541
|
: {}),
|
|
542
|
-
...((ctx.toolSelector?.layers ?? d.parentToolCeiling) !== undefined ? { toolCeiling: (ctx.toolSelector?.layers ?? d.parentToolCeiling) } : {}),
|
|
543
542
|
...(autoModeReview !== undefined ? { autoModeReview } : {}),
|
|
544
|
-
}, { workflowDepth: d.workflowDepth });
|
|
543
|
+
}, { workflowDepth: d.workflowDepth, ...((ctx.toolSelector?.layers ?? d.parentToolCeiling) !== undefined ? { toolCeiling: (ctx.toolSelector?.layers ?? d.parentToolCeiling) } : {}) });
|
|
545
544
|
}
|
|
546
545
|
catch (err) {
|
|
547
546
|
return structuredError(thrownText(err));
|
|
@@ -153,6 +153,11 @@ export declare class WorkflowJournalAppendTimeoutError extends Error {
|
|
|
153
153
|
*/
|
|
154
154
|
export interface WorkflowInternals {
|
|
155
155
|
workflowDepth?: number;
|
|
156
|
+
/** The tool selector layers of the prepared run that launched this workflow (`ToolExecuteContext.toolSelector.layers`), threaded into
|
|
157
|
+
* EVERY spawned agent as its ceiling (`RunInternals.toolCeiling`) on both spawn legs. The run that holds them judged them where it
|
|
158
|
+
* wrote them, so they are not asked again here; a ceiling a host writes itself is {@link RunWorkflowOptions.toolCeiling}, which is.
|
|
159
|
+
* Given both, both bound every agent (these layers first) and only the host-written one is judged. */
|
|
160
|
+
toolCeiling?: readonly import("../core/tool-face.js").ToolSelectorLayer[];
|
|
156
161
|
}
|
|
157
162
|
export interface WorkflowBudget {
|
|
158
163
|
/** The token ceiling, or null when none was set (then `remaining()` is Infinity). */
|
|
@@ -565,9 +570,12 @@ export interface RunWorkflowOptions {
|
|
|
565
570
|
* `run_workflow` tool wiring; a directly-started workflow may pass its own. Absent ⇒ children run
|
|
566
571
|
* under only their own gates (pre-seam behavior). TRUSTED: never a script/model argument. */
|
|
567
572
|
inheritedGate?: import("../core/runner/contracts.js").InheritedGate;
|
|
568
|
-
/**
|
|
569
|
-
*
|
|
570
|
-
*
|
|
573
|
+
/** A tool selector ceiling the HOST writes, threaded into EVERY spawned agent's trusted internals as its ceiling
|
|
574
|
+
* (`RunInternals.toolCeiling`) on both spawn legs: nothing a workflow agent's spec names can widen it. Nobody judged what the host
|
|
575
|
+
* wrote, so each agent's spec is asked of it before it launches: another spelling of a tool the agent carries (a caller tool, the
|
|
576
|
+
* catalog, a listable delegation pool) refuses that agent — `config.tool_face_control`, `detail.reason: "near_miss"`. The ceiling of the
|
|
577
|
+
* prepared run that launched the workflow rides {@link WorkflowInternals.toolCeiling} instead; given both, both bound every agent and only
|
|
578
|
+
* this one is judged. Absent ⇒ the agents are bounded only by their own lists. */
|
|
571
579
|
toolCeiling?: readonly import("../core/tool-face.js").ToolSelectorLayer[];
|
|
572
580
|
/** RB-201 FO-3 (workflow lane) — the session's auto-mode classifier, consulted BEFORE each script-spawned
|
|
573
581
|
* child starts (objective + toolset + output schema, finalized). The delegation-tool lane reviews its
|
|
@@ -20,7 +20,7 @@ import { boundInputHashOf } from "../core/canonical-json.js";
|
|
|
20
20
|
import { boundedRedactedSummary, egressThrownText } from "../core/untrusted-egress.js";
|
|
21
21
|
import { delimitUntrusted } from "../core/untrusted-text.js";
|
|
22
22
|
import { OUTPUT_TOOL_NAME } from "../core/runner/synthetic-tools.js";
|
|
23
|
-
import { deniedToolNamesOf } from "../core/runner/sub-agent-deny-lists.js";
|
|
23
|
+
import { deniedToolNamesOf, judgeHostToolCeiling } from "../core/runner/sub-agent-deny-lists.js";
|
|
24
24
|
import { compileOutputSchema } from "../core/runner/strict-output-schema.js";
|
|
25
25
|
import { WorkflowBudgetExceededError, WorkflowNestingError, WorkflowAgentBlockedError, WorkflowAgentParkedError, WorkflowAgentSchemaError, WorkflowAgentStalledError, WorkflowMaxAgentsError, WORKFLOW_SPAWN_BLOCKED_ERROR_CODE } from "./workflow-types.js";
|
|
26
26
|
import { WorkflowScriptError } from "./workflow-meta.js";
|
|
@@ -705,6 +705,13 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
|
|
|
705
705
|
o.close();
|
|
706
706
|
};
|
|
707
707
|
const sem = createSemaphore(concurrency);
|
|
708
|
+
const launchingCeiling = internals?.toolCeiling ?? undefined;
|
|
709
|
+
const hostCeiling = opts.toolCeiling ?? undefined;
|
|
710
|
+
const agentCeiling = launchingCeiling === undefined ? hostCeiling : hostCeiling === undefined ? launchingCeiling : [...launchingCeiling, ...hostCeiling];
|
|
711
|
+
const judgeHostCeiling = (spec) => {
|
|
712
|
+
if (hostCeiling !== undefined)
|
|
713
|
+
judgeHostToolCeiling(hostCeiling, spec, launchingCeiling);
|
|
714
|
+
};
|
|
708
715
|
const spawnAttribution = {
|
|
709
716
|
isDelegatedChild: true,
|
|
710
717
|
...(opts.questionFaceStripped === true ? { questionFaceStripped: true } : {}),
|
|
@@ -715,7 +722,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
|
|
|
715
722
|
...(opts.parentCenterSourceRevision !== undefined ? { parentCenterSourceRevision: opts.parentCenterSourceRevision } : {}),
|
|
716
723
|
...(opts.onForwardEvent ? { onForwardEvent: opts.onForwardEvent } : {}),
|
|
717
724
|
...(opts.inheritedGate !== undefined ? { inheritedGate: opts.inheritedGate } : {}),
|
|
718
|
-
...(
|
|
725
|
+
...(agentCeiling !== undefined ? { toolCeiling: agentCeiling } : {}),
|
|
719
726
|
...((opts.rootSessionId ?? opts.originatingSessionId) !== undefined ? { rootSessionId: opts.rootSessionId ?? opts.originatingSessionId } : {}),
|
|
720
727
|
...(opts.placementRoot !== undefined ? { placementRoot: opts.placementRoot } : {}),
|
|
721
728
|
...(opts.originatingSessionId !== undefined ? { parentSessionId: opts.originatingSessionId } : {}),
|
|
@@ -1645,6 +1652,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
|
|
|
1645
1652
|
const preReviewSpec = agentOpts.schema
|
|
1646
1653
|
? { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal, outputSchema: agentOpts.schema }
|
|
1647
1654
|
: { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal };
|
|
1655
|
+
judgeHostCeiling(preReviewSpec);
|
|
1648
1656
|
const runSpec = await reviewSpawnBeforeLaunch("ctx.agent", label, callKey, preReviewSpec, effectiveSignal);
|
|
1649
1657
|
const enrichedForward = opts.onForwardEvent !== undefined
|
|
1650
1658
|
? (e) => {
|
|
@@ -2010,6 +2018,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
|
|
|
2010
2018
|
? { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal, outputSchema: agentOpts.schema }
|
|
2011
2019
|
: { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal };
|
|
2012
2020
|
const preReviewSpec = childSessionId !== undefined ? { ...baseRunSpec, sessionId: childSessionId } : baseRunSpec;
|
|
2021
|
+
judgeHostCeiling(preReviewSpec);
|
|
2013
2022
|
const runSpec = await reviewSpawnBeforeLaunch("ctx.agentStream", label, callKey, preReviewSpec, effectiveSignal);
|
|
2014
2023
|
const enrichedForwardS = opts.onForwardEvent !== undefined
|
|
2015
2024
|
? (e) => {
|
|
@@ -1,28 +1,22 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ArtifactVerifyCode, type PromptArtifact, type PublishedPromptArtifact } from "./artifact.js";
|
|
2
2
|
export interface PromptArtifactStore {
|
|
3
|
-
/** Verified read by digest — undefined on miss OR on any verification failure of stored bytes. */
|
|
4
|
-
get(artifactDigest: string
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/** Idempotent immutable write (same digest ⇒ same bytes; the caller verified before putting). */
|
|
8
|
-
put(envelope: PublishedPromptArtifactEnvelope): Promise<void>;
|
|
3
|
+
/** Verified read by digest — undefined on a miss OR on any verification failure of the stored bytes. */
|
|
4
|
+
get(artifactDigest: string): Promise<PublishedPromptArtifact | undefined>;
|
|
5
|
+
/** Write by digest (the caller verified before putting). */
|
|
6
|
+
put(artifact: PublishedPromptArtifact): Promise<void>;
|
|
9
7
|
}
|
|
10
8
|
export declare class MemoryPromptArtifactStore implements PromptArtifactStore {
|
|
11
9
|
private readonly byDigest;
|
|
12
|
-
get(artifactDigest: string
|
|
13
|
-
|
|
14
|
-
}): Promise<PublishedPromptArtifactEnvelope | undefined>;
|
|
15
|
-
put(envelope: PublishedPromptArtifactEnvelope): Promise<void>;
|
|
10
|
+
get(artifactDigest: string): Promise<PublishedPromptArtifact | undefined>;
|
|
11
|
+
put(artifact: PublishedPromptArtifact): Promise<void>;
|
|
16
12
|
}
|
|
17
|
-
/** `artifacts/<hex>.json` under a caller-owned directory; atomic tmp+rename writes
|
|
13
|
+
/** `artifacts/<hex>.json` under a caller-owned directory; atomic tmp+rename writes. */
|
|
18
14
|
export declare class FilePromptArtifactStore implements PromptArtifactStore {
|
|
19
15
|
private readonly dir;
|
|
20
16
|
constructor(dir: string);
|
|
21
17
|
private fileFor;
|
|
22
|
-
get(artifactDigest: string
|
|
23
|
-
|
|
24
|
-
}): Promise<PublishedPromptArtifactEnvelope | undefined>;
|
|
25
|
-
put(envelope: PublishedPromptArtifactEnvelope): Promise<void>;
|
|
18
|
+
get(artifactDigest: string): Promise<PublishedPromptArtifact | undefined>;
|
|
19
|
+
put(artifact: PublishedPromptArtifact): Promise<void>;
|
|
26
20
|
}
|
|
27
21
|
export type PromptSourceState = {
|
|
28
22
|
state: "active";
|
|
@@ -49,60 +43,47 @@ export declare class FilePromptSourceStateStore implements PromptSourceStateStor
|
|
|
49
43
|
load(): Promise<PromptSourceState | undefined>;
|
|
50
44
|
save(state: PromptSourceState): Promise<void>;
|
|
51
45
|
}
|
|
52
|
-
/** The narrow face the Runner consumes (RunnerDeps.promptSource) — resolution only, no publish. */
|
|
46
|
+
/** The narrow face the Runner consumes (`RunnerDeps.promptSource`) — resolution only, no publish. */
|
|
53
47
|
export interface PromptArtifactSource {
|
|
54
|
-
/** The current
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* validated revocation (applyDisabled) ⇒ pinned sessions roll back to bundled at the next
|
|
64
|
-
* compaction; `"active"` = a validated candidate is live; `"unavailable"` = no verified state
|
|
65
|
-
* (never-configured face, store-miss boot) ⇒ conservative restate — an outage must never strip
|
|
66
|
-
* policy, only an explicit revocation does. Optional (older sources read as "unavailable"). */
|
|
67
|
-
sourceState?(): "active" | "disabled" | "unavailable";
|
|
48
|
+
/** The current verified candidate new sessions (and every top-level session at a compaction) adopt; undefined = none. */
|
|
49
|
+
current(): PublishedPromptArtifact | undefined;
|
|
50
|
+
/** Resolve a PINNED digest (the resume path). Undefined = unavailable — the caller fails loud. */
|
|
51
|
+
get(artifactDigest: string): Promise<PromptArtifact | undefined>;
|
|
52
|
+
/** The tri-state every adoption decision keys on: `"active"` = a verified candidate is live; `"disabled"` = an
|
|
53
|
+
* EXPLICIT verified revocation (`applyDisabled`) — the one state that empties a pinned center layer;
|
|
54
|
+
* `"unavailable"` = no verified state (never configured, or a store miss at boot) — an outage never strips policy,
|
|
55
|
+
* only an explicit revocation does. */
|
|
56
|
+
sourceState(): "active" | "disabled" | "unavailable";
|
|
68
57
|
}
|
|
69
58
|
/**
|
|
70
|
-
* The candidate state machine
|
|
71
|
-
* - `applySnapshot(raw)` — a fetched
|
|
72
|
-
*
|
|
73
|
-
* - `applyDisabled(sourceRevision)` — an explicit, successful disable/delete response: persist
|
|
74
|
-
*
|
|
75
|
-
* - `restore()` — boot: re-resolve persisted active state through the verified store; a miss or
|
|
76
|
-
*
|
|
59
|
+
* The candidate state machine. Publish-side entry points:
|
|
60
|
+
* - `applySnapshot(raw)` — a fetched published artifact: verify → store.put → persist active state → atomic
|
|
61
|
+
* in-memory swap. Any verification failure leaves EVERYTHING unchanged.
|
|
62
|
+
* - `applyDisabled(sourceRevision)` — an explicit, successful disable/delete response: persist disabled state +
|
|
63
|
+
* drop the candidate. (Network failure/304 = simply don't call anything.)
|
|
64
|
+
* - `restore()` — boot: re-resolve the persisted active state through the verified store; a miss or verify failure
|
|
65
|
+
* boots stateless (no candidate) without touching the persisted record.
|
|
77
66
|
*/
|
|
78
67
|
export declare class CenterPromptSource implements PromptArtifactSource {
|
|
79
68
|
private readonly store;
|
|
80
69
|
private readonly stateStore;
|
|
81
|
-
private readonly engineVersion;
|
|
82
70
|
private candidate;
|
|
83
71
|
private state;
|
|
84
|
-
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* schedule, not an exotic race. Serializing costs nothing (these are publish-rate operations) and
|
|
91
|
-
* makes the durable record and the in-memory candidate agree by construction. */
|
|
72
|
+
/** Serialization tail for the three STATE-MUTATING entry points. Each is a multi-await sequence ending in a
|
|
73
|
+
* synchronous swap of (candidate, state); with two in flight, an interleaving where B's `stateStore.save`
|
|
74
|
+
* resolves and swaps before A's would leave the persisted record naming B's digest while the in-memory candidate
|
|
75
|
+
* names A's. `CenterPromptSource` is driven by a caller's poll loop, so overlapping applies are an ordinary
|
|
76
|
+
* schedule. Serializing costs nothing (publish-rate operations) and makes the durable record and the in-memory
|
|
77
|
+
* candidate agree by construction. */
|
|
92
78
|
private tail;
|
|
93
|
-
/** Run `fn` after every previously-queued mutation settles (success OR failure — a failed apply
|
|
94
|
-
* must not wedge the queue). */
|
|
79
|
+
/** Run `fn` after every previously-queued mutation settles (success OR failure — a failed apply must not wedge the queue). */
|
|
95
80
|
private exclusive;
|
|
96
81
|
constructor(opts: {
|
|
97
82
|
store: PromptArtifactStore;
|
|
98
83
|
stateStore?: PromptSourceStateStore;
|
|
99
|
-
engineVersion: string;
|
|
100
84
|
});
|
|
101
|
-
current():
|
|
102
|
-
|
|
103
|
-
sourceRevision: string;
|
|
104
|
-
} | undefined;
|
|
105
|
-
get(artifactDigest: string): Promise<PromptEpochArtifact | undefined>;
|
|
85
|
+
current(): PublishedPromptArtifact | undefined;
|
|
86
|
+
get(artifactDigest: string): Promise<PromptArtifact | undefined>;
|
|
106
87
|
restore(): Promise<void>;
|
|
107
88
|
sourceState(): "active" | "disabled" | "unavailable";
|
|
108
89
|
applySnapshot(raw: unknown): Promise<{
|
|
@@ -110,7 +91,7 @@ export declare class CenterPromptSource implements PromptArtifactSource {
|
|
|
110
91
|
artifactDigest: string;
|
|
111
92
|
} | {
|
|
112
93
|
ok: false;
|
|
113
|
-
code:
|
|
94
|
+
code: ArtifactVerifyCode;
|
|
114
95
|
reason: string;
|
|
115
96
|
}>;
|
|
116
97
|
applyDisabled(sourceRevision: string): Promise<void>;
|
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
import { mkdirSync, promises as fs } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { verifyPromptArtifact
|
|
4
|
-
function
|
|
5
|
-
|
|
3
|
+
import { verifyPromptArtifact } from "./artifact.js";
|
|
4
|
+
function verifiedRead(bytes, artifactDigest) {
|
|
5
|
+
let parsed;
|
|
6
|
+
try {
|
|
7
|
+
parsed = JSON.parse(bytes);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const v = verifyPromptArtifact(parsed);
|
|
13
|
+
return v.ok && v.artifact.artifactDigest === artifactDigest ? v.artifact : undefined;
|
|
6
14
|
}
|
|
7
15
|
export class MemoryPromptArtifactStore {
|
|
8
16
|
byDigest = new Map();
|
|
9
|
-
async get(artifactDigest
|
|
17
|
+
async get(artifactDigest) {
|
|
10
18
|
const bytes = this.byDigest.get(artifactDigest);
|
|
11
|
-
|
|
12
|
-
return undefined;
|
|
13
|
-
let parsed;
|
|
14
|
-
try {
|
|
15
|
-
parsed = JSON.parse(bytes);
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
const v = verifyPromptArtifact(parsed, opts);
|
|
21
|
-
if (!v.ok || v.artifact.artifactDigest !== artifactDigest)
|
|
22
|
-
return undefined;
|
|
23
|
-
return normalizedEnvelope(parsed, v.artifact);
|
|
19
|
+
return bytes === undefined ? undefined : verifiedRead(bytes, artifactDigest);
|
|
24
20
|
}
|
|
25
|
-
async put(
|
|
26
|
-
this.byDigest.set(
|
|
21
|
+
async put(artifact) {
|
|
22
|
+
this.byDigest.set(artifact.artifactDigest, JSON.stringify(artifact));
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
25
|
export class FilePromptArtifactStore {
|
|
@@ -36,7 +32,7 @@ export class FilePromptArtifactStore {
|
|
|
36
32
|
const m = /^sha256:([0-9a-f]{64})$/.exec(artifactDigest);
|
|
37
33
|
return m ? path.join(this.dir, "artifacts", `${m[1]}.json`) : undefined;
|
|
38
34
|
}
|
|
39
|
-
async get(artifactDigest
|
|
35
|
+
async get(artifactDigest) {
|
|
40
36
|
const file = this.fileFor(artifactDigest);
|
|
41
37
|
if (file === undefined)
|
|
42
38
|
return undefined;
|
|
@@ -47,24 +43,14 @@ export class FilePromptArtifactStore {
|
|
|
47
43
|
catch {
|
|
48
44
|
return undefined;
|
|
49
45
|
}
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
parsed = JSON.parse(bytes);
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
const v = verifyPromptArtifact(parsed, opts);
|
|
58
|
-
if (!v.ok || v.artifact.artifactDigest !== artifactDigest)
|
|
59
|
-
return undefined;
|
|
60
|
-
return normalizedEnvelope(parsed, v.artifact);
|
|
46
|
+
return verifiedRead(bytes, artifactDigest);
|
|
61
47
|
}
|
|
62
|
-
async put(
|
|
63
|
-
const file = this.fileFor(
|
|
48
|
+
async put(artifact) {
|
|
49
|
+
const file = this.fileFor(artifact.artifactDigest);
|
|
64
50
|
if (file === undefined)
|
|
65
|
-
throw new Error(`prompt-artifact store: malformed digest ${JSON.stringify(
|
|
51
|
+
throw new Error(`prompt-artifact store: malformed digest ${JSON.stringify(artifact.artifactDigest).slice(0, 120)}`);
|
|
66
52
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
67
|
-
await fs.writeFile(tmp, JSON.stringify(
|
|
53
|
+
await fs.writeFile(tmp, JSON.stringify(artifact), "utf8");
|
|
68
54
|
await fs.rename(tmp, file);
|
|
69
55
|
}
|
|
70
56
|
}
|
|
@@ -113,7 +99,6 @@ export class FilePromptSourceStateStore {
|
|
|
113
99
|
export class CenterPromptSource {
|
|
114
100
|
store;
|
|
115
101
|
stateStore;
|
|
116
|
-
engineVersion;
|
|
117
102
|
candidate;
|
|
118
103
|
state = "unavailable";
|
|
119
104
|
tail = Promise.resolve();
|
|
@@ -125,16 +110,14 @@ export class CenterPromptSource {
|
|
|
125
110
|
constructor(opts) {
|
|
126
111
|
this.store = opts.store;
|
|
127
112
|
this.stateStore = opts.stateStore ?? new MemoryPromptSourceStateStore();
|
|
128
|
-
this.engineVersion = opts.engineVersion;
|
|
129
113
|
}
|
|
130
114
|
current() {
|
|
131
115
|
return this.candidate;
|
|
132
116
|
}
|
|
133
117
|
async get(artifactDigest) {
|
|
134
|
-
if (this.candidate?.
|
|
135
|
-
return this.candidate
|
|
136
|
-
|
|
137
|
-
return env?.artifact;
|
|
118
|
+
if (this.candidate?.artifactDigest === artifactDigest)
|
|
119
|
+
return this.candidate;
|
|
120
|
+
return this.store.get(artifactDigest);
|
|
138
121
|
}
|
|
139
122
|
async restore() {
|
|
140
123
|
return this.exclusive(async () => {
|
|
@@ -149,23 +132,22 @@ export class CenterPromptSource {
|
|
|
149
132
|
this.state = "unavailable";
|
|
150
133
|
return;
|
|
151
134
|
}
|
|
152
|
-
const
|
|
153
|
-
this.candidate =
|
|
154
|
-
this.state =
|
|
135
|
+
const stored = await this.store.get(state.artifactDigest);
|
|
136
|
+
this.candidate = stored !== undefined ? { ...stored, sourceRevision: state.sourceRevision } : undefined;
|
|
137
|
+
this.state = stored !== undefined ? "active" : "unavailable";
|
|
155
138
|
});
|
|
156
139
|
}
|
|
157
140
|
sourceState() {
|
|
158
141
|
return this.state;
|
|
159
142
|
}
|
|
160
143
|
async applySnapshot(raw) {
|
|
161
|
-
const v = verifyPromptArtifact(raw
|
|
144
|
+
const v = verifyPromptArtifact(raw);
|
|
162
145
|
if (!v.ok)
|
|
163
146
|
return v;
|
|
164
|
-
const envelope = raw;
|
|
165
147
|
return this.exclusive(async () => {
|
|
166
|
-
await this.store.put(
|
|
167
|
-
await this.stateStore.save({ state: "active", artifactDigest: v.artifact.artifactDigest, sourceRevision:
|
|
168
|
-
this.candidate =
|
|
148
|
+
await this.store.put(v.artifact);
|
|
149
|
+
await this.stateStore.save({ state: "active", artifactDigest: v.artifact.artifactDigest, sourceRevision: v.artifact.sourceRevision });
|
|
150
|
+
this.candidate = v.artifact;
|
|
169
151
|
this.state = "active";
|
|
170
152
|
return { ok: true, artifactDigest: v.artifact.artifactDigest };
|
|
171
153
|
});
|