smol-symphony 0.2.0 → 0.3.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/AGENTS.md +41 -22
- package/DESIGN.md +494 -273
- package/README.md +109 -57
- package/SPEC.md +33 -24
- package/WORKFLOW.minimal.yaml +34 -0
- package/{WORKFLOW.template.md → WORKFLOW.template.yaml} +409 -256
- package/WORKFLOW.yaml +487 -0
- package/assets/skills/symphony-issues/SKILL.md +136 -0
- package/assets/symphony-mise.system.toml +68 -0
- package/dist/src/bin/symphony.js +30 -0
- package/dist/src/bin/symphony.js.map +1 -0
- package/dist/src/core/actions/context.js +109 -0
- package/dist/src/core/actions/context.js.map +1 -0
- package/dist/{actions/parsing.js → src/core/actions/parse.js} +33 -114
- package/dist/src/core/actions/parse.js.map +1 -0
- package/dist/src/core/actions/plan.js +197 -0
- package/dist/src/core/actions/plan.js.map +1 -0
- package/dist/src/core/actions/predicates.js +111 -0
- package/dist/src/core/actions/predicates.js.map +1 -0
- package/dist/src/core/actions/run-fold.js +248 -0
- package/dist/src/core/actions/run-fold.js.map +1 -0
- package/dist/src/core/actions/template.js +118 -0
- package/dist/src/core/actions/template.js.map +1 -0
- package/dist/src/core/cli/args.js +116 -0
- package/dist/src/core/cli/args.js.map +1 -0
- package/dist/src/core/coerce.js +75 -0
- package/dist/src/core/coerce.js.map +1 -0
- package/dist/src/core/credential/account-id.js +20 -0
- package/dist/src/core/credential/account-id.js.map +1 -0
- package/dist/src/core/credential/adapter-config.js +136 -0
- package/dist/src/core/credential/adapter-config.js.map +1 -0
- package/dist/src/core/credential/availability.js +98 -0
- package/dist/src/core/credential/availability.js.map +1 -0
- package/dist/src/core/credential/extract.js +228 -0
- package/dist/src/core/credential/extract.js.map +1 -0
- package/dist/src/core/credential/fake-creds.js +171 -0
- package/dist/src/core/credential/fake-creds.js.map +1 -0
- package/dist/src/core/credential/identity.js +125 -0
- package/dist/src/core/credential/identity.js.map +1 -0
- package/dist/src/core/credential/shape.js +230 -0
- package/dist/src/core/credential/shape.js.map +1 -0
- package/dist/src/core/credential/strings.js +15 -0
- package/dist/src/core/credential/strings.js.map +1 -0
- package/dist/src/core/doctor/checks.js +303 -0
- package/dist/src/core/doctor/checks.js.map +1 -0
- package/dist/src/core/git/result.js +107 -0
- package/dist/src/core/git/result.js.map +1 -0
- package/dist/src/core/http/decisions.js +225 -0
- package/dist/src/core/http/decisions.js.map +1 -0
- package/dist/{http.js → src/core/http/render.js} +472 -738
- package/dist/src/core/http/render.js.map +1 -0
- package/dist/{http-handlers.js → src/core/http/routes.js} +52 -87
- package/dist/src/core/http/routes.js.map +1 -0
- package/dist/src/core/http/views.js +181 -0
- package/dist/src/core/http/views.js.map +1 -0
- package/dist/src/core/image/managed-image.js +95 -0
- package/dist/src/core/image/managed-image.js.map +1 -0
- package/dist/src/core/issue/file.js +149 -0
- package/dist/src/core/issue/file.js.map +1 -0
- package/dist/src/core/issue/parse.js +210 -0
- package/dist/src/core/issue/parse.js.map +1 -0
- package/dist/src/core/mcp/dispatch.js +239 -0
- package/dist/src/core/mcp/dispatch.js.map +1 -0
- package/dist/src/core/mcp/post-move.js +92 -0
- package/dist/src/core/mcp/post-move.js.map +1 -0
- package/dist/src/core/mcp/protocol.js +293 -0
- package/dist/src/core/mcp/protocol.js.map +1 -0
- package/dist/src/core/mcp/url.js +162 -0
- package/dist/src/core/mcp/url.js.map +1 -0
- package/dist/src/core/path.js +63 -0
- package/dist/src/core/path.js.map +1 -0
- package/dist/src/core/reconcile/image-decide.js +48 -0
- package/dist/src/core/reconcile/image-decide.js.map +1 -0
- package/dist/src/core/reconcile/ledger.js +142 -0
- package/dist/src/core/reconcile/ledger.js.map +1 -0
- package/dist/src/core/reconcile/pr-classify.js +62 -0
- package/dist/src/core/reconcile/pr-classify.js.map +1 -0
- package/dist/{reconciler → src/core/reconcile}/pr-decide.js +25 -12
- package/dist/src/core/reconcile/pr-decide.js.map +1 -0
- package/dist/src/core/reconcile/pr-loop.js +161 -0
- package/dist/src/core/reconcile/pr-loop.js.map +1 -0
- package/dist/src/core/reconcile/pr-notes.js +35 -0
- package/dist/src/core/reconcile/pr-notes.js.map +1 -0
- package/dist/src/core/reconcile/vm-decide.js +70 -0
- package/dist/src/core/reconcile/vm-decide.js.map +1 -0
- package/dist/src/core/reconcile/vm-reap.js +207 -0
- package/dist/src/core/reconcile/vm-reap.js.map +1 -0
- package/dist/src/core/reconcile/workspace-decide.js +162 -0
- package/dist/src/core/reconcile/workspace-decide.js.map +1 -0
- package/dist/src/core/runlog/summary.js +231 -0
- package/dist/src/core/runlog/summary.js.map +1 -0
- package/dist/src/core/runner/dispatch-config.js +95 -0
- package/dist/src/core/runner/dispatch-config.js.map +1 -0
- package/dist/src/core/runner/injection.js +61 -0
- package/dist/src/core/runner/injection.js.map +1 -0
- package/dist/src/core/runner/mise.js +210 -0
- package/dist/src/core/runner/mise.js.map +1 -0
- package/dist/src/core/runner/prompt.js +720 -0
- package/dist/src/core/runner/prompt.js.map +1 -0
- package/dist/src/core/runner/turn.js +242 -0
- package/dist/src/core/runner/turn.js.map +1 -0
- package/dist/src/core/runner/vm-plan.js +390 -0
- package/dist/src/core/runner/vm-plan.js.map +1 -0
- package/dist/src/core/schedule/admission.js +123 -0
- package/dist/src/core/schedule/admission.js.map +1 -0
- package/dist/src/core/schedule/circuit-breaker.js +111 -0
- package/dist/src/core/schedule/circuit-breaker.js.map +1 -0
- package/dist/src/core/schedule/eligibility.js +83 -0
- package/dist/src/core/schedule/eligibility.js.map +1 -0
- package/dist/src/core/schedule/reconcile-issue.js +82 -0
- package/dist/src/core/schedule/reconcile-issue.js.map +1 -0
- package/dist/src/core/schedule/retry.js +96 -0
- package/dist/src/core/schedule/retry.js.map +1 -0
- package/dist/src/core/schedule/sleep-cycle.js +133 -0
- package/dist/src/core/schedule/sleep-cycle.js.map +1 -0
- package/dist/src/core/schedule/slots.js +124 -0
- package/dist/src/core/schedule/slots.js.map +1 -0
- package/dist/src/core/schedule/tick.js +553 -0
- package/dist/src/core/schedule/tick.js.map +1 -0
- package/dist/src/core/schedule/token-fold.js +181 -0
- package/dist/src/core/schedule/token-fold.js.map +1 -0
- package/dist/src/core/state-resolve.js +86 -0
- package/dist/src/core/state-resolve.js.map +1 -0
- package/dist/src/core/vm-guards.js +278 -0
- package/dist/src/core/vm-guards.js.map +1 -0
- package/dist/src/core/workflow/derive.js +107 -0
- package/dist/src/core/workflow/derive.js.map +1 -0
- package/dist/src/core/workflow/parse.js +687 -0
- package/dist/src/core/workflow/parse.js.map +1 -0
- package/dist/src/core/workflow/prompt-probe.js +78 -0
- package/dist/src/core/workflow/prompt-probe.js.map +1 -0
- package/dist/src/core/workflow/validate.js +189 -0
- package/dist/src/core/workflow/validate.js.map +1 -0
- package/dist/src/core/workspace-key.js +19 -0
- package/dist/src/core/workspace-key.js.map +1 -0
- package/dist/src/shell/actions-runner.js +356 -0
- package/dist/src/shell/actions-runner.js.map +1 -0
- package/dist/src/shell/adapter/adapter-registry.js +45 -0
- package/dist/src/shell/adapter/adapter-registry.js.map +1 -0
- package/dist/src/shell/adapter/clock-random.js +96 -0
- package/dist/src/shell/adapter/clock-random.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-dispatch-helpers.js +158 -0
- package/dist/src/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-dispatch.js +385 -0
- package/dist/src/shell/adapter/gondolin-dispatch.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-image-converter.js +233 -0
- package/dist/src/shell/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-image-fetch.js +180 -0
- package/dist/src/shell/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/src/shell/adapter/launcher-asset.js +57 -0
- package/dist/src/shell/adapter/launcher-asset.js.map +1 -0
- package/dist/src/shell/adapter/mise-config-asset.js +65 -0
- package/dist/src/shell/adapter/mise-config-asset.js.map +1 -0
- package/dist/src/shell/adapter/workflow-loader.js +304 -0
- package/dist/src/shell/adapter/workflow-loader.js.map +1 -0
- package/dist/src/shell/cli/doctor.js +268 -0
- package/dist/src/shell/cli/doctor.js.map +1 -0
- package/dist/src/shell/effect-interpreter-families.js +314 -0
- package/dist/src/shell/effect-interpreter-families.js.map +1 -0
- package/dist/src/shell/effect-interpreter.js +29 -0
- package/dist/src/shell/effect-interpreter.js.map +1 -0
- package/dist/src/shell/interp/acp-frame.js +137 -0
- package/dist/src/shell/interp/acp-frame.js.map +1 -0
- package/dist/src/shell/interp/acp-ws-conn.js +320 -0
- package/dist/src/shell/interp/acp-ws-conn.js.map +1 -0
- package/dist/src/shell/interp/acp-ws-frames.js +159 -0
- package/dist/src/shell/interp/acp-ws-frames.js.map +1 -0
- package/dist/src/shell/interp/acp-ws.js +197 -0
- package/dist/src/shell/interp/acp-ws.js.map +1 -0
- package/dist/src/shell/interp/acp.js +319 -0
- package/dist/src/shell/interp/acp.js.map +1 -0
- package/dist/src/shell/interp/credential-defaults.js +128 -0
- package/dist/src/shell/interp/credential-defaults.js.map +1 -0
- package/dist/src/shell/interp/credential-hooks.js +149 -0
- package/dist/src/shell/interp/credential-hooks.js.map +1 -0
- package/dist/src/shell/interp/credential-registry.js +226 -0
- package/dist/src/shell/interp/credential-registry.js.map +1 -0
- package/dist/src/shell/interp/credential.js +103 -0
- package/dist/src/shell/interp/credential.js.map +1 -0
- package/dist/src/shell/interp/gh.js +163 -0
- package/dist/src/shell/interp/gh.js.map +1 -0
- package/dist/src/shell/interp/git.js +28 -0
- package/dist/src/shell/interp/git.js.map +1 -0
- package/dist/src/shell/interp/log.js +213 -0
- package/dist/src/shell/interp/log.js.map +1 -0
- package/dist/src/shell/interp/process.js +178 -0
- package/dist/src/shell/interp/process.js.map +1 -0
- package/dist/src/shell/interp/runlog.js +193 -0
- package/dist/src/shell/interp/runlog.js.map +1 -0
- package/dist/src/shell/interp/timer.js +64 -0
- package/dist/src/shell/interp/timer.js.map +1 -0
- package/dist/src/shell/interp/tracker-disk.js +99 -0
- package/dist/src/shell/interp/tracker-disk.js.map +1 -0
- package/dist/src/shell/interp/tracker-parse.js +71 -0
- package/dist/src/shell/interp/tracker-parse.js.map +1 -0
- package/dist/src/shell/interp/tracker-scan.js +238 -0
- package/dist/src/shell/interp/tracker-scan.js.map +1 -0
- package/dist/src/shell/interp/tracker-write.js +91 -0
- package/dist/src/shell/interp/tracker-write.js.map +1 -0
- package/dist/src/shell/interp/tracker.js +41 -0
- package/dist/src/shell/interp/tracker.js.map +1 -0
- package/dist/src/shell/interp/tty.js +48 -0
- package/dist/src/shell/interp/tty.js.map +1 -0
- package/dist/src/shell/interp/vm.js +199 -0
- package/dist/src/shell/interp/vm.js.map +1 -0
- package/dist/src/shell/interp/workspace.js +310 -0
- package/dist/src/shell/interp/workspace.js.map +1 -0
- package/dist/src/shell/main-acp.js +78 -0
- package/dist/src/shell/main-acp.js.map +1 -0
- package/dist/src/shell/main-adapters.js +222 -0
- package/dist/src/shell/main-adapters.js.map +1 -0
- package/dist/src/shell/main-credential.js +122 -0
- package/dist/src/shell/main-credential.js.map +1 -0
- package/dist/src/shell/main-doctor.js +22 -0
- package/dist/src/shell/main-doctor.js.map +1 -0
- package/dist/src/shell/main-entry.js +46 -0
- package/dist/src/shell/main-entry.js.map +1 -0
- package/dist/src/shell/main-http-csrf.js +45 -0
- package/dist/src/shell/main-http-csrf.js.map +1 -0
- package/dist/src/shell/main-http-handler.js +389 -0
- package/dist/src/shell/main-http-handler.js.map +1 -0
- package/dist/src/shell/main-http-mcp.js +122 -0
- package/dist/src/shell/main-http-mcp.js.map +1 -0
- package/dist/src/shell/main-http-views.js +253 -0
- package/dist/src/shell/main-http-views.js.map +1 -0
- package/dist/src/shell/main-http.js +76 -0
- package/dist/src/shell/main-http.js.map +1 -0
- package/dist/src/shell/main-loops.js +130 -0
- package/dist/src/shell/main-loops.js.map +1 -0
- package/dist/src/shell/main-mcp.js +129 -0
- package/dist/src/shell/main-mcp.js.map +1 -0
- package/dist/src/shell/main-orchestrator.js +120 -0
- package/dist/src/shell/main-orchestrator.js.map +1 -0
- package/dist/src/shell/main-preflight.js +43 -0
- package/dist/src/shell/main-preflight.js.map +1 -0
- package/dist/src/shell/main-reconcilers-helpers.js +244 -0
- package/dist/src/shell/main-reconcilers-helpers.js.map +1 -0
- package/dist/src/shell/main-reconcilers-pr.js +148 -0
- package/dist/src/shell/main-reconcilers-pr.js.map +1 -0
- package/dist/src/shell/main-reconcilers.js +225 -0
- package/dist/src/shell/main-reconcilers.js.map +1 -0
- package/dist/src/shell/main-runner.js +355 -0
- package/dist/src/shell/main-runner.js.map +1 -0
- package/dist/src/shell/main-scaffold.js +116 -0
- package/dist/src/shell/main-scaffold.js.map +1 -0
- package/dist/src/shell/main-shutdown.js +115 -0
- package/dist/src/shell/main-shutdown.js.map +1 -0
- package/dist/src/shell/main-startup.js +48 -0
- package/dist/src/shell/main-startup.js.map +1 -0
- package/dist/src/shell/main-substrates.js +43 -0
- package/dist/src/shell/main-substrates.js.map +1 -0
- package/dist/src/shell/main.js +385 -0
- package/dist/src/shell/main.js.map +1 -0
- package/dist/src/shell/orchestrator-feedback.js +69 -0
- package/dist/src/shell/orchestrator-feedback.js.map +1 -0
- package/dist/src/shell/orchestrator-image.js +167 -0
- package/dist/src/shell/orchestrator-image.js.map +1 -0
- package/dist/src/shell/orchestrator-loop.js +468 -0
- package/dist/src/shell/orchestrator-loop.js.map +1 -0
- package/dist/src/shell/orchestrator-reconcile.js +36 -0
- package/dist/src/shell/orchestrator-reconcile.js.map +1 -0
- package/dist/src/shell/reconciler-loop.js +228 -0
- package/dist/src/shell/reconciler-loop.js.map +1 -0
- package/dist/src/shell/runner-loop-turn.js +301 -0
- package/dist/src/shell/runner-loop-turn.js.map +1 -0
- package/dist/src/shell/runner-loop.js +338 -0
- package/dist/src/shell/runner-loop.js.map +1 -0
- package/dist/src/shell/server/http.js +208 -0
- package/dist/src/shell/server/http.js.map +1 -0
- package/dist/src/shell/server/mcp-runtime-effects.js +237 -0
- package/dist/src/shell/server/mcp-runtime-effects.js.map +1 -0
- package/dist/src/shell/server/mcp-runtime.js +99 -0
- package/dist/src/shell/server/mcp-runtime.js.map +1 -0
- package/dist/src/shell/workspace-key.js +14 -0
- package/dist/src/shell/workspace-key.js.map +1 -0
- package/dist/src/types/acp.js +8 -0
- package/dist/src/types/acp.js.map +1 -0
- package/dist/src/types/actions/plan.js +6 -0
- package/dist/src/types/actions/plan.js.map +1 -0
- package/dist/src/types/actions/predicates.js +6 -0
- package/dist/src/types/actions/predicates.js.map +1 -0
- package/dist/src/types/actions/run-fold.js +8 -0
- package/dist/src/types/actions/run-fold.js.map +1 -0
- package/dist/src/types/actions.js +7 -0
- package/dist/src/types/actions.js.map +1 -0
- package/dist/src/types/adapter/clock-random.js +4 -0
- package/dist/src/types/adapter/clock-random.js.map +1 -0
- package/dist/src/types/adapter/gondolin-image-converter.js +5 -0
- package/dist/src/types/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/src/types/adapter/gondolin-image-fetch.js +5 -0
- package/dist/src/types/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/src/types/adapter/workflow-loader.js +4 -0
- package/dist/src/types/adapter/workflow-loader.js.map +1 -0
- package/dist/src/types/cli/args.js +8 -0
- package/dist/src/types/cli/args.js.map +1 -0
- package/dist/src/types/config.js +8 -0
- package/dist/src/types/config.js.map +1 -0
- package/dist/src/types/credential-interp.js +6 -0
- package/dist/src/types/credential-interp.js.map +1 -0
- package/dist/src/types/credentials.js +10 -0
- package/dist/src/types/credentials.js.map +1 -0
- package/dist/src/types/doctor.js +7 -0
- package/dist/src/types/doctor.js.map +1 -0
- package/dist/src/types/domain.js +7 -0
- package/dist/src/types/domain.js.map +1 -0
- package/dist/src/types/effect.js +15 -0
- package/dist/src/types/effect.js.map +1 -0
- package/dist/src/types/errors.js +39 -0
- package/dist/src/types/errors.js.map +1 -0
- package/dist/src/types/http/decisions.js +6 -0
- package/dist/src/types/http/decisions.js.map +1 -0
- package/dist/src/types/http/render.js +10 -0
- package/dist/src/types/http/render.js.map +1 -0
- package/dist/src/types/http/views.js +6 -0
- package/dist/src/types/http/views.js.map +1 -0
- package/dist/src/types/http.js +9 -0
- package/dist/src/types/http.js.map +1 -0
- package/dist/src/types/image/managed-image.js +7 -0
- package/dist/src/types/image/managed-image.js.map +1 -0
- package/dist/src/types/interp/effect-interpreter.js +8 -0
- package/dist/src/types/interp/effect-interpreter.js.map +1 -0
- package/dist/src/types/interp/tracker.js +7 -0
- package/dist/src/types/interp/tracker.js.map +1 -0
- package/dist/src/types/issue/file.js +6 -0
- package/dist/src/types/issue/file.js.map +1 -0
- package/dist/src/types/issue/parse.js +8 -0
- package/dist/src/types/issue/parse.js.map +1 -0
- package/dist/src/types/main-acp.js +13 -0
- package/dist/src/types/main-acp.js.map +1 -0
- package/dist/src/types/main-adapters.js +5 -0
- package/dist/src/types/main-adapters.js.map +1 -0
- package/dist/src/types/main-credential.js +21 -0
- package/dist/src/types/main-credential.js.map +1 -0
- package/dist/src/types/main-doctor.js +6 -0
- package/dist/src/types/main-doctor.js.map +1 -0
- package/dist/src/types/main-http-handler.js +12 -0
- package/dist/src/types/main-http-handler.js.map +1 -0
- package/dist/src/types/main-http.js +5 -0
- package/dist/src/types/main-http.js.map +1 -0
- package/dist/src/types/main-loops.js +5 -0
- package/dist/src/types/main-loops.js.map +1 -0
- package/dist/src/types/main-mcp.js +12 -0
- package/dist/src/types/main-mcp.js.map +1 -0
- package/dist/src/types/main-orchestrator.js +5 -0
- package/dist/src/types/main-orchestrator.js.map +1 -0
- package/dist/src/types/main-reconcilers.js +11 -0
- package/dist/src/types/main-reconcilers.js.map +1 -0
- package/dist/src/types/main-runner.js +13 -0
- package/dist/src/types/main-runner.js.map +1 -0
- package/dist/src/types/main-startup.js +5 -0
- package/dist/src/types/main-startup.js.map +1 -0
- package/dist/src/types/main-substrates.js +5 -0
- package/dist/src/types/main-substrates.js.map +1 -0
- package/dist/src/types/mcp/dispatch.js +4 -0
- package/dist/src/types/mcp/dispatch.js.map +1 -0
- package/dist/src/types/mcp/post-move.js +7 -0
- package/dist/src/types/mcp/post-move.js.map +1 -0
- package/dist/src/types/mcp.js +9 -0
- package/dist/src/types/mcp.js.map +1 -0
- package/dist/src/types/ports.js +12 -0
- package/dist/src/types/ports.js.map +1 -0
- package/dist/src/types/reconcile/image-decide.js +5 -0
- package/dist/src/types/reconcile/image-decide.js.map +1 -0
- package/dist/src/types/reconcile/ledger.js +7 -0
- package/dist/src/types/reconcile/ledger.js.map +1 -0
- package/dist/src/types/reconcile/pr-loop.js +8 -0
- package/dist/src/types/reconcile/pr-loop.js.map +1 -0
- package/dist/src/types/reconcile/vm-reap.js +8 -0
- package/dist/src/types/reconcile/vm-reap.js.map +1 -0
- package/dist/src/types/reconcile/workspace-decide.js +7 -0
- package/dist/src/types/reconcile/workspace-decide.js.map +1 -0
- package/dist/src/types/reconcile.js +9 -0
- package/dist/src/types/reconcile.js.map +1 -0
- package/dist/src/types/runlog.js +7 -0
- package/dist/src/types/runlog.js.map +1 -0
- package/dist/src/types/runner/actions-runner.js +12 -0
- package/dist/src/types/runner/actions-runner.js.map +1 -0
- package/dist/src/types/runner/gondolin-dispatch.js +5 -0
- package/dist/src/types/runner/gondolin-dispatch.js.map +1 -0
- package/dist/src/types/runner/injection.js +6 -0
- package/dist/src/types/runner/injection.js.map +1 -0
- package/dist/src/types/runner/runner-loop.js +5 -0
- package/dist/src/types/runner/runner-loop.js.map +1 -0
- package/dist/src/types/runner/turn.js +4 -0
- package/dist/src/types/runner/turn.js.map +1 -0
- package/dist/src/types/runner/vm-plan.js +4 -0
- package/dist/src/types/runner/vm-plan.js.map +1 -0
- package/dist/src/types/runtime.js +9 -0
- package/dist/src/types/runtime.js.map +1 -0
- package/dist/src/types/schedule/admission.js +7 -0
- package/dist/src/types/schedule/admission.js.map +1 -0
- package/dist/src/types/schedule/circuit-breaker.js +2 -0
- package/dist/src/types/schedule/circuit-breaker.js.map +1 -0
- package/dist/src/types/schedule/eligibility.js +9 -0
- package/dist/src/types/schedule/eligibility.js.map +1 -0
- package/dist/src/types/schedule/orchestrator-loop.js +10 -0
- package/dist/src/types/schedule/orchestrator-loop.js.map +1 -0
- package/dist/src/types/schedule/sleep-cycle.js +4 -0
- package/dist/src/types/schedule/sleep-cycle.js.map +1 -0
- package/dist/src/types/schedule/slots.js +8 -0
- package/dist/src/types/schedule/slots.js.map +1 -0
- package/dist/src/types/schedule/tick.js +9 -0
- package/dist/src/types/schedule/tick.js.map +1 -0
- package/dist/src/types/server/mcp-runtime.js +8 -0
- package/dist/src/types/server/mcp-runtime.js.map +1 -0
- package/dist/src/types/workflow/parse.js +4 -0
- package/dist/src/types/workflow/parse.js.map +1 -0
- package/dist/tests/core/account-id.test.js +35 -0
- package/dist/tests/core/account-id.test.js.map +1 -0
- package/dist/tests/core/actions-parse.test.js +176 -0
- package/dist/tests/core/actions-parse.test.js.map +1 -0
- package/dist/tests/core/adapter-config.test.js +133 -0
- package/dist/tests/core/adapter-config.test.js.map +1 -0
- package/dist/tests/core/admission.test.js +215 -0
- package/dist/tests/core/admission.test.js.map +1 -0
- package/dist/tests/core/args.test.js +132 -0
- package/dist/tests/core/args.test.js.map +1 -0
- package/dist/tests/core/availability.test.js +62 -0
- package/dist/tests/core/availability.test.js.map +1 -0
- package/dist/tests/core/checks.test.js +395 -0
- package/dist/tests/core/checks.test.js.map +1 -0
- package/dist/tests/core/circuit-breaker.test.js +172 -0
- package/dist/tests/core/circuit-breaker.test.js.map +1 -0
- package/dist/tests/core/coerce.test.js +87 -0
- package/dist/tests/core/coerce.test.js.map +1 -0
- package/dist/tests/core/context.test.js +228 -0
- package/dist/tests/core/context.test.js.map +1 -0
- package/dist/tests/core/decisions.test.js +310 -0
- package/dist/tests/core/decisions.test.js.map +1 -0
- package/dist/tests/core/derive.test.js +205 -0
- package/dist/tests/core/derive.test.js.map +1 -0
- package/dist/tests/core/dispatch-config.test.js +164 -0
- package/dist/tests/core/dispatch-config.test.js.map +1 -0
- package/dist/tests/core/dispatch.test.js +302 -0
- package/dist/tests/core/dispatch.test.js.map +1 -0
- package/dist/tests/core/eligibility.test.js +163 -0
- package/dist/tests/core/eligibility.test.js.map +1 -0
- package/dist/tests/core/extract.test.js +139 -0
- package/dist/tests/core/extract.test.js.map +1 -0
- package/dist/tests/core/fake-creds.test.js +134 -0
- package/dist/tests/core/fake-creds.test.js.map +1 -0
- package/dist/tests/core/file.test.js +197 -0
- package/dist/tests/core/file.test.js.map +1 -0
- package/dist/tests/core/git-result.test.js +113 -0
- package/dist/tests/core/git-result.test.js.map +1 -0
- package/dist/tests/core/identity.test.js +180 -0
- package/dist/tests/core/identity.test.js.map +1 -0
- package/dist/tests/core/image-decide.test.js +59 -0
- package/dist/tests/core/image-decide.test.js.map +1 -0
- package/dist/tests/core/injection.test.js +163 -0
- package/dist/tests/core/injection.test.js.map +1 -0
- package/dist/tests/core/ledger.test.js +218 -0
- package/dist/tests/core/ledger.test.js.map +1 -0
- package/dist/tests/core/managed-image.test.js +68 -0
- package/dist/tests/core/managed-image.test.js.map +1 -0
- package/dist/tests/core/mise.test.js +138 -0
- package/dist/tests/core/mise.test.js.map +1 -0
- package/dist/tests/core/parse.test.js +174 -0
- package/dist/tests/core/parse.test.js.map +1 -0
- package/dist/tests/core/path.test.js +50 -0
- package/dist/tests/core/path.test.js.map +1 -0
- package/dist/tests/core/plan.test.js +218 -0
- package/dist/tests/core/plan.test.js.map +1 -0
- package/dist/tests/core/post-move.test.js +162 -0
- package/dist/tests/core/post-move.test.js.map +1 -0
- package/dist/tests/core/pr-classify.test.js +117 -0
- package/dist/tests/core/pr-classify.test.js.map +1 -0
- package/dist/tests/core/pr-decide.test.js +298 -0
- package/dist/tests/core/pr-decide.test.js.map +1 -0
- package/dist/tests/core/pr-loop.test.js +301 -0
- package/dist/tests/core/pr-loop.test.js.map +1 -0
- package/dist/tests/core/pr-notes.test.js +165 -0
- package/dist/tests/core/pr-notes.test.js.map +1 -0
- package/dist/tests/core/predicates.test.js +154 -0
- package/dist/tests/core/predicates.test.js.map +1 -0
- package/dist/tests/core/prompt.test.js +189 -0
- package/dist/tests/core/prompt.test.js.map +1 -0
- package/dist/tests/core/protocol.test.js +195 -0
- package/dist/tests/core/protocol.test.js.map +1 -0
- package/dist/tests/core/reconcile-issue.test.js +116 -0
- package/dist/tests/core/reconcile-issue.test.js.map +1 -0
- package/dist/tests/core/render.test.js +549 -0
- package/dist/tests/core/render.test.js.map +1 -0
- package/dist/tests/core/retry.test.js +186 -0
- package/dist/tests/core/retry.test.js.map +1 -0
- package/dist/tests/core/routes.test.js +247 -0
- package/dist/tests/core/routes.test.js.map +1 -0
- package/dist/tests/core/run-fold.test.js +299 -0
- package/dist/tests/core/run-fold.test.js.map +1 -0
- package/dist/tests/core/shape.test.js +185 -0
- package/dist/tests/core/shape.test.js.map +1 -0
- package/dist/tests/core/sleep-cycle.test.js +150 -0
- package/dist/tests/core/sleep-cycle.test.js.map +1 -0
- package/dist/tests/core/slots.test.js +201 -0
- package/dist/tests/core/slots.test.js.map +1 -0
- package/dist/tests/core/state-resolve.test.js +80 -0
- package/dist/tests/core/state-resolve.test.js.map +1 -0
- package/dist/tests/core/summary.test.js +200 -0
- package/dist/tests/core/summary.test.js.map +1 -0
- package/dist/tests/core/template.test.js +116 -0
- package/dist/tests/core/template.test.js.map +1 -0
- package/dist/tests/core/tick.test.js +558 -0
- package/dist/tests/core/tick.test.js.map +1 -0
- package/dist/tests/core/token-fold.test.js +176 -0
- package/dist/tests/core/token-fold.test.js.map +1 -0
- package/dist/tests/core/turn.test.js +388 -0
- package/dist/tests/core/turn.test.js.map +1 -0
- package/dist/tests/core/url.test.js +118 -0
- package/dist/tests/core/url.test.js.map +1 -0
- package/dist/tests/core/validate.test.js +247 -0
- package/dist/tests/core/validate.test.js.map +1 -0
- package/dist/tests/core/views.test.js +252 -0
- package/dist/tests/core/views.test.js.map +1 -0
- package/dist/tests/core/vm-decide.test.js +110 -0
- package/dist/tests/core/vm-decide.test.js.map +1 -0
- package/dist/tests/core/vm-guards.test.js +153 -0
- package/dist/tests/core/vm-guards.test.js.map +1 -0
- package/dist/tests/core/vm-plan.test.js +332 -0
- package/dist/tests/core/vm-plan.test.js.map +1 -0
- package/dist/tests/core/vm-reap.test.js +196 -0
- package/dist/tests/core/vm-reap.test.js.map +1 -0
- package/dist/tests/core/workflow-parse.test.js +493 -0
- package/dist/tests/core/workflow-parse.test.js.map +1 -0
- package/dist/tests/core/workspace-decide.test.js +236 -0
- package/dist/tests/core/workspace-decide.test.js.map +1 -0
- package/dist/tests/helpers/fixtures.js +167 -0
- package/dist/tests/helpers/fixtures.js.map +1 -0
- package/dist/tests/shell/acp-substrate.test.js +101 -0
- package/dist/tests/shell/acp-substrate.test.js.map +1 -0
- package/dist/tests/shell/actions-runner-push.test.js +203 -0
- package/dist/tests/shell/actions-runner-push.test.js.map +1 -0
- package/dist/tests/shell/credential-hooks.test.js +36 -0
- package/dist/tests/shell/credential-hooks.test.js.map +1 -0
- package/dist/tests/shell/credential-registry.test.js +165 -0
- package/dist/tests/shell/credential-registry.test.js.map +1 -0
- package/dist/tests/shell/credential-substrate.test.js +179 -0
- package/dist/tests/shell/credential-substrate.test.js.map +1 -0
- package/dist/tests/shell/dockerfile-mise-pin.test.js +51 -0
- package/dist/tests/shell/dockerfile-mise-pin.test.js.map +1 -0
- package/dist/tests/shell/doctor.test.js +101 -0
- package/dist/tests/shell/doctor.test.js.map +1 -0
- package/dist/tests/shell/effect-vm-create.test.js +52 -0
- package/dist/tests/shell/effect-vm-create.test.js.map +1 -0
- package/dist/tests/shell/gh-port.test.js +63 -0
- package/dist/tests/shell/gh-port.test.js.map +1 -0
- package/dist/tests/shell/gondolin-dispatch-guard.test.js +144 -0
- package/dist/tests/shell/gondolin-dispatch-guard.test.js.map +1 -0
- package/dist/tests/shell/gondolin-dispatch-shquote.test.js +168 -0
- package/dist/tests/shell/gondolin-dispatch-shquote.test.js.map +1 -0
- package/dist/tests/shell/gondolin-image-converter.test.js +208 -0
- package/dist/tests/shell/gondolin-image-converter.test.js.map +1 -0
- package/dist/tests/shell/gondolin-image-fetch.test.js +93 -0
- package/dist/tests/shell/gondolin-image-fetch.test.js.map +1 -0
- package/dist/tests/shell/http-handler.test.js +608 -0
- package/dist/tests/shell/http-handler.test.js.map +1 -0
- package/dist/tests/shell/http-server.test.js +53 -0
- package/dist/tests/shell/http-server.test.js.map +1 -0
- package/dist/tests/shell/mcp-runtime.test.js +366 -0
- package/dist/tests/shell/mcp-runtime.test.js.map +1 -0
- package/dist/tests/shell/mise-config-asset.test.js +87 -0
- package/dist/tests/shell/mise-config-asset.test.js.map +1 -0
- package/dist/tests/shell/orchestrator-loop.test.js +583 -0
- package/dist/tests/shell/orchestrator-loop.test.js.map +1 -0
- package/dist/tests/shell/reconciler-passes.test.js +314 -0
- package/dist/tests/shell/reconciler-passes.test.js.map +1 -0
- package/dist/tests/shell/runner-loop-turn.test.js +97 -0
- package/dist/tests/shell/runner-loop-turn.test.js.map +1 -0
- package/dist/tests/shell/runner-slice.test.js +536 -0
- package/dist/tests/shell/runner-slice.test.js.map +1 -0
- package/dist/tests/shell/scaffold.test.js +65 -0
- package/dist/tests/shell/scaffold.test.js.map +1 -0
- package/dist/tests/shell/tick-config.test.js +83 -0
- package/dist/tests/shell/tick-config.test.js.map +1 -0
- package/dist/tests/shell/tracker-parse-dates.test.js +44 -0
- package/dist/tests/shell/tracker-parse-dates.test.js.map +1 -0
- package/dist/tests/shell/tracker-write-issue.test.js +154 -0
- package/dist/tests/shell/tracker-write-issue.test.js.map +1 -0
- package/dist/tests/shell/workflow-prompt-split.test.js +208 -0
- package/dist/tests/shell/workflow-prompt-split.test.js.map +1 -0
- package/dist/tests/shell/workspace-live-config.test.js +140 -0
- package/dist/tests/shell/workspace-live-config.test.js.map +1 -0
- package/package.json +21 -9
- package/patches/@earendil-works+gondolin+0.12.0.patch +173 -0
- package/prompts/Reflect.md +91 -0
- package/prompts/Review.md +97 -0
- package/prompts/Todo.md +96 -0
- package/prompts/_footer.md +41 -0
- package/prompts/_preamble.md +42 -0
- package/prompts-minimal/Todo.md +26 -0
- package/scripts/postinstall.mjs +63 -0
- package/scripts/vm-agent.mjs +312 -90
- package/WORKFLOW.md +0 -744
- package/dist/acp-bridge.js +0 -324
- package/dist/acp-bridge.js.map +0 -1
- package/dist/actions/cache.js +0 -191
- package/dist/actions/cache.js.map +0 -1
- package/dist/actions/effects.js +0 -41
- package/dist/actions/effects.js.map +0 -1
- package/dist/actions/executor.js +0 -570
- package/dist/actions/executor.js.map +0 -1
- package/dist/actions/index.js +0 -13
- package/dist/actions/index.js.map +0 -1
- package/dist/actions/parsing.js.map +0 -1
- package/dist/actions/predicate-env.js +0 -27
- package/dist/actions/predicate-env.js.map +0 -1
- package/dist/actions/predicates.js +0 -49
- package/dist/actions/predicates.js.map +0 -1
- package/dist/actions/templating.js +0 -66
- package/dist/actions/templating.js.map +0 -1
- package/dist/actions/types.js +0 -15
- package/dist/actions/types.js.map +0 -1
- package/dist/agent/acp.js +0 -473
- package/dist/agent/acp.js.map +0 -1
- package/dist/agent/adapter-names.js +0 -159
- package/dist/agent/adapter-names.js.map +0 -1
- package/dist/agent/adapters.js +0 -511
- package/dist/agent/adapters.js.map +0 -1
- package/dist/agent/credential-extractors.js +0 -342
- package/dist/agent/credential-extractors.js.map +0 -1
- package/dist/agent/credential-secrets.js +0 -628
- package/dist/agent/credential-secrets.js.map +0 -1
- package/dist/agent/credential-ticker.js +0 -57
- package/dist/agent/credential-ticker.js.map +0 -1
- package/dist/agent/gondolin-creds-staging.js +0 -356
- package/dist/agent/gondolin-creds-staging.js.map +0 -1
- package/dist/agent/gondolin-dispatch.js +0 -375
- package/dist/agent/gondolin-dispatch.js.map +0 -1
- package/dist/agent/gondolin.js +0 -124
- package/dist/agent/gondolin.js.map +0 -1
- package/dist/agent/runner-decisions.js +0 -134
- package/dist/agent/runner-decisions.js.map +0 -1
- package/dist/agent/runner.js +0 -1456
- package/dist/agent/runner.js.map +0 -1
- package/dist/agent/tool-call-summary.js +0 -102
- package/dist/agent/tool-call-summary.js.map +0 -1
- package/dist/agent/vm-acp-mapping.js +0 -73
- package/dist/agent/vm-acp-mapping.js.map +0 -1
- package/dist/agent/vm-guards.js +0 -262
- package/dist/agent/vm-guards.js.map +0 -1
- package/dist/agent/vm-port.js +0 -22
- package/dist/agent/vm-port.js.map +0 -1
- package/dist/agent/vm-process-registry.js +0 -79
- package/dist/agent/vm-process-registry.js.map +0 -1
- package/dist/bin/cli-args.js +0 -105
- package/dist/bin/cli-args.js.map +0 -1
- package/dist/bin/symphony.js +0 -794
- package/dist/bin/symphony.js.map +0 -1
- package/dist/errors.js +0 -15
- package/dist/errors.js.map +0 -1
- package/dist/http-disk.js +0 -135
- package/dist/http-disk.js.map +0 -1
- package/dist/http-handlers.js.map +0 -1
- package/dist/http.js.map +0 -1
- package/dist/issues.js +0 -178
- package/dist/issues.js.map +0 -1
- package/dist/logging.js +0 -203
- package/dist/logging.js.map +0 -1
- package/dist/mcp.js +0 -706
- package/dist/mcp.js.map +0 -1
- package/dist/memory.js +0 -85
- package/dist/memory.js.map +0 -1
- package/dist/orchestrator-decisions.js +0 -331
- package/dist/orchestrator-decisions.js.map +0 -1
- package/dist/orchestrator.js +0 -1569
- package/dist/orchestrator.js.map +0 -1
- package/dist/prompt.js +0 -65
- package/dist/prompt.js.map +0 -1
- package/dist/reconciler/cache.js +0 -65
- package/dist/reconciler/cache.js.map +0 -1
- package/dist/reconciler/index.js +0 -448
- package/dist/reconciler/index.js.map +0 -1
- package/dist/reconciler/ledger.js +0 -131
- package/dist/reconciler/ledger.js.map +0 -1
- package/dist/reconciler/pr-adapters.js +0 -174
- package/dist/reconciler/pr-adapters.js.map +0 -1
- package/dist/reconciler/pr-decide.js.map +0 -1
- package/dist/reconciler/pr.js +0 -422
- package/dist/reconciler/pr.js.map +0 -1
- package/dist/reconciler/types.js +0 -12
- package/dist/reconciler/types.js.map +0 -1
- package/dist/reconciler/vm.js +0 -243
- package/dist/reconciler/vm.js.map +0 -1
- package/dist/reconciler/workspace-defaults.js +0 -83
- package/dist/reconciler/workspace-defaults.js.map +0 -1
- package/dist/reconciler/workspace.js +0 -272
- package/dist/reconciler/workspace.js.map +0 -1
- package/dist/runlog.js +0 -403
- package/dist/runlog.js.map +0 -1
- package/dist/scaffold.js +0 -165
- package/dist/scaffold.js.map +0 -1
- package/dist/trackers/local.js +0 -445
- package/dist/trackers/local.js.map +0 -1
- package/dist/trackers/types.js +0 -10
- package/dist/trackers/types.js.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/util/clock.js +0 -12
- package/dist/util/clock.js.map +0 -1
- package/dist/util/crypto.js +0 -25
- package/dist/util/crypto.js.map +0 -1
- package/dist/util/frontmatter.js +0 -70
- package/dist/util/frontmatter.js.map +0 -1
- package/dist/util/fs-issues.js +0 -22
- package/dist/util/fs-issues.js.map +0 -1
- package/dist/util/process.js +0 -152
- package/dist/util/process.js.map +0 -1
- package/dist/util/workspace-key.js +0 -10
- package/dist/util/workspace-key.js.map +0 -1
- package/dist/workflow-loader.js +0 -147
- package/dist/workflow-loader.js.map +0 -1
- package/dist/workflow.js +0 -822
- package/dist/workflow.js.map +0 -1
- package/dist/workspace-types.js +0 -8
- package/dist/workspace-types.js.map +0 -1
- package/dist/workspace.js +0 -443
- package/dist/workspace.js.map +0 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// FCIS rewrite — pure image-readiness decision core (issue 206).
|
|
2
|
+
//
|
|
3
|
+
// The auto-convert-on-reconcile gate: given the shell's image-readiness
|
|
4
|
+
// projection (gondolin.oci_image set? a cached asset present? a build in flight?
|
|
5
|
+
// did the last build fail?), decide whether the poll tick must HOLD VM dispatch
|
|
6
|
+
// this round, and whether to EMIT an `ensure_image` effect to kick off the
|
|
7
|
+
// one-time conversion. The shell does all the docker/filesystem IO (resolve the
|
|
8
|
+
// OCI digest, look the asset up in the local gondolin store, run `buildAssets`);
|
|
9
|
+
// this function only folds the resulting flags into a decision so the gate is
|
|
10
|
+
// unit-testable without docker.
|
|
11
|
+
//
|
|
12
|
+
// HARD CONSTRAINTS (mirror the sibling reconcile deciders): 100% synchronous; no
|
|
13
|
+
// async/await/Promise; no IO, node: imports, process, clock, or randomness. The
|
|
14
|
+
// side effect is RETURNED as an Effect[]; the loop executes it.
|
|
15
|
+
/**
|
|
16
|
+
* Fold the image-readiness projection into the poll tick's hold/build decision.
|
|
17
|
+
*
|
|
18
|
+
* - `gondolin.image` escape hatch set → it WINS the runtime selector
|
|
19
|
+
* (`resolveImagePath`, mirrored by `checkGondolinImage`), so the `oci_image`
|
|
20
|
+
* auto-convert path is irrelevant: never hold dispatch on its readiness and
|
|
21
|
+
* never require the one-time conversion. The escape hatch takes precedence
|
|
22
|
+
* REGARDLESS of whether `oci_image` is set / converted / failing.
|
|
23
|
+
* - oci_image unset (or no ref) → auto-convert path inactive: never hold, never
|
|
24
|
+
* build (dispatch runs against the `gondolin.image` escape hatch).
|
|
25
|
+
* - cached asset present (`ready`) → proceed: never hold, never build.
|
|
26
|
+
* - configured but not ready → HOLD dispatch, and emit `ensure_image` UNLESS a
|
|
27
|
+
* build is already in flight (`building`) or the last build for this ref failed
|
|
28
|
+
* (`failed`, so we don't hammer a broken ref every poll — the dashboard banner
|
|
29
|
+
* + doctor surface the error and the operator fixes the ref / restarts).
|
|
30
|
+
*
|
|
31
|
+
* `escapeHatchConfigured` is whether `gondolin.image` is a non-empty selector,
|
|
32
|
+
* computed by the poll reducer the same way `resolveImagePath` tests it (so the
|
|
33
|
+
* gate, doctor, and the runtime selector can never disagree on which source wins).
|
|
34
|
+
*/
|
|
35
|
+
export function decideImageReadiness(image, escapeHatchConfigured) {
|
|
36
|
+
if (escapeHatchConfigured)
|
|
37
|
+
return { holdDispatch: false, effects: [] };
|
|
38
|
+
if (!image || !image.ociConfigured || image.ref === null) {
|
|
39
|
+
return { holdDispatch: false, effects: [] };
|
|
40
|
+
}
|
|
41
|
+
if (image.ready)
|
|
42
|
+
return { holdDispatch: false, effects: [] };
|
|
43
|
+
const effects = image.building || image.failed
|
|
44
|
+
? []
|
|
45
|
+
: [{ family: 'image', kind: 'ensure', ref: image.ref }];
|
|
46
|
+
return { holdDispatch: true, effects };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=image-decide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-decide.js","sourceRoot":"","sources":["../../../../src/core/reconcile/image-decide.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,wEAAwE;AACxE,iFAAiF;AACjF,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAChF,iFAAiF;AACjF,8EAA8E;AAC9E,gCAAgC;AAChC,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gEAAgE;AAShE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAiC,EACjC,qBAA8B;IAE9B,IAAI,qBAAqB;QAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACvE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC9C,CAAC;IACD,IAAI,KAAK,CAAC,KAAK;QAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC7D,MAAM,OAAO,GACX,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM;QAC5B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// FCIS rewrite — the ONE pure ResourceActionLedger reducer shared by every
|
|
2
|
+
// reconciler resource (vm / workspace / pr / actions). Each carries a
|
|
3
|
+
// most-recent-first buffer of `ActionStatus` rows ("what is this resource doing
|
|
4
|
+
// / what did it just try") for the dashboard. The original (REF:
|
|
5
|
+
// src/reconciler/ledger.ts) was a stateful CLASS that read `Date.now()` and
|
|
6
|
+
// mutated in place; here every transition is a PURE function returning a new
|
|
7
|
+
// immutable `LedgerState` with the wall clock INJECTED as an ISO string (`at`).
|
|
8
|
+
// The original async `run(action, fn)` helper stays in the shell, composed from
|
|
9
|
+
// start → (done | error). Per-function behavior is documented inline below; the
|
|
10
|
+
// buffer keeps a `maxHistory * 2` lookback so a late done/error still finds its
|
|
11
|
+
// `in_progress` row after a flood of newer actions, while `snapshot()` slices
|
|
12
|
+
// the freshest `maxHistory`.
|
|
13
|
+
/**
|
|
14
|
+
* Snapshot slice cap. Matches what each resource exposed as its private
|
|
15
|
+
* `MAX_ACTION_HISTORY` before the refactor: bake = 8, vm = 32, workspace = 32,
|
|
16
|
+
* pr = 64. Each call site passes its prior cap so snapshot payloads are
|
|
17
|
+
* unchanged.
|
|
18
|
+
*/
|
|
19
|
+
export const DEFAULT_MAX_HISTORY = 32;
|
|
20
|
+
/** Construct an empty ledger for `resource`. `maxHistory` defaults to 32. */
|
|
21
|
+
export function createLedger(resource, maxHistory = DEFAULT_MAX_HISTORY) {
|
|
22
|
+
return { resource, maxHistory, buf: [] };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Prepend `status` and evict beyond the `maxHistory * 2` lookback window.
|
|
26
|
+
* Pure: returns a new state, leaves `state.buf` untouched.
|
|
27
|
+
*/
|
|
28
|
+
function push(state, status) {
|
|
29
|
+
const next = [status, ...state.buf];
|
|
30
|
+
const cap = state.maxHistory * 2;
|
|
31
|
+
return { ...state, buf: next.length > cap ? next.slice(0, cap) : next };
|
|
32
|
+
}
|
|
33
|
+
/** Index of the most-recent `in_progress` row for `action`, or -1. */
|
|
34
|
+
function findInProgress(state, action) {
|
|
35
|
+
return state.buf.findIndex((a) => a.action === action && a.state === 'in_progress');
|
|
36
|
+
}
|
|
37
|
+
/** Replace the row at `idx` with `next`, returning a new state. */
|
|
38
|
+
function replaceAt(state, idx, next) {
|
|
39
|
+
const buf = state.buf.slice();
|
|
40
|
+
buf[idx] = next;
|
|
41
|
+
return { ...state, buf };
|
|
42
|
+
}
|
|
43
|
+
/** Prepend an `in_progress` row started at `at` (injected ISO clock reading). */
|
|
44
|
+
export function start(state, action, at) {
|
|
45
|
+
return push(state, {
|
|
46
|
+
resource: state.resource,
|
|
47
|
+
action,
|
|
48
|
+
state: 'in_progress',
|
|
49
|
+
started_at: at,
|
|
50
|
+
finished_at: null,
|
|
51
|
+
error: null,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Flip the most-recent matching `in_progress` row to `done` (finished at `at`).
|
|
56
|
+
* Idempotent: with no matching row this returns the SAME state value.
|
|
57
|
+
*/
|
|
58
|
+
export function done(state, action, at) {
|
|
59
|
+
const idx = findInProgress(state, action);
|
|
60
|
+
if (idx < 0)
|
|
61
|
+
return state;
|
|
62
|
+
return replaceAt(state, idx, { ...state.buf[idx], state: 'done', finished_at: at });
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Flip the matching `in_progress` row to `error` (finished at `at`); when no
|
|
66
|
+
* in-progress row exists, prepend a fresh orphan-error row with
|
|
67
|
+
* `started_at === finished_at`.
|
|
68
|
+
*/
|
|
69
|
+
export function error(state, action, msg, at) {
|
|
70
|
+
const idx = findInProgress(state, action);
|
|
71
|
+
if (idx >= 0) {
|
|
72
|
+
return replaceAt(state, idx, {
|
|
73
|
+
...state.buf[idx],
|
|
74
|
+
state: 'error',
|
|
75
|
+
finished_at: at,
|
|
76
|
+
error: msg,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return push(state, {
|
|
80
|
+
resource: state.resource,
|
|
81
|
+
action,
|
|
82
|
+
state: 'error',
|
|
83
|
+
started_at: at,
|
|
84
|
+
finished_at: at,
|
|
85
|
+
error: msg,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* One-shot terminal annotation. The action is prepended already-finished;
|
|
90
|
+
* `started_at === finished_at`. Used for state that has no meaningful
|
|
91
|
+
* in-progress phase (workspace drift annotations, vm kill_session errors).
|
|
92
|
+
*/
|
|
93
|
+
export function record(state, action, outcome, at, msg = null) {
|
|
94
|
+
return push(state, {
|
|
95
|
+
resource: state.resource,
|
|
96
|
+
action,
|
|
97
|
+
state: outcome,
|
|
98
|
+
started_at: at,
|
|
99
|
+
finished_at: at,
|
|
100
|
+
error: msg,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/** Most-recent-first slice of action statuses, capped at `maxItems` (default `maxHistory`). */
|
|
104
|
+
export function snapshot(state, maxItems) {
|
|
105
|
+
return state.buf.slice(0, maxItems ?? state.maxHistory);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The newest error message in the buffer, or null. Surfaced as `last_error` in
|
|
109
|
+
* both the ResourceSnapshot and ActionsSnapshot projections. (buf is
|
|
110
|
+
* most-recent-first, so the first error row is the freshest.)
|
|
111
|
+
*/
|
|
112
|
+
function lastError(state) {
|
|
113
|
+
const row = state.buf.find((a) => a.state === 'error' && a.error !== null);
|
|
114
|
+
return row ? row.error : null;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Project a `ResourceSnapshot` for the dashboard. The ledger does not own the
|
|
118
|
+
* desired/actual convergence verdict, so the caller supplies `ready`,
|
|
119
|
+
* `desired_hash`, and (optionally) overrides `id` / `last_error`.
|
|
120
|
+
*/
|
|
121
|
+
export function resourceSnapshot(state, opts) {
|
|
122
|
+
return {
|
|
123
|
+
id: opts.id ?? state.resource,
|
|
124
|
+
ready: opts.ready,
|
|
125
|
+
desired_hash: opts.desired_hash ?? null,
|
|
126
|
+
last_error: opts.last_error !== undefined ? opts.last_error : lastError(state),
|
|
127
|
+
actions: snapshot(state, opts.maxItems),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Project an `ActionsSnapshot` (the orchestrator drains this from the actions
|
|
132
|
+
* executor between attempts). `id` is conventionally `actions:<state>`.
|
|
133
|
+
*/
|
|
134
|
+
export function actionsSnapshot(state, opts) {
|
|
135
|
+
return {
|
|
136
|
+
id: opts.id,
|
|
137
|
+
ready: opts.ready,
|
|
138
|
+
last_error: opts.last_error !== undefined ? opts.last_error : lastError(state),
|
|
139
|
+
actions: snapshot(state, opts.maxItems),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../../src/core/reconcile/ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// FCIS rewrite — pure PR-intent classifier.
|
|
2
|
+
//
|
|
3
|
+
// Functional-core port of the original `src/orchestrator-decisions.ts:
|
|
4
|
+
// classifyPrIntent`. Maps a tracker issue + the configured merge/close state
|
|
5
|
+
// names + the base branch into a `PrIntent` (the unit of work the PR autopilot
|
|
6
|
+
// reconciles) or `null` when the issue's state matches neither configured PR
|
|
7
|
+
// state.
|
|
8
|
+
//
|
|
9
|
+
// The original is already pure-ish (no IO of its own), but it took the
|
|
10
|
+
// merge-workspace path as a precomputed string — workspace pathing is an
|
|
11
|
+
// adapter concern (it depends on the workspace root + key scheme), so the
|
|
12
|
+
// SHELL still supplies `mergeWorkspacePath` here, exactly as before. Close
|
|
13
|
+
// intents drop the workspace path (terminal cleanup owns that directory), so
|
|
14
|
+
// the shell may pass anything for it on a pure-close issue.
|
|
15
|
+
//
|
|
16
|
+
// HARD CONSTRAINTS (gate-enforced):
|
|
17
|
+
// - 100% SYNCHRONOUS. No async/await/Promise anywhere.
|
|
18
|
+
// - No IO, no node: imports, no process/fetch, no wall clock, no randomness.
|
|
19
|
+
// - Imports ONLY from src/types/**.
|
|
20
|
+
//
|
|
21
|
+
// Behavior ported faithfully:
|
|
22
|
+
// - State matching is CASE-INSENSITIVE (both sides lower-cased) — the tracker
|
|
23
|
+
// stores the human-facing state label (e.g. "In Review") while the workflow
|
|
24
|
+
// config may declare it differently-cased.
|
|
25
|
+
// - `closeState === null` means "no close state configured" → never a close
|
|
26
|
+
// intent.
|
|
27
|
+
// - The emitted `state` field preserves the issue's ORIGINAL casing (the
|
|
28
|
+
// case-insensitive compare is only for matching, not for what we echo back).
|
|
29
|
+
// - Branch fallback: an empty / missing `branch_name` derives `agent/<id>`.
|
|
30
|
+
/**
|
|
31
|
+
* Classify a tracker issue into a PR autopilot intent or `null`.
|
|
32
|
+
*
|
|
33
|
+
* Returns `null` when the issue's state matches neither the configured merge
|
|
34
|
+
* state nor (if any) the configured close state. Otherwise returns a fully
|
|
35
|
+
* populated {@link PrIntent}:
|
|
36
|
+
* - `kind: 'merge'` when the state matches `mergeState` (merge takes
|
|
37
|
+
* precedence if — pathologically — both names coincide), with
|
|
38
|
+
* `workspace_path` set to the shell-supplied `mergeWorkspacePath`.
|
|
39
|
+
* - `kind: 'close'` otherwise, with `workspace_path: null`.
|
|
40
|
+
*
|
|
41
|
+
* Pure + synchronous: (data) -> data | null. No Effects: this is a pure
|
|
42
|
+
* classification, so the only "output" is the decision object itself.
|
|
43
|
+
*/
|
|
44
|
+
export function classifyPrIntent(input) {
|
|
45
|
+
const stateLower = input.issue.state.toLowerCase();
|
|
46
|
+
const isMerge = stateLower === input.mergeState.toLowerCase();
|
|
47
|
+
const isClose = input.closeState !== null && stateLower === input.closeState.toLowerCase();
|
|
48
|
+
if (!isMerge && !isClose)
|
|
49
|
+
return null;
|
|
50
|
+
const branch = input.issue.branch_name && input.issue.branch_name.length > 0
|
|
51
|
+
? input.issue.branch_name
|
|
52
|
+
: `agent/${input.issue.identifier}`;
|
|
53
|
+
return {
|
|
54
|
+
identifier: input.issue.identifier,
|
|
55
|
+
kind: isMerge ? 'merge' : 'close',
|
|
56
|
+
state: input.issue.state,
|
|
57
|
+
workspace_path: isMerge ? input.mergeWorkspacePath : null,
|
|
58
|
+
branch,
|
|
59
|
+
base_branch: input.baseBranch,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=pr-classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-classify.js","sourceRoot":"","sources":["../../../../src/core/reconcile/pr-classify.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,uEAAuE;AACvE,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,SAAS;AACT,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,2EAA2E;AAC3E,6EAA6E;AAC7E,4DAA4D;AAC5D,EAAE;AACF,oCAAoC;AACpC,yDAAyD;AACzD,+EAA+E;AAC/E,sCAAsC;AACtC,EAAE;AACF,8BAA8B;AAC9B,gFAAgF;AAChF,gFAAgF;AAChF,+CAA+C;AAC/C,8EAA8E;AAC9E,cAAc;AACd,2EAA2E;AAC3E,iFAAiF;AACjF,8EAA8E;AAsB9E;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA4B;IAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,OAAO,GAAG,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;IAC9D,MAAM,OAAO,GACX,KAAK,CAAC,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;IAC7E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,MAAM,GACV,KAAK,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAC3D,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW;QACzB,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAExC,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU;QAClC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QACjC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK;QACxB,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI;QACzD,MAAM;QACN,WAAW,EAAE,KAAK,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
//
|
|
2
|
-
// PrEffect[]` is the heart of the resource: every routing, arm, cleanup, and
|
|
3
|
-
// reroute branch lives here as a deterministic function of an observation
|
|
4
|
-
// snapshot. `pr.ts` is then the imperative shell that builds the observation,
|
|
5
|
-
// applies effects in order through the injected ports, folds outcomes back
|
|
6
|
-
// into the next observation, and re-decides until the decision list is empty.
|
|
1
|
+
// FCIS rewrite — pure PR-autopilot decision core (issue 70 / issue 105).
|
|
7
2
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
3
|
+
// Verbatim port of the original `src/reconciler/pr-decide.ts`:
|
|
4
|
+
// decidePr, buildConflictNotes, and the two private deciders decideClose /
|
|
5
|
+
// decideConflict. The original module was already a pure, synchronous
|
|
6
|
+
// (data) -> data function — it declared `No IO imports. No clock. No
|
|
7
|
+
// randomness. Domain-only.` at the top. The only change in this rewrite is
|
|
8
|
+
// structural: the type vocabulary (PrEffect, PrObservation, PrIntent, PrView,
|
|
9
|
+
// …) now lives in `src/types/reconcile.ts` and is imported here rather than
|
|
10
|
+
// declared inline. The branch logic is unchanged.
|
|
11
|
+
//
|
|
12
|
+
// `decidePr(observation) → PrEffect[]` is the heart of the resource: every
|
|
13
|
+
// routing, arm, cleanup, and reroute branch lives here as a deterministic
|
|
14
|
+
// function of an observation snapshot. The imperative shell builds the
|
|
15
|
+
// observation, applies the returned effects in order through injected ports,
|
|
16
|
+
// folds outcomes back into the next observation, and re-decides until the
|
|
17
|
+
// decision list is empty.
|
|
10
18
|
//
|
|
11
19
|
// Multi-pass semantics: outcomes of IO effects (summary lookup, view fetch)
|
|
12
20
|
// drive subsequent decisions. The shell records each outcome into the
|
|
@@ -14,10 +22,10 @@
|
|
|
14
22
|
// `summaryResolved` / `viewResolved` to decide whether the next observation
|
|
15
23
|
// step has run yet. The loop terminates when `decidePr` returns `[]`.
|
|
16
24
|
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
25
|
+
// HARD CONSTRAINTS (gate-enforced):
|
|
26
|
+
// - 100% SYNCHRONOUS. No async/await/Promise anywhere.
|
|
27
|
+
// - No IO, no node: imports, no process/fetch, no wall clock, no randomness.
|
|
28
|
+
// - Imports ONLY from src/types/**.
|
|
21
29
|
/**
|
|
22
30
|
* Pure decision: given an observation, return the next batch of effects the
|
|
23
31
|
* shell should apply. After applying, the shell rebuilds the observation
|
|
@@ -136,6 +144,11 @@ function decideClose(obs) {
|
|
|
136
144
|
*/
|
|
137
145
|
function decideConflict(obs) {
|
|
138
146
|
const id = obs.intent.identifier;
|
|
147
|
+
// `decideConflict` is only reached from the MERGEABLE-branch guard in
|
|
148
|
+
// `decidePr` after `obs.view === null` has been ruled out, so the view is
|
|
149
|
+
// always present here. The original asserted this with a non-null assertion
|
|
150
|
+
// (`obs.view!`); we narrow explicitly instead to keep the module free of
|
|
151
|
+
// `!` and still hand a defined `PrView` to `buildConflictNotes`.
|
|
139
152
|
const view = obs.view;
|
|
140
153
|
return [
|
|
141
154
|
{
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-decide.js","sourceRoot":"","sources":["../../../../src/core/reconcile/pr-decide.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// FCIS rewrite — pure multi-pass driver of `decidePr` (the PR autopilot's
|
|
2
|
+
// per-intent decide → apply → re-decide loop).
|
|
3
|
+
//
|
|
4
|
+
// Ported faithfully from the reference `src/reconciler/pr.ts`
|
|
5
|
+
// (`processIntent` + `applyEffect`). The reference was an async driver that:
|
|
6
|
+
//
|
|
7
|
+
// • built a fresh `PrObservation` from live `PerIssueState`,
|
|
8
|
+
// • looped up to 12 times calling the pure `decidePr(obs)`,
|
|
9
|
+
// • AWAITED each emitted `PrEffect` against injected `gh` / tracker / cleanup
|
|
10
|
+
// ports (IO), and
|
|
11
|
+
// • folded each effect's OUTCOME back into the next observation
|
|
12
|
+
// (`summaryResolved`/`summary`, `viewResolved`/`view`, `closeAttempted`/
|
|
13
|
+
// `closeOutcome`, `halt`, and the sticky per-issue cache view: `armed` /
|
|
14
|
+
// `lastObservedHeadSha` / `completed`).
|
|
15
|
+
//
|
|
16
|
+
// In the functional core all the IO disappears. This module is JUST the fold:
|
|
17
|
+
//
|
|
18
|
+
// • The shell APPLIES each `PrEffect` (running the matching gh/tracker/fs
|
|
19
|
+
// port) and hands the result back as a `PrEffectOutcome` — the exact data
|
|
20
|
+
// the reference's `applyEffect` derived from its awaited IO call.
|
|
21
|
+
// • `foldPrEffectOutcome(obs, effect, outcome)` reproduces the reference's
|
|
22
|
+
// `applyEffect` switch as a pure `(obs, effect, outcome) -> obs` reducer:
|
|
23
|
+
// it threads the next observation (including the sticky cache view) without
|
|
24
|
+
// touching any port.
|
|
25
|
+
// • `decidePrPass(obs, decide)` runs ONE `decidePr` call and returns the
|
|
26
|
+
// emitted effects (or `[]` to stop) — `decide` is the pure `decidePr`
|
|
27
|
+
// injected as a plain parameter so this driver stays import-clean and
|
|
28
|
+
// independently testable.
|
|
29
|
+
// • `MAX_PR_DECIDE_ITERATIONS` is the reference's defensive 12-pass cap; the
|
|
30
|
+
// shell drives the outer loop and emits an `iteration_cap_reached` log when
|
|
31
|
+
// `driveStartState`/the loop signals it.
|
|
32
|
+
//
|
|
33
|
+
// The reference's sticky-cache mutations (`PerIssueState.armed` /
|
|
34
|
+
// `lastObservedHeadSha` / `completed`, and the `resetTransient` wipe) lived in
|
|
35
|
+
// the live `PerIssueState` map; here they ride in the `PrCacheView` carried by
|
|
36
|
+
// the observation. The shell folds the returned `obs.cache` back into its
|
|
37
|
+
// per-issue state after each pass.
|
|
38
|
+
//
|
|
39
|
+
// 100% SYNCHRONOUS. No async / await / Promise. No IO, no node: imports, no
|
|
40
|
+
// wall clock or randomness. Imports ONLY from src/types. (NodeNext ESM → .js
|
|
41
|
+
// extensions on relative imports.)
|
|
42
|
+
/**
|
|
43
|
+
* Defensive iteration cap, mirroring the reference's `for (let i = 0; i < 12;`
|
|
44
|
+
* loop in `processIntent`. `decidePr` strictly reduces work on every iteration
|
|
45
|
+
* (a `*_resolved` flag flips, a cache latch lands, or `halt` is set), so the
|
|
46
|
+
* loop terminates well inside this bound; the cap only guards against a future
|
|
47
|
+
* decide-table regression looping forever.
|
|
48
|
+
*/
|
|
49
|
+
export const MAX_PR_DECIDE_ITERATIONS = 12;
|
|
50
|
+
/**
|
|
51
|
+
* Run one `decidePr` pass over the current observation. Returns the effects the
|
|
52
|
+
* shell should apply (in order), or `[]` to terminate the per-intent loop.
|
|
53
|
+
*
|
|
54
|
+
* Mirrors the reference's `const effects = decidePr(obs); if (effects.length
|
|
55
|
+
* === 0) return;`. Kept as a one-liner seam so the shell never imports
|
|
56
|
+
* `decidePr` directly and the cap loop below has a single decide entry point.
|
|
57
|
+
*/
|
|
58
|
+
export function decidePrPass(obs, decide) {
|
|
59
|
+
return decide(obs);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Fold one applied `PrEffect`'s outcome back into the next observation. Pure
|
|
63
|
+
* reproduction of the reference `applyEffect` switch (`src/reconciler/pr.ts`):
|
|
64
|
+
* the shell runs the IO for `effect`, hands back the matching `PrEffectOutcome`,
|
|
65
|
+
* and this returns the observation the next `decidePr` call should see.
|
|
66
|
+
*
|
|
67
|
+
* Every branch returns a NEW observation object (never mutates the input),
|
|
68
|
+
* matching the reference's `{ ...obs, ... }` spreads.
|
|
69
|
+
*/
|
|
70
|
+
export function foldPrEffectOutcome(obs, effect, outcome) {
|
|
71
|
+
switch (effect.kind) {
|
|
72
|
+
case 'observe_summary': {
|
|
73
|
+
// Reference: `{ ...obs, summaryResolved: true, summary, cache }`.
|
|
74
|
+
const summary = outcome.kind === 'summary' ? outcome.summary : null;
|
|
75
|
+
const cache = outcome.kind === 'summary' ? outcome.cache : obs.cache;
|
|
76
|
+
return { ...obs, summaryResolved: true, summary, cache };
|
|
77
|
+
}
|
|
78
|
+
case 'observe_view': {
|
|
79
|
+
// Reference: `{ ...obs, viewResolved: true, view, cache }` — the shell's
|
|
80
|
+
// `fetchPrView` also folds `armed` / `lastObservedHeadSha` from the view
|
|
81
|
+
// into the cache, which arrives here in `outcome.cache`.
|
|
82
|
+
const view = outcome.kind === 'view' ? outcome.view : null;
|
|
83
|
+
const cache = outcome.kind === 'view' ? outcome.cache : obs.cache;
|
|
84
|
+
return { ...obs, viewResolved: true, view, cache };
|
|
85
|
+
}
|
|
86
|
+
case 'arm_auto_merge': {
|
|
87
|
+
// Reference: sets `st.armed = true`, returns `{ ...obs, cache }`.
|
|
88
|
+
const cache = outcome.kind === 'cache' ? outcome.cache : obs.cache;
|
|
89
|
+
return { ...obs, cache };
|
|
90
|
+
}
|
|
91
|
+
case 'update_branch':
|
|
92
|
+
// Reference: `{ ...obs, halt: true }`. The cached view still reads BEHIND;
|
|
93
|
+
// halting prevents re-emitting `update_branch` every iteration.
|
|
94
|
+
return { ...obs, halt: true };
|
|
95
|
+
case 'close_pr': {
|
|
96
|
+
// Reference: `{ ...obs, closeAttempted: true, closeOutcome: { ok } }`.
|
|
97
|
+
const ok = outcome.kind === 'close' ? outcome.ok : false;
|
|
98
|
+
return { ...obs, closeAttempted: true, closeOutcome: { ok } };
|
|
99
|
+
}
|
|
100
|
+
case 'delete_remote_branch':
|
|
101
|
+
case 'cleanup_workspace':
|
|
102
|
+
// Reference: returns `obs` unchanged (fire-and-forget, best-effort).
|
|
103
|
+
return obs;
|
|
104
|
+
case 'route_conflict':
|
|
105
|
+
// Reference: `{ ...obs, halt: true }`. Terminal for this pass; the paired
|
|
106
|
+
// `reset_transient` effect carries the cache wipe.
|
|
107
|
+
return { ...obs, halt: true };
|
|
108
|
+
case 'update_observed_head': {
|
|
109
|
+
// Reference: sets `st.lastObservedHeadSha = eff.sha`, returns `{ ...obs, cache }`.
|
|
110
|
+
const cache = outcome.kind === 'cache' ? outcome.cache : obs.cache;
|
|
111
|
+
return { ...obs, cache };
|
|
112
|
+
}
|
|
113
|
+
case 'mark_completed': {
|
|
114
|
+
// Reference: sets `st.completed = true`, returns `{ ...obs, cache }`.
|
|
115
|
+
const cache = outcome.kind === 'cache' ? outcome.cache : obs.cache;
|
|
116
|
+
return { ...obs, cache };
|
|
117
|
+
}
|
|
118
|
+
case 'reset_transient': {
|
|
119
|
+
// Reference: `resetTransient(st)` then `{ ...obs, cache, halt: true }`.
|
|
120
|
+
// Always paired with `route_conflict`; terminal for this pass. The shell
|
|
121
|
+
// hands back the wiped cache view (or the EMPTY cache if the per-issue
|
|
122
|
+
// state had already been dropped).
|
|
123
|
+
const cache = outcome.kind === 'cache' ? outcome.cache : obs.cache;
|
|
124
|
+
return { ...obs, cache, halt: true };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Pure multi-pass driver: the functional-core form of the reference
|
|
130
|
+
* `processIntent`. Repeatedly runs `decide(obs)`; if it emits no effects the
|
|
131
|
+
* loop ends; otherwise it folds each effect's applied outcome (via `apply`)
|
|
132
|
+
* back into the observation and re-decides — capped at
|
|
133
|
+
* {@link MAX_PR_DECIDE_ITERATIONS} passes.
|
|
134
|
+
*
|
|
135
|
+
* `apply` is synchronous on purpose: in production the shell drives the loop
|
|
136
|
+
* directly (awaiting IO between folds); this helper exists for pure tests and
|
|
137
|
+
* for shells that can resolve every effect synchronously. The fold reducer
|
|
138
|
+
* ({@link foldPrEffectOutcome}) and the pass seam ({@link decidePrPass}) are the
|
|
139
|
+
* load-bearing pure pieces — `drivePr` just sequences them, exactly like the
|
|
140
|
+
* reference loop, with no IO of its own.
|
|
141
|
+
*/
|
|
142
|
+
export function drivePr(initial, decide, apply) {
|
|
143
|
+
let obs = initial;
|
|
144
|
+
const steps = [];
|
|
145
|
+
for (let i = 0; i < MAX_PR_DECIDE_ITERATIONS; i += 1) {
|
|
146
|
+
const effects = decidePrPass(obs, decide);
|
|
147
|
+
if (effects.length === 0) {
|
|
148
|
+
return { observation: obs, steps, stop: 'idle' };
|
|
149
|
+
}
|
|
150
|
+
for (const effect of effects) {
|
|
151
|
+
const outcome = apply(effect, obs);
|
|
152
|
+
obs = foldPrEffectOutcome(obs, effect, outcome);
|
|
153
|
+
}
|
|
154
|
+
steps.push({ effects, observation: obs });
|
|
155
|
+
// A halt set by this pass means decidePr will return [] next iteration; we
|
|
156
|
+
// let the loop spin once more so the terminating `[]` is observed (matching
|
|
157
|
+
// the reference, where the next `decidePr` short-circuits on `obs.halt`).
|
|
158
|
+
}
|
|
159
|
+
return { observation: obs, steps, stop: 'iteration_cap' };
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=pr-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-loop.js","sourceRoot":"","sources":["../../../../src/core/reconcile/pr-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// FCIS rewrite — pure per-PR cache TTL freshness predicates.
|
|
2
|
+
//
|
|
3
|
+
// Extracted from the original `src/reconciler/pr.ts` (`PrResource.lookupPrSummary`
|
|
4
|
+
// + `PrResource.fetchPrView`), which tangled these freshness checks into the same
|
|
5
|
+
// async methods that shelled out to `gh pr list`/`gh pr view` and mutated state.
|
|
6
|
+
// Here it is ONLY the decision: given an injected `now` plus the prior
|
|
7
|
+
// `lastLookupAt`/`lastViewAt` and the cached payloads, reuse or re-poll/re-fetch.
|
|
8
|
+
//
|
|
9
|
+
// Two INDEPENDENT predicates (issue 70 "sticky cache" mustFix):
|
|
10
|
+
// 1. Summary (sticky): once a PR is FOUND it is reused forever — PR numbers
|
|
11
|
+
// don't change and a found PR moving OPEN→MERGED/CLOSED must keep its cached
|
|
12
|
+
// number so the autopilot can observe the terminal state. `lastLookupAt`
|
|
13
|
+
// governs ONLY the cache-MISS (null) re-poll.
|
|
14
|
+
// 2. View (TTL): plain time-to-live on the detailed view, keyed solely on its
|
|
15
|
+
// own `lastViewAt` — never coupled to the summary re-poll.
|
|
16
|
+
//
|
|
17
|
+
// `pollIntervalMs === 0` disables caching on both paths: the strict `<` makes any
|
|
18
|
+
// elapsed (>= 0) fall outside the window. Pure + synchronous: `now` is injected.
|
|
19
|
+
/** Mirrors the head of `PrResource.lookupPrSummary`: sticky short-circuit, then null-result TTL guard. */
|
|
20
|
+
export function decidePrSummaryFreshness(input) {
|
|
21
|
+
if (input.summary)
|
|
22
|
+
return { kind: 'reuse', summary: input.summary };
|
|
23
|
+
if (input.summary === null && input.now - input.lastLookupAt < input.pollIntervalMs) {
|
|
24
|
+
return { kind: 'defer' };
|
|
25
|
+
}
|
|
26
|
+
return { kind: 'repoll' };
|
|
27
|
+
}
|
|
28
|
+
/** Mirrors the head of `PrResource.fetchPrView`: reuse while inside the TTL, else re-fetch (strict `<`). */
|
|
29
|
+
export function decidePrViewFreshness(input) {
|
|
30
|
+
if (input.view !== null && input.now - input.lastViewAt < input.pollIntervalMs) {
|
|
31
|
+
return { kind: 'reuse', view: input.view };
|
|
32
|
+
}
|
|
33
|
+
return { kind: 'refetch' };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=pr-notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-notes.js","sourceRoot":"","sources":["../../../../src/core/reconcile/pr-notes.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,mFAAmF;AACnF,kFAAkF;AAClF,iFAAiF;AACjF,uEAAuE;AACvE,kFAAkF;AAClF,EAAE;AACF,gEAAgE;AAChE,8EAA8E;AAC9E,kFAAkF;AAClF,8EAA8E;AAC9E,mDAAmD;AACnD,gFAAgF;AAChF,gEAAgE;AAChE,EAAE;AACF,kFAAkF;AAClF,iFAAiF;AAsBjF,0GAA0G;AAC1G,MAAM,UAAU,wBAAwB,CAAC,KAA8B;IACrE,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACpE,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QACpF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5B,CAAC;AAmBD,4GAA4G;AAC5G,MAAM,UAAU,qBAAqB,CAAC,KAA2B;IAC/D,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QAC/E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// FCIS rewrite — pure VM-reaper decision core (issue 33 / reconciler stage 2;
|
|
2
|
+
// Gondolin migration Phase 4).
|
|
3
|
+
//
|
|
4
|
+
// Verbatim port of the original `src/reconciler/vm.ts:decideVm`. The original
|
|
5
|
+
// module mixed the pure decision (`decideVm`) with the imperative reaper loop
|
|
6
|
+
// (`VmResource`, gc / listSessions / process.kill / setTimeout). This rewrite
|
|
7
|
+
// extracts ONLY the pure decision; the SIGTERM→grace→SIGKILL escalation, the
|
|
8
|
+
// Gondolin gc, the session enumeration, and the ledger all live in the shell.
|
|
9
|
+
//
|
|
10
|
+
// The decision: given the observed live Gondolin session set, the orchestrator's
|
|
11
|
+
// intended label set, and the reaper's own pid, return one `kill_session`
|
|
12
|
+
// effect per session that is a LIVE orphan — a `symphony-`-prefixed session that
|
|
13
|
+
// the orchestrator does NOT intend to keep alive AND whose host pid is safe to
|
|
14
|
+
// signal (a sane positive integer that is not the reaper itself).
|
|
15
|
+
//
|
|
16
|
+
// Pid safety (verbatim from the original): a host signal is only ever emitted
|
|
17
|
+
// for a `pid` that is a safe positive integer and is NOT the reaper's own pid.
|
|
18
|
+
// The shell delivers the signal with `process.kill(pid, sig)`, which signals the
|
|
19
|
+
// whole PROCESS GROUP for `pid <= 0` and would target the orchestrator itself
|
|
20
|
+
// for `pid === selfPid`. A session carrying a `0`/`NaN`/negative/self pid is a
|
|
21
|
+
// registry anomaly, never a legitimate orphan, so it is left untouched here.
|
|
22
|
+
//
|
|
23
|
+
// Namespace safety (verbatim): anything outside the symphony-prefixed namespace
|
|
24
|
+
// — a session with no label, or a label that doesn't start with the prefix — is
|
|
25
|
+
// left untouched (operator VMs, sibling tools' sessions). STALE/dead-pid
|
|
26
|
+
// sessions and orphan sockets are NOT this function's concern; Gondolin's
|
|
27
|
+
// `gc()` collects them in the shell before the live session set reaches here.
|
|
28
|
+
//
|
|
29
|
+
// HARD CONSTRAINTS (gate-enforced): 100% synchronous; no async/await/Promise; no
|
|
30
|
+
// IO, node: imports, process, clock, or randomness. Imports ONLY from
|
|
31
|
+
// src/types. Every side effect is RETURNED as a `KillSessionAction[]`; the
|
|
32
|
+
// shell executes it.
|
|
33
|
+
/**
|
|
34
|
+
* Domain constant. Every VM the orchestrator creates is labelled with this
|
|
35
|
+
* prefix (the runner mints `sessionLabel = symphony-<identifier>`); the reaper
|
|
36
|
+
* only acts on labels that match. The vm-port adapter in the shell mirrors the
|
|
37
|
+
* same value — keep them in sync.
|
|
38
|
+
*/
|
|
39
|
+
export const SYMPHONY_VM_PREFIX = 'symphony-';
|
|
40
|
+
/**
|
|
41
|
+
* Pure decision: given the observed Gondolin session state, return the
|
|
42
|
+
* `kill_session` effects the shell should apply. No IO, no clock reads, no
|
|
43
|
+
* logging.
|
|
44
|
+
*
|
|
45
|
+
* Effect rule:
|
|
46
|
+
* • Session has a `label` that starts with SYMPHONY_VM_PREFIX and isn't
|
|
47
|
+
* intended, AND a sane, non-self host pid → `kill_session` (the shell
|
|
48
|
+
* SIGTERM→SIGKILLs its host pid).
|
|
49
|
+
*/
|
|
50
|
+
export function decideVm(state) {
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const s of state.sessions) {
|
|
53
|
+
const label = s.label;
|
|
54
|
+
if (label === undefined)
|
|
55
|
+
continue;
|
|
56
|
+
if (!label.startsWith(SYMPHONY_VM_PREFIX))
|
|
57
|
+
continue;
|
|
58
|
+
if (state.intendedLabels.has(label))
|
|
59
|
+
continue;
|
|
60
|
+
// Pid safety: skip anomalous pids (0/NaN/negative — process-group / invalid)
|
|
61
|
+
// and never signal the reaper's own process.
|
|
62
|
+
if (!Number.isSafeInteger(s.pid) || s.pid <= 0)
|
|
63
|
+
continue;
|
|
64
|
+
if (s.pid === state.selfPid)
|
|
65
|
+
continue;
|
|
66
|
+
out.push({ kind: 'kill_session', pid: s.pid, label });
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=vm-decide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vm-decide.js","sourceRoot":"","sources":["../../../../src/core/reconcile/vm-decide.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,+BAA+B;AAC/B,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAC9E,EAAE;AACF,iFAAiF;AACjF,0EAA0E;AAC1E,iFAAiF;AACjF,+EAA+E;AAC/E,kEAAkE;AAClE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,iFAAiF;AACjF,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,yEAAyE;AACzE,0EAA0E;AAC1E,8EAA8E;AAC9E,EAAE;AACF,iFAAiF;AACjF,sEAAsE;AACtE,2EAA2E;AAC3E,qBAAqB;AAIrB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE9C;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAsB;IAC7C,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;QACtB,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAAC;YAAE,SAAS;QACpD,IAAI,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QAC9C,6EAA6E;QAC7E,6CAA6C;QAC7C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;YAAE,SAAS;QACzD,IAAI,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,OAAO;YAAE,SAAS;QACtC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|