@cleocode/core 2026.6.12 → 2026.6.13
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/dist/conduit/local-transport.d.ts +12 -0
- package/dist/conduit/local-transport.d.ts.map +1 -1
- package/dist/conduit/local-transport.js +53 -23
- package/dist/conduit/local-transport.js.map +1 -1
- package/dist/crypto/credentials.d.ts +37 -0
- package/dist/crypto/credentials.d.ts.map +1 -1
- package/dist/crypto/credentials.js +110 -0
- package/dist/crypto/credentials.js.map +1 -1
- package/dist/dispatch/contracts/derive-output-contract.d.ts +86 -0
- package/dist/dispatch/contracts/derive-output-contract.d.ts.map +1 -0
- package/dist/dispatch/contracts/derive-output-contract.js +347 -0
- package/dist/dispatch/contracts/derive-output-contract.js.map +1 -0
- package/dist/dispatch/contracts/ensures-schema.d.ts +77 -0
- package/dist/dispatch/contracts/ensures-schema.d.ts.map +1 -0
- package/dist/dispatch/contracts/ensures-schema.js +91 -0
- package/dist/dispatch/contracts/ensures-schema.js.map +1 -0
- package/dist/dispatch/contracts/output-contracts.d.ts +27 -5
- package/dist/dispatch/contracts/output-contracts.d.ts.map +1 -1
- package/dist/dispatch/contracts/output-contracts.js +29 -6
- package/dist/dispatch/contracts/output-contracts.js.map +1 -1
- package/dist/docs/export-document.js +2294 -1250
- package/dist/docs/export-document.js.map +3 -3
- package/dist/go/driver.d.ts +132 -7
- package/dist/go/driver.d.ts.map +1 -1
- package/dist/go/driver.js +135 -10
- package/dist/go/driver.js.map +1 -1
- package/dist/go/index.d.ts +1 -1
- package/dist/go/index.d.ts.map +1 -1
- package/dist/go/index.js +1 -1
- package/dist/go/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +13 -10
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +11 -11
- package/dist/internal.js.map +1 -1
- package/dist/lifecycle/engine-ops.d.ts.map +1 -1
- package/dist/lifecycle/engine-ops.js +7 -4
- package/dist/lifecycle/engine-ops.js.map +1 -1
- package/dist/lifecycle/ivtr-loop.d.ts +108 -183
- package/dist/lifecycle/ivtr-loop.d.ts.map +1 -1
- package/dist/lifecycle/ivtr-loop.js +207 -522
- package/dist/lifecycle/ivtr-loop.js.map +1 -1
- package/dist/llm/auxiliary-fallback.js +1 -1
- package/dist/llm/auxiliary-fallback.js.map +1 -1
- package/dist/llm/cli-ops.d.ts +14 -1
- package/dist/llm/cli-ops.d.ts.map +1 -1
- package/dist/llm/cli-ops.js +41 -12
- package/dist/llm/cli-ops.js.map +1 -1
- package/dist/llm/concrete-session.d.ts.map +1 -1
- package/dist/llm/concrete-session.js +4 -0
- package/dist/llm/concrete-session.js.map +1 -1
- package/dist/llm/credentials.d.ts +35 -0
- package/dist/llm/credentials.d.ts.map +1 -1
- package/dist/llm/credentials.js +49 -0
- package/dist/llm/credentials.js.map +1 -1
- package/dist/llm/index.d.ts +4 -0
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +4 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/pi/gondolin-loader.d.ts +241 -0
- package/dist/llm/pi/gondolin-loader.d.ts.map +1 -0
- package/dist/llm/pi/gondolin-loader.js +195 -0
- package/dist/llm/pi/gondolin-loader.js.map +1 -0
- package/dist/llm/pi/index.d.ts +28 -0
- package/dist/llm/pi/index.d.ts.map +1 -0
- package/dist/llm/pi/index.js +27 -0
- package/dist/llm/pi/index.js.map +1 -0
- package/dist/llm/pi/pi-agent-adapter.d.ts +135 -0
- package/dist/llm/pi/pi-agent-adapter.d.ts.map +1 -0
- package/dist/llm/pi/pi-agent-adapter.js +329 -0
- package/dist/llm/pi/pi-agent-adapter.js.map +1 -0
- package/dist/llm/pi/pi-errors.d.ts +161 -0
- package/dist/llm/pi/pi-errors.d.ts.map +1 -0
- package/dist/llm/pi/pi-errors.js +296 -0
- package/dist/llm/pi/pi-errors.js.map +1 -0
- package/dist/llm/pi/pi-execution-env.d.ts +286 -0
- package/dist/llm/pi/pi-execution-env.d.ts.map +1 -0
- package/dist/llm/pi/pi-execution-env.js +406 -0
- package/dist/llm/pi/pi-execution-env.js.map +1 -0
- package/dist/llm/pi/pi-gondolin-env.d.ts +227 -0
- package/dist/llm/pi/pi-gondolin-env.d.ts.map +1 -0
- package/dist/llm/pi/pi-gondolin-env.js +541 -0
- package/dist/llm/pi/pi-gondolin-env.js.map +1 -0
- package/dist/llm/pi/pi-session-storage.d.ts +154 -0
- package/dist/llm/pi/pi-session-storage.d.ts.map +1 -0
- package/dist/llm/pi/pi-session-storage.js +314 -0
- package/dist/llm/pi/pi-session-storage.js.map +1 -0
- package/dist/llm/pi/pi-stream-fn.d.ts +124 -0
- package/dist/llm/pi/pi-stream-fn.d.ts.map +1 -0
- package/dist/llm/pi/pi-stream-fn.js +504 -0
- package/dist/llm/pi/pi-stream-fn.js.map +1 -0
- package/dist/llm/pi/pi-tool-bridge.d.ts +99 -0
- package/dist/llm/pi/pi-tool-bridge.d.ts.map +1 -0
- package/dist/llm/pi/pi-tool-bridge.js +117 -0
- package/dist/llm/pi/pi-tool-bridge.js.map +1 -0
- package/dist/llm/pi/pi-types.d.ts +56 -0
- package/dist/llm/pi/pi-types.d.ts.map +1 -0
- package/dist/llm/pi/pi-types.js +16 -0
- package/dist/llm/pi/pi-types.js.map +1 -0
- package/dist/llm/pi/resolve-execution-env.d.ts +194 -0
- package/dist/llm/pi/resolve-execution-env.d.ts.map +1 -0
- package/dist/llm/pi/resolve-execution-env.js +132 -0
- package/dist/llm/pi/resolve-execution-env.js.map +1 -0
- package/dist/llm/plugin-facade.js +2253 -1151
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/llm/role-executor.d.ts.map +1 -1
- package/dist/llm/role-executor.js +8 -5
- package/dist/llm/role-executor.js.map +1 -1
- package/dist/llm/role-resolver.d.ts +46 -14
- package/dist/llm/role-resolver.d.ts.map +1 -1
- package/dist/llm/role-resolver.js +178 -20
- package/dist/llm/role-resolver.js.map +1 -1
- package/dist/llm/sealed-credential.d.ts +125 -0
- package/dist/llm/sealed-credential.d.ts.map +1 -0
- package/dist/llm/sealed-credential.js +133 -0
- package/dist/llm/sealed-credential.js.map +1 -0
- package/dist/llm/session-factory.d.ts.map +1 -1
- package/dist/llm/session-factory.js +6 -2
- package/dist/llm/session-factory.js.map +1 -1
- package/dist/llm/system-key.d.ts +67 -0
- package/dist/llm/system-key.d.ts.map +1 -0
- package/dist/llm/system-key.js +87 -0
- package/dist/llm/system-key.js.map +1 -0
- package/dist/llm/system-of-use-registry.d.ts +119 -0
- package/dist/llm/system-of-use-registry.d.ts.map +1 -0
- package/dist/llm/system-of-use-registry.js +200 -0
- package/dist/llm/system-of-use-registry.js.map +1 -0
- package/dist/llm/system-resolver.d.ts +32 -10
- package/dist/llm/system-resolver.d.ts.map +1 -1
- package/dist/llm/system-resolver.js +70 -18
- package/dist/llm/system-resolver.js.map +1 -1
- package/dist/memory/brain-writer-thread.d.ts.map +1 -1
- package/dist/memory/brain-writer-thread.js +116 -11
- package/dist/memory/brain-writer-thread.js.map +1 -1
- package/dist/memory/claude-mem-migration.d.ts.map +1 -1
- package/dist/memory/claude-mem-migration.js +21 -0
- package/dist/memory/claude-mem-migration.js.map +1 -1
- package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
- package/dist/memory/graph-memory-bridge.js +32 -25
- package/dist/memory/graph-memory-bridge.js.map +1 -1
- package/dist/memory/llm-backend-resolver.js +23 -5
- package/dist/memory/llm-backend-resolver.js.map +1 -1
- package/dist/nexus/migrations/M-split-graph.d.ts.map +1 -1
- package/dist/nexus/migrations/M-split-graph.js +60 -53
- package/dist/nexus/migrations/M-split-graph.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +20 -2
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/release/engine-ops.js +2 -2
- package/dist/release/engine-ops.js.map +1 -1
- package/dist/routing/capability-matrix.d.ts.map +1 -1
- package/dist/routing/capability-matrix.js +0 -57
- package/dist/routing/capability-matrix.js.map +1 -1
- package/dist/selfimprove/budget.d.ts +206 -0
- package/dist/selfimprove/budget.d.ts.map +1 -0
- package/dist/selfimprove/budget.js +203 -0
- package/dist/selfimprove/budget.js.map +1 -0
- package/dist/selfimprove/dhq-adapter.d.ts +105 -0
- package/dist/selfimprove/dhq-adapter.d.ts.map +1 -0
- package/dist/selfimprove/dhq-adapter.js +95 -0
- package/dist/selfimprove/dhq-adapter.js.map +1 -0
- package/dist/selfimprove/draft-pr.d.ts +129 -0
- package/dist/selfimprove/draft-pr.d.ts.map +1 -0
- package/dist/selfimprove/draft-pr.js +158 -0
- package/dist/selfimprove/draft-pr.js.map +1 -0
- package/dist/selfimprove/envelope-diff.d.ts +162 -0
- package/dist/selfimprove/envelope-diff.d.ts.map +1 -0
- package/dist/selfimprove/envelope-diff.js +321 -0
- package/dist/selfimprove/envelope-diff.js.map +1 -0
- package/dist/selfimprove/replay.d.ts +121 -0
- package/dist/selfimprove/replay.d.ts.map +1 -0
- package/dist/selfimprove/replay.js +109 -0
- package/dist/selfimprove/replay.js.map +1 -0
- package/dist/selfimprove/run-loop.d.ts +148 -0
- package/dist/selfimprove/run-loop.d.ts.map +1 -0
- package/dist/selfimprove/run-loop.js +240 -0
- package/dist/selfimprove/run-loop.js.map +1 -0
- package/dist/selfimprove/scenario.d.ts +145 -0
- package/dist/selfimprove/scenario.d.ts.map +1 -0
- package/dist/selfimprove/scenario.js +243 -0
- package/dist/selfimprove/scenario.js.map +1 -0
- package/dist/sentient/daemon-entry.js +5 -0
- package/dist/sentient/daemon-entry.js.map +1 -1
- package/dist/sentient/daemon.d.ts.map +1 -1
- package/dist/sentient/daemon.js +19 -0
- package/dist/sentient/daemon.js.map +1 -1
- package/dist/sentient/hygiene-scan.d.ts.map +1 -1
- package/dist/sentient/hygiene-scan.js +14 -6
- package/dist/sentient/hygiene-scan.js.map +1 -1
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +13 -9
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/connection-session-handle.d.ts +161 -0
- package/dist/sessions/connection-session-handle.d.ts.map +1 -0
- package/dist/sessions/connection-session-handle.js +168 -0
- package/dist/sessions/connection-session-handle.js.map +1 -0
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/handoff.js +9 -0
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/sessions/index.d.ts +4 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +31 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/session-id.d.ts +34 -0
- package/dist/sessions/session-id.d.ts.map +1 -1
- package/dist/sessions/session-id.js +37 -0
- package/dist/sessions/session-id.js.map +1 -1
- package/dist/sessions/session-manifest-mirror.d.ts +115 -0
- package/dist/sessions/session-manifest-mirror.d.ts.map +1 -0
- package/dist/sessions/session-manifest-mirror.js +250 -0
- package/dist/sessions/session-manifest-mirror.js.map +1 -0
- package/dist/sessions/session-switch.d.ts.map +1 -1
- package/dist/sessions/session-switch.js +5 -2
- package/dist/sessions/session-switch.js.map +1 -1
- package/dist/store/converters.d.ts.map +1 -1
- package/dist/store/converters.js +2 -0
- package/dist/store/converters.js.map +1 -1
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +2 -0
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +87 -47
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/pi-session-store.d.ts +151 -0
- package/dist/store/pi-session-store.d.ts.map +1 -0
- package/dist/store/pi-session-store.js +166 -0
- package/dist/store/pi-session-store.js.map +1 -0
- package/dist/store/safety-data-accessor.d.ts +1 -0
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +5 -0
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/schema/cleo-global/accounts.d.ts +357 -0
- package/dist/store/schema/cleo-global/accounts.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/accounts.js +136 -0
- package/dist/store/schema/cleo-global/accounts.js.map +1 -0
- package/dist/store/schema/cleo-global/index.d.ts +2 -0
- package/dist/store/schema/cleo-global/index.d.ts.map +1 -1
- package/dist/store/schema/cleo-global/index.js +2 -0
- package/dist/store/schema/cleo-global/index.js.map +1 -1
- package/dist/store/schema/cleo-global/session-manifest.d.ts +217 -0
- package/dist/store/schema/cleo-global/session-manifest.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/session-manifest.js +99 -0
- package/dist/store/schema/cleo-global/session-manifest.js.map +1 -0
- package/dist/store/schema/cleo-project/tasks-core.d.ts +16 -0
- package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.js +14 -0
- package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
- package/dist/store/schema/tasks.d.ts +16 -0
- package/dist/store/schema/tasks.d.ts.map +1 -1
- package/dist/store/schema/tasks.js +10 -0
- package/dist/store/schema/tasks.js.map +1 -1
- package/dist/store/selfimprove-dhq-schema.d.ts +284 -0
- package/dist/store/selfimprove-dhq-schema.d.ts.map +1 -0
- package/dist/store/selfimprove-dhq-schema.js +128 -0
- package/dist/store/selfimprove-dhq-schema.js.map +1 -0
- package/dist/store/selfimprove-dhq-store.d.ts +175 -0
- package/dist/store/selfimprove-dhq-store.d.ts.map +1 -0
- package/dist/store/selfimprove-dhq-store.js +182 -0
- package/dist/store/selfimprove-dhq-store.js.map +1 -0
- package/dist/store/session-store.d.ts +52 -13
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +71 -13
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +7 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/umbrella-data-accessor.d.ts +1 -0
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +5 -0
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +32 -0
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/store/writer-lease-schema.d.ts +392 -0
- package/dist/store/writer-lease-schema.d.ts.map +1 -0
- package/dist/store/writer-lease-schema.js +142 -0
- package/dist/store/writer-lease-schema.js.map +1 -0
- package/dist/store/writer-lease.d.ts +368 -0
- package/dist/store/writer-lease.d.ts.map +1 -0
- package/dist/store/writer-lease.js +1002 -0
- package/dist/store/writer-lease.js.map +1 -0
- package/dist/tasks/backfill-child-projections.d.ts.map +1 -1
- package/dist/tasks/backfill-child-projections.js +14 -9
- package/dist/tasks/backfill-child-projections.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +7 -10
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/duplicate-detector.d.ts.map +1 -1
- package/dist/tasks/duplicate-detector.js +14 -7
- package/dist/tasks/duplicate-detector.js.map +1 -1
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +10 -4
- package/dist/telemetry/index.js.map +1 -1
- package/dist/tools/agent-registry.d.ts +250 -0
- package/dist/tools/agent-registry.d.ts.map +1 -0
- package/dist/tools/agent-registry.js +292 -0
- package/dist/tools/agent-registry.js.map +1 -0
- package/dist/tools/agent-tool-families.d.ts +107 -0
- package/dist/tools/agent-tool-families.d.ts.map +1 -0
- package/dist/tools/agent-tool-families.js +527 -0
- package/dist/tools/agent-tool-families.js.map +1 -0
- package/dist/tools/browser-driver.d.ts +183 -0
- package/dist/tools/browser-driver.d.ts.map +1 -0
- package/dist/tools/browser-driver.js +242 -0
- package/dist/tools/browser-driver.js.map +1 -0
- package/dist/tools/builtin-agent-tools.d.ts +36 -0
- package/dist/tools/builtin-agent-tools.d.ts.map +1 -0
- package/dist/tools/builtin-agent-tools.js +150 -0
- package/dist/tools/builtin-agent-tools.js.map +1 -0
- package/dist/tools/dispatch.d.ts +370 -0
- package/dist/tools/dispatch.d.ts.map +1 -0
- package/dist/tools/dispatch.js +505 -0
- package/dist/tools/dispatch.js.map +1 -0
- package/dist/tools/env-scrub.d.ts +93 -0
- package/dist/tools/env-scrub.d.ts.map +1 -0
- package/dist/tools/env-scrub.js +176 -0
- package/dist/tools/env-scrub.js.map +1 -0
- package/dist/tools/fs.d.ts +30 -0
- package/dist/tools/fs.d.ts.map +1 -1
- package/dist/tools/fs.js +55 -2
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/guard.d.ts +15 -0
- package/dist/tools/guard.d.ts.map +1 -1
- package/dist/tools/guard.js +49 -12
- package/dist/tools/guard.js.map +1 -1
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +37 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/pty.d.ts +45 -0
- package/dist/tools/pty.d.ts.map +1 -0
- package/dist/tools/pty.js +166 -0
- package/dist/tools/pty.js.map +1 -0
- package/dist/tools/schema-gen.d.ts +57 -0
- package/dist/tools/schema-gen.d.ts.map +1 -0
- package/dist/tools/schema-gen.js +52 -0
- package/dist/tools/schema-gen.js.map +1 -0
- package/dist/tools/shell.d.ts +12 -0
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +14 -1
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/web-agent-tools.d.ts +72 -0
- package/dist/tools/web-agent-tools.d.ts.map +1 -0
- package/dist/tools/web-agent-tools.js +393 -0
- package/dist/tools/web-agent-tools.js.map +1 -0
- package/dist/tools/web-search-backends.d.ts +156 -0
- package/dist/tools/web-search-backends.d.ts.map +1 -0
- package/dist/tools/web-search-backends.js +290 -0
- package/dist/tools/web-search-backends.js.map +1 -0
- package/dist/validation/ops.d.ts +1 -15
- package/dist/validation/ops.d.ts.map +1 -1
- package/dist/validation/ops.js +0 -20
- package/dist/validation/ops.js.map +1 -1
- package/migrations/drizzle-cleo-global/20260607000000_t11891-writer-leases/migration.sql +55 -0
- package/migrations/drizzle-cleo-global/20260607010000_t11639-session-manifest/migration.sql +43 -0
- package/migrations/drizzle-cleo-global/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
- package/migrations/drizzle-cleo-global/20260608010000_t11709-accounts-credential-pool/migration.sql +72 -0
- package/migrations/drizzle-cleo-global/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
- package/migrations/drizzle-cleo-project/20260607000000_t11891-writer-leases/migration.sql +55 -0
- package/migrations/drizzle-cleo-project/20260607010000_t11639-session-parent/migration.sql +22 -0
- package/migrations/drizzle-cleo-project/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
- package/migrations/drizzle-cleo-project/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
- package/package.json +15 -13
- package/dist/lifecycle/chain-composition.d.ts +0 -30
- package/dist/lifecycle/chain-composition.d.ts.map +0 -1
- package/dist/lifecycle/chain-composition.js +0 -152
- package/dist/lifecycle/chain-composition.js.map +0 -1
- package/dist/lifecycle/chain-store.d.ts +0 -70
- package/dist/lifecycle/chain-store.d.ts.map +0 -1
- package/dist/lifecycle/chain-store.js +0 -246
- package/dist/lifecycle/chain-store.js.map +0 -1
- package/dist/lifecycle/default-chain.d.ts +0 -39
- package/dist/lifecycle/default-chain.d.ts.map +0 -1
- package/dist/lifecycle/default-chain.js +0 -176
- package/dist/lifecycle/default-chain.js.map +0 -1
- package/dist/lifecycle/tessera-engine.d.ts +0 -48
- package/dist/lifecycle/tessera-engine.d.ts.map +0 -1
- package/dist/lifecycle/tessera-engine.js +0 -249
- package/dist/lifecycle/tessera-engine.js.map +0 -1
- package/dist/validation/chain-validation.d.ts +0 -43
- package/dist/validation/chain-validation.d.ts.map +0 -1
- package/dist/validation/chain-validation.js +0 -146
- package/dist/validation/chain-validation.js.map +0 -1
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* IVTR
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
2
|
+
* IVTR `ivtr_state` record — read + cantbook-mirror surface.
|
|
3
|
+
*
|
|
4
|
+
* The Implement → Validate → Audit → Test → Release phase loop now runs on the
|
|
5
|
+
* cantbook runtime (the survivor state machine after the T11764 collapse). The
|
|
6
|
+
* hand-rolled phase-walk functions (`startIvtr`/`advanceIvtr`/`loopBackIvtr`/
|
|
7
|
+
* `releaseIvtr`) plus the per-phase prompt/auto-gate helpers were deleted in
|
|
8
|
+
* T11896 once `cleo go` (default) drives `executePlaybook(ivtr.cantbook)` and
|
|
9
|
+
* the manual `cleo orchestrate ivtr` mutate ops were deprecated.
|
|
10
|
+
*
|
|
11
|
+
* This module now owns the RETAINED `ivtr_state` surface (one deprecation
|
|
12
|
+
* cycle):
|
|
13
|
+
* - {@link IvtrState} / {@link IvtrPhase} / {@link IvtrPhaseEntry} — the JSON
|
|
14
|
+
* shape persisted in the `ivtr_state` column on `tasks`.
|
|
15
|
+
* - {@link getIvtrState} — the read path backing `cleo show --ivtr-history`
|
|
16
|
+
* and the strict `E_IVTR_INCOMPLETE` completion gate (`tasks/complete.ts`).
|
|
17
|
+
* - {@link seedIvtrForPlaybook} / {@link finalizeIvtrFromPlaybook} — the
|
|
18
|
+
* `cleo go` cantbook seam (T11805): seed the column at `implement` and
|
|
19
|
+
* mirror the run's terminal status back so the completion gate stays
|
|
20
|
+
* load-bearing.
|
|
21
|
+
* - {@link MAX_LOOP_BACKS_PER_PHASE} — read by `classify-readiness.ts`.
|
|
22
|
+
* - {@link validateSpawnRequest} — Lead authorship-bypass guard (ADR-070).
|
|
18
23
|
*
|
|
19
24
|
* Evidence refs are sha256 hashes of attachment blobs stored under
|
|
20
25
|
* .cleo/attachments (see ADR T796 attachment store).
|
|
@@ -22,32 +27,17 @@
|
|
|
22
27
|
* @epic T810
|
|
23
28
|
* @task T811
|
|
24
29
|
* @task T813
|
|
30
|
+
* @task T11805 — cantbook seam (seed + finalize mirror)
|
|
31
|
+
* @task T11896 — phase-walk functions deleted; this is the read/mirror surface
|
|
25
32
|
*/
|
|
26
33
|
import { createHash } from 'node:crypto';
|
|
27
34
|
import { eq } from 'drizzle-orm';
|
|
28
35
|
import { getLogger } from '../logger.js';
|
|
29
|
-
import { getProjectRoot } from '../paths.js';
|
|
30
36
|
import { createAttachmentStore } from '../store/attachment-store.js';
|
|
31
37
|
import { getDb } from '../store/sqlite.js';
|
|
32
38
|
import * as schema from '../store/tasks-schema.js';
|
|
33
|
-
import { extractTypedGates, runGates } from '../tasks/gate-runner.js';
|
|
34
|
-
import { buildBlastRadiusTestScopeSection, detectInfrastructureTouch } from './infra-touch.js';
|
|
35
39
|
const log = getLogger('lifecycle:ivtr');
|
|
36
40
|
// =============================================================================
|
|
37
|
-
// PHASE ORDER
|
|
38
|
-
// =============================================================================
|
|
39
|
-
/** @task T9216 — 'audit' inserted between validate and test */
|
|
40
|
-
const PHASE_ORDER = ['implement', 'validate', 'audit', 'test', 'released'];
|
|
41
|
-
/**
|
|
42
|
-
* Return the next phase after `current`, or null if already at `released`.
|
|
43
|
-
*/
|
|
44
|
-
function nextPhase(current) {
|
|
45
|
-
const idx = PHASE_ORDER.indexOf(current);
|
|
46
|
-
if (idx === -1 || idx >= PHASE_ORDER.length - 1)
|
|
47
|
-
return null;
|
|
48
|
-
return PHASE_ORDER[idx + 1] ?? null;
|
|
49
|
-
}
|
|
50
|
-
// =============================================================================
|
|
51
41
|
// PERSISTENCE HELPERS
|
|
52
42
|
// =============================================================================
|
|
53
43
|
/**
|
|
@@ -101,32 +91,29 @@ async function writeIvtrState(state, cwd) {
|
|
|
101
91
|
// PUBLIC API
|
|
102
92
|
// =============================================================================
|
|
103
93
|
/**
|
|
104
|
-
*
|
|
94
|
+
* Build the canonical fresh {@link IvtrState} seeded at the `implement` phase.
|
|
105
95
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
96
|
+
* The historical manual walk (`startIvtr`) was deleted in T11896 when the IVTR
|
|
97
|
+
* loop was collapsed onto the cantbook runtime; {@link seedIvtrForPlaybook}
|
|
98
|
+
* (the `cleo go` seam, T11805) is now the sole producer of a fresh IvtrState
|
|
99
|
+
* and delegates here so the seeded state is byte-identical to the retired walk.
|
|
109
100
|
*
|
|
110
|
-
* @param taskId - Task
|
|
111
|
-
* @param
|
|
112
|
-
*
|
|
101
|
+
* @param taskId - Task the IVTR loop is seeded for.
|
|
102
|
+
* @param agentIdentity - Agent identity string for the first phase entry, or
|
|
103
|
+
* `null` when unknown.
|
|
104
|
+
* @returns A fresh schema-v2 {@link IvtrState} at `currentPhase: 'implement'`.
|
|
113
105
|
*/
|
|
114
|
-
|
|
115
|
-
const existing = await readIvtrStateRaw(taskId, options?.cwd);
|
|
116
|
-
if (existing) {
|
|
117
|
-
log.info({ taskId }, 'IVTR already started; returning existing state');
|
|
118
|
-
return existing;
|
|
119
|
-
}
|
|
106
|
+
function buildInitialIvtrState(taskId, agentIdentity) {
|
|
120
107
|
const now = new Date().toISOString();
|
|
121
108
|
const entry = {
|
|
122
109
|
phase: 'implement',
|
|
123
|
-
agentIdentity
|
|
110
|
+
agentIdentity,
|
|
124
111
|
startedAt: now,
|
|
125
112
|
completedAt: null,
|
|
126
113
|
passed: null,
|
|
127
114
|
evidenceRefs: [],
|
|
128
115
|
};
|
|
129
|
-
|
|
116
|
+
return {
|
|
130
117
|
taskId,
|
|
131
118
|
schemaVersion: 2,
|
|
132
119
|
currentPhase: 'implement',
|
|
@@ -134,493 +121,191 @@ export async function startIvtr(taskId, options) {
|
|
|
134
121
|
startedAt: now,
|
|
135
122
|
loopBackCount: { implement: 0, validate: 0, audit: 0, test: 0, released: 0 },
|
|
136
123
|
};
|
|
137
|
-
await writeIvtrState(state, options?.cwd);
|
|
138
|
-
log.info({ taskId }, 'IVTR loop started at implement phase');
|
|
139
|
-
return state;
|
|
140
124
|
}
|
|
141
125
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* @
|
|
154
|
-
*
|
|
126
|
+
* Seed the `tasks.ivtr_state` mirror for a task whose IVTR loop is now driven
|
|
127
|
+
* by `executePlaybook(ivtr.cantbook)` rather than the hand-rolled phase walk
|
|
128
|
+
* (T11805 · collapse-plan §3 item 4).
|
|
129
|
+
*
|
|
130
|
+
* The strict completion gate `E_IVTR_INCOMPLETE` (`tasks/complete.ts`) fires
|
|
131
|
+
* **only when `ivtr_state !== null`**. The `cleo go` seam removed `startIvtr`
|
|
132
|
+
* — the historical sole writer of that column — from the autopilot path; this
|
|
133
|
+
* helper restores the writer so the gate stays load-bearing while the column
|
|
134
|
+
* is retained for one deprecation cycle. It is intentionally **not**
|
|
135
|
+
* `startIvtr`: AC4 of T11805 requires the go path to no longer call
|
|
136
|
+
* `startIvtr`, but the seeded state must remain identical, so both share
|
|
137
|
+
* {@link buildInitialIvtrState}.
|
|
138
|
+
*
|
|
139
|
+
* Idempotent: a task that already has IVTR state is left untouched and its
|
|
140
|
+
* existing state is returned.
|
|
141
|
+
*
|
|
142
|
+
* @param taskId - Task to seed `ivtr_state` for.
|
|
143
|
+
* @param options - Optional cwd and agent identity for the first phase entry.
|
|
144
|
+
* @returns The current (possibly newly seeded) {@link IvtrState}.
|
|
155
145
|
*/
|
|
156
|
-
export async function
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (state.currentPhase === 'released') {
|
|
162
|
-
throw new Error(`Task ${taskId} is already released. Use releaseIvtr to finalise.`);
|
|
163
|
-
}
|
|
164
|
-
const now = new Date().toISOString();
|
|
165
|
-
// Close the current active phase entry.
|
|
166
|
-
const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
|
|
167
|
-
if (activeEntry) {
|
|
168
|
-
activeEntry.completedAt = now;
|
|
169
|
-
activeEntry.passed = true;
|
|
170
|
-
activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, ...evidence];
|
|
171
|
-
}
|
|
172
|
-
const next = nextPhase(state.currentPhase);
|
|
173
|
-
if (!next) {
|
|
174
|
-
throw new Error(`Cannot advance beyond released phase for task ${taskId}`);
|
|
175
|
-
}
|
|
176
|
-
state.currentPhase = next;
|
|
177
|
-
if (next !== 'released') {
|
|
178
|
-
const nextEntry = {
|
|
179
|
-
phase: next,
|
|
180
|
-
agentIdentity: options?.agentIdentity ?? null,
|
|
181
|
-
startedAt: now,
|
|
182
|
-
completedAt: null,
|
|
183
|
-
passed: null,
|
|
184
|
-
evidenceRefs: [],
|
|
185
|
-
};
|
|
186
|
-
state.phaseHistory.push(nextEntry);
|
|
146
|
+
export async function seedIvtrForPlaybook(taskId, options) {
|
|
147
|
+
const existing = await readIvtrStateRaw(taskId, options?.cwd);
|
|
148
|
+
if (existing) {
|
|
149
|
+
log.info({ taskId }, 'IVTR state already present; seam seed is a no-op');
|
|
150
|
+
return existing;
|
|
187
151
|
}
|
|
152
|
+
const state = buildInitialIvtrState(taskId, options?.agentIdentity ?? null);
|
|
188
153
|
await writeIvtrState(state, options?.cwd);
|
|
189
|
-
log.info({ taskId,
|
|
154
|
+
log.info({ taskId }, 'IVTR state mirror seeded for cantbook-driven run');
|
|
190
155
|
return state;
|
|
191
156
|
}
|
|
192
157
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* `
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
* @param
|
|
222
|
-
* @
|
|
223
|
-
* @
|
|
224
|
-
*
|
|
158
|
+
* Mirror the terminal status of a cantbook-driven IVTR run back into
|
|
159
|
+
* `tasks.ivtr_state` (T11805 · collapse-plan §3 item 4 + Risk #2).
|
|
160
|
+
*
|
|
161
|
+
* The `cleo go` seam seeds `ivtr_state` at the `implement` phase via
|
|
162
|
+
* {@link seedIvtrForPlaybook} but the cantbook runtime (`executePlaybook`)
|
|
163
|
+
* only writes `playbook_runs` — it never touches `ivtr_state`. Without this
|
|
164
|
+
* mirror a fully-successful autonomous run leaves `ivtr_state.currentPhase`
|
|
165
|
+
* frozen at `'implement'`, so the strict `E_IVTR_INCOMPLETE` completion gate
|
|
166
|
+
* (`tasks/complete.ts`) permanently rejects `cleo complete`. This function
|
|
167
|
+
* closes that gap by translating the runtime's terminal status into the
|
|
168
|
+
* equivalent `ivtr_state` transition:
|
|
169
|
+
*
|
|
170
|
+
* - **`completed`** → walk every required phase to a passing
|
|
171
|
+
* {@link IvtrPhaseEntry} and set `currentPhase = 'released'`, so the gate
|
|
172
|
+
* passes exactly as the legacy `advanceIvtr`→`releaseIvtr` walk did. A
|
|
173
|
+
* content-addressed provenance blob (runId + terminalStatus + a bounded
|
|
174
|
+
* `finalContext` snapshot) is written to the attachment store and its
|
|
175
|
+
* sha256 recorded on the released entry's `evidenceRefs`, reproducing the
|
|
176
|
+
* per-phase evidence write the old walk produced (collapse-plan §3
|
|
177
|
+
* "evidence refs (sha256 attachments)").
|
|
178
|
+
* - **`failed` / `exceeded_iteration_cap`** → mark the active phase entry
|
|
179
|
+
* `passed: false` with the runtime error as the `reason`, leaving
|
|
180
|
+
* `currentPhase` un-advanced so the gate correctly blocks completion.
|
|
181
|
+
* - **`pending_approval`** → no-op (the run is awaiting a HITL gate; a later
|
|
182
|
+
* resume turn finalizes it).
|
|
183
|
+
*
|
|
184
|
+
* Idempotent: a state already at `'released'` is returned untouched.
|
|
185
|
+
*
|
|
186
|
+
* @param taskId - Task whose `ivtr_state` mirror is being finalized.
|
|
187
|
+
* @param terminalStatus - Terminal status from the cantbook run.
|
|
188
|
+
* @param options - Optional cwd, agent identity, runId, error reason, and a
|
|
189
|
+
* bounded `finalContext` snapshot for the provenance blob.
|
|
190
|
+
* @returns The finalized state + optional provenance evidence ref.
|
|
191
|
+
*
|
|
192
|
+
* @task T11805 — E-ORCH-STATE-MACHINE-COLLAPSE / T11764
|
|
225
193
|
*/
|
|
226
|
-
export async function
|
|
227
|
-
if (toPhase === 'released') {
|
|
228
|
-
throw new Error(`Cannot loop back to 'released'. Use releaseIvtr to finalise.`);
|
|
229
|
-
}
|
|
194
|
+
export async function finalizeIvtrFromPlaybook(taskId, terminalStatus, options) {
|
|
230
195
|
const state = await readIvtrStateRaw(taskId, options?.cwd);
|
|
231
196
|
if (!state) {
|
|
232
|
-
|
|
197
|
+
log.warn({ taskId, terminalStatus }, 'finalizeIvtrFromPlaybook: no ivtr_state to mirror (seed step skipped?)');
|
|
198
|
+
return { state: null };
|
|
233
199
|
}
|
|
200
|
+
// Already released — nothing to do (idempotent re-finalization).
|
|
234
201
|
if (state.currentPhase === 'released') {
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
// Backward-compat: legacy states may not have loopBackCount or audit field.
|
|
238
|
-
if (!state.loopBackCount) {
|
|
239
|
-
state.loopBackCount = { implement: 0, validate: 0, audit: 0, test: 0, released: 0 };
|
|
240
|
-
}
|
|
241
|
-
// Defensive: legacy rows predating T9216 won't have loopBackCount.audit.
|
|
242
|
-
state.loopBackCount.audit = state.loopBackCount.audit ?? 0;
|
|
243
|
-
// Check max BEFORE any mutation so the state stays clean on reject.
|
|
244
|
-
const currentCount = state.loopBackCount[toPhase] ?? 0;
|
|
245
|
-
if (currentCount >= MAX_LOOP_BACKS_PER_PHASE) {
|
|
246
|
-
throw new Error(`${E_IVTR_MAX_RETRIES}: Task ${taskId} has reached the maximum of ${MAX_LOOP_BACKS_PER_PHASE} loop-backs to phase '${toPhase}'. ` +
|
|
247
|
-
`HITL escalation required — review the loop-back history and resolve the root cause manually before retrying.`);
|
|
202
|
+
return { state };
|
|
248
203
|
}
|
|
249
204
|
const now = new Date().toISOString();
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, ...evidence];
|
|
256
|
-
activeEntry.reason = reason;
|
|
205
|
+
const agentIdentity = options?.agentIdentity ?? null;
|
|
206
|
+
if (terminalStatus === 'pending_approval') {
|
|
207
|
+
// The run paused on a HITL gate; a later resume turn finalizes it.
|
|
208
|
+
log.info({ taskId }, 'finalizeIvtrFromPlaybook: run pending approval — leaving ivtr_state as-is');
|
|
209
|
+
return { state };
|
|
257
210
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
await writeIvtrState(state, options?.cwd);
|
|
272
|
-
log.info({ taskId, toPhase, reason, loopBackCount: state.loopBackCount[toPhase] }, 'IVTR loop-back recorded');
|
|
273
|
-
return state;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Attempt to release a task after all three phases have passed.
|
|
277
|
-
*
|
|
278
|
-
* Validates that implement, validate, and test all have at least one passing
|
|
279
|
-
* phase entry. If validation passes, marks the task status = 'done' and
|
|
280
|
-
* sets `currentPhase = 'released'`.
|
|
281
|
-
*
|
|
282
|
-
* @param taskId - Task to release.
|
|
283
|
-
* @param options - Optional cwd.
|
|
284
|
-
* @returns `{ released: true }` on success, or `{ released: false, failures }` listing missing phases.
|
|
285
|
-
*/
|
|
286
|
-
export async function releaseIvtr(taskId, options) {
|
|
287
|
-
const state = await readIvtrStateRaw(taskId, options?.cwd);
|
|
288
|
-
if (!state) {
|
|
289
|
-
return { released: false, failures: [`No IVTR state for task ${taskId}`] };
|
|
211
|
+
if (terminalStatus === 'failed' || terminalStatus === 'exceeded_iteration_cap') {
|
|
212
|
+
// Mark the active phase entry as failed so the gate blocks completion and
|
|
213
|
+
// the failure is auditable; do NOT advance currentPhase.
|
|
214
|
+
const reason = options?.error ?? `cantbook run ${terminalStatus}`;
|
|
215
|
+
const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
|
|
216
|
+
if (activeEntry) {
|
|
217
|
+
activeEntry.completedAt = now;
|
|
218
|
+
activeEntry.passed = false;
|
|
219
|
+
activeEntry.reason = `Playbook ${terminalStatus}: ${reason}`;
|
|
220
|
+
}
|
|
221
|
+
await writeIvtrState(state, options?.cwd);
|
|
222
|
+
log.info({ taskId, terminalStatus, currentPhase: state.currentPhase }, 'finalizeIvtrFromPlaybook: marked active phase failed (gate stays blocking)');
|
|
223
|
+
return { state };
|
|
290
224
|
}
|
|
291
|
-
|
|
292
|
-
|
|
225
|
+
// terminalStatus === 'completed' — write the provenance evidence blob first
|
|
226
|
+
// so its sha256 can be recorded on the released phase history (reproduces the
|
|
227
|
+
// legacy attachment-store write). Best-effort: a store failure must not block
|
|
228
|
+
// the terminal mirror, since the gate-passability fix is the load-bearing
|
|
229
|
+
// half — but we surface the failure in logs.
|
|
230
|
+
let evidenceRef;
|
|
231
|
+
try {
|
|
232
|
+
evidenceRef = await writeIvtrPlaybookProvenance(taskId, terminalStatus, options?.runId, options?.finalContext, agentIdentity, options?.cwd);
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
log.warn({ taskId, err: err instanceof Error ? err.message : String(err) }, 'finalizeIvtrFromPlaybook: provenance attachment write failed (non-fatal)');
|
|
293
236
|
}
|
|
294
|
-
|
|
295
|
-
//
|
|
237
|
+
// Walk every required phase to a passing entry, then mark released. The
|
|
238
|
+
// E_IVTR_INCOMPLETE gate (complete.ts) requires implement/validate/test to
|
|
239
|
+
// each have a passing entry AND currentPhase === 'released'.
|
|
296
240
|
const required = [
|
|
297
241
|
'implement',
|
|
298
242
|
'validate',
|
|
299
243
|
'audit',
|
|
300
244
|
'test',
|
|
301
245
|
];
|
|
302
|
-
|
|
303
|
-
const passed = state.phaseHistory.some((e) => e.phase === phase && e.passed === true);
|
|
304
|
-
if (!passed) {
|
|
305
|
-
failures.push(`Phase '${phase}' has no passing entry`);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
if (failures.length > 0) {
|
|
309
|
-
return { released: false, failures };
|
|
310
|
-
}
|
|
311
|
-
// Close the active test entry if still open.
|
|
312
|
-
const now = new Date().toISOString();
|
|
246
|
+
// Close any in-progress entry as passed (the active implement seed).
|
|
313
247
|
const activeEntry = state.phaseHistory.findLast((e) => e.completedAt === null);
|
|
314
248
|
if (activeEntry) {
|
|
315
249
|
activeEntry.completedAt = now;
|
|
316
250
|
activeEntry.passed = true;
|
|
251
|
+
if (evidenceRef)
|
|
252
|
+
activeEntry.evidenceRefs = [...activeEntry.evidenceRefs, evidenceRef];
|
|
253
|
+
}
|
|
254
|
+
// Ensure every required phase has at least one passing entry. Append a
|
|
255
|
+
// synthetic passing entry for any phase the seeded state lacks (the cantbook
|
|
256
|
+
// seed only writes the implement entry).
|
|
257
|
+
for (const phase of required) {
|
|
258
|
+
const hasPassed = state.phaseHistory.some((e) => e.phase === phase && e.passed === true);
|
|
259
|
+
if (!hasPassed) {
|
|
260
|
+
const entry = {
|
|
261
|
+
phase,
|
|
262
|
+
agentIdentity,
|
|
263
|
+
startedAt: now,
|
|
264
|
+
completedAt: now,
|
|
265
|
+
passed: true,
|
|
266
|
+
evidenceRefs: evidenceRef ? [evidenceRef] : [],
|
|
267
|
+
reason: `Cantbook run ${options?.runId ?? '(unknown run)'} completed — phase mirrored from playbook terminal status`,
|
|
268
|
+
};
|
|
269
|
+
state.phaseHistory.push(entry);
|
|
270
|
+
}
|
|
317
271
|
}
|
|
318
272
|
state.currentPhase = 'released';
|
|
319
273
|
await writeIvtrState(state, options?.cwd);
|
|
320
|
-
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
.
|
|
324
|
-
|
|
325
|
-
.where(eq(schema.tasks.id, taskId))
|
|
326
|
-
.all();
|
|
327
|
-
log.info({ taskId }, 'IVTR released --- task marked done');
|
|
328
|
-
return { released: true };
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Retrieve the current IVTR state for a task, or null if the loop has not
|
|
332
|
-
* been started.
|
|
333
|
-
*
|
|
334
|
-
* @param taskId - Task ID to inspect.
|
|
335
|
-
* @param options - Optional cwd.
|
|
336
|
-
* @returns IvtrState or null.
|
|
337
|
-
*/
|
|
338
|
-
export async function getIvtrState(taskId, options) {
|
|
339
|
-
return readIvtrStateRaw(taskId, options?.cwd);
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Build the validate-phase evidence bundle section (T812 §2).
|
|
343
|
-
*
|
|
344
|
-
* Renders a structured Markdown table when enriched summaries are provided,
|
|
345
|
-
* or falls back to listing raw sha256 refs from the passed phase entries.
|
|
346
|
-
*
|
|
347
|
-
* @param implEntries - Implement phase entries with `passed === true`.
|
|
348
|
-
* @param evidenceBundle - Optional enriched summaries from the attachment store.
|
|
349
|
-
*/
|
|
350
|
-
function buildValidateEvidenceBundle(implEntries, evidenceBundle) {
|
|
351
|
-
if (evidenceBundle.length > 0) {
|
|
352
|
-
const rows = evidenceBundle.map((e) => {
|
|
353
|
-
const files = e.filesChanged && e.filesChanged.length > 0 ? e.filesChanged.join(', ') : '(unknown)';
|
|
354
|
-
const added = e.linesAdded !== undefined ? `+${e.linesAdded}` : '?';
|
|
355
|
-
const removed = e.linesRemoved !== undefined ? `-${e.linesRemoved}` : '?';
|
|
356
|
-
const duration = e.durationMs !== undefined ? `${e.durationMs}ms` : '?';
|
|
357
|
-
return `| \`${e.attachmentSha256.slice(0, 16)}...\` | ${e.kind} | ${files} | ${added}/${removed} | ${duration} |`;
|
|
358
|
-
});
|
|
359
|
-
return `## Implement-Phase Evidence Bundle
|
|
360
|
-
|
|
361
|
-
| sha256 (prefix) | kind | filesChanged | linesAdded/Removed | duration |
|
|
362
|
-
|---|---|---|---|---|
|
|
363
|
-
${rows.join('\n')}
|
|
364
|
-
|
|
365
|
-
> Retrieve full diff: \`cleo docs show <sha256>\``;
|
|
366
|
-
}
|
|
367
|
-
// Fallback: list raw refs from phase history.
|
|
368
|
-
const allRefs = implEntries.flatMap((e) => e.evidenceRefs);
|
|
369
|
-
if (allRefs.length === 0) {
|
|
370
|
-
return '## Implement-Phase Evidence Bundle\n(none recorded — impl agent may not have produced attachments)';
|
|
371
|
-
}
|
|
372
|
-
return `## Implement-Phase Evidence Bundle (sha256 refs)
|
|
373
|
-
${allRefs.map((r) => `- \`${r}\``).join('\n')}
|
|
374
|
-
|
|
375
|
-
> Retrieve diff content: \`cleo docs show <sha256>\``;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Build the validate-phase instruction block + REJECT criteria (T812 §§3–4).
|
|
379
|
-
*
|
|
380
|
-
* @param taskId - Task ID for CLI command references.
|
|
381
|
-
* @param state - Current IvtrState (currentPhase === 'validate').
|
|
382
|
-
* @param evidenceBundle - Pre-fetched implement evidence summaries (may be empty).
|
|
383
|
-
*/
|
|
384
|
-
function buildValidatePhaseInstruction(taskId, state, evidenceBundle) {
|
|
385
|
-
const loopCount = state.loopBackCount?.validate ?? 0;
|
|
386
|
-
const escalationNote = loopCount >= 2
|
|
387
|
-
? '\n> WARNING: This is loop-back attempt 3+. HITL escalation is required if this validate phase fails again.\n'
|
|
388
|
-
: '';
|
|
389
|
-
const implRefHint = evidenceBundle.length > 0
|
|
390
|
-
? evidenceBundle
|
|
391
|
-
.map((e) => `- \`${e.attachmentSha256.slice(0, 16)}...\` (${e.kind}${e.filesChanged ? ', ' + e.filesChanged.length + ' file(s)' : ''})`)
|
|
392
|
-
.join('\n')
|
|
393
|
-
: '(enumerate REQ-IDs from the task specification above and cross-reference the impl-diff sha256 refs in the evidence bundle)';
|
|
394
|
-
// T9842 — Blast-radius infrastructure-touch detection. Aggregate every
|
|
395
|
-
// `filesChanged` array from the impl-phase evidence bundle and feed it to
|
|
396
|
-
// the detector. When the impl touched an infrastructure path, the rendered
|
|
397
|
-
// section instructs the Lead to run full per-package tests rather than the
|
|
398
|
-
// targeted subset called out in the task spec.
|
|
399
|
-
const allFilesChanged = evidenceBundle.flatMap((e) => e.filesChanged ?? []);
|
|
400
|
-
const infraTouch = detectInfrastructureTouch(allFilesChanged);
|
|
401
|
-
const blastRadiusSection = buildBlastRadiusTestScopeSection(infraTouch);
|
|
402
|
-
const blastRadiusBlock = blastRadiusSection ? `\n\n${blastRadiusSection}\n` : '';
|
|
403
|
-
const blastRadiusRejectLine = infraTouch.affected
|
|
404
|
-
? '\n- **Infra-test-scope violation (T9842)**: infrastructure paths were touched (see the Blast-Radius Test Scope section above) but no full per-package vitest run was attached. Loop-back reason: `infra-test-scope-violation`.'
|
|
405
|
-
: '';
|
|
406
|
-
return `## Phase: Validate
|
|
407
|
-
You are the Validate agent for task ${taskId}. Read the impl diff + evidence listed in the Implement-Phase Evidence Bundle above. Check spec↔code alignment per each acceptance criterion and REQ-ID.${escalationNote}
|
|
408
|
-
|
|
409
|
-
### Your responsibilities
|
|
410
|
-
|
|
411
|
-
1. Read the task spec and each evidence attachment in the Implement-Phase Evidence Bundle above.
|
|
412
|
-
2. Retrieve each diff blob: \`cleo docs show <sha256>\`
|
|
413
|
-
3. For every acceptance criterion and REQ-ID in the task spec, verify it is traceable to a concrete code change in the impl diff.
|
|
414
|
-
4. Produce a \`ValidateSpecCheckRecord\` (\`kind: 'validate-spec-check'\`) and write it to a JSON file:
|
|
415
|
-
\`\`\`json
|
|
416
|
-
{
|
|
417
|
-
"kind": "validate-spec-check",
|
|
418
|
-
"phase": "validate",
|
|
419
|
-
"agentIdentity": "<your-agent-id>",
|
|
420
|
-
"attachmentSha256": "<sha256-of-this-report>",
|
|
421
|
-
"reqIdsChecked": ["<REQ-ID-1>", "<REQ-ID-2>"],
|
|
422
|
-
"passed": true,
|
|
423
|
-
"details": "<per-REQ-ID verdict, one sentence each>",
|
|
424
|
-
"ranAt": "<ISO-8601-timestamp>",
|
|
425
|
-
"durationMs": 0
|
|
426
|
-
}
|
|
427
|
-
\`\`\`
|
|
428
|
-
5. Attach the report: \`cleo docs add <file> --task ${taskId}\`
|
|
429
|
-
6. Pass the returned sha256 to \`--next\`:
|
|
430
|
-
- **PASS**: \`cleo orchestrate ivtr ${taskId} --next --evidence <sha256>\`
|
|
431
|
-
- **FAIL**: \`cleo orchestrate ivtr ${taskId} --loop-back --phase implement --reason "<details>"\`
|
|
432
|
-
|
|
433
|
-
### Impl-diff attachment refs to review
|
|
434
|
-
|
|
435
|
-
${implRefHint}${blastRadiusBlock}
|
|
436
|
-
### REJECT criteria — trigger loop-back if ANY of the following are true
|
|
437
|
-
|
|
438
|
-
- **Spec-code mismatch**: an acceptance criterion or REQ-ID has no traceable code change in the impl diff.
|
|
439
|
-
- **Missing test**: an acceptance criterion that requires test coverage has no corresponding test added or updated in the diff.
|
|
440
|
-
- **Undocumented deviation**: the implementation deviates from the task spec without a documented reason (comment, ADR reference, or inline note in the diff).
|
|
441
|
-
- **Quality gate not run**: the impl-phase evidence does not include proof that \`pnpm biome check\` and \`pnpm run build\` both passed (lint-report or command-output attachment with exit code 0).${blastRadiusRejectLine}`;
|
|
274
|
+
log.info({ taskId, runId: options?.runId, evidenceRef }, 'finalizeIvtrFromPlaybook: ivtr_state mirrored to released (gate now passes)');
|
|
275
|
+
const result = { state };
|
|
276
|
+
if (evidenceRef !== undefined)
|
|
277
|
+
result.evidenceRef = evidenceRef;
|
|
278
|
+
return result;
|
|
442
279
|
}
|
|
443
280
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* When advancing to the `validate` phase the prompt is enriched with four
|
|
447
|
-
* additional sections required by T812:
|
|
448
|
-
*
|
|
449
|
-
* 1. **Original task spec** — always included.
|
|
450
|
-
* 2. **Implement-phase evidence bundle** — all `IvtrPhaseEntry` records where
|
|
451
|
-
* `phase === 'implement'` and `passed === true`, rendered with attachment
|
|
452
|
-
* metadata (sha256, kind, filesChanged, linesAdded/Removed, duration).
|
|
453
|
-
* Callers pass the optional `evidenceBundle` to supply pre-fetched metadata
|
|
454
|
-
* from the attachment store; the function falls back to raw sha256 refs if
|
|
455
|
-
* the bundle is empty.
|
|
456
|
-
* 3. **Validate-agent instructions** — how to produce a `ValidateSpecCheckRecord`
|
|
457
|
-
* (`kind: 'validate-spec-check'`) and attach it via `cleo docs add`.
|
|
458
|
-
* 4. **Explicit REJECT criteria** — conditions under which the validate agent
|
|
459
|
-
* MUST trigger a loop-back to implement.
|
|
281
|
+
* Write a content-addressed provenance blob for a completed cantbook IVTR run
|
|
282
|
+
* to the attachment store and return its sha256.
|
|
460
283
|
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
284
|
+
* This reproduces the attachment-store write the legacy `autoRunGatesAndRecord`
|
|
285
|
+
* / `advanceIvtr` walk performed (collapse-plan §3 mapping row "evidence refs
|
|
286
|
+
* (sha256 attachments)"), so downstream observers (`cleo show --ivtr-history`,
|
|
287
|
+
* release observation reads) still find content-addressed evidence for
|
|
288
|
+
* autonomously-driven tasks.
|
|
463
289
|
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
290
|
+
* The `finalContext` snapshot is bounded to its top-level keys' JSON to avoid
|
|
291
|
+
* persisting an unbounded agent context.
|
|
466
292
|
*
|
|
467
|
-
* @
|
|
468
|
-
* @param state - Current IvtrState (after the transition to the target phase).
|
|
469
|
-
* @param taskTitle - Short task title (from cleo show).
|
|
470
|
-
* @param taskDesc - Full task description / spec including REQ-IDs.
|
|
471
|
-
* @param acceptanceGates - Optional typed AcceptanceGate objects (used by the test phase).
|
|
472
|
-
* @param evidenceBundle - Optional pre-fetched implement-phase evidence summaries
|
|
473
|
-
* (used by the validate phase; ignored for other phases).
|
|
474
|
-
* @returns Prompt string for the phase's assigned agent.
|
|
293
|
+
* @internal
|
|
475
294
|
*/
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
${bundleSection}
|
|
489
|
-
|
|
490
|
-
${instructionSection}
|
|
491
|
-
`;
|
|
492
|
-
}
|
|
493
|
-
// ── Generic evidence refs section (implement / test / released) ───────────
|
|
494
|
-
const priorEvidence = state.phaseHistory
|
|
495
|
-
.filter((e) => e.passed === true)
|
|
496
|
-
.flatMap((e) => e.evidenceRefs);
|
|
497
|
-
const evidenceSection = priorEvidence.length > 0
|
|
498
|
-
? `## Prior Phase Evidence (sha256 attachment refs)\n${priorEvidence.map((r) => `- ${r}`).join('\n')}`
|
|
499
|
-
: '## Prior Phase Evidence\n(none — first phase)';
|
|
500
|
-
// Build loop-back context section when re-spawning Implement after a failure (T814).
|
|
501
|
-
const failedEntries = state.phaseHistory.filter((e) => e.passed === false);
|
|
502
|
-
let loopBackSection = '';
|
|
503
|
-
if (state.currentPhase === 'implement' && failedEntries.length > 0) {
|
|
504
|
-
const triggeringFailure = failedEntries[failedEntries.length - 1];
|
|
505
|
-
const failureEvidenceLines = triggeringFailure.evidenceRefs.length > 0
|
|
506
|
-
? triggeringFailure.evidenceRefs.map((r) => `- ${r}`).join('\n')
|
|
507
|
-
: '(no attachment refs --- check the reason text above for details)';
|
|
508
|
-
const historyLines = failedEntries
|
|
509
|
-
.map((e, idx) => `${idx + 1}. Phase: ${e.phase.toUpperCase()} | Reason: ${e.reason ?? '(none)'} | CompletedAt: ${e.completedAt ?? 'unknown'}`)
|
|
510
|
-
.join('\n');
|
|
511
|
-
loopBackSection = `
|
|
512
|
-
## LOOP-BACK CONTEXT --- READ THIS CAREFULLY
|
|
513
|
-
|
|
514
|
-
**Previous attempt failed at phase: ${triggeringFailure.phase.toUpperCase()}**
|
|
515
|
-
**Failure reason**: ${triggeringFailure.reason ?? '(none)'}
|
|
516
|
-
|
|
517
|
-
### Failure Evidence (sha256 refs from the failing phase)
|
|
518
|
-
${failureEvidenceLines}
|
|
519
|
-
|
|
520
|
-
### Loop-back History (all prior failures for this task)
|
|
521
|
-
${historyLines}
|
|
522
|
-
|
|
523
|
-
**CRITICAL INSTRUCTION**: Previous attempt(s) failed. Read the failure evidence above.
|
|
524
|
-
Fix the ROOT CAUSE --- do NOT retry the same approach.
|
|
525
|
-
If the test phase failed, check what tests broke and WHY.
|
|
526
|
-
If the validate phase failed, check which acceptance criteria were not met and ensure they are addressed.
|
|
527
|
-
`;
|
|
528
|
-
}
|
|
529
|
-
// Build the typed gates section for the test phase prompt.
|
|
530
|
-
const gatesSection = acceptanceGates && acceptanceGates.length > 0
|
|
531
|
-
? `\n## Typed AcceptanceGates (programmatic --- run via cleo verify --run)\n${acceptanceGates
|
|
532
|
-
.map((g, i) => {
|
|
533
|
-
const label = 'command' in g
|
|
534
|
-
? g.command
|
|
535
|
-
: 'url' in g
|
|
536
|
-
? g.url
|
|
537
|
-
: g.kind;
|
|
538
|
-
return `${i + 1}. [${g.kind}] ${g.req ?? '(no req)'} --- ${label}`;
|
|
539
|
-
})
|
|
540
|
-
.join('\n')}`
|
|
541
|
-
: '';
|
|
542
|
-
const phaseInstructions = {
|
|
543
|
-
implement: `## Phase: Implement
|
|
544
|
-
You are the Implementation agent for task ${taskId}.
|
|
545
|
-
|
|
546
|
-
Your responsibilities:
|
|
547
|
-
1. Read the task spec below in full.
|
|
548
|
-
2. Write, modify, or extend code to satisfy the acceptance criteria.
|
|
549
|
-
3. Run quality gates: pnpm biome check --write . then pnpm run build.
|
|
550
|
-
4. Produce a git diff or file list as evidence.
|
|
551
|
-
5. Report your sha256 attachment refs as evidence when you call cleo orchestrate ivtr ${taskId} --next.`,
|
|
552
|
-
validate: '', // handled above — this branch is unreachable when currentPhase === 'validate'
|
|
553
|
-
audit: `## Phase: Audit
|
|
554
|
-
You are the independent Auditor agent for task ${taskId}.
|
|
555
|
-
|
|
556
|
-
Your responsibilities:
|
|
557
|
-
1. Run cleo verify ${taskId} --explain to re-validate every ADR-051 evidence atom (commit reachable, file sha256, test-run hash, tool exit code) against the live git/fs/toolchain.
|
|
558
|
-
2. Read the captured evidence atoms from prior phases — do NOT trust the agent's prose claims, only the re-validated atom set.
|
|
559
|
-
3. If every required gate is backed by a passing atom: call cleo orchestrate ivtr ${taskId} --next.
|
|
560
|
-
4. If any atom fails re-validation (E_EVIDENCE_STALE, E_EVIDENCE_TESTS_FAILED, E_EVIDENCE_TOOL_FAILED) or any required gate is unbacked: call cleo orchestrate ivtr ${taskId} --loop-back --phase implement --reason "<atom diagnostic>".
|
|
561
|
-
The Pre-Complete Gate Ritual (ADR-051) is the only enforcement surface — atoms re-validate against external state, so the Implementer cannot fake them.`,
|
|
562
|
-
test: `## Phase: Test
|
|
563
|
-
You are the Testing agent for task ${taskId}.
|
|
564
|
-
|
|
565
|
-
Your responsibilities:
|
|
566
|
-
1. Read the task spec and all prior-phase evidence refs listed above (impl + validate).
|
|
567
|
-
2. Run cleo verify ${taskId} --run to execute all programmatic AcceptanceGates.
|
|
568
|
-
3. Attach the full gate-run output via cleo docs add --labels test-output.
|
|
569
|
-
4. Compute or capture the sha256 of the attached output.
|
|
570
|
-
5. Pass the sha256 + gate-pass-count + gate-fail-count back in your --next call as:
|
|
571
|
-
EvidenceRecord{kind:'test-output', command:'cleo verify ${taskId} --run', exitCode, testsPassed, testsFailed}
|
|
572
|
-
6. If all gates pass, call cleo orchestrate ivtr ${taskId} --next --evidence <sha256>.
|
|
573
|
-
7. If any gate fails, call cleo orchestrate ivtr ${taskId} --loop-back --phase implement --reason "<failure summary>".
|
|
574
|
-
${gatesSection}`,
|
|
575
|
-
released: `## Phase: Released
|
|
576
|
-
Task ${taskId} has been released. No further agent action required.`,
|
|
295
|
+
async function writeIvtrPlaybookProvenance(taskId, terminalStatus, runId, finalContext, agentIdentity, cwd) {
|
|
296
|
+
const provenance = {
|
|
297
|
+
kind: 'ivtr-playbook-provenance',
|
|
298
|
+
taskId,
|
|
299
|
+
runId: runId ?? null,
|
|
300
|
+
terminalStatus,
|
|
301
|
+
finalizedAt: new Date().toISOString(),
|
|
302
|
+
// Snapshot only the bindings the cantbook nodes emitted (bounded). Internal
|
|
303
|
+
// bookkeeping keys (prefixed `__`) are stripped to keep the blob auditable.
|
|
304
|
+
bindings: finalContext
|
|
305
|
+
? Object.fromEntries(Object.entries(finalContext).filter(([k]) => !k.startsWith('__')))
|
|
306
|
+
: {},
|
|
577
307
|
};
|
|
578
|
-
|
|
579
|
-
Phase: **${state.currentPhase.toUpperCase()}**
|
|
580
|
-
|
|
581
|
-
## Task Specification
|
|
582
|
-
${taskDesc}
|
|
583
|
-
|
|
584
|
-
${evidenceSection}
|
|
585
|
-
${loopBackSection}
|
|
586
|
-
${phaseInstructions[state.currentPhase]}
|
|
587
|
-
`;
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Execute all typed AcceptanceGates for a task atomically during an IVTR
|
|
591
|
-
* --next transition with --auto-run-tests set.
|
|
592
|
-
*
|
|
593
|
-
* Steps performed in a single atomic operation:
|
|
594
|
-
* 1. Accept the typed gates array (strings already filtered by caller).
|
|
595
|
-
* 2. Run each gate via runGates().
|
|
596
|
-
* 3. Serialise the results to JSON and store via AttachmentStore.
|
|
597
|
-
* 4. Synthesise a TestOutputRecord carrying the sha256, pass/fail counts,
|
|
598
|
-
* and exit code.
|
|
599
|
-
* 5. Append the sha256 to the active phaseHistory entry's evidenceRefs and
|
|
600
|
-
* persist the updated IvtrState.
|
|
601
|
-
*
|
|
602
|
-
* @param taskId - Task ID being tested.
|
|
603
|
-
* @param acceptanceItems - Mixed acceptance array from the task record (strings
|
|
604
|
-
* are silently ignored; only typed gates are executed).
|
|
605
|
-
* @param agentIdentity - Optional agent identity string for provenance.
|
|
606
|
-
* @param cwd - Optional working directory.
|
|
607
|
-
* @returns AutoRunGatesResult with the attachment sha256 and counts.
|
|
608
|
-
*/
|
|
609
|
-
export async function autoRunGatesAndRecord(taskId, acceptanceItems, agentIdentity, cwd) {
|
|
610
|
-
const projectRoot = getProjectRoot(cwd);
|
|
611
|
-
const ranAt = new Date().toISOString();
|
|
612
|
-
const startMs = Date.now();
|
|
613
|
-
// 1. Filter to typed gates only (strings are silently skipped).
|
|
614
|
-
const typedGateEntries = extractTypedGates(acceptanceItems);
|
|
615
|
-
const gates = typedGateEntries.map((e) => e.gate);
|
|
616
|
-
// 2. Execute gates.
|
|
617
|
-
const results = await runGates(gates, { projectRoot, skipManual: true });
|
|
618
|
-
const testsPassed = results.filter((r) => r.result === 'pass').length;
|
|
619
|
-
const testsFailed = results.filter((r) => r.result === 'fail' || r.result === 'error').length;
|
|
620
|
-
const exitCode = testsFailed > 0 ? 1 : 0;
|
|
621
|
-
const durationMs = Date.now() - startMs;
|
|
622
|
-
// 3. Serialise gate results as JSON and store as an attachment.
|
|
623
|
-
const outputJson = JSON.stringify({ taskId, gates: results, testsPassed, testsFailed }, null, 2);
|
|
308
|
+
const outputJson = JSON.stringify(provenance, null, 2);
|
|
624
309
|
const attachmentSha256 = createHash('sha256').update(outputJson).digest('hex');
|
|
625
310
|
const store = createAttachmentStore();
|
|
626
311
|
await store.put(outputJson, {
|
|
@@ -628,31 +313,31 @@ export async function autoRunGatesAndRecord(taskId, acceptanceItems, agentIdenti
|
|
|
628
313
|
storageKey: '',
|
|
629
314
|
mime: 'application/json',
|
|
630
315
|
size: Buffer.byteLength(outputJson),
|
|
631
|
-
}, 'task', taskId, agentIdentity ?? 'ivtr-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
return
|
|
316
|
+
}, 'task', taskId, agentIdentity ?? 'ivtr-playbook-seam', cwd);
|
|
317
|
+
return attachmentSha256;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Maximum number of loop-backs allowed per phase before HITL escalation.
|
|
321
|
+
*
|
|
322
|
+
* The hand-rolled loop-back walk (`loopBackIvtr`) that enforced this cap was
|
|
323
|
+
* deleted in T11896 (the IVTR loop now runs on the cantbook runtime). The
|
|
324
|
+
* constant is RETAINED because {@link classifyReadiness} still reads it to
|
|
325
|
+
* detect tasks whose `ivtr_state.loopBackCount` has reached the monotonic
|
|
326
|
+
* per-target cap (the audit's "Gap A" parity check) and must escalate to HITL.
|
|
327
|
+
*
|
|
328
|
+
* @see packages/core/src/orchestration/classify-readiness.ts
|
|
329
|
+
*/
|
|
330
|
+
export const MAX_LOOP_BACKS_PER_PHASE = 2;
|
|
331
|
+
/**
|
|
332
|
+
* Retrieve the current IVTR state for a task, or null if the loop has not
|
|
333
|
+
* been started.
|
|
334
|
+
*
|
|
335
|
+
* @param taskId - Task ID to inspect.
|
|
336
|
+
* @param options - Optional cwd.
|
|
337
|
+
* @returns IvtrState or null.
|
|
338
|
+
*/
|
|
339
|
+
export async function getIvtrState(taskId, options) {
|
|
340
|
+
return readIvtrStateRaw(taskId, options?.cwd);
|
|
656
341
|
}
|
|
657
342
|
/**
|
|
658
343
|
* Validate whether a Lead agent is permitted to write the `implemented` gate
|