@interf/compiler 0.18.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/build-plan.d.ts +2 -0
- package/dist/cli/commands/build-plan.js +376 -0
- package/dist/cli/commands/{compile.d.ts → build.d.ts} +2 -2
- package/dist/cli/commands/{compile.js → build.js} +18 -18
- package/dist/cli/commands/doctor.js +2 -2
- package/dist/cli/commands/mcp.d.ts +0 -34
- package/dist/cli/commands/mcp.js +261 -60
- package/dist/cli/commands/prep.js +67 -35
- package/dist/cli/commands/reset.d.ts +1 -1
- package/dist/cli/commands/reset.js +6 -6
- package/dist/cli/commands/runs.js +105 -33
- package/dist/cli/commands/status.js +4 -2
- package/dist/cli/commands/test.d.ts +10 -0
- package/dist/cli/commands/{verify.js → test.js} +19 -21
- package/dist/cli/commands/web.js +82 -8
- package/dist/cli/commands/wizard.js +63 -64
- package/dist/cli/index.d.ts +4 -4
- package/dist/cli/index.js +7 -7
- package/dist/interf-ui/404.html +1 -0
- package/dist/interf-ui/__next.__PAGE__.txt +10 -0
- package/dist/{compiler-ui → interf-ui}/__next._full.txt +12 -12
- package/dist/interf-ui/__next._head.txt +5 -0
- package/dist/{compiler-ui → interf-ui}/__next._index.txt +4 -4
- package/dist/{compiler-ui → interf-ui}/__next._tree.txt +3 -3
- package/dist/interf-ui/_next/static/chunks/0.tjb6f4golw..css +3 -0
- package/dist/interf-ui/_next/static/chunks/085-n_jv2ng_q.css +1 -0
- package/dist/{compiler-ui/_next/static/chunks/0_i-3_5l9t2qe.js → interf-ui/_next/static/chunks/0dn41fa_zvgsl.js} +1 -1
- package/dist/interf-ui/_next/static/chunks/0g-ea0zj5d-0k.js +1 -0
- package/dist/interf-ui/_next/static/chunks/0gwqglc4iz583.js +1 -0
- package/dist/interf-ui/_next/static/chunks/0haldgm65ve6l.js +1 -0
- package/dist/{compiler-ui/_next/static/chunks/08g7lvje.te.u.js → interf-ui/_next/static/chunks/0nv3am99vjzn4.js} +1 -1
- package/dist/{compiler-ui/_next/static/chunks/0n51hrfoufc7g.js → interf-ui/_next/static/chunks/0s77gt_o4jwtx.js} +1 -1
- package/dist/interf-ui/_next/static/chunks/0~a36ujuzpaz..js +116 -0
- package/dist/interf-ui/_next/static/chunks/10jeodxe4nkgj.js +31 -0
- package/dist/interf-ui/_next/static/chunks/119h2rouych2t.js +1 -0
- package/dist/interf-ui/_next/static/chunks/13c8b~m8knjsf.js +1 -0
- package/dist/{compiler-ui/_next/static/chunks/08m7vf5asqlsm.js → interf-ui/_next/static/chunks/14dznb2qpt-ho.js} +5 -5
- package/dist/interf-ui/_next/static/chunks/15z_en80lrq-3.js +5 -0
- package/dist/{compiler-ui/_next/static/chunks/turbopack-10e~t1yzi4svj.js → interf-ui/_next/static/chunks/turbopack-0p.pvcjrtq-jh.js} +1 -1
- package/dist/interf-ui/_next/static/chunks/turbopack-0usj_75.8frlw.js +1 -0
- package/dist/{compiler-ui → interf-ui}/_not-found/__next._full.txt +9 -9
- package/dist/interf-ui/_not-found/__next._head.txt +5 -0
- package/dist/{compiler-ui → interf-ui}/_not-found/__next._index.txt +4 -4
- package/dist/{compiler-ui → interf-ui}/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/interf-ui/_not-found/__next._not-found.txt +5 -0
- package/dist/{compiler-ui → interf-ui}/_not-found/__next._tree.txt +2 -2
- package/dist/interf-ui/_not-found.html +1 -0
- package/dist/{compiler-ui → interf-ui}/_not-found.txt +9 -9
- package/dist/interf-ui/index.html +1 -0
- package/dist/{compiler-ui → interf-ui}/index.txt +12 -12
- package/dist/packages/build-plans/authoring/build-plan-authoring.d.ts +36 -0
- package/dist/packages/{methods/authoring/method-authoring.js → build-plans/authoring/build-plan-authoring.js} +57 -88
- package/dist/packages/build-plans/authoring/build-plan-edit-session.d.ts +18 -0
- package/dist/packages/{methods/authoring/method-edit-session.js → build-plans/authoring/build-plan-edit-session.js} +34 -34
- package/dist/packages/build-plans/authoring/build-plan-improvement.d.ts +23 -0
- package/dist/packages/build-plans/authoring/build-plan-improvement.js +216 -0
- package/dist/packages/build-plans/authoring/index.d.ts +4 -0
- package/dist/packages/build-plans/authoring/index.js +4 -0
- package/dist/packages/{methods/authoring/lib/method-edit-utils.d.ts → build-plans/authoring/lib/build-plan-edit-utils.d.ts} +3 -3
- package/dist/packages/build-plans/build-plan-resolution.d.ts +6 -0
- package/dist/packages/build-plans/build-plan-resolution.js +7 -0
- package/dist/packages/build-plans/index.d.ts +2 -0
- package/dist/packages/build-plans/index.js +2 -0
- package/dist/packages/build-plans/package/build-plan-definitions.d.ts +61 -0
- package/dist/packages/build-plans/package/build-plan-definitions.js +214 -0
- package/dist/packages/{methods/package/method-helpers.d.ts → build-plans/package/build-plan-helpers.d.ts} +7 -7
- package/dist/packages/{methods/package/method-helpers.js → build-plans/package/build-plan-helpers.js} +20 -20
- package/dist/packages/build-plans/package/build-plan-review-paths.d.ts +10 -0
- package/dist/packages/build-plans/package/build-plan-review-paths.js +31 -0
- package/dist/packages/{methods/package/method-stage-runner.d.ts → build-plans/package/build-plan-stage-runner.d.ts} +12 -12
- package/dist/packages/{methods/package/method-stage-runner.js → build-plans/package/build-plan-stage-runner.js} +10 -10
- package/dist/packages/build-plans/package/builtin-build-plan.d.ts +37 -0
- package/dist/packages/build-plans/package/builtin-build-plan.js +91 -0
- package/dist/packages/{methods → build-plans}/package/context-interface.d.ts +11 -11
- package/dist/packages/{methods → build-plans}/package/context-interface.js +23 -23
- package/dist/packages/build-plans/package/interf-build-plan-package.d.ts +31 -0
- package/dist/packages/build-plans/package/interf-build-plan-package.js +466 -0
- package/dist/packages/{methods → build-plans}/package/lib/package-root.js +1 -1
- package/dist/packages/build-plans/package/local-build-plans.d.ts +74 -0
- package/dist/packages/build-plans/package/local-build-plans.js +472 -0
- package/dist/packages/build-plans/package/user-build-plans.d.ts +17 -0
- package/dist/packages/build-plans/package/user-build-plans.js +77 -0
- package/dist/packages/contracts/index.d.ts +1 -1
- package/dist/packages/contracts/lib/preparation-paths.d.ts +37 -37
- package/dist/packages/contracts/lib/preparation-paths.js +43 -43
- package/dist/packages/contracts/lib/schema.d.ts +38 -41
- package/dist/packages/contracts/lib/schema.js +44 -35
- package/dist/packages/engine/action-definitions.d.ts +228 -67
- package/dist/packages/engine/action-definitions.js +277 -273
- package/dist/packages/engine/action-planner.d.ts +2 -2
- package/dist/packages/engine/action-planner.js +8 -15
- package/dist/packages/engine/action-values.d.ts +1 -1
- package/dist/packages/engine/action-values.js +1 -1
- package/dist/packages/engine/agents/index.d.ts +2 -2
- package/dist/packages/engine/agents/index.js +1 -1
- package/dist/packages/engine/agents/lib/args.d.ts +2 -2
- package/dist/packages/engine/agents/lib/args.js +1 -1
- package/dist/packages/engine/agents/lib/constants.js +1 -1
- package/dist/packages/engine/agents/lib/execution-profile.d.ts +5 -5
- package/dist/packages/engine/agents/lib/execution-profile.js +3 -3
- package/dist/packages/engine/agents/lib/executors.d.ts +11 -11
- package/dist/packages/engine/agents/lib/render.js +4 -4
- package/dist/packages/engine/agents/lib/shells.d.ts +33 -31
- package/dist/packages/engine/agents/lib/shells.js +254 -250
- package/dist/packages/engine/agents/lib/types.d.ts +2 -2
- package/dist/packages/engine/agents/lib/verifiable-context-bootstrap.d.ts +3 -0
- package/dist/packages/engine/agents/lib/verifiable-context-bootstrap.js +19 -0
- package/dist/packages/engine/agents/role-executors.d.ts +7 -7
- package/dist/packages/engine/agents/role-executors.js +2 -2
- package/dist/packages/engine/agents/role-router.d.ts +2 -2
- package/dist/packages/engine/agents/role-router.js +1 -1
- package/dist/packages/engine/build/artifact-counts.d.ts +1 -0
- package/dist/packages/engine/{compile → build}/artifact-counts.js +7 -7
- package/dist/packages/engine/{compile → build}/artifact-status.d.ts +8 -8
- package/dist/packages/engine/{compile → build}/artifact-status.js +19 -19
- package/dist/packages/engine/{compile → build}/billing-events.d.ts +4 -4
- package/dist/packages/engine/{compile → build}/billing-events.js +4 -4
- package/dist/packages/engine/build/build-execution.d.ts +4 -0
- package/dist/packages/engine/build/build-execution.js +4 -0
- package/dist/packages/engine/build/build-pipeline.d.ts +56 -0
- package/dist/packages/engine/{compile/compiled-pipeline.js → build/build-pipeline.js} +55 -55
- package/dist/packages/engine/build/build-plan-primitives.d.ts +2 -0
- package/dist/packages/engine/{compile/method-primitives.js → build/build-plan-primitives.js} +1 -1
- package/dist/packages/engine/build/build-plan-runs.d.ts +14 -0
- package/dist/packages/engine/build/build-plan-runs.js +31 -0
- package/dist/packages/engine/build/build-stage-plan.d.ts +16 -0
- package/dist/packages/engine/build/build-stage-plan.js +100 -0
- package/dist/packages/engine/build/build-stage-runner.d.ts +15 -0
- package/dist/packages/engine/{compile/compiled-stage-runner.js → build/build-stage-runner.js} +21 -21
- package/dist/packages/engine/build/build-target.d.ts +11 -0
- package/dist/packages/engine/build/build-target.js +16 -0
- package/dist/packages/engine/{compile → build}/check-evaluator.d.ts +4 -4
- package/dist/packages/engine/{compile → build}/check-evaluator.js +1 -1
- package/dist/packages/engine/{compile → build}/discovery.d.ts +2 -2
- package/dist/packages/engine/{compile → build}/discovery.js +4 -4
- package/dist/packages/engine/{compile → build}/index.d.ts +6 -6
- package/dist/packages/engine/{compile → build}/index.js +5 -5
- package/dist/packages/engine/{compile → build}/lib/schema.d.ts +79 -79
- package/dist/packages/engine/{compile → build}/lib/schema.js +71 -71
- package/dist/packages/engine/build/reset.d.ts +2 -0
- package/dist/packages/engine/build/reset.js +74 -0
- package/dist/packages/engine/{compile → build}/runtime-contracts.js +8 -8
- package/dist/packages/engine/build/runtime-inventory.d.ts +7 -0
- package/dist/packages/engine/{compile → build}/runtime-inventory.js +8 -8
- package/dist/packages/engine/{compile → build}/runtime-paths.js +6 -6
- package/dist/packages/engine/{compile → build}/runtime-prompt.js +11 -11
- package/dist/packages/engine/build/runtime-reconcile.d.ts +2 -0
- package/dist/packages/engine/{compile → build}/runtime-reconcile.js +18 -18
- package/dist/packages/engine/{compile → build}/runtime-runs.js +27 -27
- package/dist/packages/engine/{compile → build}/runtime-types.d.ts +10 -10
- package/dist/packages/engine/build/source-files.d.ts +46 -0
- package/dist/packages/engine/{compile → build}/source-files.js +32 -32
- package/dist/packages/engine/build/state-artifacts.d.ts +9 -0
- package/dist/packages/engine/build/state-artifacts.js +14 -0
- package/dist/packages/engine/build/state-health.d.ts +4 -0
- package/dist/packages/engine/{compile → build}/state-health.js +40 -40
- package/dist/packages/engine/build/state-io.d.ts +11 -0
- package/dist/packages/engine/{compile → build}/state-io.js +22 -22
- package/dist/packages/engine/build/state-paths.js +16 -0
- package/dist/packages/engine/build/state-view.d.ts +5 -0
- package/dist/packages/engine/{compile → build}/state-view.js +29 -29
- package/dist/packages/engine/build/state.d.ts +7 -0
- package/dist/packages/engine/build/state.js +12 -0
- package/dist/packages/engine/build/validate-verifiable-context.d.ts +27 -0
- package/dist/packages/engine/{compile/validate-compiled.js → build/validate-verifiable-context.js} +73 -73
- package/dist/packages/engine/{compile → build}/validate.d.ts +4 -4
- package/dist/packages/engine/{compile → build}/validate.js +27 -27
- package/dist/packages/engine/build/verifiable-context-paths.d.ts +47 -0
- package/dist/packages/engine/build/verifiable-context-paths.js +121 -0
- package/dist/packages/engine/build/verifiable-context-schema.d.ts +21 -0
- package/dist/packages/engine/build/verifiable-context-schema.js +126 -0
- package/dist/packages/engine/client.d.ts +16 -16
- package/dist/packages/engine/client.js +21 -21
- package/dist/packages/engine/cloud-seams.d.ts +3 -3
- package/dist/packages/engine/connection-config.js +1 -1
- package/dist/packages/engine/execution/index.d.ts +2 -2
- package/dist/packages/engine/execution/index.js +1 -1
- package/dist/packages/engine/execution/lib/schema.d.ts +100 -95
- package/dist/packages/engine/execution/lib/schema.js +31 -31
- package/dist/packages/engine/index.d.ts +7 -7
- package/dist/packages/engine/index.js +3 -3
- package/dist/packages/engine/instance-paths.d.ts +45 -39
- package/dist/packages/engine/instance-paths.js +54 -48
- package/dist/packages/engine/lib/schema.d.ts +1568 -484
- package/dist/packages/engine/lib/schema.js +172 -161
- package/dist/packages/engine/native-run-handlers.d.ts +12 -12
- package/dist/packages/engine/native-run-handlers.js +138 -136
- package/dist/packages/engine/preparation-store.d.ts +31 -36
- package/dist/packages/engine/preparation-store.js +42 -31
- package/dist/packages/engine/readiness-check-draft.d.ts +2 -2
- package/dist/packages/engine/readiness-check-draft.js +1 -1
- package/dist/packages/engine/requested-artifacts.d.ts +5 -0
- package/dist/packages/engine/requested-artifacts.js +36 -0
- package/dist/packages/engine/routes.d.ts +18 -17
- package/dist/packages/engine/routes.js +20 -19
- package/dist/packages/engine/run-observability.d.ts +5 -3
- package/dist/packages/engine/run-observability.js +103 -90
- package/dist/packages/engine/runtime-caches.d.ts +16 -16
- package/dist/packages/engine/runtime-caches.js +26 -26
- package/dist/packages/engine/runtime-event-applier.d.ts +2 -2
- package/dist/packages/engine/runtime-event-applier.js +1 -1
- package/dist/packages/engine/runtime-persistence.d.ts +9 -9
- package/dist/packages/engine/runtime-persistence.js +16 -16
- package/dist/packages/engine/runtime-proposal-helpers.d.ts +15 -15
- package/dist/packages/engine/runtime-proposal-helpers.js +81 -85
- package/dist/packages/engine/runtime-resource-builders.d.ts +16 -11
- package/dist/packages/engine/runtime-resource-builders.js +32 -21
- package/dist/packages/engine/runtime.d.ts +53 -60
- package/dist/packages/engine/runtime.js +555 -453
- package/dist/packages/engine/server.d.ts +2 -2
- package/dist/packages/engine/server.js +226 -143
- package/dist/packages/engine/service-registry.d.ts +5 -17
- package/dist/packages/engine/service-registry.js +5 -20
- package/dist/packages/engine/verify/lib/schema.d.ts +19 -19
- package/dist/packages/engine/verify/lib/schema.js +36 -8
- package/dist/packages/engine/verify/readiness-check-run.d.ts +15 -16
- package/dist/packages/engine/verify/readiness-check-run.js +46 -46
- package/dist/packages/engine/verify/verify-execution.d.ts +3 -3
- package/dist/packages/engine/verify/verify-execution.js +10 -10
- package/dist/packages/engine/verify/verify-paths.d.ts +4 -4
- package/dist/packages/engine/verify/verify-paths.js +17 -17
- package/dist/packages/engine/verify/verify-sandbox.d.ts +1 -1
- package/dist/packages/engine/verify/verify-sandbox.js +26 -26
- package/dist/packages/engine/verify/verify-targets.d.ts +2 -2
- package/dist/packages/engine/verify/verify-targets.js +17 -17
- package/dist/packages/engine/verify/verify-types.d.ts +2 -2
- package/dist/packages/engine/verify/verify.d.ts +1 -1
- package/dist/packages/engine/verify/verify.js +1 -1
- package/dist/packages/engine/wire-schemas.d.ts +42 -40
- package/dist/packages/engine/wire-schemas.js +13 -13
- package/dist/packages/project/index.d.ts +1 -1
- package/dist/packages/project/interf-bootstrap.d.ts +1 -1
- package/dist/packages/project/interf-bootstrap.js +1 -1
- package/dist/packages/project/interf-detect.d.ts +11 -11
- package/dist/packages/project/interf-detect.js +36 -36
- package/dist/packages/project/interf-scaffold.d.ts +3 -3
- package/dist/packages/project/interf-scaffold.js +72 -72
- package/dist/packages/project/interf.d.ts +4 -4
- package/dist/packages/project/interf.js +3 -3
- package/dist/packages/project/lib/schema.d.ts +205 -12
- package/dist/packages/project/lib/schema.js +59 -14
- package/dist/packages/project/preparation-entries.d.ts +3 -3
- package/dist/packages/project/preparation-entries.js +19 -19
- package/dist/packages/project/source-config.d.ts +10 -10
- package/dist/packages/project/source-config.js +62 -58
- package/dist/packages/project/source-folders.js +1 -1
- package/package.json +14 -17
- package/public-repo/CONTRIBUTING.md +47 -0
- package/public-repo/README.md +327 -0
- package/public-repo/SECURITY.md +67 -0
- package/public-repo/build-plans/interf-default/README.md +33 -0
- package/public-repo/build-plans/interf-default/build/stages/shape/SKILL.md +27 -0
- package/{builtin-methods/interf-default/compile → public-repo/build-plans/interf-default/build}/stages/structure/SKILL.md +2 -2
- package/{builtin-methods/interf-default/compile → public-repo/build-plans/interf-default/build}/stages/summarize/SKILL.md +1 -1
- package/{builtin-methods/interf-default/method.json → public-repo/build-plans/interf-default/build-plan.json} +16 -16
- package/{builtin-methods/interf-default/method.schema.json → public-repo/build-plans/interf-default/build-plan.schema.json} +4 -4
- package/public-repo/build-plans/interf-default/improve/SKILL.md +18 -0
- package/public-repo/build-plans/interf-default/use/query/SKILL.md +23 -0
- package/public-repo/plugins/README.md +9 -0
- package/public-repo/plugins/interf/.claude-plugin/plugin.json +21 -0
- package/public-repo/plugins/interf/.mcp.json +12 -0
- package/public-repo/plugins/interf/README.md +32 -0
- package/public-repo/plugins/interf/skills/interf/SKILL.md +376 -0
- package/public-repo/skills/interf/SKILL.md +376 -0
- package/README.md +0 -311
- package/agent-skills/interf-actions/SKILL.md +0 -185
- package/agent-skills/interf-actions/references/cli.md +0 -243
- package/builtin-methods/interf-default/README.md +0 -29
- package/builtin-methods/interf-default/compile/stages/shape/SKILL.md +0 -31
- package/builtin-methods/interf-default/improve/SKILL.md +0 -18
- package/builtin-methods/interf-default/use/query/SKILL.md +0 -28
- package/dist/cli/commands/method.d.ts +0 -2
- package/dist/cli/commands/method.js +0 -113
- package/dist/cli/commands/verify.d.ts +0 -10
- package/dist/compiler-ui/404.html +0 -1
- package/dist/compiler-ui/__next.__PAGE__.txt +0 -10
- package/dist/compiler-ui/__next._head.txt +0 -5
- package/dist/compiler-ui/_next/static/chunks/06yhdspx~ca5-.js +0 -5
- package/dist/compiler-ui/_next/static/chunks/06z~l3kwb891e.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0_c_tvh-cukjz.css +0 -3
- package/dist/compiler-ui/_next/static/chunks/0b-ywny_j0g~0.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0b52v41o1gixx.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0f_geuwdesg_c.js +0 -114
- package/dist/compiler-ui/_next/static/chunks/0gpzgsv0w.q~m.js +0 -31
- package/dist/compiler-ui/_next/static/chunks/0ilwfezfvu6~-.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0xxmf45eskdt~.css +0 -1
- package/dist/compiler-ui/_next/static/chunks/14wtz~vq25~qq.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/turbopack-0.uq1k8c0j4s..js +0 -1
- package/dist/compiler-ui/_not-found/__next._head.txt +0 -5
- package/dist/compiler-ui/_not-found/__next._not-found.txt +0 -5
- package/dist/compiler-ui/_not-found.html +0 -1
- package/dist/compiler-ui/index.html +0 -1
- package/dist/packages/engine/agents/lib/compiled-bootstrap.d.ts +0 -3
- package/dist/packages/engine/agents/lib/compiled-bootstrap.js +0 -19
- package/dist/packages/engine/compile/artifact-counts.d.ts +0 -1
- package/dist/packages/engine/compile/compiled-compile.d.ts +0 -4
- package/dist/packages/engine/compile/compiled-compile.js +0 -4
- package/dist/packages/engine/compile/compiled-paths.d.ts +0 -47
- package/dist/packages/engine/compile/compiled-paths.js +0 -121
- package/dist/packages/engine/compile/compiled-pipeline.d.ts +0 -56
- package/dist/packages/engine/compile/compiled-schema.d.ts +0 -21
- package/dist/packages/engine/compile/compiled-schema.js +0 -126
- package/dist/packages/engine/compile/compiled-stage-plan.d.ts +0 -16
- package/dist/packages/engine/compile/compiled-stage-plan.js +0 -100
- package/dist/packages/engine/compile/compiled-stage-runner.d.ts +0 -15
- package/dist/packages/engine/compile/compiled-target.d.ts +0 -11
- package/dist/packages/engine/compile/compiled-target.js +0 -16
- package/dist/packages/engine/compile/method-primitives.d.ts +0 -2
- package/dist/packages/engine/compile/method-runs.d.ts +0 -14
- package/dist/packages/engine/compile/method-runs.js +0 -31
- package/dist/packages/engine/compile/reset.d.ts +0 -2
- package/dist/packages/engine/compile/reset.js +0 -74
- package/dist/packages/engine/compile/runtime-inventory.d.ts +0 -7
- package/dist/packages/engine/compile/runtime-reconcile.d.ts +0 -2
- package/dist/packages/engine/compile/source-files.d.ts +0 -46
- package/dist/packages/engine/compile/state-artifacts.d.ts +0 -9
- package/dist/packages/engine/compile/state-artifacts.js +0 -14
- package/dist/packages/engine/compile/state-health.d.ts +0 -4
- package/dist/packages/engine/compile/state-io.d.ts +0 -11
- package/dist/packages/engine/compile/state-paths.js +0 -16
- package/dist/packages/engine/compile/state-view.d.ts +0 -5
- package/dist/packages/engine/compile/state.d.ts +0 -7
- package/dist/packages/engine/compile/state.js +0 -12
- package/dist/packages/engine/compile/validate-compiled.d.ts +0 -27
- package/dist/packages/methods/authoring/index.d.ts +0 -4
- package/dist/packages/methods/authoring/index.js +0 -4
- package/dist/packages/methods/authoring/method-authoring.d.ts +0 -34
- package/dist/packages/methods/authoring/method-edit-session.d.ts +0 -18
- package/dist/packages/methods/authoring/method-improvement.d.ts +0 -23
- package/dist/packages/methods/authoring/method-improvement.js +0 -217
- package/dist/packages/methods/index.d.ts +0 -2
- package/dist/packages/methods/index.js +0 -2
- package/dist/packages/methods/method-resolution.d.ts +0 -6
- package/dist/packages/methods/method-resolution.js +0 -7
- package/dist/packages/methods/package/builtin-compiled-method.d.ts +0 -37
- package/dist/packages/methods/package/builtin-compiled-method.js +0 -91
- package/dist/packages/methods/package/interf-method-package.d.ts +0 -31
- package/dist/packages/methods/package/interf-method-package.js +0 -466
- package/dist/packages/methods/package/local-methods.d.ts +0 -73
- package/dist/packages/methods/package/local-methods.js +0 -457
- package/dist/packages/methods/package/method-definitions.d.ts +0 -61
- package/dist/packages/methods/package/method-definitions.js +0 -214
- package/dist/packages/methods/package/method-review-paths.d.ts +0 -10
- package/dist/packages/methods/package/method-review-paths.js +0 -31
- package/dist/packages/methods/package/user-methods.d.ts +0 -17
- package/dist/packages/methods/package/user-methods.js +0 -77
- /package/dist/{compiler-ui/_next/static/6qyE1u9m_oBUkvAhhoCmO → interf-ui/_next/static/_qJKnA0dammQ306MG_zMq}/_buildManifest.js +0 -0
- /package/dist/{compiler-ui/_next/static/6qyE1u9m_oBUkvAhhoCmO → interf-ui/_next/static/_qJKnA0dammQ306MG_zMq}/_clientMiddlewareManifest.js +0 -0
- /package/dist/{compiler-ui/_next/static/6qyE1u9m_oBUkvAhhoCmO → interf-ui/_next/static/_qJKnA0dammQ306MG_zMq}/_ssgManifest.js +0 -0
- /package/dist/{compiler-ui → interf-ui}/_next/static/chunks/03~yq9q893hmn.js +0 -0
- /package/dist/{compiler-ui → interf-ui}/_next/static/chunks/0y5z3t-z1c8ks.js.map +0 -0
- /package/dist/{compiler-ui → interf-ui}/_next/static/chunks/turbopack-worker-0sjn--fhq~1cg.js +0 -0
- /package/dist/{compiler-ui → interf-ui}/_next/static/media/GeistMono_Variable.p.17jn9btb_52pq.woff2 +0 -0
- /package/dist/{compiler-ui → interf-ui}/_next/static/media/Geist_Variable-s.p.0-te~ja_gpvcf.woff2 +0 -0
- /package/dist/{compiler-ui → interf-ui}/_next/static/media/worker.102zas1s52_pf.js +0 -0
- /package/dist/packages/{methods/authoring/lib/method-edit-utils.js → build-plans/authoring/lib/build-plan-edit-utils.js} +0 -0
- /package/dist/packages/{methods → build-plans}/package/lib/package-root.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/runtime-contracts.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/runtime-paths.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/runtime-prompt.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/runtime-runs.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/runtime-types.js +0 -0
- /package/dist/packages/engine/{compile → build}/runtime.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/runtime.js +0 -0
- /package/dist/packages/engine/{compile → build}/state-paths.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/validate-helpers.d.ts +0 -0
- /package/dist/packages/engine/{compile → build}/validate-helpers.js +0 -0
- /package/{LICENSE.md → public-repo/LICENSE.md} +0 -0
- /package/{TRADEMARKS.md → public-repo/TRADEMARKS.md} +0 -0
|
@@ -1,43 +1,62 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, rmSync, statSync, } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { BuildRunSchema, } from "./execution/lib/schema.js";
|
|
4
4
|
import { createRunEventId, createRunEventTimestamp, } from "./execution/events.js";
|
|
5
|
-
import { loadState, } from "./
|
|
6
|
-
import { actionProposalPath, actionProposalsRoot, byCreatedAtDesc,
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { ACTION_PLANNER_CLARIFICATION_MESSAGE, actionAssistantMessage, actionCommandPreview, actionTypeFromValues,
|
|
5
|
+
import { loadState, } from "./build/state.js";
|
|
6
|
+
import { actionProposalPath, actionProposalsRoot, byCreatedAtDesc, buildRunPath, buildRunsRoot, listJsonFiles, localJobPath, localJobsRoot, newestFirst, readActionProposalAt, readBuildRunAt, readLocalJobRunAt, readRuntimeRunHistory, readVerifyRunAt, verifyRunPath, verifyRunsRoot, timestampKey, writeJsonFile, } from "./runtime-persistence.js";
|
|
7
|
+
import { BuildPlanListingCache, MtimeListingCache, ReadinessCache, RunListingCache, } from "./runtime-caches.js";
|
|
8
|
+
import { applyEventToBuildRun, applyEventToLocalJob, } from "./runtime-event-applier.js";
|
|
9
|
+
import { buildBuildPlanResource, buildPreparationResource, createRunId, logsForRuntimeRun, logsForStageRun, proofForStage, readinessStateToPreparationReadiness, readinessSummaryForStatus, readinessTargetResult, stageArtifactRefs, } from "./runtime-resource-builders.js";
|
|
10
|
+
import { ACTION_PLANNER_CLARIFICATION_MESSAGE, actionAssistantMessage, actionCommandPreview, actionTypeFromValues, actionValueBuildPlanTaskPrompt, configuredAgentName, createActionProposalId, detachBuildPlanFromPreparation, detectedExecutorOptions, directServiceEndpointForAction, hasVerifiableContextTestTarget, buildPlanAuthoringHintFromPrompt, buildPlanAuthoringPromptFallback, buildPlanIdForProposal, buildPlanLabelFromId, numberValue, requireSelectedBuildPlan, sanitizeActionProposalPlan, stringValue, testModeFromValues, } from "./runtime-proposal-helpers.js";
|
|
11
11
|
import { ReadinessSchema, } from "../contracts/lib/schema.js";
|
|
12
|
-
import { discoverSourceFiles, } from "./
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { findSourcePreparationConfig, fingerprintReadinessChecks, listSourcePreparationConfigs, loadSourceFolderConfig,
|
|
12
|
+
import { discoverSourceFiles, } from "./build/discovery.js";
|
|
13
|
+
import { resetBuildGeneratedState, } from "./build/reset.js";
|
|
14
|
+
import { ensureVerifiableContextScaffold, readInterfConfig, } from "../project/interf.js";
|
|
15
|
+
import { findSourcePreparationConfig, fingerprintReadinessChecks, listSourcePreparationConfigs, loadSourceFolderConfig, DEFAULT_BUILD_PLAN_ID, buildPlanIdForSourcePreparationConfig, resolveConfiguredSourceFolderPath, resolveSourcePreparationPath, removeSourcePreparationConfig, saveSourceFolderConfig, syncVerifiableContextInterfConfigFromSourcePreparationConfig, upsertSourcePreparationConfig, } from "../project/source-config.js";
|
|
16
16
|
import { listSourceFolderChoices, } from "../project/source-folders.js";
|
|
17
|
-
import { asPreparationDataDir,
|
|
18
|
-
import {
|
|
19
|
-
import { computeArtifactStatuses, } from "./
|
|
20
|
-
import { JsonlBillingEventSink, buildCompilationEventsForRun, defaultBillingEventLogPath, } from "./
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { PACKAGE_ROOT } from "../
|
|
17
|
+
import { asPreparationDataDir, preparationVerifiableContextPath, userBuildPlansRoot, preparationConfigPath, preparationBuildPlanPackagePath, preparationBuildPlansRoot, } from "../contracts/lib/preparation-paths.js";
|
|
18
|
+
import { getBuildPlan, listBuildPlanChoices, } from "../build-plans/package/build-plan-definitions.js";
|
|
19
|
+
import { aggregateArtifactVerdict, computeArtifactStatuses, } from "./build/artifact-status.js";
|
|
20
|
+
import { JsonlBillingEventSink, buildCompilationEventsForRun, defaultBillingEventLogPath, } from "./build/billing-events.js";
|
|
21
|
+
import { buildPlanDefinitionPath, resolveBuildPlanPackageSourcePath, } from "../build-plans/package/local-build-plans.js";
|
|
22
|
+
import { seedLocalBuildPlanPackageFromBase, } from "../build-plans/package/interf-build-plan-package.js";
|
|
23
|
+
import { PACKAGE_ROOT } from "../build-plans/package/lib/package-root.js";
|
|
24
24
|
import { resolveAgent, detectAgents, supportsAutomatedRuns, } from "./agents/lib/detection.js";
|
|
25
25
|
import { loadUserConfig, saveUserConfig, } from "./agents/lib/user-config.js";
|
|
26
26
|
import { loadAgentsRegistry, registerCustomAgent, unregisterCustomAgent, patchRoleMap, setActiveAgent, } from "./agents/registry.js";
|
|
27
27
|
import { readSavedReadinessCheckRun, } from "./verify/readiness-check-run.js";
|
|
28
|
-
import {
|
|
29
|
-
import { ActionProposalApprovalRequestSchema, ActionProposalCreateRequestSchema, ActionProposalPlanSchema, ActionProposalResourceSchema, ActionProposalTypeSchema,
|
|
28
|
+
import { createVerifiableContextTestTarget, } from "./verify/verify-targets.js";
|
|
29
|
+
import { ActionProposalApprovalRequestSchema, ActionProposalCreateRequestSchema, ActionProposalPlanSchema, ActionProposalResourceSchema, ActionProposalTypeSchema, BuildRunCreateRequestSchema, BuildRunResourceSchema, LocalExecutorStatusSchema, LocalExecutorSelectRequestSchema, LocalServiceHealthSchema, LocalRunHandlerResultSchema, LocalJobEventAppendRequestSchema, LocalJobRunCreateRequestSchema, LocalJobRunResourceSchema, SourceFileResourceSchema, VerifiableContextResourceSchema, PreparationSetupCreateRequestSchema, PreparationSetupResultSchema, BuildPlanChangeCreateRequestSchema, BuildPlanChangeResultSchema, PreparationChangeCreateRequestSchema, PreparationChangeResultSchema, ReadinessCheckDraftCreateRequestSchema, ReadinessCheckDraftResultSchema, ResetRequestSchema, ResetResultSchema, VerifyRunCreateRequestSchema, VerifyRunResourceSchema, BuildPlanAuthoringCreateRequestSchema, BuildPlanAuthoringResultSchema, } from "./lib/schema.js";
|
|
30
30
|
import { buildLocalServiceUrl, } from "./routes.js";
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
|
|
31
|
+
import { BuildPlanAuthoringActionValuesSchema, PreparationSetupActionValuesSchema, } from "./action-values.js";
|
|
32
|
+
import { buildRunToObservability, jobRunToObservability, verifyRunToObservability, uniqueArtifacts, } from "./run-observability.js";
|
|
33
|
+
import { artifactRequirementsFromRequestedArtifacts } from "./requested-artifacts.js";
|
|
34
|
+
/** TTL for `POS../../build-runs` idempotency-key dedupe entries. */
|
|
34
35
|
const IDEMPOTENCY_TTL_MS = 60 * 60 * 1000;
|
|
35
36
|
/** Idempotency cache size at which to schedule an opportunistic prune. */
|
|
36
37
|
const IDEMPOTENCY_PRUNE_THRESHOLD = 64;
|
|
37
|
-
const INTERRUPTED_COMPILE_RUN_MESSAGE = "
|
|
38
|
-
|
|
38
|
+
const INTERRUPTED_COMPILE_RUN_MESSAGE = "Build run interrupted because the Interf engine stopped before the run reached a terminal state.";
|
|
39
|
+
const INTERRUPTED_JOB_RUN_MESSAGE = "Job interrupted because the Interf engine stopped before the job reached a terminal state.";
|
|
40
|
+
function isTerminalBuildRunStatus(status) {
|
|
39
41
|
return status === "succeeded" || status === "failed" || status === "cancelled";
|
|
40
42
|
}
|
|
43
|
+
function isTerminalJobStatus(status) {
|
|
44
|
+
return status === "succeeded" || status === "failed" || status === "cancelled";
|
|
45
|
+
}
|
|
46
|
+
function countsFromVerifiableContextState(state) {
|
|
47
|
+
const counts = {};
|
|
48
|
+
for (const stage of Object.values(state.stages ?? {})) {
|
|
49
|
+
for (const [key, value] of Object.entries(stage.counts ?? {})) {
|
|
50
|
+
if (Number.isFinite(value))
|
|
51
|
+
counts[key] = Math.max(counts[key] ?? 0, value);
|
|
52
|
+
}
|
|
53
|
+
for (const [key, value] of Object.entries(stage.artifact_counts ?? {})) {
|
|
54
|
+
if (Number.isFinite(value))
|
|
55
|
+
counts[key] = Math.max(counts[key] ?? 0, value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return counts;
|
|
59
|
+
}
|
|
41
60
|
export class LocalServiceRuntime {
|
|
42
61
|
host;
|
|
43
62
|
port;
|
|
@@ -47,8 +66,8 @@ export class LocalServiceRuntime {
|
|
|
47
66
|
/**
|
|
48
67
|
* The seed root path the runtime was constructed with. Used as a
|
|
49
68
|
* non-preparation fallback when a preparation-independent route
|
|
50
|
-
* (
|
|
51
|
-
* shared state (user-library
|
|
69
|
+
* (Build Plans, action proposals, runs listings) needs an anchor to load
|
|
70
|
+
* shared state (user-library Build Plans, bundled Build Plans, etc).
|
|
52
71
|
*/
|
|
53
72
|
rootPath;
|
|
54
73
|
/**
|
|
@@ -63,8 +82,8 @@ export class LocalServiceRuntime {
|
|
|
63
82
|
/** In-flight runs across all preparations. Used for `idle_for_seconds`. */
|
|
64
83
|
activeRunCount = 0;
|
|
65
84
|
/**
|
|
66
|
-
* Active
|
|
67
|
-
* when a
|
|
85
|
+
* Active Build run cancellation handles, keyed by run id. Populated
|
|
86
|
+
* when a Build run is launched and cleared once the run reaches a
|
|
68
87
|
* terminal state. Each entry remembers where the persisted record lives
|
|
69
88
|
* so cancel can mark it without re-resolving the Preparation.
|
|
70
89
|
*
|
|
@@ -73,9 +92,9 @@ export class LocalServiceRuntime {
|
|
|
73
92
|
* need a shared lease store so a replica can take over a run whose
|
|
74
93
|
* owning replica died.
|
|
75
94
|
*/
|
|
76
|
-
|
|
95
|
+
activeBuildRuns = new Map();
|
|
77
96
|
/**
|
|
78
|
-
* Idempotency-key cache for `
|
|
97
|
+
* Idempotency-key cache for `POS../../build-runs`. Outer key is the
|
|
79
98
|
* resolved preparation root; inner key is the client-supplied idempotency
|
|
80
99
|
* value. Namespacing per preparation prevents key collisions across
|
|
81
100
|
* tenants on the same engine (CSO finding: a malicious preparation could
|
|
@@ -89,17 +108,17 @@ export class LocalServiceRuntime {
|
|
|
89
108
|
*/
|
|
90
109
|
idempotencyKeyCache = new Map();
|
|
91
110
|
/**
|
|
92
|
-
* Read-side caches. Polling clients (
|
|
111
|
+
* Read-side caches. Polling clients (Interf UI, CLI status loops)
|
|
93
112
|
* hit list/get endpoints multiple times per second; without these,
|
|
94
113
|
* every request re-walks the filesystem and re-parses every JSON
|
|
95
114
|
* record through Zod. The runtime invalidates each cache on the
|
|
96
115
|
* matching write path. See {@link runtime-caches} for design notes.
|
|
97
116
|
*/
|
|
98
|
-
|
|
117
|
+
buildRunCache = new RunListingCache();
|
|
99
118
|
verifyRunCache = new RunListingCache();
|
|
100
119
|
readinessCache = new ReadinessCache();
|
|
101
120
|
sourceFilesCache = new MtimeListingCache();
|
|
102
|
-
|
|
121
|
+
buildPlanListingCache = new BuildPlanListingCache();
|
|
103
122
|
/**
|
|
104
123
|
* 0.17 — sink for per-Artifact billing events. Set once at construction.
|
|
105
124
|
* Lazy-defaults to a per-run JSONL writer when no override was injected.
|
|
@@ -130,7 +149,7 @@ export class LocalServiceRuntime {
|
|
|
130
149
|
// Auto-register the initial preparation so single-preparation callers
|
|
131
150
|
// (existing tests, the current `interf web` command) work without
|
|
132
151
|
// additional bootstrapping. The constructor seed is the only role
|
|
133
|
-
// `options.rootPath` plays; runtime
|
|
152
|
+
// `options.rootPath` plays; runtime operations take `prepDataDir`
|
|
134
153
|
// explicitly afterwards.
|
|
135
154
|
this.registerPreparation(this.rootPath);
|
|
136
155
|
}
|
|
@@ -172,7 +191,8 @@ export class LocalServiceRuntime {
|
|
|
172
191
|
lastActivity: now,
|
|
173
192
|
};
|
|
174
193
|
this.preparationContexts.set(resolved, context);
|
|
175
|
-
this.
|
|
194
|
+
this.finalizeInterruptedBuildRuns(resolved);
|
|
195
|
+
this.finalizeInterruptedJobRuns(resolved);
|
|
176
196
|
this.onRegistryChanged?.();
|
|
177
197
|
return context;
|
|
178
198
|
}
|
|
@@ -248,20 +268,6 @@ export class LocalServiceRuntime {
|
|
|
248
268
|
context.lastActivity = new Date().toISOString();
|
|
249
269
|
}
|
|
250
270
|
}
|
|
251
|
-
/**
|
|
252
|
-
* Snapshot of registered preparations for the registry / status output.
|
|
253
|
-
* Wire shape (`ServiceRegistryWorkspace`) keeps the legacy
|
|
254
|
-
* "workspace" name for backward compatibility with the public health
|
|
255
|
-
* response and `~/.interf/services.json`. Synthetic-workspace bridge
|
|
256
|
-
* code; do not rename without coordinating an API break.
|
|
257
|
-
*/
|
|
258
|
-
registeredPreparationSnapshots() {
|
|
259
|
-
return this.listRegisteredPreparations().map((context) => ServiceRegistryWorkspaceSchema.parse({
|
|
260
|
-
control_path: context.rootPath,
|
|
261
|
-
registered_at: context.startedAt,
|
|
262
|
-
last_activity: context.lastActivity,
|
|
263
|
-
}));
|
|
264
|
-
}
|
|
265
271
|
/** Seconds since the most recent preparation activity (0 if active). */
|
|
266
272
|
idleForSeconds() {
|
|
267
273
|
const all = this.listRegisteredPreparations();
|
|
@@ -294,7 +300,6 @@ export class LocalServiceRuntime {
|
|
|
294
300
|
started_at: this.startedAt,
|
|
295
301
|
...(this.packageVersion ? { package_version: this.packageVersion } : {}),
|
|
296
302
|
instance_started_at: this.startedAt,
|
|
297
|
-
registered_workspaces: this.registeredPreparationSnapshots(),
|
|
298
303
|
active_runs: this.activeRunCount,
|
|
299
304
|
idle_for_seconds: this.idleForSeconds(),
|
|
300
305
|
});
|
|
@@ -302,14 +307,14 @@ export class LocalServiceRuntime {
|
|
|
302
307
|
listPreparations(prepDataDir) {
|
|
303
308
|
const config = loadSourceFolderConfig(prepDataDir);
|
|
304
309
|
return listSourcePreparationConfigs(config).map((preparation) => {
|
|
305
|
-
const
|
|
310
|
+
const buildRuns = this.listBuildRunsForPreparation(prepDataDir, preparation.name);
|
|
306
311
|
const verifyRuns = this.listVerifyRunsForPreparation(prepDataDir, preparation.name);
|
|
307
312
|
const readiness = this.computePreparationReadiness(prepDataDir, preparation);
|
|
308
|
-
return buildPreparationResource(prepDataDir, preparation, readiness,
|
|
309
|
-
// 0.17 — surface per-Artifact status from the latest
|
|
313
|
+
return buildPreparationResource(prepDataDir, preparation, readiness, buildRuns[0]?.run_id ?? null, verifyRuns[0]?.run_id ?? null,
|
|
314
|
+
// 0.17 — surface per-Artifact status from the latest build
|
|
310
315
|
// run so the UI can render artifact rows on the Preparation
|
|
311
316
|
// page without a separate fetch.
|
|
312
|
-
|
|
317
|
+
buildRuns[0]?.artifacts ?? []);
|
|
313
318
|
});
|
|
314
319
|
}
|
|
315
320
|
getPreparation(prepDataDir, preparationName) {
|
|
@@ -335,60 +340,67 @@ export class LocalServiceRuntime {
|
|
|
335
340
|
}
|
|
336
341
|
computePreparationReadinessUncached(prepDataDir, preparation) {
|
|
337
342
|
const generatedAt = new Date().toISOString();
|
|
338
|
-
const
|
|
339
|
-
const contextExists = existsSync(
|
|
340
|
-
const
|
|
341
|
-
const contextReady =
|
|
342
|
-
const
|
|
343
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparation.name);
|
|
344
|
+
const contextExists = existsSync(verifiableContextPath);
|
|
345
|
+
const verifiableContextTarget = createVerifiableContextTestTarget(verifiableContextPath, preparation.name, buildPlanIdForSourcePreparationConfig(preparation) ?? DEFAULT_BUILD_PLAN_ID);
|
|
346
|
+
const contextReady = verifiableContextTarget.eligible;
|
|
347
|
+
const buildRun = this.listBuildRunsForPreparation(prepDataDir, preparation.name)[0] ?? null;
|
|
343
348
|
const verifyRun = this.listVerifyRunsForPreparation(prepDataDir, preparation.name)[0] ?? null;
|
|
344
349
|
const readinessRun = this.readLatestReadinessRun(prepDataDir, preparation.name);
|
|
350
|
+
const artifactStatuses = buildRun?.artifacts ?? [];
|
|
351
|
+
const hasArtifactContract = artifactStatuses.length > 0;
|
|
352
|
+
const artifactVerdict = aggregateArtifactVerdict(artifactStatuses);
|
|
353
|
+
const artifactFailures = artifactStatuses.filter((artifact) => artifact.status !== "ready");
|
|
354
|
+
const artifactProofs = artifactStatuses.flatMap((artifact) => artifact.proofs ?? []);
|
|
355
|
+
const requiredArtifactProofs = artifactProofs.filter((proof) => proof.required !== false);
|
|
356
|
+
const passedArtifactProofs = requiredArtifactProofs.filter((proof) => proof.passed);
|
|
345
357
|
const configuredChecks = preparation.checks.length;
|
|
346
358
|
const currentFingerprint = configuredChecks > 0 ? fingerprintReadinessChecks(preparation.checks) : null;
|
|
347
359
|
const readinessRunFingerprint = readinessRun?.checks_fingerprint ?? null;
|
|
348
360
|
const sourceResult = readinessTargetResult(readinessRun?.source_files, currentFingerprint, readinessRunFingerprint);
|
|
349
|
-
const contextResult = readinessTargetResult(readinessRun?.
|
|
361
|
+
const contextResult = readinessTargetResult(readinessRun?.verifiable_context, currentFingerprint, readinessRunFingerprint);
|
|
350
362
|
const checksStale = Boolean(currentFingerprint && readinessRunFingerprint && currentFingerprint !== readinessRunFingerprint);
|
|
351
|
-
const
|
|
352
|
-
if (!
|
|
363
|
+
const buildCheck = (() => {
|
|
364
|
+
if (!buildRun) {
|
|
353
365
|
return {
|
|
354
|
-
gate: "
|
|
366
|
+
gate: "build-run",
|
|
355
367
|
ok: false,
|
|
356
368
|
status: "not-built",
|
|
357
|
-
summary: "No
|
|
358
|
-
artifact_path: contextReady ?
|
|
369
|
+
summary: "No Build run has built verifiable context yet.",
|
|
370
|
+
artifact_path: contextReady ? verifiableContextPath : null,
|
|
359
371
|
};
|
|
360
372
|
}
|
|
361
|
-
if (
|
|
373
|
+
if (buildRun.status === "succeeded") {
|
|
362
374
|
return {
|
|
363
|
-
gate: "
|
|
375
|
+
gate: "build-run",
|
|
364
376
|
ok: contextReady,
|
|
365
377
|
status: contextReady ? "built" : "failed",
|
|
366
378
|
summary: contextReady
|
|
367
|
-
? "Latest
|
|
368
|
-
: "Latest
|
|
369
|
-
run_id:
|
|
370
|
-
artifact_path: contextReady ?
|
|
379
|
+
? "Latest Build run built verifiable context."
|
|
380
|
+
: "Latest Build run finished, but verifiable context is missing.",
|
|
381
|
+
run_id: buildRun.run_id,
|
|
382
|
+
artifact_path: contextReady ? verifiableContextPath : null,
|
|
371
383
|
};
|
|
372
384
|
}
|
|
373
|
-
if (
|
|
385
|
+
if (buildRun.status === "queued" || buildRun.status === "running") {
|
|
374
386
|
return {
|
|
375
|
-
gate: "
|
|
387
|
+
gate: "build-run",
|
|
376
388
|
ok: false,
|
|
377
389
|
status: "building",
|
|
378
|
-
summary: "Latest
|
|
379
|
-
run_id:
|
|
380
|
-
artifact_path: contextExists ?
|
|
390
|
+
summary: "Latest Build run is still building verifiable context.",
|
|
391
|
+
run_id: buildRun.run_id,
|
|
392
|
+
artifact_path: contextExists ? verifiableContextPath : null,
|
|
381
393
|
};
|
|
382
394
|
}
|
|
383
395
|
return {
|
|
384
|
-
gate: "
|
|
396
|
+
gate: "build-run",
|
|
385
397
|
ok: false,
|
|
386
398
|
status: "failed",
|
|
387
|
-
summary:
|
|
388
|
-
? "Latest
|
|
389
|
-
: "Latest
|
|
390
|
-
run_id:
|
|
391
|
-
artifact_path: contextReady ?
|
|
399
|
+
summary: buildRun.status === "cancelled"
|
|
400
|
+
? "Latest Build run was cancelled."
|
|
401
|
+
: "Latest Build run failed.",
|
|
402
|
+
run_id: buildRun.run_id,
|
|
403
|
+
artifact_path: contextReady ? verifiableContextPath : null,
|
|
392
404
|
};
|
|
393
405
|
})();
|
|
394
406
|
const checks = [
|
|
@@ -398,22 +410,34 @@ export class LocalServiceRuntime {
|
|
|
398
410
|
summary: "Preparation is saved in this control plane folder.",
|
|
399
411
|
},
|
|
400
412
|
{
|
|
401
|
-
gate: "
|
|
413
|
+
gate: "verifiable-context",
|
|
402
414
|
ok: contextReady,
|
|
403
415
|
status: contextReady ? "built" : "not-built",
|
|
404
416
|
summary: contextReady
|
|
405
|
-
? "
|
|
406
|
-
: "
|
|
407
|
-
artifact_path: contextReady ?
|
|
417
|
+
? "Verifiable context is built."
|
|
418
|
+
: "Verifiable context has not been built.",
|
|
419
|
+
artifact_path: contextReady ? verifiableContextPath : null,
|
|
420
|
+
},
|
|
421
|
+
buildCheck,
|
|
422
|
+
{
|
|
423
|
+
gate: "artifact-checks",
|
|
424
|
+
ok: !hasArtifactContract || artifactVerdict === "ready",
|
|
425
|
+
status: !hasArtifactContract
|
|
426
|
+
? "not-configured"
|
|
427
|
+
: artifactVerdict === "ready" ? "ready" : "not-ready",
|
|
428
|
+
summary: !hasArtifactContract
|
|
429
|
+
? "No Artifacts are declared by the selected Build Plan."
|
|
430
|
+
: artifactVerdict === "ready"
|
|
431
|
+
? `${artifactStatuses.length} Artifact${artifactStatuses.length === 1 ? "" : "s"} ready; ${passedArtifactProofs.length}/${requiredArtifactProofs.length} required Artifact check${requiredArtifactProofs.length === 1 ? "" : "s"} passed.`
|
|
432
|
+
: `${artifactFailures.length} Artifact${artifactFailures.length === 1 ? "" : "s"} not ready.`,
|
|
408
433
|
},
|
|
409
|
-
compileCheck,
|
|
410
434
|
{
|
|
411
435
|
gate: "readiness-checks",
|
|
412
|
-
ok:
|
|
436
|
+
ok: true,
|
|
413
437
|
status: configuredChecks > 0 ? "built" : "not-configured",
|
|
414
438
|
summary: configuredChecks > 0
|
|
415
439
|
? `${configuredChecks} readiness check${configuredChecks === 1 ? "" : "s"} configured.`
|
|
416
|
-
: "No readiness checks are configured.",
|
|
440
|
+
: "No optional readiness checks are configured.",
|
|
417
441
|
},
|
|
418
442
|
{
|
|
419
443
|
gate: "checks-current",
|
|
@@ -425,18 +449,20 @@ export class LocalServiceRuntime {
|
|
|
425
449
|
},
|
|
426
450
|
];
|
|
427
451
|
const status = (() => {
|
|
428
|
-
if (
|
|
452
|
+
if (buildRun?.status === "queued" || buildRun?.status === "running")
|
|
429
453
|
return "building";
|
|
430
454
|
if (verifyRun?.status === "queued" || verifyRun?.status === "running")
|
|
431
455
|
return "checking";
|
|
432
|
-
if (
|
|
456
|
+
if (buildRun?.status === "failed" || buildRun?.status === "cancelled")
|
|
433
457
|
return "failed";
|
|
434
|
-
if (!
|
|
458
|
+
if (!buildRun || !contextReady)
|
|
435
459
|
return "not-built";
|
|
436
|
-
if (
|
|
437
|
-
return "not-
|
|
460
|
+
if (hasArtifactContract && artifactVerdict !== "ready")
|
|
461
|
+
return "not-ready";
|
|
438
462
|
if (checksStale)
|
|
439
463
|
return "stale";
|
|
464
|
+
if (configuredChecks === 0)
|
|
465
|
+
return hasArtifactContract ? "ready" : "built";
|
|
440
466
|
if (!contextResult)
|
|
441
467
|
return "built";
|
|
442
468
|
return contextResult.total > 0 && contextResult.passed === contextResult.total ? "ready" : "not-ready";
|
|
@@ -450,15 +476,15 @@ export class LocalServiceRuntime {
|
|
|
450
476
|
status,
|
|
451
477
|
ready,
|
|
452
478
|
summary: readinessSummaryForStatus(status),
|
|
453
|
-
|
|
454
|
-
|
|
479
|
+
verifiable_context_path: contextReady ? verifiableContextPath : null,
|
|
480
|
+
latest_build_run_id: buildRun?.run_id ?? null,
|
|
455
481
|
latest_test_run_id: verifyRun?.run_id ?? null,
|
|
456
|
-
|
|
482
|
+
build: buildCheck,
|
|
457
483
|
check_results: {
|
|
458
484
|
configured: configuredChecks,
|
|
459
485
|
fingerprint: currentFingerprint,
|
|
460
486
|
source_files: sourceResult,
|
|
461
|
-
|
|
487
|
+
verifiable_context: contextResult,
|
|
462
488
|
},
|
|
463
489
|
checks,
|
|
464
490
|
});
|
|
@@ -469,19 +495,19 @@ export class LocalServiceRuntime {
|
|
|
469
495
|
.filter((preparation) => !preparationName || preparation.name === preparationName);
|
|
470
496
|
// 0.13+ source binding: the source folder is the user-supplied
|
|
471
497
|
// absolute path on `source_folder.path`. `preparation.path` is the
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
// the actual source bytes, not the
|
|
498
|
+
// verifiable-context name inside `prepDataDir` (legacy field; in the
|
|
499
|
+
// current Preparation layout it equals `preparation.name`). Walk
|
|
500
|
+
// the actual source bytes, not the verifiable-context subdir.
|
|
475
501
|
const sourceFolderPath = resolveConfiguredSourceFolderPath(prepDataDir, config) ?? prepDataDir;
|
|
476
502
|
return preparations.flatMap((preparation) => {
|
|
477
|
-
const
|
|
503
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparation.name);
|
|
478
504
|
// Cache by source-folder root mtime so identical UI polls do not
|
|
479
505
|
// re-walk and re-stat the entire tree. The cache imposes a short
|
|
480
506
|
// TTL (see runtime-caches.ts) so deeper changes are still picked
|
|
481
507
|
// up promptly.
|
|
482
|
-
const cacheKey = `${preparation.name}\0${sourceFolderPath}\0${
|
|
508
|
+
const cacheKey = `${preparation.name}\0${sourceFolderPath}\0${verifiableContextPath}`;
|
|
483
509
|
return this.sourceFilesCache.get(cacheKey, sourceFolderPath, () => {
|
|
484
|
-
return discoverSourceFiles(sourceFolderPath,
|
|
510
|
+
return discoverSourceFiles(sourceFolderPath, verifiableContextPath).sourceFiles.map((relativePath) => {
|
|
485
511
|
const absolutePath = join(sourceFolderPath, relativePath);
|
|
486
512
|
let sizeBytes = 0;
|
|
487
513
|
let modifiedAt = null;
|
|
@@ -506,55 +532,34 @@ export class LocalServiceRuntime {
|
|
|
506
532
|
});
|
|
507
533
|
});
|
|
508
534
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
let modifiedAt = null;
|
|
515
|
-
try {
|
|
516
|
-
const stat = statSync(absolutePath);
|
|
517
|
-
sizeBytes = stat.size;
|
|
518
|
-
modifiedAt = stat.mtime.toISOString();
|
|
519
|
-
}
|
|
520
|
-
catch {
|
|
521
|
-
sizeBytes = 0;
|
|
522
|
-
modifiedAt = null;
|
|
523
|
-
}
|
|
524
|
-
return WorkspaceFileResourceSchema.parse({
|
|
525
|
-
path: relativePath,
|
|
526
|
-
absolute_path: absolutePath,
|
|
527
|
-
size_bytes: sizeBytes,
|
|
528
|
-
modified_at: modifiedAt,
|
|
529
|
-
});
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
listMethods(prepDataDir) {
|
|
533
|
-
// The Method choices list is dominated by repeated reads of
|
|
534
|
-
// method.json + context-interface across builtin / user / workspace
|
|
535
|
-
// method roots. Key the cache off mtimes for the three roots; if
|
|
536
|
-
// any of them changes (a new local Method, an edit to the user
|
|
535
|
+
listBuildPlans(prepDataDir) {
|
|
536
|
+
// The Build Plan choices list is dominated by repeated reads of
|
|
537
|
+
// build-plan.json + context-interface across bundled, user-library, and
|
|
538
|
+
// Preparation-local Build Plan package roots. Key the cache off mtimes; if
|
|
539
|
+
// any of them changes (a new local Build Plan, an edit to the user
|
|
537
540
|
// library, etc.) the cache misses and we re-resolve.
|
|
538
|
-
const builtinRoot = join(PACKAGE_ROOT, "
|
|
539
|
-
const localRoot =
|
|
540
|
-
const userRoot =
|
|
541
|
-
return this.
|
|
541
|
+
const builtinRoot = join(PACKAGE_ROOT, "public-repo", "build-plans");
|
|
542
|
+
const localRoot = preparationBuildPlansRoot(asPreparationDataDir(prepDataDir));
|
|
543
|
+
const userRoot = userBuildPlansRoot();
|
|
544
|
+
return this.buildPlanListingCache.get(prepDataDir, [builtinRoot, localRoot, userRoot], () => {
|
|
542
545
|
const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir));
|
|
543
|
-
const choices =
|
|
544
|
-
return choices.map((
|
|
546
|
+
const choices = listBuildPlanChoices(prepDataDir);
|
|
547
|
+
return choices.map((buildPlan) => {
|
|
545
548
|
const activeForPreparations = preparations
|
|
546
|
-
.filter((preparation) =>
|
|
549
|
+
.filter((preparation) => buildPlanIdForSourcePreparationConfig(preparation) === buildPlan.id)
|
|
547
550
|
.map((preparation) => preparation.name);
|
|
548
|
-
return
|
|
549
|
-
id:
|
|
550
|
-
path:
|
|
551
|
-
label:
|
|
552
|
-
hint:
|
|
553
|
-
|
|
554
|
-
|
|
551
|
+
return buildBuildPlanResource({
|
|
552
|
+
id: buildPlan.id,
|
|
553
|
+
path: resolveBuildPlanPackageSourcePath(prepDataDir, buildPlan.id) ?? buildPlan.id,
|
|
554
|
+
label: buildPlan.label,
|
|
555
|
+
hint: buildPlan.hint,
|
|
556
|
+
purpose: buildPlan.purpose,
|
|
557
|
+
inputs: buildPlan.inputs,
|
|
558
|
+
source_kind: buildPlan.scope === "builtin" ? "builtin" : "local",
|
|
559
|
+
built_in: buildPlan.scope === "builtin",
|
|
555
560
|
active_for_preparations: activeForPreparations,
|
|
556
|
-
artifacts:
|
|
557
|
-
stages:
|
|
561
|
+
artifacts: buildPlan.contextInterface?.artifacts ?? [],
|
|
562
|
+
stages: buildPlan.stages.map((stage) => ({
|
|
558
563
|
id: stage.id,
|
|
559
564
|
label: stage.label,
|
|
560
565
|
description: stage.description,
|
|
@@ -568,8 +573,8 @@ export class LocalServiceRuntime {
|
|
|
568
573
|
});
|
|
569
574
|
});
|
|
570
575
|
}
|
|
571
|
-
|
|
572
|
-
return this.
|
|
576
|
+
getBuildPlanResource(prepDataDir, buildPlanId) {
|
|
577
|
+
return this.listBuildPlans(prepDataDir).find((buildPlan) => buildPlan.id === buildPlanId) ?? null;
|
|
573
578
|
}
|
|
574
579
|
listJobs(prepDataDir) {
|
|
575
580
|
return byCreatedAtDesc(listJsonFiles(localJobsRoot(prepDataDir))
|
|
@@ -754,7 +759,10 @@ export class LocalServiceRuntime {
|
|
|
754
759
|
}
|
|
755
760
|
listRunObservability(prepDataDir) {
|
|
756
761
|
return [
|
|
757
|
-
...this.
|
|
762
|
+
...this.listBuildRuns(prepDataDir).map((resource) => buildRunToObservability({
|
|
763
|
+
...resource.run,
|
|
764
|
+
readiness: this.getReadiness(prepDataDir, resource.run.preparation),
|
|
765
|
+
})),
|
|
758
766
|
...this.listVerifyRuns(prepDataDir).map(verifyRunToObservability),
|
|
759
767
|
...this.listJobs(prepDataDir).map(jobRunToObservability),
|
|
760
768
|
].sort((left, right) => {
|
|
@@ -767,17 +775,17 @@ export class LocalServiceRuntime {
|
|
|
767
775
|
return this.listRunObservability(prepDataDir).find((run) => run.run_id === runId) ?? null;
|
|
768
776
|
}
|
|
769
777
|
/**
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
* `GET /v1/
|
|
773
|
-
* trail of authoring + improvement work
|
|
778
|
+
* Build Plan Activity runs: every Build Plan draft or improvement job whose
|
|
779
|
+
* Build Plan id matches `buildPlanId`. Surfaced through
|
|
780
|
+
* `GET /v1/build-plans/<id>/runs` so Build Plan detail can show the full
|
|
781
|
+
* audit trail of authoring + improvement work.
|
|
774
782
|
*/
|
|
775
|
-
|
|
783
|
+
listBuildPlanRuns(prepDataDir, buildPlanId) {
|
|
776
784
|
return this.listRunObservability(prepDataDir).filter((run) => {
|
|
777
|
-
if (run.
|
|
785
|
+
if (run.build_plan !== buildPlanId)
|
|
778
786
|
return false;
|
|
779
|
-
return (run.run_type === "
|
|
780
|
-
run.run_type === "
|
|
787
|
+
return (run.run_type === "build-plan-draft" ||
|
|
788
|
+
run.run_type === "build-plan-improvement");
|
|
781
789
|
});
|
|
782
790
|
}
|
|
783
791
|
createJobRun(prepDataDir, requestValue) {
|
|
@@ -792,7 +800,7 @@ export class LocalServiceRuntime {
|
|
|
792
800
|
status: "running",
|
|
793
801
|
title: request.title,
|
|
794
802
|
...(request.preparation !== undefined ? { preparation: request.preparation } : {}),
|
|
795
|
-
...(request.
|
|
803
|
+
...(request.build_plan !== undefined ? { build_plan: request.build_plan } : {}),
|
|
796
804
|
...(request.source_path !== undefined ? { source_path: request.source_path } : {}),
|
|
797
805
|
...(request.output_path !== undefined ? { output_path: request.output_path } : {}),
|
|
798
806
|
...(request.agent !== undefined ? { agent: request.agent } : {}),
|
|
@@ -895,108 +903,116 @@ export class LocalServiceRuntime {
|
|
|
895
903
|
void this.runReadinessCheckDraftInBackground(prepDataDir, request, job.run_id);
|
|
896
904
|
return this.getJob(prepDataDir, job.run_id) ?? job;
|
|
897
905
|
}
|
|
898
|
-
|
|
899
|
-
const request =
|
|
906
|
+
applyBuildPlanChange(prepDataDir, requestValue) {
|
|
907
|
+
const request = BuildPlanChangeCreateRequestSchema.parse(requestValue);
|
|
908
|
+
const buildPlanId = request.build_plan;
|
|
900
909
|
const outputPath = request.operation === "duplicate"
|
|
901
|
-
?
|
|
902
|
-
:
|
|
910
|
+
? buildPlanDefinitionPath(prepDataDir, request.new_build_plan_id)
|
|
911
|
+
: buildPlanDefinitionPath(prepDataDir, buildPlanId);
|
|
903
912
|
if (request.operation === "duplicate") {
|
|
904
|
-
if (
|
|
905
|
-
throw new Error(`
|
|
913
|
+
if (resolveBuildPlanPackageSourcePath(prepDataDir, request.new_build_plan_id)) {
|
|
914
|
+
throw new Error(`Build Plan "${request.new_build_plan_id}" already exists.`);
|
|
906
915
|
}
|
|
907
|
-
if (!
|
|
908
|
-
throw new Error(`
|
|
916
|
+
if (!resolveBuildPlanPackageSourcePath(prepDataDir, buildPlanId)) {
|
|
917
|
+
throw new Error(`Build Plan "${buildPlanId}" does not exist.`);
|
|
909
918
|
}
|
|
910
|
-
const label = request.label ??
|
|
911
|
-
const hint = request.hint ?? `Duplicate of ${
|
|
912
|
-
const
|
|
919
|
+
const label = request.label ?? buildPlanLabelFromId(request.new_build_plan_id);
|
|
920
|
+
const hint = request.hint ?? `Duplicate of ${buildPlanId}`;
|
|
921
|
+
const buildPlanPath = seedLocalBuildPlanPackageFromBase({
|
|
913
922
|
prepDataDir,
|
|
914
|
-
|
|
915
|
-
|
|
923
|
+
baseBuildPlanId: buildPlanId,
|
|
924
|
+
buildPlanId: request.new_build_plan_id,
|
|
916
925
|
label,
|
|
917
926
|
hint,
|
|
918
927
|
});
|
|
919
|
-
this.
|
|
920
|
-
return
|
|
921
|
-
kind: "interf-
|
|
928
|
+
this.buildPlanListingCache.invalidate(prepDataDir);
|
|
929
|
+
return BuildPlanChangeResultSchema.parse({
|
|
930
|
+
kind: "interf-build-plan-change-result",
|
|
922
931
|
version: 1,
|
|
923
932
|
operation: "duplicate",
|
|
924
|
-
|
|
925
|
-
|
|
933
|
+
build_plan: buildPlanId,
|
|
934
|
+
new_build_plan_id: request.new_build_plan_id,
|
|
926
935
|
updated_preparations: [],
|
|
927
|
-
|
|
936
|
+
build_plan_path: buildPlanPath,
|
|
928
937
|
changed: true,
|
|
929
|
-
message: `Duplicated
|
|
938
|
+
message: `Duplicated Build Plan ${buildPlanId} as ${request.new_build_plan_id}.`,
|
|
930
939
|
});
|
|
931
940
|
}
|
|
932
|
-
if (request.confirmation !==
|
|
933
|
-
throw new Error(`Type ${
|
|
941
|
+
if (request.confirmation !== buildPlanId) {
|
|
942
|
+
throw new Error(`Type ${buildPlanId} to confirm Build Plan removal.`);
|
|
934
943
|
}
|
|
935
|
-
const
|
|
936
|
-
if (
|
|
937
|
-
throw new Error(`
|
|
944
|
+
const localBuildPlanPath = buildPlanDefinitionPath(prepDataDir, buildPlanId);
|
|
945
|
+
if (buildPlanId === DEFAULT_BUILD_PLAN_ID || !existsSync(localBuildPlanPath)) {
|
|
946
|
+
throw new Error(`Build Plan "${buildPlanId}" is not a removable local Build Plan.`);
|
|
938
947
|
}
|
|
939
948
|
const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir));
|
|
940
949
|
const updatedPreparations = preparations
|
|
941
|
-
.filter((preparation) =>
|
|
950
|
+
.filter((preparation) => buildPlanIdForSourcePreparationConfig(preparation) === buildPlanId);
|
|
942
951
|
if (updatedPreparations.length > 0) {
|
|
943
952
|
saveSourceFolderConfig(prepDataDir, {
|
|
944
|
-
preparations: preparations.map((preparation) =>
|
|
953
|
+
preparations: preparations.map((preparation) => detachBuildPlanFromPreparation(preparation, buildPlanId)),
|
|
945
954
|
});
|
|
946
|
-
// Detaching a
|
|
955
|
+
// Detaching a Build Plan changes readiness shape for those Preparations.
|
|
947
956
|
for (const preparation of updatedPreparations) {
|
|
948
957
|
this.readinessCache.invalidatePreparation(prepDataDir, preparation.name);
|
|
949
958
|
}
|
|
950
959
|
}
|
|
951
960
|
rmSync(outputPath, { recursive: true, force: true });
|
|
952
|
-
this.
|
|
953
|
-
return
|
|
954
|
-
kind: "interf-
|
|
961
|
+
this.buildPlanListingCache.invalidate(prepDataDir);
|
|
962
|
+
return BuildPlanChangeResultSchema.parse({
|
|
963
|
+
kind: "interf-build-plan-change-result",
|
|
955
964
|
version: 1,
|
|
956
965
|
operation: "remove",
|
|
957
|
-
|
|
966
|
+
build_plan: buildPlanId,
|
|
958
967
|
updated_preparations: updatedPreparations.map((preparation) => preparation.name),
|
|
959
|
-
|
|
968
|
+
build_plan_path: outputPath,
|
|
960
969
|
changed: true,
|
|
961
970
|
message: updatedPreparations.length > 0
|
|
962
|
-
? `Removed
|
|
963
|
-
: `Removed
|
|
971
|
+
? `Removed Build Plan ${buildPlanId} and cleared it from ${updatedPreparations.length} Preparation(s).`
|
|
972
|
+
: `Removed Build Plan ${buildPlanId}.`,
|
|
964
973
|
});
|
|
965
974
|
}
|
|
966
975
|
applyPreparationSetup(prepDataDir, requestValue) {
|
|
967
976
|
const request = PreparationSetupCreateRequestSchema.parse(requestValue);
|
|
968
977
|
const preparationConfig = request.preparation;
|
|
969
|
-
const
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
978
|
+
const buildPlanId = buildPlanIdForSourcePreparationConfig(preparationConfig);
|
|
979
|
+
if (request.setup_mode === "select-build-plan" && !buildPlanId) {
|
|
980
|
+
throw new Error("Build Plan is required when selecting a Build Plan for a Preparation.");
|
|
981
|
+
}
|
|
982
|
+
const normalizedPreparationConfig = buildPlanId
|
|
983
|
+
? { ...preparationConfig, build_plan: buildPlanId }
|
|
984
|
+
: (() => {
|
|
985
|
+
const { build_plan: _ignoredBuildPlan, ...withoutBuildPlan } = preparationConfig;
|
|
986
|
+
return withoutBuildPlan;
|
|
987
|
+
})();
|
|
974
988
|
const sourceFolderPath = resolveSourcePreparationPath(prepDataDir, normalizedPreparationConfig);
|
|
975
989
|
if (!existsSync(sourceFolderPath) || !statSync(sourceFolderPath).isDirectory()) {
|
|
976
990
|
throw new Error(`Source folder "${preparationConfig.path}" is not available.`);
|
|
977
991
|
}
|
|
978
992
|
upsertSourcePreparationConfig(prepDataDir, normalizedPreparationConfig);
|
|
979
|
-
// The Preparation's bound source folder +
|
|
980
|
-
// bust the per-preparation readiness, runs, and
|
|
993
|
+
// The Preparation's bound source folder + Build Plan may have changed:
|
|
994
|
+
// bust the per-preparation readiness, runs, and Build Plan listing
|
|
981
995
|
// caches so the next read reflects the new shape.
|
|
982
996
|
this.readinessCache.invalidatePreparation(prepDataDir, normalizedPreparationConfig.name);
|
|
983
|
-
this.
|
|
997
|
+
this.buildRunCache.invalidatePreparation(prepDataDir, normalizedPreparationConfig.name);
|
|
984
998
|
this.verifyRunCache.invalidatePreparation(prepDataDir, normalizedPreparationConfig.name);
|
|
985
|
-
this.
|
|
986
|
-
const operation = request.setup_mode === "select-
|
|
999
|
+
this.buildPlanListingCache.invalidate(prepDataDir);
|
|
1000
|
+
const operation = request.setup_mode === "select-build-plan" ? "select-build-plan" : "create";
|
|
987
1001
|
return PreparationSetupResultSchema.parse({
|
|
988
1002
|
kind: "interf-preparation-setup-result",
|
|
989
1003
|
version: 1,
|
|
990
1004
|
operation,
|
|
991
1005
|
preparation: normalizedPreparationConfig.name,
|
|
992
|
-
|
|
1006
|
+
build_plan: buildPlanId ?? null,
|
|
993
1007
|
source_folder_path: sourceFolderPath,
|
|
994
1008
|
config_path: preparationConfigPath(asPreparationDataDir(prepDataDir)),
|
|
995
|
-
|
|
1009
|
+
verifiable_context_path: preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), normalizedPreparationConfig.name),
|
|
996
1010
|
changed: true,
|
|
997
|
-
message: operation === "select-
|
|
998
|
-
? `Preparation ${normalizedPreparationConfig.name} now uses
|
|
999
|
-
:
|
|
1011
|
+
message: operation === "select-build-plan"
|
|
1012
|
+
? `Preparation ${normalizedPreparationConfig.name} now uses Build Plan ${buildPlanId}.`
|
|
1013
|
+
: buildPlanId
|
|
1014
|
+
? `Preparation ${normalizedPreparationConfig.name} is saved with Build Plan ${buildPlanId}.`
|
|
1015
|
+
: `Preparation ${normalizedPreparationConfig.name} is saved. Draft or select a Build Plan before building.`,
|
|
1000
1016
|
});
|
|
1001
1017
|
}
|
|
1002
1018
|
applyPreparationChange(prepDataDir, requestValue) {
|
|
@@ -1010,19 +1026,19 @@ export class LocalServiceRuntime {
|
|
|
1010
1026
|
}
|
|
1011
1027
|
removeSourcePreparationConfig(prepDataDir, request.preparation);
|
|
1012
1028
|
this.readinessCache.invalidatePreparation(prepDataDir, request.preparation);
|
|
1013
|
-
this.
|
|
1029
|
+
this.buildRunCache.invalidatePreparation(prepDataDir, request.preparation);
|
|
1014
1030
|
this.verifyRunCache.invalidatePreparation(prepDataDir, request.preparation);
|
|
1015
|
-
this.
|
|
1031
|
+
this.buildPlanListingCache.invalidate(prepDataDir);
|
|
1016
1032
|
return PreparationChangeResultSchema.parse({
|
|
1017
1033
|
kind: "interf-preparation-change-result",
|
|
1018
1034
|
version: 1,
|
|
1019
1035
|
operation: "remove",
|
|
1020
1036
|
preparation: request.preparation,
|
|
1021
1037
|
config_path: preparationConfigPath(asPreparationDataDir(prepDataDir)),
|
|
1022
|
-
|
|
1023
|
-
|
|
1038
|
+
verifiable_context_path: preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), request.preparation),
|
|
1039
|
+
verifiable_context_retained: true,
|
|
1024
1040
|
changed: true,
|
|
1025
|
-
message: `Removed Preparation ${request.preparation}.
|
|
1041
|
+
message: `Removed Preparation ${request.preparation}. Verifiable context files were retained.`,
|
|
1026
1042
|
});
|
|
1027
1043
|
}
|
|
1028
1044
|
applyReset(prepDataDir, requestValue) {
|
|
@@ -1031,13 +1047,13 @@ export class LocalServiceRuntime {
|
|
|
1031
1047
|
if (!preparation) {
|
|
1032
1048
|
throw new Error(`Preparation "${request.preparation}" is not saved.`);
|
|
1033
1049
|
}
|
|
1034
|
-
const
|
|
1035
|
-
if (!existsSync(
|
|
1036
|
-
throw new Error(`
|
|
1050
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), request.preparation);
|
|
1051
|
+
if (!existsSync(verifiableContextPath)) {
|
|
1052
|
+
throw new Error(`Verifiable context for Preparation "${request.preparation}" does not exist.`);
|
|
1037
1053
|
}
|
|
1038
|
-
|
|
1039
|
-
// Reset wipes generated state, including saved
|
|
1040
|
-
this.
|
|
1054
|
+
resetBuildGeneratedState(verifiableContextPath, request.scope);
|
|
1055
|
+
// Reset wipes generated state, including saved build/test/readiness records.
|
|
1056
|
+
this.buildRunCache.invalidatePreparation(prepDataDir, request.preparation);
|
|
1041
1057
|
this.verifyRunCache.invalidatePreparation(prepDataDir, request.preparation);
|
|
1042
1058
|
this.readinessCache.invalidatePreparation(prepDataDir, request.preparation);
|
|
1043
1059
|
return ResetResultSchema.parse({
|
|
@@ -1045,21 +1061,31 @@ export class LocalServiceRuntime {
|
|
|
1045
1061
|
version: 1,
|
|
1046
1062
|
preparation: request.preparation,
|
|
1047
1063
|
scope: request.scope,
|
|
1048
|
-
|
|
1064
|
+
verifiable_context_path: verifiableContextPath,
|
|
1049
1065
|
changed: true,
|
|
1050
1066
|
message: `Reset ${request.scope} state for Preparation ${request.preparation}.`,
|
|
1051
1067
|
});
|
|
1052
1068
|
}
|
|
1053
|
-
async
|
|
1054
|
-
const
|
|
1055
|
-
const
|
|
1069
|
+
async createBuildPlanAuthoringRun(prepDataDir, requestValue, jobType = "build-plan-draft") {
|
|
1070
|
+
const parsedRequest = BuildPlanAuthoringCreateRequestSchema.parse(requestValue);
|
|
1071
|
+
const savedPreparation = parsedRequest.preparation
|
|
1072
|
+
? findSourcePreparationConfig(loadSourceFolderConfig(prepDataDir), parsedRequest.preparation)
|
|
1073
|
+
: null;
|
|
1074
|
+
const request = {
|
|
1075
|
+
...parsedRequest,
|
|
1076
|
+
requested_artifacts: parsedRequest.requested_artifacts.length > 0
|
|
1077
|
+
? parsedRequest.requested_artifacts
|
|
1078
|
+
: savedPreparation?.requested_artifacts ?? [],
|
|
1079
|
+
source_profile: parsedRequest.source_profile ?? savedPreparation?.source_profile ?? null,
|
|
1080
|
+
};
|
|
1081
|
+
const isImprovement = jobType === "build-plan-improvement";
|
|
1056
1082
|
const job = this.createJobRun(prepDataDir, {
|
|
1057
1083
|
job_type: jobType,
|
|
1058
|
-
title: isImprovement ? `Improve
|
|
1084
|
+
title: isImprovement ? `Improve Build Plan ${request.build_plan_id}` : `Draft Build Plan ${request.build_plan_id}`,
|
|
1059
1085
|
preparation: request.preparation ?? null,
|
|
1060
|
-
|
|
1086
|
+
build_plan: request.build_plan_id,
|
|
1061
1087
|
source_path: request.source_folder_path,
|
|
1062
|
-
output_path:
|
|
1088
|
+
output_path: preparationBuildPlanPackagePath(asPreparationDataDir(prepDataDir), request.build_plan_id),
|
|
1063
1089
|
steps: [
|
|
1064
1090
|
{
|
|
1065
1091
|
id: "inspect-source",
|
|
@@ -1068,23 +1094,25 @@ export class LocalServiceRuntime {
|
|
|
1068
1094
|
preparation: request.preparation ?? null,
|
|
1069
1095
|
source_folder_path: request.source_folder_path,
|
|
1070
1096
|
checks: request.checks.length,
|
|
1097
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1071
1098
|
},
|
|
1072
1099
|
},
|
|
1073
1100
|
{
|
|
1074
1101
|
id: "draft-package",
|
|
1075
|
-
label: isImprovement ? "Improve
|
|
1102
|
+
label: isImprovement ? "Improve Build Plan definition" : "Draft Build Plan definition",
|
|
1076
1103
|
input: {
|
|
1077
|
-
|
|
1104
|
+
build_plan_id: request.build_plan_id,
|
|
1078
1105
|
label: request.label,
|
|
1079
1106
|
task_prompt: request.task_prompt,
|
|
1107
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1080
1108
|
artifact_requirements: request.artifact_requirements.length,
|
|
1081
1109
|
},
|
|
1082
1110
|
},
|
|
1083
1111
|
{
|
|
1084
1112
|
id: "validate-package",
|
|
1085
|
-
label: "Validate
|
|
1113
|
+
label: "Validate Build Plan definition",
|
|
1086
1114
|
input: {
|
|
1087
|
-
|
|
1115
|
+
build_plan_id: request.build_plan_id,
|
|
1088
1116
|
},
|
|
1089
1117
|
},
|
|
1090
1118
|
],
|
|
@@ -1092,11 +1120,12 @@ export class LocalServiceRuntime {
|
|
|
1092
1120
|
this.appendJobRunEvent(prepDataDir, job.run_id, {
|
|
1093
1121
|
type: "step.started",
|
|
1094
1122
|
step_id: "inspect-source",
|
|
1095
|
-
message: isImprovement ? "Inspecting source files for
|
|
1123
|
+
message: isImprovement ? "Inspecting source files for Build Plan improvement." : "Inspecting source files for Build Plan drafting.",
|
|
1096
1124
|
input: {
|
|
1097
1125
|
preparation: request.preparation ?? null,
|
|
1098
1126
|
source_folder_path: request.source_folder_path,
|
|
1099
1127
|
checks: request.checks.length,
|
|
1128
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1100
1129
|
},
|
|
1101
1130
|
});
|
|
1102
1131
|
this.appendJobRunEvent(prepDataDir, job.run_id, {
|
|
@@ -1106,122 +1135,124 @@ export class LocalServiceRuntime {
|
|
|
1106
1135
|
output: {
|
|
1107
1136
|
source_folder_path: request.source_folder_path,
|
|
1108
1137
|
checks: request.checks.length,
|
|
1138
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1109
1139
|
},
|
|
1110
1140
|
});
|
|
1111
1141
|
this.appendJobRunEvent(prepDataDir, job.run_id, {
|
|
1112
1142
|
type: "step.started",
|
|
1113
1143
|
step_id: "draft-package",
|
|
1114
|
-
message: isImprovement ? "Improving
|
|
1144
|
+
message: isImprovement ? "Improving Build Plan definition." : "Drafting Build Plan definition.",
|
|
1115
1145
|
input: {
|
|
1116
|
-
|
|
1146
|
+
build_plan_id: request.build_plan_id,
|
|
1117
1147
|
label: request.label,
|
|
1118
1148
|
task_prompt: request.task_prompt,
|
|
1149
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1119
1150
|
artifact_requirements: request.artifact_requirements.length,
|
|
1120
1151
|
},
|
|
1121
1152
|
});
|
|
1122
|
-
void this.
|
|
1153
|
+
void this.runBuildPlanAuthoringInBackground(prepDataDir, request, job.run_id);
|
|
1123
1154
|
return this.getJob(prepDataDir, job.run_id) ?? job;
|
|
1124
1155
|
}
|
|
1125
|
-
|
|
1156
|
+
listVerifiableContexts(prepDataDir) {
|
|
1126
1157
|
return listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir))
|
|
1127
|
-
.map((preparation) => this.
|
|
1158
|
+
.map((preparation) => this.getVerifiableContext(prepDataDir, preparation.name))
|
|
1128
1159
|
.filter((context) => context !== null);
|
|
1129
1160
|
}
|
|
1130
|
-
|
|
1161
|
+
getVerifiableContext(prepDataDir, preparationName) {
|
|
1131
1162
|
const preparation = findSourcePreparationConfig(loadSourceFolderConfig(prepDataDir), preparationName);
|
|
1132
1163
|
if (!preparation)
|
|
1133
1164
|
return null;
|
|
1134
|
-
const path =
|
|
1165
|
+
const path = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparation.name);
|
|
1135
1166
|
const config = readInterfConfig(path);
|
|
1136
|
-
const
|
|
1167
|
+
const buildRuns = this.listBuildRunsForPreparation(prepDataDir, preparation.name);
|
|
1137
1168
|
const verifyRuns = this.listVerifyRunsForPreparation(prepDataDir, preparation.name);
|
|
1138
1169
|
const readiness = this.computePreparationReadiness(prepDataDir, preparation);
|
|
1139
|
-
const
|
|
1140
|
-
return
|
|
1170
|
+
const buildPlan = config?.build_plan ?? buildPlanIdForSourcePreparationConfig(preparation);
|
|
1171
|
+
return VerifiableContextResourceSchema.parse({
|
|
1141
1172
|
preparation: preparation.name,
|
|
1142
1173
|
path,
|
|
1143
1174
|
exists: existsSync(path),
|
|
1144
1175
|
readiness,
|
|
1145
|
-
|
|
1146
|
-
|
|
1176
|
+
build_plan: buildPlan,
|
|
1177
|
+
latest_build_run_id: buildRuns[0]?.run_id ?? null,
|
|
1147
1178
|
latest_test_run_id: verifyRuns[0]?.run_id ?? null,
|
|
1148
|
-
artifacts: uniqueArtifacts(
|
|
1179
|
+
artifacts: uniqueArtifacts(buildRuns[0]?.stages.flatMap((stage) => stage.artifacts) ?? []),
|
|
1149
1180
|
});
|
|
1150
1181
|
}
|
|
1151
|
-
|
|
1182
|
+
listBuildRuns(prepDataDir) {
|
|
1152
1183
|
return byCreatedAtDesc(listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir))
|
|
1153
|
-
.flatMap((preparation) => this.
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
return this.
|
|
1157
|
-
const
|
|
1158
|
-
return byCreatedAtDesc(listJsonFiles(
|
|
1159
|
-
.map(
|
|
1160
|
-
.filter((run) => run !== null));
|
|
1184
|
+
.flatMap((preparation) => this.listBuildRunsForPreparation(prepDataDir, preparation.name))).map((run) => BuildRunResourceSchema.parse({ run }));
|
|
1185
|
+
}
|
|
1186
|
+
listBuildRunsForPreparation(prepDataDir, preparationName) {
|
|
1187
|
+
return this.buildRunCache.get(prepDataDir, preparationName, () => {
|
|
1188
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparationName);
|
|
1189
|
+
return byCreatedAtDesc(listJsonFiles(buildRunsRoot(verifiableContextPath))
|
|
1190
|
+
.map(readBuildRunAt)
|
|
1191
|
+
.filter((run) => run !== null)).map((run) => this.hydrateBuildRunFromRuntime(prepDataDir, verifiableContextPath, run));
|
|
1161
1192
|
}, (run) => run.run_id);
|
|
1162
1193
|
}
|
|
1163
|
-
|
|
1194
|
+
getBuildRun(prepDataDir, runId) {
|
|
1164
1195
|
// Fast path: if the runId was seen during a recent listing, look up
|
|
1165
1196
|
// its owning preparation directly and return that preparation's
|
|
1166
1197
|
// cached entry instead of scanning every preparation on disk.
|
|
1167
|
-
const known = this.
|
|
1198
|
+
const known = this.buildRunCache.preparationFor(prepDataDir, runId);
|
|
1168
1199
|
if (known) {
|
|
1169
|
-
const found = this.
|
|
1200
|
+
const found = this.listBuildRunsForPreparation(prepDataDir, known).find((entry) => entry.run_id === runId);
|
|
1170
1201
|
if (found)
|
|
1171
|
-
return
|
|
1202
|
+
return BuildRunResourceSchema.parse({ run: found });
|
|
1172
1203
|
}
|
|
1173
1204
|
// Slow path: scan all preparations. Falls through after a cache
|
|
1174
1205
|
// miss for an in-flight run created before this process restarted.
|
|
1175
|
-
for (const resource of this.
|
|
1206
|
+
for (const resource of this.listBuildRuns(prepDataDir)) {
|
|
1176
1207
|
if (resource.run.run_id === runId)
|
|
1177
1208
|
return resource;
|
|
1178
1209
|
}
|
|
1179
1210
|
return null;
|
|
1180
1211
|
}
|
|
1181
|
-
|
|
1182
|
-
return this.
|
|
1212
|
+
getBuildRunEvents(prepDataDir, runId) {
|
|
1213
|
+
return this.getBuildRun(prepDataDir, runId)?.run.events ?? null;
|
|
1183
1214
|
}
|
|
1184
|
-
|
|
1185
|
-
const run = this.
|
|
1215
|
+
getBuildRunProof(prepDataDir, runId) {
|
|
1216
|
+
const run = this.getBuildRun(prepDataDir, runId)?.run;
|
|
1186
1217
|
if (!run)
|
|
1187
1218
|
return null;
|
|
1188
1219
|
return run.stages
|
|
1189
1220
|
.map((stage) => stage.latest_proof ?? null)
|
|
1190
1221
|
.filter((proof) => proof !== null);
|
|
1191
1222
|
}
|
|
1192
|
-
|
|
1193
|
-
const run = this.
|
|
1223
|
+
getBuildRunArtifacts(prepDataDir, runId) {
|
|
1224
|
+
const run = this.getBuildRun(prepDataDir, runId)?.run;
|
|
1194
1225
|
if (!run)
|
|
1195
1226
|
return null;
|
|
1196
1227
|
return uniqueArtifacts(run.stages.flatMap((stage) => stage.artifacts));
|
|
1197
1228
|
}
|
|
1198
|
-
async
|
|
1199
|
-
const request =
|
|
1229
|
+
async createBuildRun(prepDataDir, requestValue) {
|
|
1230
|
+
const request = BuildRunCreateRequestSchema.parse(requestValue);
|
|
1200
1231
|
const preparationConfig = this.resolvePreparationConfig(prepDataDir, request.preparation, {
|
|
1201
|
-
|
|
1232
|
+
build_plan: request.build_plan,
|
|
1202
1233
|
max_attempts: request.max_attempts,
|
|
1203
1234
|
max_loops: request.max_loops,
|
|
1204
1235
|
});
|
|
1205
|
-
const
|
|
1206
|
-
const runId = createRunId("
|
|
1236
|
+
const verifiableContextPath = this.ensureVerifiableContextForRun(prepDataDir, preparationConfig);
|
|
1237
|
+
const runId = createRunId("build");
|
|
1207
1238
|
const now = new Date().toISOString();
|
|
1208
|
-
const
|
|
1239
|
+
const buildPlan = getBuildPlan(requireSelectedBuildPlan(preparationConfig), {
|
|
1209
1240
|
prepDataDir,
|
|
1210
1241
|
});
|
|
1211
|
-
const stageTotal =
|
|
1212
|
-
const run =
|
|
1213
|
-
kind: "interf-
|
|
1242
|
+
const stageTotal = buildPlan.stages.length;
|
|
1243
|
+
const run = BuildRunSchema.parse({
|
|
1244
|
+
kind: "interf-build-run",
|
|
1214
1245
|
version: 1,
|
|
1215
1246
|
run_id: runId,
|
|
1216
1247
|
status: "running",
|
|
1217
1248
|
preparation: preparationConfig.name,
|
|
1218
|
-
|
|
1249
|
+
build_plan: buildPlan.id,
|
|
1219
1250
|
backend: "native",
|
|
1220
1251
|
source_path: resolveSourcePreparationPath(prepDataDir, preparationConfig),
|
|
1221
|
-
|
|
1252
|
+
verifiable_context_path: verifiableContextPath,
|
|
1222
1253
|
created_at: now,
|
|
1223
1254
|
started_at: now,
|
|
1224
|
-
stages:
|
|
1255
|
+
stages: buildPlan.stages
|
|
1225
1256
|
.map((stage, index) => {
|
|
1226
1257
|
return {
|
|
1227
1258
|
run_id: runId,
|
|
@@ -1242,45 +1273,45 @@ export class LocalServiceRuntime {
|
|
|
1242
1273
|
}),
|
|
1243
1274
|
events: [],
|
|
1244
1275
|
});
|
|
1245
|
-
this.
|
|
1246
|
-
this.
|
|
1276
|
+
this.writeBuildRun(prepDataDir, verifiableContextPath, run);
|
|
1277
|
+
this.activeBuildRuns.set(runId, {
|
|
1247
1278
|
prepDataDir,
|
|
1248
|
-
|
|
1279
|
+
verifiableContextPath,
|
|
1249
1280
|
preparation: preparationConfig.name,
|
|
1250
1281
|
cancelled: false,
|
|
1251
1282
|
});
|
|
1252
|
-
await this.
|
|
1283
|
+
await this.recordBuildRunEvent(prepDataDir, verifiableContextPath, runId, {
|
|
1253
1284
|
type: "run.started",
|
|
1254
1285
|
event_id: createRunEventId("event"),
|
|
1255
1286
|
run_id: runId,
|
|
1256
1287
|
timestamp: now,
|
|
1257
1288
|
preparation: preparationConfig.name,
|
|
1258
|
-
|
|
1259
|
-
|
|
1289
|
+
build_plan: buildPlan.id,
|
|
1290
|
+
verifiable_context_path: verifiableContextPath,
|
|
1260
1291
|
backend: "native",
|
|
1261
1292
|
});
|
|
1262
1293
|
const sink = {
|
|
1263
|
-
emit: (event) => this.
|
|
1294
|
+
emit: (event) => this.recordBuildRunEvent(prepDataDir, verifiableContextPath, runId, event),
|
|
1264
1295
|
};
|
|
1265
|
-
void this.
|
|
1296
|
+
void this.runBuildInBackground(prepDataDir, request, {
|
|
1266
1297
|
runId,
|
|
1267
1298
|
sourcePath: prepDataDir,
|
|
1268
|
-
|
|
1299
|
+
verifiableContextPath,
|
|
1269
1300
|
preparationConfig,
|
|
1270
1301
|
events: sink,
|
|
1271
1302
|
});
|
|
1272
|
-
const saved = this.
|
|
1273
|
-
return
|
|
1303
|
+
const saved = this.readBuildRun(verifiableContextPath, runId) ?? run;
|
|
1304
|
+
return BuildRunResourceSchema.parse({ run: saved });
|
|
1274
1305
|
}
|
|
1275
1306
|
/**
|
|
1276
|
-
* Cancel an in-flight
|
|
1307
|
+
* Cancel an in-flight Build run. Marks the persisted record as
|
|
1277
1308
|
* `cancelled`, emits a `run.cancelled` event to capture the cancellation in
|
|
1278
1309
|
* the run timeline, and clears the active handle so retries may start a
|
|
1279
1310
|
* fresh run. If the run already finished, returns
|
|
1280
1311
|
* `{ cancelled: false, reason: "already finished" }` and persists nothing.
|
|
1281
1312
|
*/
|
|
1282
|
-
|
|
1283
|
-
const handle = this.
|
|
1313
|
+
cancelBuildRun(runId) {
|
|
1314
|
+
const handle = this.activeBuildRuns.get(runId);
|
|
1284
1315
|
if (!handle) {
|
|
1285
1316
|
// Either unknown or already terminal. The server route already 404s
|
|
1286
1317
|
// unknown ids before calling this, so anything reaching here is a run
|
|
@@ -1293,14 +1324,14 @@ export class LocalServiceRuntime {
|
|
|
1293
1324
|
const cancelledAt = new Date().toISOString();
|
|
1294
1325
|
handle.cancelled = true;
|
|
1295
1326
|
handle.cancelledAt = cancelledAt;
|
|
1296
|
-
const current = this.
|
|
1297
|
-
if (current && !
|
|
1298
|
-
this.
|
|
1327
|
+
const current = this.readBuildRun(handle.verifiableContextPath, runId);
|
|
1328
|
+
if (current && !isTerminalBuildRunStatus(current.status)) {
|
|
1329
|
+
this.writeBuildRun(handle.prepDataDir, handle.verifiableContextPath, applyEventToBuildRun(current, {
|
|
1299
1330
|
type: "run.cancelled",
|
|
1300
1331
|
event_id: createRunEventId("event"),
|
|
1301
1332
|
run_id: runId,
|
|
1302
1333
|
timestamp: cancelledAt,
|
|
1303
|
-
reason: "
|
|
1334
|
+
reason: "Build run cancelled by request.",
|
|
1304
1335
|
}));
|
|
1305
1336
|
}
|
|
1306
1337
|
return { cancelled: true };
|
|
@@ -1311,7 +1342,7 @@ export class LocalServiceRuntime {
|
|
|
1311
1342
|
* elapsed. The preparation argument is required so that the same key in
|
|
1312
1343
|
* two different preparations always returns two different runs.
|
|
1313
1344
|
*/
|
|
1314
|
-
|
|
1345
|
+
findIdempotentBuildRun(prepDataDir, key) {
|
|
1315
1346
|
const resolvedRoot = resolve(prepDataDir);
|
|
1316
1347
|
const bucket = this.idempotencyKeyCache.get(resolvedRoot);
|
|
1317
1348
|
if (!bucket)
|
|
@@ -1322,7 +1353,7 @@ export class LocalServiceRuntime {
|
|
|
1322
1353
|
if (entry.expiresAt <= Date.now()) {
|
|
1323
1354
|
// Opportunistic single-key prune. The bulk prune runs on writes
|
|
1324
1355
|
// when the cache crosses the size threshold (see
|
|
1325
|
-
// {@link
|
|
1356
|
+
// {@link recordIdempotentBuildRun}).
|
|
1326
1357
|
bucket.delete(key);
|
|
1327
1358
|
if (bucket.size === 0)
|
|
1328
1359
|
this.idempotencyKeyCache.delete(resolvedRoot);
|
|
@@ -1337,7 +1368,7 @@ export class LocalServiceRuntime {
|
|
|
1337
1368
|
* every read AND write, which was O(N) per request. Now we only sweep
|
|
1338
1369
|
* when the cache grows past {@link IDEMPOTENCY_PRUNE_THRESHOLD}.
|
|
1339
1370
|
*/
|
|
1340
|
-
|
|
1371
|
+
recordIdempotentBuildRun(prepDataDir, key, runId) {
|
|
1341
1372
|
const resolvedRoot = resolve(prepDataDir);
|
|
1342
1373
|
let bucket = this.idempotencyKeyCache.get(resolvedRoot);
|
|
1343
1374
|
if (!bucket) {
|
|
@@ -1393,8 +1424,8 @@ export class LocalServiceRuntime {
|
|
|
1393
1424
|
}
|
|
1394
1425
|
listVerifyRunsForPreparation(prepDataDir, preparationName) {
|
|
1395
1426
|
return this.verifyRunCache.get(prepDataDir, preparationName, () => {
|
|
1396
|
-
const
|
|
1397
|
-
return newestFirst(listJsonFiles(verifyRunsRoot(
|
|
1427
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparationName);
|
|
1428
|
+
return newestFirst(listJsonFiles(verifyRunsRoot(verifiableContextPath))
|
|
1398
1429
|
.map(readVerifyRunAt)
|
|
1399
1430
|
.filter((run) => run !== null));
|
|
1400
1431
|
}, (run) => run.run_id);
|
|
@@ -1411,8 +1442,8 @@ export class LocalServiceRuntime {
|
|
|
1411
1442
|
async createVerifyRun(prepDataDir, requestValue) {
|
|
1412
1443
|
const request = VerifyRunCreateRequestSchema.parse(requestValue);
|
|
1413
1444
|
const preparationConfig = this.resolvePreparationConfig(prepDataDir, request.preparation);
|
|
1414
|
-
const
|
|
1415
|
-
const
|
|
1445
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparationConfig.name);
|
|
1446
|
+
const verifiableContextTarget = createVerifiableContextTestTarget(verifiableContextPath, preparationConfig.name, buildPlanIdForSourcePreparationConfig(preparationConfig) ?? DEFAULT_BUILD_PLAN_ID);
|
|
1416
1447
|
const runId = createRunId("verify");
|
|
1417
1448
|
const now = new Date().toISOString();
|
|
1418
1449
|
const initial = VerifyRunResourceSchema.parse({
|
|
@@ -1420,74 +1451,74 @@ export class LocalServiceRuntime {
|
|
|
1420
1451
|
status: "running",
|
|
1421
1452
|
preparation: preparationConfig.name,
|
|
1422
1453
|
source_path: prepDataDir,
|
|
1423
|
-
|
|
1454
|
+
verifiable_context_path: verifiableContextTarget.eligible ? verifiableContextPath : null,
|
|
1424
1455
|
started_at: now,
|
|
1425
1456
|
readiness_run: null,
|
|
1426
1457
|
events: [],
|
|
1427
1458
|
});
|
|
1428
|
-
this.writeVerifyRun(prepDataDir,
|
|
1459
|
+
this.writeVerifyRun(prepDataDir, verifiableContextPath, initial);
|
|
1429
1460
|
void this.runTestInBackground(prepDataDir, request, {
|
|
1430
1461
|
runId,
|
|
1431
1462
|
sourcePath: prepDataDir,
|
|
1432
|
-
|
|
1463
|
+
verifiableContextPath,
|
|
1433
1464
|
preparationConfig,
|
|
1434
1465
|
}, initial);
|
|
1435
1466
|
return initial;
|
|
1436
1467
|
}
|
|
1437
|
-
async
|
|
1468
|
+
async runBuildInBackground(prepDataDir, request, context) {
|
|
1438
1469
|
this.beginActiveRun();
|
|
1439
1470
|
try {
|
|
1440
|
-
if (!this.handlers.
|
|
1441
|
-
throw new Error("No
|
|
1471
|
+
if (!this.handlers.createBuildRun) {
|
|
1472
|
+
throw new Error("No build-run handler is configured for this local service.");
|
|
1442
1473
|
}
|
|
1443
|
-
const result = LocalRunHandlerResultSchema.parse(await this.handlers.
|
|
1444
|
-
const wasCancelled = this.
|
|
1474
|
+
const result = LocalRunHandlerResultSchema.parse(await this.handlers.createBuildRun(request, context));
|
|
1475
|
+
const wasCancelled = this.activeBuildRuns.get(context.runId)?.cancelled === true;
|
|
1445
1476
|
if (wasCancelled) {
|
|
1446
1477
|
// The run was cancelled while the handler was still running. The
|
|
1447
1478
|
// cancellation path already wrote a `cancelled` record; just refresh
|
|
1448
1479
|
// observability and skip emitting a second terminal event.
|
|
1449
|
-
this.
|
|
1450
|
-
await this.emitRuntimeDerivedEvents(prepDataDir, context.
|
|
1451
|
-
await this.
|
|
1480
|
+
this.refreshBuildRunFromRuntime(prepDataDir, context.verifiableContextPath, context.runId);
|
|
1481
|
+
await this.emitRuntimeDerivedEvents(prepDataDir, context.verifiableContextPath, context.runId);
|
|
1482
|
+
await this.recordBuildRunEvent(prepDataDir, context.verifiableContextPath, context.runId, this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, this.computePreparationReadiness(prepDataDir, context.preparationConfig)));
|
|
1452
1483
|
return;
|
|
1453
1484
|
}
|
|
1454
|
-
this.
|
|
1455
|
-
await this.emitRuntimeDerivedEvents(prepDataDir, context.
|
|
1485
|
+
this.refreshBuildRunFromRuntime(prepDataDir, context.verifiableContextPath, context.runId);
|
|
1486
|
+
await this.emitRuntimeDerivedEvents(prepDataDir, context.verifiableContextPath, context.runId);
|
|
1456
1487
|
if (!result.ok) {
|
|
1457
|
-
await this.
|
|
1488
|
+
await this.recordBuildRunEvent(prepDataDir, context.verifiableContextPath, context.runId, {
|
|
1458
1489
|
type: "run.failed",
|
|
1459
1490
|
event_id: createRunEventId("event"),
|
|
1460
1491
|
run_id: context.runId,
|
|
1461
1492
|
timestamp: createRunEventTimestamp(),
|
|
1462
|
-
error: result.error ?? "
|
|
1493
|
+
error: result.error ?? "Build run failed.",
|
|
1463
1494
|
});
|
|
1464
1495
|
}
|
|
1465
1496
|
else {
|
|
1466
|
-
await this.
|
|
1497
|
+
await this.recordBuildRunEvent(prepDataDir, context.verifiableContextPath, context.runId, {
|
|
1467
1498
|
type: "run.completed",
|
|
1468
1499
|
event_id: createRunEventId("event"),
|
|
1469
1500
|
run_id: context.runId,
|
|
1470
1501
|
timestamp: createRunEventTimestamp(),
|
|
1471
|
-
summary: "
|
|
1502
|
+
summary: "Verifiable context ready.",
|
|
1472
1503
|
});
|
|
1473
1504
|
}
|
|
1474
|
-
await this.
|
|
1505
|
+
await this.recordBuildRunEvent(prepDataDir, context.verifiableContextPath, context.runId, this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, this.computePreparationReadiness(prepDataDir, context.preparationConfig)));
|
|
1475
1506
|
// 0.17 — emit per-Artifact billing events (stub form: JSONL).
|
|
1476
1507
|
// Production sink (Metronome HTTP) wires in 0.18+.
|
|
1477
1508
|
this.emitBillingEventsForRun(prepDataDir, context);
|
|
1478
1509
|
}
|
|
1479
1510
|
catch (error) {
|
|
1480
|
-
await this.
|
|
1511
|
+
await this.recordBuildRunEvent(prepDataDir, context.verifiableContextPath, context.runId, {
|
|
1481
1512
|
type: "run.failed",
|
|
1482
1513
|
event_id: createRunEventId("event"),
|
|
1483
1514
|
run_id: context.runId,
|
|
1484
1515
|
timestamp: createRunEventTimestamp(),
|
|
1485
1516
|
error: error instanceof Error ? error.message : String(error),
|
|
1486
1517
|
});
|
|
1487
|
-
await this.
|
|
1518
|
+
await this.recordBuildRunEvent(prepDataDir, context.verifiableContextPath, context.runId, this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, this.computePreparationReadiness(prepDataDir, context.preparationConfig)));
|
|
1488
1519
|
}
|
|
1489
1520
|
finally {
|
|
1490
|
-
this.
|
|
1521
|
+
this.activeBuildRuns.delete(context.runId);
|
|
1491
1522
|
this.endActiveRun();
|
|
1492
1523
|
}
|
|
1493
1524
|
}
|
|
@@ -1510,7 +1541,7 @@ export class LocalServiceRuntime {
|
|
|
1510
1541
|
events: resultEvent ? [resultEvent] : [],
|
|
1511
1542
|
...(!result.ok ? { error: result.error ?? "Readiness check failed." } : {}),
|
|
1512
1543
|
});
|
|
1513
|
-
this.writeVerifyRun(prepDataDir, context.
|
|
1544
|
+
this.writeVerifyRun(prepDataDir, context.verifiableContextPath, nextWithoutReadiness);
|
|
1514
1545
|
const readiness = this.computePreparationReadiness(prepDataDir, context.preparationConfig);
|
|
1515
1546
|
const next = VerifyRunResourceSchema.parse({
|
|
1516
1547
|
...nextWithoutReadiness,
|
|
@@ -1520,7 +1551,7 @@ export class LocalServiceRuntime {
|
|
|
1520
1551
|
this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, readiness),
|
|
1521
1552
|
],
|
|
1522
1553
|
});
|
|
1523
|
-
this.writeVerifyRun(prepDataDir, context.
|
|
1554
|
+
this.writeVerifyRun(prepDataDir, context.verifiableContextPath, next);
|
|
1524
1555
|
}
|
|
1525
1556
|
catch (error) {
|
|
1526
1557
|
const failedWithoutReadiness = VerifyRunResourceSchema.parse({
|
|
@@ -1529,14 +1560,14 @@ export class LocalServiceRuntime {
|
|
|
1529
1560
|
finished_at: new Date().toISOString(),
|
|
1530
1561
|
error: error instanceof Error ? error.message : String(error),
|
|
1531
1562
|
});
|
|
1532
|
-
this.writeVerifyRun(prepDataDir, context.
|
|
1563
|
+
this.writeVerifyRun(prepDataDir, context.verifiableContextPath, failedWithoutReadiness);
|
|
1533
1564
|
const readiness = this.computePreparationReadiness(prepDataDir, context.preparationConfig);
|
|
1534
1565
|
const next = VerifyRunResourceSchema.parse({
|
|
1535
1566
|
...failedWithoutReadiness,
|
|
1536
1567
|
readiness,
|
|
1537
1568
|
events: [this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, readiness)],
|
|
1538
1569
|
});
|
|
1539
|
-
this.writeVerifyRun(prepDataDir, context.
|
|
1570
|
+
this.writeVerifyRun(prepDataDir, context.verifiableContextPath, next);
|
|
1540
1571
|
}
|
|
1541
1572
|
finally {
|
|
1542
1573
|
this.endActiveRun();
|
|
@@ -1600,18 +1631,18 @@ export class LocalServiceRuntime {
|
|
|
1600
1631
|
});
|
|
1601
1632
|
}
|
|
1602
1633
|
}
|
|
1603
|
-
async
|
|
1634
|
+
async runBuildPlanAuthoringInBackground(prepDataDir, request, runId) {
|
|
1604
1635
|
this.beginActiveRun();
|
|
1605
|
-
return this.
|
|
1636
|
+
return this.runBuildPlanAuthoringInBackgroundInner(prepDataDir, request, runId).finally(() => {
|
|
1606
1637
|
this.endActiveRun();
|
|
1607
1638
|
});
|
|
1608
1639
|
}
|
|
1609
|
-
async
|
|
1640
|
+
async runBuildPlanAuthoringInBackgroundInner(prepDataDir, request, runId) {
|
|
1610
1641
|
try {
|
|
1611
|
-
if (!this.handlers.
|
|
1612
|
-
throw new Error("No
|
|
1642
|
+
if (!this.handlers.createBuildPlanAuthoringRun) {
|
|
1643
|
+
throw new Error("No Build Plan-authoring handler is configured for this local service.");
|
|
1613
1644
|
}
|
|
1614
|
-
const result =
|
|
1645
|
+
const result = BuildPlanAuthoringResultSchema.parse(await this.handlers.createBuildPlanAuthoringRun(request, this.jobRunContext(prepDataDir, runId)));
|
|
1615
1646
|
this.setJobRunResult(prepDataDir, runId, result);
|
|
1616
1647
|
this.appendJobRunEvent(prepDataDir, runId, {
|
|
1617
1648
|
type: result.status === "executor-failed" ? "step.failed" : "step.completed",
|
|
@@ -1620,31 +1651,48 @@ export class LocalServiceRuntime {
|
|
|
1620
1651
|
output: {
|
|
1621
1652
|
status: result.status,
|
|
1622
1653
|
changed: result.changed,
|
|
1623
|
-
|
|
1654
|
+
build_plan_path: result.build_plan_path,
|
|
1624
1655
|
shell_path: result.shell_path,
|
|
1625
1656
|
},
|
|
1626
1657
|
});
|
|
1627
1658
|
this.appendJobRunEvent(prepDataDir, runId, {
|
|
1628
1659
|
type: "step.started",
|
|
1629
1660
|
step_id: "validate-package",
|
|
1630
|
-
message: "Validating
|
|
1661
|
+
message: "Validating Build Plan package structure and stage contract.",
|
|
1631
1662
|
input: {
|
|
1632
|
-
|
|
1663
|
+
build_plan_path: result.build_plan_path,
|
|
1633
1664
|
},
|
|
1634
1665
|
});
|
|
1635
1666
|
if (result.status === "updated" || result.status === "no-change") {
|
|
1667
|
+
let selectedPreparation = null;
|
|
1668
|
+
if (request.preparation) {
|
|
1669
|
+
const selected = this.resolvePreparationConfig(prepDataDir, request.preparation, {
|
|
1670
|
+
build_plan: request.build_plan_id,
|
|
1671
|
+
});
|
|
1672
|
+
upsertSourcePreparationConfig(prepDataDir, selected);
|
|
1673
|
+
this.readinessCache.invalidatePreparation(prepDataDir, selected.name);
|
|
1674
|
+
this.buildRunCache.invalidatePreparation(prepDataDir, selected.name);
|
|
1675
|
+
this.verifyRunCache.invalidatePreparation(prepDataDir, selected.name);
|
|
1676
|
+
this.buildPlanListingCache.invalidate(prepDataDir);
|
|
1677
|
+
selectedPreparation = selected.name;
|
|
1678
|
+
}
|
|
1636
1679
|
this.appendJobRunEvent(prepDataDir, runId, {
|
|
1637
1680
|
type: "step.completed",
|
|
1638
1681
|
step_id: "validate-package",
|
|
1639
|
-
message:
|
|
1682
|
+
message: selectedPreparation
|
|
1683
|
+
? `${result.summary} Selected Build Plan ${request.build_plan_id} for Preparation ${selectedPreparation}.`
|
|
1684
|
+
: result.summary,
|
|
1640
1685
|
output: {
|
|
1641
1686
|
status: result.status,
|
|
1642
1687
|
validation: result.validation ?? null,
|
|
1688
|
+
selected_preparation: selectedPreparation,
|
|
1643
1689
|
},
|
|
1644
1690
|
});
|
|
1645
1691
|
this.appendJobRunEvent(prepDataDir, runId, {
|
|
1646
1692
|
type: "job.completed",
|
|
1647
|
-
message:
|
|
1693
|
+
message: selectedPreparation
|
|
1694
|
+
? `${result.summary} Selected Build Plan ${request.build_plan_id} for Preparation ${selectedPreparation}.`
|
|
1695
|
+
: result.summary,
|
|
1648
1696
|
});
|
|
1649
1697
|
}
|
|
1650
1698
|
else {
|
|
@@ -1700,7 +1748,7 @@ export class LocalServiceRuntime {
|
|
|
1700
1748
|
return ActionProposalPlanSchema.parse({
|
|
1701
1749
|
action_type: "clarification",
|
|
1702
1750
|
...(request.preparation ? { preparation: request.preparation } : {}),
|
|
1703
|
-
assistant_message: "No local action planner is configured for this Interf
|
|
1751
|
+
assistant_message: "No local action planner is configured for this Interf instance.",
|
|
1704
1752
|
});
|
|
1705
1753
|
}
|
|
1706
1754
|
const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir));
|
|
@@ -1711,13 +1759,13 @@ export class LocalServiceRuntime {
|
|
|
1711
1759
|
preparations,
|
|
1712
1760
|
preparationHealth: preparations.map((preparation) => {
|
|
1713
1761
|
const readinessChecks = preparation.checks?.length ?? 0;
|
|
1714
|
-
const
|
|
1762
|
+
const verifiableContextReady = hasVerifiableContextTestTarget(prepDataDir, preparation);
|
|
1715
1763
|
return {
|
|
1716
1764
|
name: preparation.name,
|
|
1717
1765
|
readiness_checks: readinessChecks,
|
|
1718
|
-
|
|
1719
|
-
can_check_readiness: readinessChecks > 0 &&
|
|
1720
|
-
recommended_next_actions:
|
|
1766
|
+
verifiable_context_ready: verifiableContextReady,
|
|
1767
|
+
can_check_readiness: readinessChecks > 0 && verifiableContextReady,
|
|
1768
|
+
recommended_next_actions: verifiableContextReady
|
|
1721
1769
|
? readinessChecks > 0
|
|
1722
1770
|
? ["check readiness", "improve", "prepare again"]
|
|
1723
1771
|
: ["draft readiness checks", "prepare again"]
|
|
@@ -1751,8 +1799,8 @@ export class LocalServiceRuntime {
|
|
|
1751
1799
|
}
|
|
1752
1800
|
const label = options.actionType === "preparation-setup"
|
|
1753
1801
|
? "Preparation setup"
|
|
1754
|
-
: options.actionType === "
|
|
1755
|
-
? "
|
|
1802
|
+
: options.actionType === "build-plan-change"
|
|
1803
|
+
? "Build Plan change"
|
|
1756
1804
|
: "Preparation change";
|
|
1757
1805
|
const now = new Date().toISOString();
|
|
1758
1806
|
return ActionProposalResourceSchema.parse({
|
|
@@ -1766,7 +1814,7 @@ export class LocalServiceRuntime {
|
|
|
1766
1814
|
assistant_message: `${label} must be submitted directly to ${endpoint}. Action proposals are only for freeform planning or async local-agent-backed work.`,
|
|
1767
1815
|
message: options.message,
|
|
1768
1816
|
preparation: options.preparation ?? null,
|
|
1769
|
-
|
|
1817
|
+
build_plan: options.buildPlan ?? null,
|
|
1770
1818
|
request: {
|
|
1771
1819
|
message: options.message,
|
|
1772
1820
|
endpoint,
|
|
@@ -1784,7 +1832,7 @@ export class LocalServiceRuntime {
|
|
|
1784
1832
|
}
|
|
1785
1833
|
async buildActionProposal(prepDataDir, request) {
|
|
1786
1834
|
const structuredPreparationSetup = PreparationSetupActionValuesSchema.safeParse(request.values);
|
|
1787
|
-
const
|
|
1835
|
+
const structuredBuildPlanAuthoring = BuildPlanAuthoringActionValuesSchema.safeParse(request.values);
|
|
1788
1836
|
const structuredActionType = actionTypeFromValues(request.values);
|
|
1789
1837
|
const structuredDirectActionType = structuredPreparationSetup.success
|
|
1790
1838
|
? "preparation-setup"
|
|
@@ -1795,12 +1843,14 @@ export class LocalServiceRuntime {
|
|
|
1795
1843
|
return this.directServiceActionClarification({
|
|
1796
1844
|
actionType: structuredDirectActionType,
|
|
1797
1845
|
message: request.message,
|
|
1798
|
-
|
|
1846
|
+
buildPlan: stringValue(request.values, "build_plan") ??
|
|
1847
|
+
stringValue(request.values, "build_plan_id") ??
|
|
1848
|
+
stringValue(request.values, "new_build_plan_id"),
|
|
1799
1849
|
preparation: request.preparation ?? stringValue(request.values, "preparation") ?? stringValue(request.values, "name"),
|
|
1800
1850
|
values: request.values,
|
|
1801
1851
|
});
|
|
1802
1852
|
}
|
|
1803
|
-
const structuredPlanActionType =
|
|
1853
|
+
const structuredPlanActionType = structuredBuildPlanAuthoring.success ? "build-plan-draft" : structuredActionType;
|
|
1804
1854
|
// Typed UI/CLI actions already carry the service contract; only freeform chat needs planner inference.
|
|
1805
1855
|
const plan = structuredPlanActionType
|
|
1806
1856
|
? ActionProposalPlanSchema.parse({
|
|
@@ -1813,7 +1863,11 @@ export class LocalServiceRuntime {
|
|
|
1813
1863
|
return this.directServiceActionClarification({
|
|
1814
1864
|
actionType,
|
|
1815
1865
|
message: request.message,
|
|
1816
|
-
|
|
1866
|
+
buildPlan: plan.build_plan ??
|
|
1867
|
+
stringValue(plan.values, "build_plan") ??
|
|
1868
|
+
stringValue(plan.values, "build_plan_id") ??
|
|
1869
|
+
stringValue(request.values, "build_plan") ??
|
|
1870
|
+
stringValue(request.values, "build_plan_id"),
|
|
1817
1871
|
preparation: plan.preparation ?? request.preparation ?? stringValue(plan.values, "preparation") ?? stringValue(request.values, "preparation"),
|
|
1818
1872
|
values: {
|
|
1819
1873
|
...(plan.values ?? {}),
|
|
@@ -1836,7 +1890,7 @@ export class LocalServiceRuntime {
|
|
|
1836
1890
|
...(plan.command_preview ? { command_preview: plan.command_preview } : {}),
|
|
1837
1891
|
message: request.message,
|
|
1838
1892
|
preparation: plan.preparation ?? request.preparation ?? null,
|
|
1839
|
-
|
|
1893
|
+
build_plan: plan.build_plan ?? null,
|
|
1840
1894
|
request: {
|
|
1841
1895
|
message: request.message,
|
|
1842
1896
|
...(plan.values ? { values: plan.values } : {}),
|
|
@@ -1854,7 +1908,7 @@ export class LocalServiceRuntime {
|
|
|
1854
1908
|
...(plan.values ?? {}),
|
|
1855
1909
|
...(request.values ?? {}),
|
|
1856
1910
|
};
|
|
1857
|
-
if (actionType === "
|
|
1911
|
+
if (actionType === "build-plan-draft" || actionType === "build-plan-improvement") {
|
|
1858
1912
|
const requestedPreparationName = plan.preparation ?? request.preparation ?? null;
|
|
1859
1913
|
const fallbackPreparation = requestedPreparationName
|
|
1860
1914
|
? null
|
|
@@ -1865,43 +1919,50 @@ export class LocalServiceRuntime {
|
|
|
1865
1919
|
const preparationPath = preparationConfig
|
|
1866
1920
|
? resolveSourcePreparationPath(prepDataDir, preparationConfig)
|
|
1867
1921
|
: resolveConfiguredSourceFolderPath(prepDataDir) ?? prepDataDir;
|
|
1868
|
-
const
|
|
1869
|
-
stringValue(request.values, "
|
|
1870
|
-
const
|
|
1871
|
-
stringValue(plan.values, "
|
|
1872
|
-
stringValue(plan.values, "
|
|
1873
|
-
const
|
|
1874
|
-
const taskPrompt =
|
|
1922
|
+
const requestedBuildPlanId = stringValue(request.values, "build_plan_id") ??
|
|
1923
|
+
stringValue(request.values, "build_plan");
|
|
1924
|
+
const plannedBuildPlanId = plan.build_plan ??
|
|
1925
|
+
stringValue(plan.values, "build_plan_id") ??
|
|
1926
|
+
stringValue(plan.values, "build_plan");
|
|
1927
|
+
const buildPlanId = requestedBuildPlanId ?? plannedBuildPlanId ?? buildPlanIdForProposal(request.message, proposalValues);
|
|
1928
|
+
const taskPrompt = actionValueBuildPlanTaskPrompt(proposalValues) ??
|
|
1875
1929
|
stringValue(proposalValues, "task_prompt") ??
|
|
1876
|
-
|
|
1877
|
-
const hint = stringValue(proposalValues, "hint") ??
|
|
1930
|
+
buildPlanAuthoringPromptFallback(request.message, buildPlanId);
|
|
1931
|
+
const hint = stringValue(proposalValues, "hint") ?? buildPlanAuthoringHintFromPrompt(taskPrompt);
|
|
1878
1932
|
const actionRequest = {
|
|
1879
1933
|
preparation: preparationConfig?.name ?? null,
|
|
1880
1934
|
source_folder_path: preparationPath,
|
|
1881
|
-
|
|
1882
|
-
...(stringValue(proposalValues, "
|
|
1883
|
-
|
|
1884
|
-
|
|
1935
|
+
build_plan_id: buildPlanId,
|
|
1936
|
+
...(stringValue(proposalValues, "base_build_plan_id") ?? stringValue(proposalValues, "base_build_plan_id")
|
|
1937
|
+
? { base_build_plan_id: stringValue(proposalValues, "base_build_plan_id") ?? stringValue(proposalValues, "base_build_plan_id") }
|
|
1938
|
+
: {}),
|
|
1939
|
+
...(stringValue(proposalValues, "reference_build_plan_id") ?? stringValue(proposalValues, "reference_build_plan_id")
|
|
1940
|
+
? { reference_build_plan_id: stringValue(proposalValues, "reference_build_plan_id") ?? stringValue(proposalValues, "reference_build_plan_id") }
|
|
1941
|
+
: {}),
|
|
1942
|
+
label: stringValue(proposalValues, "label") ?? buildPlanLabelFromId(buildPlanId),
|
|
1885
1943
|
hint,
|
|
1886
1944
|
task_prompt: taskPrompt,
|
|
1887
1945
|
checks: preparationConfig?.checks ?? [],
|
|
1946
|
+
requested_artifacts: preparationConfig?.requested_artifacts ?? [],
|
|
1947
|
+
source_profile: preparationConfig?.source_profile ?? null,
|
|
1948
|
+
artifact_requirements: artifactRequirementsFromRequestedArtifacts(preparationConfig?.requested_artifacts ?? []),
|
|
1888
1949
|
};
|
|
1889
1950
|
const commandPreview = (usePlannerText ? plan.command_preview : undefined) ??
|
|
1890
|
-
actionCommandPreview(actionType, preparationConfig?.name ?? null,
|
|
1951
|
+
actionCommandPreview(actionType, preparationConfig?.name ?? null, buildPlanId, proposalValues);
|
|
1891
1952
|
return ActionProposalResourceSchema.parse({
|
|
1892
1953
|
kind: "interf-action-proposal",
|
|
1893
1954
|
version: 1,
|
|
1894
1955
|
proposal_id: createActionProposalId(),
|
|
1895
1956
|
status: "awaiting_approval",
|
|
1896
1957
|
action_type: actionType,
|
|
1897
|
-
title: (usePlannerText ? plan.title : undefined) ?? `Draft
|
|
1898
|
-
summary: (usePlannerText ? plan.summary : undefined) ?? "Ask the configured local executor to create a reusable
|
|
1958
|
+
title: (usePlannerText ? plan.title : undefined) ?? `Draft Build Plan ${buildPlanId}`,
|
|
1959
|
+
summary: (usePlannerText ? plan.summary : undefined) ?? "Ask the configured local executor to create a reusable Build Plan.",
|
|
1899
1960
|
assistant_message: (usePlannerText ? plan.assistant_message : undefined) ??
|
|
1900
1961
|
actionAssistantMessage(actionType, preparationConfig?.name ?? null, commandPreview),
|
|
1901
1962
|
command_preview: commandPreview,
|
|
1902
1963
|
message: request.message,
|
|
1903
1964
|
preparation: preparationConfig?.name ?? null,
|
|
1904
|
-
|
|
1965
|
+
build_plan: buildPlanId,
|
|
1905
1966
|
request: actionRequest,
|
|
1906
1967
|
created_at: now,
|
|
1907
1968
|
updated_at: now,
|
|
@@ -1915,12 +1976,12 @@ export class LocalServiceRuntime {
|
|
|
1915
1976
|
const preparationConfig = this.resolvePreparationConfig(prepDataDir, plan.preparation ?? request.preparation ?? this.defaultPreparationName(prepDataDir));
|
|
1916
1977
|
const proposalActionType = ActionProposalTypeSchema.parse(actionType);
|
|
1917
1978
|
const preparationPath = resolveSourcePreparationPath(prepDataDir, preparationConfig);
|
|
1918
|
-
const
|
|
1919
|
-
stringValue(request.values, "
|
|
1920
|
-
const
|
|
1921
|
-
stringValue(plan.values, "
|
|
1922
|
-
stringValue(plan.values, "
|
|
1923
|
-
const
|
|
1979
|
+
const requestedBuildPlanId = stringValue(request.values, "build_plan_id") ??
|
|
1980
|
+
stringValue(request.values, "build_plan");
|
|
1981
|
+
const plannedBuildPlanId = plan.build_plan ??
|
|
1982
|
+
stringValue(plan.values, "build_plan_id") ??
|
|
1983
|
+
stringValue(plan.values, "build_plan");
|
|
1984
|
+
const buildPlanId = requestedBuildPlanId ?? plannedBuildPlanId ?? buildPlanIdForSourcePreparationConfig(preparationConfig);
|
|
1924
1985
|
const clarifyResolvedAction = (options) => ActionProposalResourceSchema.parse({
|
|
1925
1986
|
kind: "interf-action-proposal",
|
|
1926
1987
|
version: 1,
|
|
@@ -1932,7 +1993,7 @@ export class LocalServiceRuntime {
|
|
|
1932
1993
|
assistant_message: options.assistantMessage,
|
|
1933
1994
|
message: request.message,
|
|
1934
1995
|
preparation: preparationConfig.name,
|
|
1935
|
-
|
|
1996
|
+
build_plan: buildPlanId ?? null,
|
|
1936
1997
|
request: {
|
|
1937
1998
|
message: request.message,
|
|
1938
1999
|
...(proposalValues ? { values: proposalValues } : {}),
|
|
@@ -1948,7 +2009,7 @@ export class LocalServiceRuntime {
|
|
|
1948
2009
|
if (actionType === "test") {
|
|
1949
2010
|
const requestedMode = testModeFromValues(proposalValues);
|
|
1950
2011
|
const hasReadinessChecks = (preparationConfig.checks ?? []).length > 0;
|
|
1951
|
-
const
|
|
2012
|
+
const verifiableContextReady = hasVerifiableContextTestTarget(prepDataDir, preparationConfig);
|
|
1952
2013
|
if (!hasReadinessChecks) {
|
|
1953
2014
|
return clarifyResolvedAction({
|
|
1954
2015
|
title: `Add readiness checks for ${preparationConfig.name}`,
|
|
@@ -1956,24 +2017,24 @@ export class LocalServiceRuntime {
|
|
|
1956
2017
|
assistantMessage: `Preparation "${preparationConfig.name}" does not have saved readiness checks yet. Ask me to draft readiness checks after the Source Folder is prepared, or add readiness guidance first.`,
|
|
1957
2018
|
});
|
|
1958
2019
|
}
|
|
1959
|
-
if (!
|
|
2020
|
+
if (!verifiableContextReady && requestedMode !== "source-files") {
|
|
1960
2021
|
return clarifyResolvedAction({
|
|
1961
|
-
title: `
|
|
1962
|
-
summary: "Readiness checks need
|
|
1963
|
-
assistantMessage: `Preparation "${preparationConfig.name}" has no
|
|
2022
|
+
title: `Build ${preparationConfig.name} first`,
|
|
2023
|
+
summary: "Readiness checks need verifiable context unless you explicitly ask for a source-files-only baseline.",
|
|
2024
|
+
assistantMessage: `Preparation "${preparationConfig.name}" has no built verifiable context yet. Build it first; after that Interf can check readiness. If you specifically want a source-files-only baseline, ask for source files only.`,
|
|
1964
2025
|
});
|
|
1965
2026
|
}
|
|
1966
2027
|
}
|
|
1967
2028
|
const actionRequest = (() => {
|
|
1968
|
-
if (actionType === "
|
|
2029
|
+
if (actionType === "build") {
|
|
1969
2030
|
return {
|
|
1970
2031
|
preparation: preparationConfig.name,
|
|
1971
|
-
...(
|
|
2032
|
+
...(buildPlanId ? { build_plan: buildPlanId } : {}),
|
|
1972
2033
|
};
|
|
1973
2034
|
}
|
|
1974
2035
|
if (actionType === "test") {
|
|
1975
|
-
// 0.15 — verify runs always judge against the
|
|
1976
|
-
//
|
|
2036
|
+
// 0.15 — verify runs always judge against the verifiable context
|
|
2037
|
+
// verifiable context. The legacy `mode` field is gone from the
|
|
1977
2038
|
// wire request shape.
|
|
1978
2039
|
return {
|
|
1979
2040
|
preparation: preparationConfig.name,
|
|
@@ -1987,47 +2048,54 @@ export class LocalServiceRuntime {
|
|
|
1987
2048
|
target_count: Math.max(1, Math.min(8, Math.round(numberValue(proposalValues, "target_count") ?? 4))),
|
|
1988
2049
|
};
|
|
1989
2050
|
}
|
|
1990
|
-
const
|
|
1991
|
-
const taskPrompt =
|
|
2051
|
+
const fallbackBuildPlanId = buildPlanId ?? buildPlanIdForProposal(request.message, proposalValues);
|
|
2052
|
+
const taskPrompt = actionValueBuildPlanTaskPrompt(proposalValues) ??
|
|
1992
2053
|
stringValue(proposalValues, "task_prompt") ??
|
|
1993
|
-
|
|
1994
|
-
const hint = stringValue(proposalValues, "hint") ??
|
|
2054
|
+
buildPlanAuthoringPromptFallback(request.message, fallbackBuildPlanId);
|
|
2055
|
+
const hint = stringValue(proposalValues, "hint") ?? buildPlanAuthoringHintFromPrompt(taskPrompt);
|
|
1995
2056
|
return {
|
|
1996
2057
|
preparation: preparationConfig.name,
|
|
1997
2058
|
source_folder_path: preparationPath,
|
|
1998
|
-
|
|
1999
|
-
...(stringValue(proposalValues, "
|
|
2000
|
-
|
|
2001
|
-
|
|
2059
|
+
build_plan_id: fallbackBuildPlanId,
|
|
2060
|
+
...(stringValue(proposalValues, "base_build_plan_id") ?? stringValue(proposalValues, "base_build_plan_id")
|
|
2061
|
+
? { base_build_plan_id: stringValue(proposalValues, "base_build_plan_id") ?? stringValue(proposalValues, "base_build_plan_id") }
|
|
2062
|
+
: {}),
|
|
2063
|
+
...(stringValue(proposalValues, "reference_build_plan_id") ?? stringValue(proposalValues, "reference_build_plan_id")
|
|
2064
|
+
? { reference_build_plan_id: stringValue(proposalValues, "reference_build_plan_id") ?? stringValue(proposalValues, "reference_build_plan_id") }
|
|
2065
|
+
: {}),
|
|
2066
|
+
label: stringValue(proposalValues, "label") ?? buildPlanLabelFromId(fallbackBuildPlanId),
|
|
2002
2067
|
hint,
|
|
2003
2068
|
task_prompt: taskPrompt,
|
|
2004
2069
|
checks: preparationConfig.checks ?? [],
|
|
2070
|
+
requested_artifacts: preparationConfig.requested_artifacts ?? [],
|
|
2071
|
+
source_profile: preparationConfig.source_profile ?? null,
|
|
2072
|
+
artifact_requirements: artifactRequirementsFromRequestedArtifacts(preparationConfig.requested_artifacts ?? []),
|
|
2005
2073
|
};
|
|
2006
2074
|
})();
|
|
2007
2075
|
const title = (() => {
|
|
2008
2076
|
if (plan.title)
|
|
2009
2077
|
return plan.title;
|
|
2010
|
-
if (proposalActionType === "
|
|
2011
|
-
return `
|
|
2078
|
+
if (proposalActionType === "build")
|
|
2079
|
+
return `Build ${preparationConfig.name}`;
|
|
2012
2080
|
if (proposalActionType === "test")
|
|
2013
2081
|
return `Check readiness for ${preparationConfig.name}`;
|
|
2014
2082
|
if (proposalActionType === "readiness-check-draft")
|
|
2015
2083
|
return `Draft readiness checks for ${preparationConfig.name}`;
|
|
2016
|
-
return `Draft
|
|
2084
|
+
return `Draft Build Plan ${buildPlanId}`;
|
|
2017
2085
|
})();
|
|
2018
2086
|
const summary = (() => {
|
|
2019
2087
|
if (plan.summary)
|
|
2020
2088
|
return plan.summary;
|
|
2021
|
-
if (proposalActionType === "
|
|
2022
|
-
return "Build
|
|
2089
|
+
if (proposalActionType === "build")
|
|
2090
|
+
return "Build verifiable context agents can use.";
|
|
2023
2091
|
if (proposalActionType === "test")
|
|
2024
|
-
return "Run readiness checks against source files and
|
|
2092
|
+
return "Run readiness checks against source files and verifiable context.";
|
|
2025
2093
|
if (proposalActionType === "readiness-check-draft")
|
|
2026
2094
|
return "Ask the configured local executor to draft saved readiness checks.";
|
|
2027
|
-
return "Ask the configured local executor to create a reusable
|
|
2095
|
+
return "Ask the configured local executor to create a reusable Build Plan.";
|
|
2028
2096
|
})();
|
|
2029
2097
|
const previewValues = proposalValues;
|
|
2030
|
-
const commandPreview = plan.command_preview ?? actionCommandPreview(proposalActionType, preparationConfig.name,
|
|
2098
|
+
const commandPreview = plan.command_preview ?? actionCommandPreview(proposalActionType, preparationConfig.name, buildPlanId, previewValues);
|
|
2031
2099
|
return ActionProposalResourceSchema.parse({
|
|
2032
2100
|
kind: "interf-action-proposal",
|
|
2033
2101
|
version: 1,
|
|
@@ -2040,7 +2108,7 @@ export class LocalServiceRuntime {
|
|
|
2040
2108
|
command_preview: commandPreview,
|
|
2041
2109
|
message: request.message,
|
|
2042
2110
|
preparation: preparationConfig.name,
|
|
2043
|
-
|
|
2111
|
+
build_plan: buildPlanId,
|
|
2044
2112
|
request: actionRequest,
|
|
2045
2113
|
created_at: now,
|
|
2046
2114
|
updated_at: now,
|
|
@@ -2055,11 +2123,11 @@ export class LocalServiceRuntime {
|
|
|
2055
2123
|
if (proposal.action_type === "clarification") {
|
|
2056
2124
|
throw new Error("Clarification proposals cannot be submitted.");
|
|
2057
2125
|
}
|
|
2058
|
-
if (proposal.action_type === "
|
|
2059
|
-
const resource = await this.
|
|
2126
|
+
if (proposal.action_type === "build") {
|
|
2127
|
+
const resource = await this.createBuildRun(prepDataDir, proposal.request);
|
|
2060
2128
|
return {
|
|
2061
2129
|
runId: resource.run.run_id,
|
|
2062
|
-
runType: "
|
|
2130
|
+
runType: "build-run",
|
|
2063
2131
|
};
|
|
2064
2132
|
}
|
|
2065
2133
|
if (proposal.action_type === "test") {
|
|
@@ -2080,7 +2148,7 @@ export class LocalServiceRuntime {
|
|
|
2080
2148
|
if (directEndpoint) {
|
|
2081
2149
|
throw new Error(`Action "${proposal.action_type}" must be submitted directly to ${directEndpoint}.`);
|
|
2082
2150
|
}
|
|
2083
|
-
const job = await this.
|
|
2151
|
+
const job = await this.createBuildPlanAuthoringRun(prepDataDir, proposal.request, proposal.action_type === "build-plan-improvement" ? "build-plan-improvement" : "build-plan-draft");
|
|
2084
2152
|
return {
|
|
2085
2153
|
runId: job.run_id,
|
|
2086
2154
|
runType: "job-run",
|
|
@@ -2091,24 +2159,30 @@ export class LocalServiceRuntime {
|
|
|
2091
2159
|
if (!preparation) {
|
|
2092
2160
|
throw new Error(`Preparation "${preparationName}" is not saved in this control plane folder.`);
|
|
2093
2161
|
}
|
|
2094
|
-
const
|
|
2162
|
+
const buildPlan = overrides.build_plan ?? buildPlanIdForSourcePreparationConfig(preparation) ?? undefined;
|
|
2095
2163
|
return {
|
|
2096
2164
|
...preparation,
|
|
2097
|
-
...(
|
|
2165
|
+
...(buildPlan ? { build_plan: buildPlan } : {}),
|
|
2098
2166
|
...(typeof overrides.max_attempts === "number" ? { max_attempts: overrides.max_attempts } : {}),
|
|
2099
2167
|
...(typeof overrides.max_loops === "number" ? { max_loops: overrides.max_loops } : {}),
|
|
2100
2168
|
};
|
|
2101
2169
|
}
|
|
2102
|
-
|
|
2103
|
-
const
|
|
2104
|
-
const
|
|
2105
|
-
|
|
2106
|
-
return
|
|
2170
|
+
ensureVerifiableContextForRun(prepDataDir, preparationConfig) {
|
|
2171
|
+
const buildPlanId = requireSelectedBuildPlan(preparationConfig);
|
|
2172
|
+
const verifiableContextPath = ensureVerifiableContextScaffold(prepDataDir, preparationConfig.name, buildPlanId);
|
|
2173
|
+
syncVerifiableContextInterfConfigFromSourcePreparationConfig(verifiableContextPath, preparationConfig);
|
|
2174
|
+
return verifiableContextPath;
|
|
2107
2175
|
}
|
|
2108
|
-
|
|
2109
|
-
return
|
|
2176
|
+
readBuildRun(verifiableContextPath, runId) {
|
|
2177
|
+
return readBuildRunAt(buildRunPath(verifiableContextPath, runId));
|
|
2110
2178
|
}
|
|
2111
|
-
|
|
2179
|
+
hydrateBuildRunFromRuntime(prepDataDir, verifiableContextPath, run) {
|
|
2180
|
+
if (!isTerminalBuildRunStatus(run.status))
|
|
2181
|
+
return run;
|
|
2182
|
+
this.refreshBuildRunFromRuntime(prepDataDir, verifiableContextPath, run.run_id);
|
|
2183
|
+
return this.readBuildRun(verifiableContextPath, run.run_id) ?? run;
|
|
2184
|
+
}
|
|
2185
|
+
finalizeInterruptedBuildRuns(prepDataDir) {
|
|
2112
2186
|
let preparations;
|
|
2113
2187
|
try {
|
|
2114
2188
|
preparations = listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir));
|
|
@@ -2117,11 +2191,11 @@ export class LocalServiceRuntime {
|
|
|
2117
2191
|
return;
|
|
2118
2192
|
}
|
|
2119
2193
|
for (const preparation of preparations) {
|
|
2120
|
-
const
|
|
2121
|
-
for (const run of listJsonFiles(
|
|
2122
|
-
.map(
|
|
2194
|
+
const verifiableContextPath = preparationVerifiableContextPath(asPreparationDataDir(prepDataDir), preparation.name);
|
|
2195
|
+
for (const run of listJsonFiles(buildRunsRoot(verifiableContextPath))
|
|
2196
|
+
.map(readBuildRunAt)
|
|
2123
2197
|
.filter((entry) => entry !== null)) {
|
|
2124
|
-
if (
|
|
2198
|
+
if (isTerminalBuildRunStatus(run.status) || this.activeBuildRuns.has(run.run_id))
|
|
2125
2199
|
continue;
|
|
2126
2200
|
const timestamp = createRunEventTimestamp();
|
|
2127
2201
|
const interruptedRun = {
|
|
@@ -2138,7 +2212,7 @@ export class LocalServiceRuntime {
|
|
|
2138
2212
|
};
|
|
2139
2213
|
}),
|
|
2140
2214
|
};
|
|
2141
|
-
this.
|
|
2215
|
+
this.writeBuildRun(prepDataDir, verifiableContextPath, applyEventToBuildRun(interruptedRun, {
|
|
2142
2216
|
type: "run.cancelled",
|
|
2143
2217
|
event_id: createRunEventId("event"),
|
|
2144
2218
|
run_id: run.run_id,
|
|
@@ -2148,8 +2222,35 @@ export class LocalServiceRuntime {
|
|
|
2148
2222
|
}
|
|
2149
2223
|
}
|
|
2150
2224
|
}
|
|
2225
|
+
finalizeInterruptedJobRuns(prepDataDir) {
|
|
2226
|
+
for (const run of this.listJobs(prepDataDir)) {
|
|
2227
|
+
if (isTerminalJobStatus(run.status))
|
|
2228
|
+
continue;
|
|
2229
|
+
const timestamp = createRunEventTimestamp();
|
|
2230
|
+
const interruptedRun = LocalJobRunResourceSchema.parse({
|
|
2231
|
+
...run,
|
|
2232
|
+
steps: run.steps.map((step) => {
|
|
2233
|
+
if (step.status !== "running")
|
|
2234
|
+
return step;
|
|
2235
|
+
return {
|
|
2236
|
+
...step,
|
|
2237
|
+
status: "failed",
|
|
2238
|
+
finished_at: step.finished_at ?? timestamp,
|
|
2239
|
+
summary: step.summary ?? INTERRUPTED_JOB_RUN_MESSAGE,
|
|
2240
|
+
};
|
|
2241
|
+
}),
|
|
2242
|
+
});
|
|
2243
|
+
this.writeJobRun(prepDataDir, applyEventToLocalJob(interruptedRun, {
|
|
2244
|
+
type: "job.failed",
|
|
2245
|
+
event_id: createRunEventId("event"),
|
|
2246
|
+
run_id: run.run_id,
|
|
2247
|
+
timestamp,
|
|
2248
|
+
message: INTERRUPTED_JOB_RUN_MESSAGE,
|
|
2249
|
+
}));
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2151
2252
|
/**
|
|
2152
|
-
* 0.17 — emit per-Artifact billing events when a
|
|
2253
|
+
* 0.17 — emit per-Artifact billing events when a Build run reaches
|
|
2153
2254
|
* a terminal state. STUB FORM: writes a JSONL file alongside the run
|
|
2154
2255
|
* record by default. Production sink (Metronome HTTP) wires in 0.18+.
|
|
2155
2256
|
* The JSONL output is observability/dev fixture, NOT production
|
|
@@ -2157,7 +2258,7 @@ export class LocalServiceRuntime {
|
|
|
2157
2258
|
*/
|
|
2158
2259
|
emitBillingEventsForRun(prepDataDir, context) {
|
|
2159
2260
|
try {
|
|
2160
|
-
const run = this.
|
|
2261
|
+
const run = this.readBuildRun(context.verifiableContextPath, context.runId);
|
|
2161
2262
|
if (!run || run.artifacts.length === 0)
|
|
2162
2263
|
return;
|
|
2163
2264
|
const sink = this.billingEventSink ?? new JsonlBillingEventSink(defaultBillingEventLogPath({
|
|
@@ -2168,7 +2269,7 @@ export class LocalServiceRuntime {
|
|
|
2168
2269
|
const events = buildCompilationEventsForRun({
|
|
2169
2270
|
runId: context.runId,
|
|
2170
2271
|
preparation: run.preparation,
|
|
2171
|
-
|
|
2272
|
+
buildPlanId: run.build_plan,
|
|
2172
2273
|
accountId: null, // 0.17 — loopback only; cloud variant fills via tokenValidator (B4.3).
|
|
2173
2274
|
artifacts: run.artifacts,
|
|
2174
2275
|
startedAt: run.started_at ?? null,
|
|
@@ -2180,17 +2281,17 @@ export class LocalServiceRuntime {
|
|
|
2180
2281
|
}
|
|
2181
2282
|
catch {
|
|
2182
2283
|
// Billing is observability-only in 0.17; never let stub failures
|
|
2183
|
-
// block a successful
|
|
2284
|
+
// block a successful build.
|
|
2184
2285
|
}
|
|
2185
2286
|
}
|
|
2186
|
-
|
|
2187
|
-
mkdirSync(
|
|
2188
|
-
writeJsonFile(
|
|
2287
|
+
writeBuildRun(prepDataDir, verifiableContextPath, run) {
|
|
2288
|
+
mkdirSync(buildRunsRoot(verifiableContextPath), { recursive: true });
|
|
2289
|
+
writeJsonFile(buildRunPath(verifiableContextPath, run.run_id), BuildRunSchema.parse(run));
|
|
2189
2290
|
// Bust per-preparation list + readiness caches so the next read
|
|
2190
2291
|
// reflects the write. We invalidate broadly (per-preparation, not
|
|
2191
2292
|
// per-record) because list recompute cost is bounded by run count
|
|
2192
2293
|
// and the simpler model avoids fan-out bugs.
|
|
2193
|
-
this.
|
|
2294
|
+
this.buildRunCache.invalidatePreparation(prepDataDir, run.preparation);
|
|
2194
2295
|
this.readinessCache.invalidatePreparation(prepDataDir, run.preparation);
|
|
2195
2296
|
}
|
|
2196
2297
|
writeJobRun(prepDataDir, run) {
|
|
@@ -2217,24 +2318,24 @@ export class LocalServiceRuntime {
|
|
|
2217
2318
|
result: normalizedResult,
|
|
2218
2319
|
}));
|
|
2219
2320
|
}
|
|
2220
|
-
async
|
|
2221
|
-
const current = this.
|
|
2321
|
+
async recordBuildRunEvent(prepDataDir, verifiableContextPath, runId, event) {
|
|
2322
|
+
const current = this.readBuildRun(verifiableContextPath, runId);
|
|
2222
2323
|
if (!current)
|
|
2223
2324
|
return;
|
|
2224
|
-
this.
|
|
2325
|
+
this.writeBuildRun(prepDataDir, verifiableContextPath, applyEventToBuildRun(current, event));
|
|
2225
2326
|
if (event.type === "stage.passed" || event.type === "stage.failed") {
|
|
2226
|
-
this.
|
|
2327
|
+
this.refreshBuildRunFromRuntime(prepDataDir, verifiableContextPath, runId);
|
|
2227
2328
|
}
|
|
2228
2329
|
}
|
|
2229
|
-
|
|
2230
|
-
const current = this.
|
|
2330
|
+
refreshBuildRunFromRuntime(prepDataDir, verifiableContextPath, runId) {
|
|
2331
|
+
const current = this.readBuildRun(verifiableContextPath, runId);
|
|
2231
2332
|
if (!current)
|
|
2232
2333
|
return;
|
|
2233
|
-
const state = loadState(
|
|
2334
|
+
const state = loadState(verifiableContextPath);
|
|
2234
2335
|
if (!state?.stages)
|
|
2235
2336
|
return;
|
|
2236
2337
|
const historyByStage = new Map();
|
|
2237
|
-
for (const run of readRuntimeRunHistory(
|
|
2338
|
+
for (const run of readRuntimeRunHistory(verifiableContextPath)) {
|
|
2238
2339
|
if (run.target_name !== current.preparation)
|
|
2239
2340
|
continue;
|
|
2240
2341
|
const existing = historyByStage.get(run.stage);
|
|
@@ -2273,24 +2374,25 @@ export class LocalServiceRuntime {
|
|
|
2273
2374
|
}),
|
|
2274
2375
|
};
|
|
2275
2376
|
next.latest_proof = [...next.stages].reverse().find((stage) => Boolean(stage.latest_proof))?.latest_proof ?? next.latest_proof;
|
|
2276
|
-
// Recompute per-Artifact status whenever the
|
|
2377
|
+
// Recompute per-Artifact status whenever the Build run is
|
|
2277
2378
|
// refreshed from runtime state.
|
|
2278
2379
|
try {
|
|
2279
|
-
const
|
|
2380
|
+
const buildPlan = getBuildPlan(current.build_plan, { prepDataDir });
|
|
2280
2381
|
next.artifacts = computeArtifactStatuses({
|
|
2281
|
-
|
|
2282
|
-
|
|
2382
|
+
buildPlan,
|
|
2383
|
+
verifiableContextPath,
|
|
2283
2384
|
stageRuns: next.stages,
|
|
2385
|
+
counts: countsFromVerifiableContextState(state),
|
|
2284
2386
|
});
|
|
2285
2387
|
}
|
|
2286
2388
|
catch {
|
|
2287
2389
|
next.artifacts = current.artifacts ?? [];
|
|
2288
2390
|
}
|
|
2289
|
-
this.
|
|
2391
|
+
this.writeBuildRun(prepDataDir, verifiableContextPath, next);
|
|
2290
2392
|
}
|
|
2291
|
-
async emitRuntimeDerivedEvents(prepDataDir,
|
|
2292
|
-
const state = loadState(
|
|
2293
|
-
const run = this.
|
|
2393
|
+
async emitRuntimeDerivedEvents(prepDataDir, verifiableContextPath, runId) {
|
|
2394
|
+
const state = loadState(verifiableContextPath);
|
|
2395
|
+
const run = this.readBuildRun(verifiableContextPath, runId);
|
|
2294
2396
|
if (!state?.stages || !run)
|
|
2295
2397
|
return;
|
|
2296
2398
|
for (const stage of run.stages) {
|
|
@@ -2299,7 +2401,7 @@ export class LocalServiceRuntime {
|
|
|
2299
2401
|
continue;
|
|
2300
2402
|
const artifacts = stageArtifactRefs(stage.stage_id, stageState.artifacts);
|
|
2301
2403
|
for (const artifact of artifacts) {
|
|
2302
|
-
await this.
|
|
2404
|
+
await this.recordBuildRunEvent(prepDataDir, verifiableContextPath, runId, {
|
|
2303
2405
|
type: "artifact.written",
|
|
2304
2406
|
event_id: createRunEventId("event"),
|
|
2305
2407
|
run_id: runId,
|
|
@@ -2308,7 +2410,7 @@ export class LocalServiceRuntime {
|
|
|
2308
2410
|
artifact,
|
|
2309
2411
|
});
|
|
2310
2412
|
}
|
|
2311
|
-
await this.
|
|
2413
|
+
await this.recordBuildRunEvent(prepDataDir, verifiableContextPath, runId, {
|
|
2312
2414
|
type: "proof.updated",
|
|
2313
2415
|
event_id: createRunEventId("event"),
|
|
2314
2416
|
run_id: runId,
|
|
@@ -2328,7 +2430,7 @@ export class LocalServiceRuntime {
|
|
|
2328
2430
|
return readSavedReadinessCheckRun(prepDataDir, preparationName);
|
|
2329
2431
|
}
|
|
2330
2432
|
checksEvaluatedEvent(runId, readinessRun) {
|
|
2331
|
-
const target = readinessRun.
|
|
2433
|
+
const target = readinessRun.verifiable_context ?? readinessRun.source_files;
|
|
2332
2434
|
return {
|
|
2333
2435
|
type: "checks.evaluated",
|
|
2334
2436
|
event_id: createRunEventId("event"),
|
|
@@ -2349,9 +2451,9 @@ export class LocalServiceRuntime {
|
|
|
2349
2451
|
readiness,
|
|
2350
2452
|
};
|
|
2351
2453
|
}
|
|
2352
|
-
writeVerifyRun(prepDataDir,
|
|
2353
|
-
mkdirSync(verifyRunsRoot(
|
|
2354
|
-
writeJsonFile(verifyRunPath(
|
|
2454
|
+
writeVerifyRun(prepDataDir, verifiableContextPath, run) {
|
|
2455
|
+
mkdirSync(verifyRunsRoot(verifiableContextPath), { recursive: true });
|
|
2456
|
+
writeJsonFile(verifyRunPath(verifiableContextPath, run.run_id), VerifyRunResourceSchema.parse(run));
|
|
2355
2457
|
this.verifyRunCache.invalidatePreparation(prepDataDir, run.preparation);
|
|
2356
2458
|
this.readinessCache.invalidatePreparation(prepDataDir, run.preparation);
|
|
2357
2459
|
}
|