@tea-agent/loop-agent 0.40.0-next.9 → 0.41.0-beta.1
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/AGENTS.md +1 -1
- package/CHANGELOG.md +130 -3
- package/README.md +2 -2
- package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
- package/dist/adapters/context-transfer/pi-session.js +61 -0
- package/dist/application/dag/generate-task-dag.js +6 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +21 -5
- package/dist/cli/program.js +61 -4
- package/dist/commands/client-recovery.js +8 -36
- package/dist/commands/dag-artifact.js +284 -0
- package/dist/commands/dag-context.js +184 -0
- package/dist/commands/dag-rerun.js +206 -1
- package/dist/commands/init-model-catalog.js +22 -0
- package/dist/commands/task-advance.js +23 -1
- package/dist/commands/task-source-prepare.js +5 -0
- package/dist/commands/task-status.js +1 -0
- package/dist/executors/dag-pi-executor.js +39 -12
- package/dist/executors/pi-sdk-executor.js +36 -5
- package/dist/executors/shell-executor.js +64 -17
- package/dist/governance/checks.js +1 -0
- package/dist/{worker → infrastructure}/console/app-data.js +4 -0
- package/dist/infrastructure/console/artifact-revision-store.js +430 -0
- package/dist/infrastructure/console/context-export-store.js +160 -0
- package/dist/infrastructure/console/dir-lock.js +132 -0
- package/dist/{worker → infrastructure}/console/operation-store.js +28 -0
- package/dist/infrastructure/harness/artifact-store.js +10 -1
- package/dist/infrastructure/harness/atomic-write.js +12 -2
- package/dist/shared/context-transfer/artifact-revision.js +172 -0
- package/dist/shared/context-transfer.js +418 -0
- package/dist/shared/operator/capabilities.js +23 -1
- package/dist/shared/operator/safe-run-summary.js +1 -0
- package/dist/shared/path-safety.js +93 -0
- package/dist/shared/pi-context-pressure/checkpoint.js +116 -0
- package/dist/shared/pi-context-pressure/compaction-policy.js +151 -0
- package/dist/shared/pi-context-pressure/env.js +58 -0
- package/dist/shared/pi-context-pressure/extension.js +100 -0
- package/dist/shared/pi-context-pressure/index.js +7 -0
- package/dist/shared/pi-context-pressure/overflow.js +252 -0
- package/dist/shared/pi-context-pressure/sift-bridge.js +386 -0
- package/dist/shared/pi-context-pressure/telemetry.js +51 -0
- package/dist/shared/preview.js +28 -4
- package/dist/task/config-types.js +2 -1
- package/dist/task/task-demand-routing.js +3 -0
- package/dist/worker/console/chat/assistant-content.js +7 -0
- package/dist/worker/console/chat/chat-event-store.js +84 -13
- package/dist/worker/console/chat/goal-round-driver.js +72 -0
- package/dist/worker/console/chat/goals.js +300 -0
- package/dist/worker/console/chat/pi-runtime.js +285 -8
- package/dist/worker/console/chat/provider-error.js +2 -1
- package/dist/worker/console/chat/repo-browser.js +94 -12
- package/dist/worker/console/chat/resource-preferences-store.js +1 -1
- package/dist/worker/console/chat/routes.js +487 -30
- package/dist/worker/console/chat/session-catalog.js +48 -0
- package/dist/worker/console/chat/session-stats.js +96 -0
- package/dist/worker/console/chat/session-store.js +28 -19
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/sift-bridge.js +1 -0
- package/dist/worker/console/chat/turn-process.js +32 -3
- package/dist/worker/console/chat/user-questions.js +1 -1
- package/dist/worker/console/console-update-runtime.js +1 -1
- package/dist/worker/console/context-transfer-diagnostics.js +198 -0
- package/dist/worker/console/dag-confirmation.js +1 -1
- package/dist/worker/console/dag-execution-receipt.js +21 -3
- package/dist/worker/console/doctor.js +1 -1
- package/dist/worker/console/draft-store.js +1 -1
- package/dist/worker/console/human-gate-token.js +1 -1
- package/dist/worker/console/index.js +3 -3
- package/dist/worker/console/interview/assessment.js +1 -1
- package/dist/worker/console/interview/session.js +1 -1
- package/dist/worker/console/operation-runner.js +45 -4
- package/dist/worker/console/operation-sse.js +1 -1
- package/dist/worker/console/operation-wait.js +1 -1
- package/dist/worker/console/operator-actions.js +124 -8
- package/dist/worker/console/operator-selection.js +6 -2
- package/dist/worker/console/operator-surface-health.js +1 -1
- package/dist/worker/console/operator-user-error.js +169 -0
- package/dist/worker/console/pi-plugins.catalog.json +73658 -0
- package/dist/worker/console/pi-plugins.js +179 -0
- package/dist/worker/console/routes.js +864 -13
- package/dist/worker/console/security.js +35 -0
- package/dist/worker/console/server.js +177 -44
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bs-CDAXM.js → abnfDiagram-N423BO3Z-DSVcg1YO.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CAkA3We3.js → arc-BtXhIqui.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEmI_zqr.js → architectureDiagram-T3A2C74G-B-nh-ilJ.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-uDHANebE.js → blockDiagram-VBNYF7ZC-BIUSVdZI.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Bv97b4_B.js → c4Diagram-5PPSVZJV-Cmw3L4qM.js} +1 -1
- package/dist/worker/console/static/assets/channel-BhZFNefx.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-shmQKsFz.js → chunk-2GRJ4B5K-CGpMMjGm.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BAraNvcN.js → chunk-2Q5K7J3B-BNBkEpEJ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BirhxUop.js → chunk-5RXB4S5H-ubln3eaU.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C9LgUJpR.js → chunk-5VM5RSS4-_XcBTt1i.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DrU-s-t7.js → chunk-6Q2QTUOP-Ln30Pgrh.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Tx-H_FA2.js → chunk-GF5L2VYU-ESH3lhSx.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BjLtNFrR.js → chunk-JWPE2WC7-DAJt-qXB.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-UNLVwSsy.js → chunk-KBJHAD2P-Cx10LIcH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CBEUX8XD.js → chunk-RYQCIY6F-CENeOxoJ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-WTL7IZOq.js → chunk-XXDRQBXY-DXqK-D38.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Sbv-NJni.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Sbv-NJni.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CkHG6W3s.js → cose-bilkent-JH36ORCC-CE4dmvGY.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BRzFqTaL.js → cynefin-VYW2F7L2-CRacN1zK.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-2_CFp_i7.js → cynefinDiagram-MW4NZA55-Cneukjrt.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJtsmdkE.js → dagre-VZM6K2ZE-DPFboRoL.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DNEFFo6w.js → diagram-7IWD3JNH-DIAQgcOP.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B_IWV7eo.js → diagram-B4RE2ZJO-VrYMKxuy.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DvvRx2dz.js → diagram-LBJQPF4R-CLHvBghn.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CsibsWLg.js → diagram-Q27KOJAE-DVCWBif8.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-les_djBQ.js → diagram-UB23O5K3-BTMmbBzJ.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BEm2n7qJ.js → ebnfDiagram-BXEA7PRR-BUZsKJ56.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BI7vHHVm.js → erDiagram-JOGREHBK-BsBZ5NXC.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CUFCERrB.js → flowDiagram-UKHOOZJN-D7fH_kDa.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-wxyLiGWt.js → ganttDiagram-PKOTCBZU-Bza5OohY.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bt897K8Z.js → gitGraphDiagram-DS77QQ5N-DpkoGR_Y.js} +1 -1
- package/dist/worker/console/static/assets/index-Ius3vxhf.css +1 -0
- package/dist/worker/console/static/assets/index-yASzcbBr.js +451 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DYNx_IPv.js → infoDiagram-6WML65LV-BYm3g6LT.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CzpLNEu6.js → ishikawaDiagram-WSZJBQD7-C2RS_H4v.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-97f9owNU.js → journeyDiagram-NVQOT4AX-B4slKpCo.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BxM9hyBn.js → kanban-definition-27J2QSJJ-B7orRNpI.js} +1 -1
- package/dist/worker/console/static/assets/{linear-ByuxcHvp.js → linear-D1BeBxLQ.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DwPGvpCv.js → mermaid.core-0TtMP8k4.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DCoqG9RT.js → mindmap-definition-FAOFIHXS-XL5EbCtT.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BLSBmBMx.js → pegDiagram-VL7TDLO6-CwF7uas5.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B0t_0oJW.js → pieDiagram-7S7Q4E2Y-A_Jo-72f.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js → quadrantDiagram-CIZ2JOQS-CxOa4gKL.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-B3jRdATC.js → railroadDiagram-AXF67PYL-DoAoswIH.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-cTtXEN.js → requirementDiagram-LRYGKXZP-C1Lc1MlD.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B25igJRE.js → sankeyDiagram-W5VNT64P-DFXOkq0U.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-jW_lM1_D.js → sequenceDiagram-SI44F4Z6-B0ufUCuW.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CrzTgsHE.js → sizeCapture-X5ZJPWSS-iPbW55g3.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B01MvlqE.js → stateDiagram-OKZ733FA-CHiXzEKP.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BtMgzo_H.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-YcF12FiU.js → swimlanes-SLNWSIFB-LyFs7TpX.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cb-OVd9Y.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ClnRcg2s.js → timeline-definition-Z64GVDOM-tNkJnb6z.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B6gr_z-q.js → vennDiagram-T6HMQDX7-DFm7Oo8o.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CvSgguGH.js → wardleyDiagram-T6FBY63Y-tpblTp9i.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-23OtSZCb.js → xychartDiagram-ELKLHX3M-BCDLWR_D.js} +1 -1
- package/dist/worker/console/static/index.html +7 -2
- package/dist/worker/console/static-src/app/useOperatorActions.js +3 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +95 -25
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +35 -1
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +3 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +26 -19
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +0 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +14 -1
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +34 -4
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
- package/dist/worker/console/static-src/operator-chat/workspace-reorder.js +18 -0
- package/dist/worker/console/static-src/shell/console-update-reload.js +25 -0
- package/dist/worker/console/static-src/shell/useWorkspaces.js +150 -34
- package/dist/worker/console/static-src/shell/workspace-route.js +3 -1
- package/dist/worker/console/workspace-context.js +56 -5
- package/dist/worker/console/workspace-registry.js +335 -62
- package/dist/worker/continuation/worker-continuation.js +278 -0
- package/dist/worker/observe/health.js +1 -1
- package/dist/worker/observe/node-transparency.js +572 -0
- package/dist/worker/observe/routes.js +51 -1
- package/dist/worker/observe/static/api.js +69 -5
- package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
- package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
- package/dist/worker/observe/static/inspect-bootstrap.d.ts +8 -0
- package/dist/worker/observe/static/inspect-bootstrap.js +57 -0
- package/dist/worker/observe/static/inspect-workspace.js +54 -10
- package/dist/worker/observe/static/operator-chrome.css +23 -4
- package/dist/worker/observe/static/operator-chrome.js +7 -2
- package/dist/worker/observe/static/state.js +3 -1
- package/dist/worker/observe/static/styles.css +1108 -135
- package/dist/worker/observe/static/views/dag-inspector.js +1257 -59
- package/dist/worker/observe/static/views/dags.js +7 -5
- package/dist/worker/observe/static/views/session-timeline.js +210 -10
- package/dist/worker/outcomes/adapters.js +19 -0
- package/dist/worker/outcomes/types.js +1 -0
- package/dist/worker/pool/attempt-lease.js +97 -66
- package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
- package/dist/worker/pool/reconcile.js +46 -1
- package/dist/worker/pool/run-store.js +2 -0
- package/dist/worker/pool/state-projection.js +2 -0
- package/dist/worker/task-spec/workflow-routing.js +8 -3
- package/dist/workflows/dag/artifact-bindings.js +149 -0
- package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +162 -8
- package/dist/workflows/dag/backend-test-pytest-collection.js +70 -2
- package/dist/workflows/dag/backend-test-result-contract.js +4 -0
- package/dist/workflows/dag/backend-test-scenario-param.js +339 -53
- package/dist/workflows/dag/backend-test-writer-completeness.js +11 -0
- package/dist/workflows/dag/budget-enforcement.js +10 -0
- package/dist/workflows/dag/context-receipt.js +305 -0
- package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
- package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
- package/dist/workflows/dag/context-transfer/renderers.js +93 -0
- package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
- package/dist/workflows/dag/init-hybrid.js +151 -4
- package/dist/workflows/dag/node-execution.js +112 -27
- package/dist/workflows/dag/path-safety.js +1 -0
- package/dist/workflows/dag/prompt.js +29 -4
- package/dist/workflows/dag/rerun-plan.js +555 -1
- package/dist/workflows/dag/rerun-run.js +601 -15
- package/dist/workflows/dag/runner.js +20 -1
- package/dist/workflows/dag/skill-snapshot.js +17 -0
- package/dist/workflows/dag/types.js +183 -7
- package/docs/architecture/runtime-boundaries.md +8 -7
- package/docs/architecture/worker-and-feature.md +1 -1
- package/docs/templates/agent-dag.schema.json +32 -0
- package/docs/templates/backend-test-dag.json +6 -5
- package/docs/templates/init-managed-agents.md +1 -1
- package/docs/templates/product-line/task.yaml +1 -1
- package/package.json +5 -2
- package/skills/loop-agent/references/command-reference.md +21 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +0 -1
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +0 -407
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +0 -8
- /package/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
|
@@ -307,6 +307,19 @@ export async function runDag(spec, opts) {
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
export async function runDagContinuation(opts) {
|
|
310
|
+
assertValidDagSpec(opts.spec);
|
|
311
|
+
assertFrozenBudget(opts.spec.budget, opts.state.budget, opts.state.runId);
|
|
312
|
+
if (opts.spec.budget) {
|
|
313
|
+
const ledger = opts.state.budgetLedger;
|
|
314
|
+
if (!ledger ||
|
|
315
|
+
ledger.mode !== opts.spec.budget.mode ||
|
|
316
|
+
JSON.stringify(ledger.limits) !== JSON.stringify(opts.spec.budget.limits)) {
|
|
317
|
+
throw new Error(`dag continuation ${opts.state.runId} is missing a matching cumulative budget ledger`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const { assertDagSpecAllowsNewWriterExecution, assertTaskContractBindingConsistent, } = await import("./task-contract-binding.js");
|
|
321
|
+
assertDagSpecAllowsNewWriterExecution(opts.spec);
|
|
322
|
+
await assertTaskContractBindingConsistent({ repoRoot: opts.cwd, spec: opts.spec });
|
|
310
323
|
const { maxConcurrent } = resolveEffectiveMaxConcurrent(Math.max(1, opts.maxConcurrent ?? 4), opts.spec.budget);
|
|
311
324
|
const state = opts.state;
|
|
312
325
|
state.status = "running";
|
|
@@ -328,6 +341,7 @@ export async function runDagContinuation(opts) {
|
|
|
328
341
|
cwd: opts.cwd,
|
|
329
342
|
maxConcurrent,
|
|
330
343
|
executeNode: opts.executeNode,
|
|
344
|
+
beforeTerminalArchive: opts.beforeTerminalArchive,
|
|
331
345
|
observer: opts.observer,
|
|
332
346
|
abortSignal: opts.abortSignal,
|
|
333
347
|
activeRunDir,
|
|
@@ -712,6 +726,10 @@ async function executeDagCheckpoint(input) {
|
|
|
712
726
|
}
|
|
713
727
|
await notifyRunObserver(input.observer, "onRunFinish", state);
|
|
714
728
|
if (!recoveryPending) {
|
|
729
|
+
if (input.beforeTerminalArchive) {
|
|
730
|
+
await input.beforeTerminalArchive({ runDir, state });
|
|
731
|
+
await persistState();
|
|
732
|
+
}
|
|
715
733
|
try {
|
|
716
734
|
const terminalCheckpoint = await captureWorkspaceCheckpoint(cwd);
|
|
717
735
|
await writeWorkspaceCheckpoint(runDir, WORKSPACE_CHECKPOINT_TERMINAL_REL, terminalCheckpoint);
|
|
@@ -942,7 +960,8 @@ export async function finalizeTerminalRunStatus(state, taskCount, runDir, cwd) {
|
|
|
942
960
|
// mechanical partial_failed just because prewrite FINISHED while the writer
|
|
943
961
|
// was SKIPPED. Fail closed on retryable-invalid/blocked before aggregation.
|
|
944
962
|
let recoveryPending = false;
|
|
945
|
-
const skipFrontendRecovery = state.failureCategory === "controller-interrupted"
|
|
963
|
+
const skipFrontendRecovery = state.failureCategory === "controller-interrupted" ||
|
|
964
|
+
state.continuation?.writerTransaction !== undefined;
|
|
946
965
|
const hasFrontendWriter = Object.keys(state.nodes).some((id) => FRONTEND_WRITER_NODE_IDS.includes(id));
|
|
947
966
|
if (hasFrontendWriter && !skipFrontendRecovery) {
|
|
948
967
|
const admission = await readFrontendPrewriteResult(runDir);
|
|
@@ -333,11 +333,27 @@ function parseSnapshot(value) {
|
|
|
333
333
|
export async function cloneParentSkillSnapshotForContinuation(input) {
|
|
334
334
|
const parentSnapshot = await readSkillSnapshot(input.parentRunDir, input.parentRef, { expectedRunId: input.parentRunId });
|
|
335
335
|
const parentSnapshotSha256 = hashSkillSnapshot(parentSnapshot);
|
|
336
|
+
const initialTaskIds = input.spec
|
|
337
|
+
? input.spec.tasks.map((task) => task.id)
|
|
338
|
+
: parentSnapshot.initialTaskIds;
|
|
339
|
+
const bindings = input.spec
|
|
340
|
+
? collectDagSkillSnapshotBindings(input.spec, initialTaskIds)
|
|
341
|
+
: parentSnapshot.bindings;
|
|
342
|
+
const boundProfileIds = new Set(bindings.map((binding) => binding.profileId));
|
|
343
|
+
const profiles = parentSnapshot.profiles.filter((profile) => boundProfileIds.has(profile.id));
|
|
344
|
+
for (const profileId of boundProfileIds) {
|
|
345
|
+
if (!profiles.some((profile) => profile.id === profileId)) {
|
|
346
|
+
throw new DagSkillSnapshotIntegrityError(`continuation run spec requires profile missing from parent snapshot: ${profileId}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
336
349
|
const cloned = {
|
|
337
350
|
...structuredClone(parentSnapshot),
|
|
338
351
|
runId: input.newRunId,
|
|
339
352
|
createdAt: (input.now ?? new Date()).toISOString(),
|
|
340
353
|
mode: "continuation-from-parent",
|
|
354
|
+
initialTaskIds,
|
|
355
|
+
bindings,
|
|
356
|
+
profiles,
|
|
341
357
|
};
|
|
342
358
|
const ref = await writeSkillSnapshot(input.newRunDir, cloned);
|
|
343
359
|
await writeJsonAtomic(path.join(input.newRunDir, ...SKILL_SNAPSHOT_CONTINUATION_REL_PATH.split("/")), {
|
|
@@ -540,6 +556,7 @@ export function buildNodePromptFromSnapshot(input) {
|
|
|
540
556
|
spec: input.spec,
|
|
541
557
|
task: input.task,
|
|
542
558
|
upstream: input.upstream,
|
|
559
|
+
runDir: input.runDir,
|
|
543
560
|
resolvedSkills: skillNames,
|
|
544
561
|
resolvedSkillInstructions,
|
|
545
562
|
maxUpstreamChars: policy.resolveMaxUpstreamChars(input.task),
|
|
@@ -80,7 +80,10 @@ export const dagShellVerifyEvidenceSchema = z.object({
|
|
|
80
80
|
selectionReasons: z.array(z.string()).default([]),
|
|
81
81
|
/** Non-executing generation-time cwd/local-script validation evidence. */
|
|
82
82
|
preflight: z
|
|
83
|
-
.array(z.object({
|
|
83
|
+
.array(z.object({
|
|
84
|
+
label: z.string(),
|
|
85
|
+
status: z.enum(["ok", "future-delivery-script"]),
|
|
86
|
+
}))
|
|
84
87
|
.default([]),
|
|
85
88
|
/** Effective timeout applied independently to each shell command. */
|
|
86
89
|
commandTimeoutMs: z.number().int().positive().optional(),
|
|
@@ -734,7 +737,58 @@ export const structuredContractOutputSchemaIds = [
|
|
|
734
737
|
"frontend-implementation-contract-plan-patch-v1",
|
|
735
738
|
"frontend-implementation-contract-revision-patch-v1",
|
|
736
739
|
];
|
|
737
|
-
export const
|
|
740
|
+
export const dagArtifactIdentitySchema = z
|
|
741
|
+
.string()
|
|
742
|
+
.regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/, "artifact id must be stable lower-case dot/kebab syntax");
|
|
743
|
+
const dagArtifactRelativePathSchema = z
|
|
744
|
+
.string()
|
|
745
|
+
.min(1)
|
|
746
|
+
.refine((value) => !value.includes("\0"), "artifact path must not contain NUL")
|
|
747
|
+
.refine((value) => !value.includes("\\"), "artifact path must use POSIX separators")
|
|
748
|
+
.refine((value) => !value.startsWith("/") && !/^[A-Za-z]:/.test(value), "artifact path must be run-relative")
|
|
749
|
+
.refine((value) => value.split("/").every((segment) => segment !== "" && segment !== ".."), "artifact path must not escape the run");
|
|
750
|
+
export const dagProducedArtifactSchema = z
|
|
751
|
+
.object({
|
|
752
|
+
artifactId: dagArtifactIdentitySchema,
|
|
753
|
+
kind: z.enum(["structured", "assistant", "stdout"]),
|
|
754
|
+
path: dagArtifactRelativePathSchema,
|
|
755
|
+
mediaType: z.string().min(1),
|
|
756
|
+
schemaId: z.string().min(1).optional(),
|
|
757
|
+
revisionPolicy: z.enum(["immutable", "replace-file"]),
|
|
758
|
+
})
|
|
759
|
+
.strict()
|
|
760
|
+
.superRefine((value, ctx) => {
|
|
761
|
+
if (value.kind === "structured" && !value.schemaId) {
|
|
762
|
+
ctx.addIssue({
|
|
763
|
+
code: z.ZodIssueCode.custom,
|
|
764
|
+
path: ["schemaId"],
|
|
765
|
+
message: "structured artifact requires schemaId",
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
if (value.kind !== "structured" && value.schemaId) {
|
|
769
|
+
ctx.addIssue({
|
|
770
|
+
code: z.ZodIssueCode.custom,
|
|
771
|
+
path: ["schemaId"],
|
|
772
|
+
message: "only structured artifacts may declare schemaId",
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
if (value.revisionPolicy === "replace-file" &&
|
|
776
|
+
value.kind !== "structured") {
|
|
777
|
+
ctx.addIssue({
|
|
778
|
+
code: z.ZodIssueCode.custom,
|
|
779
|
+
path: ["revisionPolicy"],
|
|
780
|
+
message: "MVP revisions are limited to structured artifacts",
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
export const dagConsumedArtifactSchema = z
|
|
785
|
+
.object({
|
|
786
|
+
artifactId: dagArtifactIdentitySchema,
|
|
787
|
+
required: z.boolean().default(true),
|
|
788
|
+
})
|
|
789
|
+
.strict();
|
|
790
|
+
export const dagTaskSchema = z.object({
|
|
791
|
+
id: z.string().regex(/^[a-z][a-z0-9-]*$/, "task id must be kebab-case"),
|
|
738
792
|
depends_on: z.array(z.string()).default([]),
|
|
739
793
|
/**
|
|
740
794
|
* How SKIPPED upstreams affect readiness.
|
|
@@ -797,6 +851,15 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
|
|
|
797
851
|
shell: dagShellConfigSchema.optional(),
|
|
798
852
|
static: dagStaticConfigSchema.optional(),
|
|
799
853
|
outputContract: z.string().optional(),
|
|
854
|
+
/**
|
|
855
|
+
* Frozen producer declarations for run-owned artifacts. These declarations,
|
|
856
|
+
* together with consumesArtifacts, are the only authority for artifact
|
|
857
|
+
* lineage and impact analysis. Prompt/outputContract/path heuristics are
|
|
858
|
+
* intentionally forbidden.
|
|
859
|
+
*/
|
|
860
|
+
producesArtifacts: z.array(dagProducedArtifactSchema).optional(),
|
|
861
|
+
/** Frozen logical artifact inputs consumed by this node. */
|
|
862
|
+
consumesArtifacts: z.array(dagConsumedArtifactSchema).optional(),
|
|
800
863
|
outputMode: dagOutputModeSchema.optional(),
|
|
801
864
|
firstProtocolLine: z.string().min(1).optional(),
|
|
802
865
|
/**
|
|
@@ -825,8 +888,7 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
|
|
|
825
888
|
})
|
|
826
889
|
.strict()
|
|
827
890
|
.superRefine((value, ctx) => {
|
|
828
|
-
if (value.schemaId ===
|
|
829
|
-
"frontend-implementation-contract-plan-patch-v1" &&
|
|
891
|
+
if (value.schemaId === "frontend-implementation-contract-plan-patch-v1" &&
|
|
830
892
|
!value.skeleton) {
|
|
831
893
|
ctx.addIssue({
|
|
832
894
|
code: "custom",
|
|
@@ -881,6 +943,121 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
|
|
|
881
943
|
dynamicCondition: dagDynamicConditionSchema.optional(),
|
|
882
944
|
dynamicLoopUntil: dagDynamicLoopUntilSchema.optional(),
|
|
883
945
|
});
|
|
946
|
+
function hasTransitiveDependency(tasksById, consumerNodeId, producerNodeId) {
|
|
947
|
+
const queue = [...(tasksById.get(consumerNodeId)?.depends_on ?? [])];
|
|
948
|
+
const seen = new Set();
|
|
949
|
+
while (queue.length > 0) {
|
|
950
|
+
const nodeId = queue.shift();
|
|
951
|
+
if (nodeId === producerNodeId)
|
|
952
|
+
return true;
|
|
953
|
+
if (seen.has(nodeId))
|
|
954
|
+
continue;
|
|
955
|
+
seen.add(nodeId);
|
|
956
|
+
queue.push(...(tasksById.get(nodeId)?.depends_on ?? []));
|
|
957
|
+
}
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
function validateFrozenArtifactBindings(tasks, ctx) {
|
|
961
|
+
const tasksById = new Map(tasks.map((task) => [task.id, task]));
|
|
962
|
+
const producers = new Map();
|
|
963
|
+
const paths = new Map();
|
|
964
|
+
for (const [taskIndex, task] of tasks.entries()) {
|
|
965
|
+
const localIds = new Set();
|
|
966
|
+
for (const [artifactIndex, artifact] of (task.producesArtifacts ?? []).entries()) {
|
|
967
|
+
if (localIds.has(artifact.artifactId) ||
|
|
968
|
+
producers.has(artifact.artifactId)) {
|
|
969
|
+
ctx.addIssue({
|
|
970
|
+
code: z.ZodIssueCode.custom,
|
|
971
|
+
path: [
|
|
972
|
+
"tasks",
|
|
973
|
+
taskIndex,
|
|
974
|
+
"producesArtifacts",
|
|
975
|
+
artifactIndex,
|
|
976
|
+
"artifactId",
|
|
977
|
+
],
|
|
978
|
+
message: `artifact ${artifact.artifactId} must have exactly one producer`,
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
producers.set(artifact.artifactId, {
|
|
983
|
+
nodeId: task.id,
|
|
984
|
+
taskIndex,
|
|
985
|
+
artifactIndex,
|
|
986
|
+
path: artifact.path,
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
localIds.add(artifact.artifactId);
|
|
990
|
+
const foldedPath = artifact.path
|
|
991
|
+
.normalize("NFC")
|
|
992
|
+
.toLocaleLowerCase("en-US");
|
|
993
|
+
const existingArtifactId = paths.get(foldedPath);
|
|
994
|
+
if (existingArtifactId && existingArtifactId !== artifact.artifactId) {
|
|
995
|
+
ctx.addIssue({
|
|
996
|
+
code: z.ZodIssueCode.custom,
|
|
997
|
+
path: [
|
|
998
|
+
"tasks",
|
|
999
|
+
taskIndex,
|
|
1000
|
+
"producesArtifacts",
|
|
1001
|
+
artifactIndex,
|
|
1002
|
+
"path",
|
|
1003
|
+
],
|
|
1004
|
+
message: `artifact path collides with ${existingArtifactId} under case folding`,
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
else {
|
|
1008
|
+
paths.set(foldedPath, artifact.artifactId);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
for (const [taskIndex, task] of tasks.entries()) {
|
|
1013
|
+
const consumed = new Set();
|
|
1014
|
+
for (const [artifactIndex, binding] of (task.consumesArtifacts ?? []).entries()) {
|
|
1015
|
+
if (consumed.has(binding.artifactId)) {
|
|
1016
|
+
ctx.addIssue({
|
|
1017
|
+
code: z.ZodIssueCode.custom,
|
|
1018
|
+
path: [
|
|
1019
|
+
"tasks",
|
|
1020
|
+
taskIndex,
|
|
1021
|
+
"consumesArtifacts",
|
|
1022
|
+
artifactIndex,
|
|
1023
|
+
"artifactId",
|
|
1024
|
+
],
|
|
1025
|
+
message: `artifact ${binding.artifactId} is consumed more than once by ${task.id}`,
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
consumed.add(binding.artifactId);
|
|
1029
|
+
const producer = producers.get(binding.artifactId);
|
|
1030
|
+
if (!producer) {
|
|
1031
|
+
ctx.addIssue({
|
|
1032
|
+
code: z.ZodIssueCode.custom,
|
|
1033
|
+
path: [
|
|
1034
|
+
"tasks",
|
|
1035
|
+
taskIndex,
|
|
1036
|
+
"consumesArtifacts",
|
|
1037
|
+
artifactIndex,
|
|
1038
|
+
"artifactId",
|
|
1039
|
+
],
|
|
1040
|
+
message: `artifact ${binding.artifactId} has no declared producer`,
|
|
1041
|
+
});
|
|
1042
|
+
continue;
|
|
1043
|
+
}
|
|
1044
|
+
if (producer.nodeId === task.id ||
|
|
1045
|
+
!hasTransitiveDependency(tasksById, task.id, producer.nodeId)) {
|
|
1046
|
+
ctx.addIssue({
|
|
1047
|
+
code: z.ZodIssueCode.custom,
|
|
1048
|
+
path: [
|
|
1049
|
+
"tasks",
|
|
1050
|
+
taskIndex,
|
|
1051
|
+
"consumesArtifacts",
|
|
1052
|
+
artifactIndex,
|
|
1053
|
+
"artifactId",
|
|
1054
|
+
],
|
|
1055
|
+
message: `consumer ${task.id} must be downstream of producer ${producer.nodeId}`,
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
884
1061
|
export const dagModelsSchema = z
|
|
885
1062
|
.object({
|
|
886
1063
|
HIGH: z.string().optional(),
|
|
@@ -910,9 +1087,7 @@ export const dagBudgetSchema = campaignBudgetSchema;
|
|
|
910
1087
|
export const dagSourceBindingSourceSchema = z.object({
|
|
911
1088
|
kind: z.enum(["requirement", "constraint", "reference"]),
|
|
912
1089
|
path: z.string().min(1),
|
|
913
|
-
sha256: z
|
|
914
|
-
.string()
|
|
915
|
-
.regex(/^[a-f0-9]{64}$/, "sha256 must be lowercase hex"),
|
|
1090
|
+
sha256: z.string().regex(/^[a-f0-9]{64}$/, "sha256 must be lowercase hex"),
|
|
916
1091
|
});
|
|
917
1092
|
/**
|
|
918
1093
|
* DagSourceBinding v1:无 ledger 字段(schemaVersion=1,.strict() 拒绝 ledger
|
|
@@ -1063,6 +1238,7 @@ export const dagSpecSchema = z
|
|
|
1063
1238
|
})
|
|
1064
1239
|
.superRefine((spec, ctx) => {
|
|
1065
1240
|
const supportsV3Fields = spec.version === 3 || spec.version === 4;
|
|
1241
|
+
validateFrozenArtifactBindings(spec.tasks, ctx);
|
|
1066
1242
|
if (spec.evaluation && !supportsV3Fields) {
|
|
1067
1243
|
ctx.addIssue({
|
|
1068
1244
|
code: z.ZodIssueCode.custom,
|
|
@@ -160,18 +160,18 @@ Runner / Loop ──(迁移中)──> 逐步改为仅经 Store / Appli
|
|
|
160
160
|
|
|
161
161
|
| From | May import | Must not import |
|
|
162
162
|
| ------ | ------------ | ----------------- |
|
|
163
|
-
| `src/commands/**` | application, workflows, infrastructure, task, records, executors, shared |
|
|
164
|
-
| `src/workflows/**` | executors, task, records, shared, application(目标) | `src/commands/**` |
|
|
163
|
+
| `src/commands/**` | application, workflows, infrastructure, task, records, executors, shared | `src/worker/**` |
|
|
164
|
+
| `src/workflows/**` | executors, task, records, shared, infrastructure, application(目标) | `src/commands/**` |
|
|
165
165
|
| `src/executors/**` | shared, 外部 SDK | `src/commands/**`, `src/cli/**` |
|
|
166
|
-
| `src/worker/**` | worker-local modules, task contracts, shared, Node APIs | `src/commands/**`, `src/cli/**`, `src/application/**` |
|
|
167
|
-
| `src/cli/**` | commands, adapters, shared, application(目标) | — |
|
|
166
|
+
| `src/worker/**` | worker-local modules, task contracts, shared, infrastructure, Node APIs | `src/commands/**`, `src/cli/**`, `src/application/**` |
|
|
167
|
+
| `src/cli/**` | commands, adapters, shared, infrastructure, application(目标) | — |
|
|
168
168
|
| `.agents/skills/**` | (Markdown 引用,非 TS import) | 运行时 TS 模块 |
|
|
169
169
|
|
|
170
170
|
## 已知过渡耦合
|
|
171
171
|
|
|
172
|
-
当前没有允许的 `src/workflows/**` / `src/executors/**` forbidden import,也没有允许的 `src/worker/**` → `src/{cli,commands,application}/**` TypeScript import。
|
|
172
|
+
当前没有允许的 `src/workflows/**` / `src/executors/**` forbidden import,也没有允许的 `src/worker/**` → `src/{cli,commands,application}/**` 或 `src/commands/**` → `src/worker/**` TypeScript import。Console app-data 存储(operations、context exports、artifact revisions、app-data path helpers)位于 `src/infrastructure/console/**`,由 Console(worker 层)与 CLI 命令共同向下依赖;Console 专属的 route/action 编排仍留在 `src/worker/console/**`。
|
|
173
173
|
|
|
174
|
-
`scripts/check-architecture-boundaries.sh` 的 transitional allowlist 保持为空。任何新增的 `workflows/executors/worker` forbidden import 必须导致检查 **exit 1**;如果未来确有临时例外,必须先写入 active exec plan,说明移除时间和验证门禁。
|
|
174
|
+
`scripts/check-architecture-boundaries.sh` 的 transitional allowlist 保持为空。任何新增的 `workflows/executors/worker/commands` forbidden import 必须导致检查 **exit 1**;如果未来确有临时例外,必须先写入 active exec plan,说明移除时间和验证门禁。
|
|
175
175
|
|
|
176
176
|
## Governance 钩子
|
|
177
177
|
|
|
@@ -207,7 +207,8 @@ Runtime 变更另需 `npm run typecheck` 及对应 targeted Vitest(见 exec pl
|
|
|
207
207
|
| --- | --- | --- |
|
|
208
208
|
| OpenCode transient-retry | `.opencode/plugins/loop-agent-transient-retry.js`(init surface `generated`) | 仅瞬态 UnknownError resume;busy/retry 门控 + backoff;overflow/401/配额/取消/业务标 permanent(`plugin-ignore-permanent-error`),**不** compact |
|
|
209
209
|
| OpenCode overflow-compact | `.opencode/plugins/loop-agent-context-overflow-compact.js`(init surface `generated`) | 仅 context overflow → `session.compact`(无则 `summarize`)+ 有限 `promptAsync` 续接;`MAX_OVERFLOW_RECOVERIES ≤ 2`;session 锁;非 overflow 不动作 |
|
|
210
|
-
| Pi project extension | `.pi/extensions/loop-agent-context-overflow.js`(init surface `generated`) | `message_end` 上将 overflow `errorMessage` 幂等改写为 `context_length_exceeded:` 前缀,触发 Pi 原生 compact/retry
|
|
210
|
+
| Pi project extension | `.pi/extensions/loop-agent-context-overflow.js`(init surface `generated`) | `message_end` 上将 overflow `errorMessage` 幂等改写为 `context_length_exceeded:` 前缀,触发 Pi 原生 compact/retry;分类器与控制器共享 P1–P10 / N1–N5 语料(含嵌套 JSON);**不**写 `~/.pi` settings / compaction / 模型窗口,**不**投影 sift native |
|
|
211
|
+
| Console / DAG 运行时 | npm 内置 inline extension + 可选 `@agent-context/sift` | 默认开启 L0/L1/L2;`HARNESS_CONTEXT_PRESSURE_MODE=off` 关 L0/L2;`HARNESS_CONSOLE_SIFT` / `HARNESS_DAG_SIFT` 的 `0\|false\|off` 关 L1。DAG 不做 streaming 主动 compact。不进入目标项目 init 文件 |
|
|
211
212
|
| Pi 用户配置 | `~/.pi/agent/settings.json` | **不**进入项目 `.harness/init-surface.json` hash;仅 `--client-recovery=user` 可字段级补缺并原子写;`auto`/`project`/`off` 与 `check-update` 默认零写 home;读取时只有 `ENOENT` 视为缺文件,其他 I/O 错误 fail closed |
|
|
212
213
|
| CLI mode | `--client-recovery=auto\|project\|user\|off`(默认 `auto`) | `auto`/`project` 安装上述三份项目产物;`user` = 三产物 + 显式 Pi retry 合并;`off` 全跳过 |
|
|
213
214
|
| Ownership | recorded sha256 + apply-safe | 三份 generated 缺失可补、与 recorded hash 一致可升级;用户改过 → model merge / human decision,禁止静默覆盖 |
|
|
@@ -61,7 +61,7 @@ controller identity 与 DAG skill snapshot 是两个不同冻结层(前者跨
|
|
|
61
61
|
|
|
62
62
|
- schema/validate:`src/worker/task-spec/{schema,validate}.ts`。
|
|
63
63
|
- 校验验收条件、依赖、验证命令;`agent-worker task validate-feature` 等用之。
|
|
64
|
-
- **0.16.0+**:可选 `execution.workflow` 映射到 loop-agent `taskKind
|
|
64
|
+
- **0.16.0+**:可选 `execution.workflow` 映射到 loop-agent `taskKind`(agent-dag / frontend-implementation / backend-test-analysis / backend-test / frontend-test);`backend-test-analysis` 只读生成严格 analysis artifact,不执行测试;typed Task Outcome 与 artifact-aware Ready 门禁见 completed `2026-07-19-taskspec-workflow-routing.md`。
|
|
65
65
|
- 文档映射镜像:`docs/architecture/taskspec-to-loop-agent-mapping.md`(runtime 真源仍在 `src/worker/` 与 materialize 路径)。
|
|
66
66
|
|
|
67
67
|
### Task Pool
|
|
@@ -483,6 +483,28 @@
|
|
|
483
483
|
"sha256": { "type": "string", "minLength": 1 }
|
|
484
484
|
}
|
|
485
485
|
},
|
|
486
|
+
"producedArtifact": {
|
|
487
|
+
"type": "object",
|
|
488
|
+
"additionalProperties": false,
|
|
489
|
+
"required": ["artifactId", "kind", "path", "mediaType", "revisionPolicy"],
|
|
490
|
+
"properties": {
|
|
491
|
+
"artifactId": { "type": "string", "pattern": "^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$" },
|
|
492
|
+
"kind": { "enum": ["structured", "assistant", "stdout"] },
|
|
493
|
+
"path": { "type": "string", "pattern": "^(?!/)(?![A-Za-z]:)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$" },
|
|
494
|
+
"mediaType": { "type": "string", "minLength": 1 },
|
|
495
|
+
"schemaId": { "type": "string", "minLength": 1 },
|
|
496
|
+
"revisionPolicy": { "enum": ["immutable", "replace-file"] }
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
"consumedArtifact": {
|
|
500
|
+
"type": "object",
|
|
501
|
+
"additionalProperties": false,
|
|
502
|
+
"required": ["artifactId"],
|
|
503
|
+
"properties": {
|
|
504
|
+
"artifactId": { "type": "string", "pattern": "^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$" },
|
|
505
|
+
"required": { "type": "boolean", "default": true }
|
|
506
|
+
}
|
|
507
|
+
},
|
|
486
508
|
"task": {
|
|
487
509
|
"type": "object",
|
|
488
510
|
"additionalProperties": false,
|
|
@@ -570,6 +592,16 @@
|
|
|
570
592
|
"type": "string",
|
|
571
593
|
"minLength": 1
|
|
572
594
|
},
|
|
595
|
+
"producesArtifacts": {
|
|
596
|
+
"type": "array",
|
|
597
|
+
"items": { "$ref": "#/$defs/producedArtifact" },
|
|
598
|
+
"description": "Frozen producer declarations. Artifact lineage and impact analysis must use these declarations, never prompt/outputContract/path heuristics."
|
|
599
|
+
},
|
|
600
|
+
"consumesArtifacts": {
|
|
601
|
+
"type": "array",
|
|
602
|
+
"items": { "$ref": "#/$defs/consumedArtifact" },
|
|
603
|
+
"description": "Frozen logical artifact inputs consumed by this node."
|
|
604
|
+
},
|
|
573
605
|
"outputMode": {
|
|
574
606
|
"enum": ["default", "structured-required"],
|
|
575
607
|
"description": "Optional output semantics for Pi nodes. structured-required means oversized assistant output must not be accepted as a truncated success; eligible read-only nodes may compact-retry and downstream gates should rely on canonical structured artifacts."
|