smol-symphony 0.1.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 +125 -39
- package/DESIGN.md +494 -273
- package/PRODUCT.md +2 -1
- package/README.md +259 -110
- package/SPEC.md +565 -1928
- package/WORKFLOW.minimal.yaml +34 -0
- package/WORKFLOW.template.yaml +1100 -0
- 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/src/core/actions/parse.js +192 -0
- 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/src/core/http/render.js +1635 -0
- package/dist/src/core/http/render.js.map +1 -0
- package/dist/src/core/http/routes.js +145 -0
- 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/src/core/reconcile/pr-decide.js +180 -0
- 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 +31 -11
- 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 +433 -0
- package/WORKFLOW.md +0 -269
- package/WORKFLOW.template.md +0 -307
- package/dist/agent/acp.js +0 -304
- package/dist/agent/acp.js.map +0 -1
- package/dist/agent/adapters.js +0 -275
- package/dist/agent/adapters.js.map +0 -1
- package/dist/agent/codex.js +0 -439
- package/dist/agent/codex.js.map +0 -1
- package/dist/agent/runner.js +0 -394
- package/dist/agent/runner.js.map +0 -1
- package/dist/agent/smolvm.js +0 -174
- package/dist/agent/smolvm.js.map +0 -1
- package/dist/bin/symphony.js +0 -205
- package/dist/bin/symphony.js.map +0 -1
- package/dist/http.js +0 -1189
- package/dist/http.js.map +0 -1
- package/dist/logging.js +0 -45
- package/dist/logging.js.map +0 -1
- package/dist/mcp.js +0 -478
- package/dist/mcp.js.map +0 -1
- package/dist/orchestrator.js +0 -683
- package/dist/orchestrator.js.map +0 -1
- package/dist/prompt.js +0 -65
- package/dist/prompt.js.map +0 -1
- package/dist/trackers/local.js +0 -344
- 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/workflow.js +0 -385
- package/dist/workflow.js.map +0 -1
- package/dist/workspace.js +0 -196
- package/dist/workspace.js.map +0 -1
- package/scripts/build-vm.sh +0 -67
|
@@ -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"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// FCIS rewrite — pure PR-autopilot decision core (issue 70 / issue 105).
|
|
2
|
+
//
|
|
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.
|
|
18
|
+
//
|
|
19
|
+
// Multi-pass semantics: outcomes of IO effects (summary lookup, view fetch)
|
|
20
|
+
// drive subsequent decisions. The shell records each outcome into the
|
|
21
|
+
// observation and calls `decidePr` again; the function looks at
|
|
22
|
+
// `summaryResolved` / `viewResolved` to decide whether the next observation
|
|
23
|
+
// step has run yet. The loop terminates when `decidePr` returns `[]`.
|
|
24
|
+
//
|
|
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/**.
|
|
29
|
+
/**
|
|
30
|
+
* Pure decision: given an observation, return the next batch of effects the
|
|
31
|
+
* shell should apply. After applying, the shell rebuilds the observation
|
|
32
|
+
* (with new IO outcomes folded in) and calls `decidePr` again. The loop ends
|
|
33
|
+
* when the result is empty.
|
|
34
|
+
*/
|
|
35
|
+
export function decidePr(obs) {
|
|
36
|
+
const { intent, cache } = obs;
|
|
37
|
+
const id = intent.identifier;
|
|
38
|
+
if (obs.halt)
|
|
39
|
+
return [];
|
|
40
|
+
if (cache.completed)
|
|
41
|
+
return [];
|
|
42
|
+
if (!obs.summaryResolved) {
|
|
43
|
+
return [{ kind: 'observe_summary', identifier: id, branch: intent.branch }];
|
|
44
|
+
}
|
|
45
|
+
if (intent.kind === 'close')
|
|
46
|
+
return decideClose(obs);
|
|
47
|
+
// merge intent below
|
|
48
|
+
if (obs.summary === null)
|
|
49
|
+
return [];
|
|
50
|
+
if (!obs.viewResolved) {
|
|
51
|
+
return [{ kind: 'observe_view', identifier: id, prNumber: obs.summary.number }];
|
|
52
|
+
}
|
|
53
|
+
if (obs.view === null)
|
|
54
|
+
return [];
|
|
55
|
+
const view = obs.view;
|
|
56
|
+
if (view.state === 'MERGED' || view.state === 'CLOSED') {
|
|
57
|
+
return [
|
|
58
|
+
{ kind: 'delete_remote_branch', identifier: id, branch: intent.branch },
|
|
59
|
+
{ kind: 'cleanup_workspace', identifier: id },
|
|
60
|
+
{ kind: 'mark_completed', identifier: id },
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
// CONFLICTING → route the issue back to the implementing state so the
|
|
64
|
+
// dispatched agent rebases onto a freshly-fetched `origin/<base>` as part
|
|
65
|
+
// of its normal work. The autopilot no longer drives a rebase from the
|
|
66
|
+
// workspace; "is my branch mergeable?" is the agent's responsibility now.
|
|
67
|
+
if (view.mergeable === 'CONFLICTING')
|
|
68
|
+
return decideConflict(obs);
|
|
69
|
+
// UNKNOWN: GitHub is still computing mergeability — defer until the next
|
|
70
|
+
// pass. Arming on UNKNOWN works (auto-merge waits for the computed state)
|
|
71
|
+
// but produces noisier ledgers; the per-PR poll TTL means UNKNOWN
|
|
72
|
+
// typically resolves within one tick.
|
|
73
|
+
if (view.mergeable === 'UNKNOWN') {
|
|
74
|
+
// Pin the observed head SHA so the next pass can detect concurrent
|
|
75
|
+
// pushes if the agent has pushed in the meantime.
|
|
76
|
+
if (cache.lastObservedHeadSha !== view.head_ref_oid) {
|
|
77
|
+
return [{ kind: 'update_observed_head', identifier: id, sha: view.head_ref_oid }];
|
|
78
|
+
}
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
// MERGEABLE: arm `gh pr merge --auto` once. GitHub handles the wait-for-
|
|
82
|
+
// checks-and-reviews part on its own; we just keep the auto-merge armed.
|
|
83
|
+
if (!cache.armed) {
|
|
84
|
+
return [
|
|
85
|
+
{
|
|
86
|
+
kind: 'arm_auto_merge',
|
|
87
|
+
identifier: id,
|
|
88
|
+
prNumber: view.number,
|
|
89
|
+
strategy: obs.config.strategy,
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
// Armed but BEHIND: branch protection's "require branches up to date" rule
|
|
94
|
+
// blocks the auto-merge until the branch catches up to base. The diffs
|
|
95
|
+
// don't textually conflict (mergeable=MERGEABLE), so the CONFLICTING route
|
|
96
|
+
// never fires — without an explicit nudge the PR sits armed-and-stuck
|
|
97
|
+
// forever. Advance the branch via `gh pr update-branch`; once the head
|
|
98
|
+
// moves, head_ref_oid changes (update_observed_head absorbs it) and the
|
|
99
|
+
// status leaves BEHIND, so the effect stops firing. See issue 105.
|
|
100
|
+
if (view.merge_state_status === 'BEHIND') {
|
|
101
|
+
return [{ kind: 'update_branch', identifier: id, prNumber: view.number }];
|
|
102
|
+
}
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
function decideClose(obs) {
|
|
106
|
+
const id = obs.intent.identifier;
|
|
107
|
+
if (obs.summary === null)
|
|
108
|
+
return [{ kind: 'mark_completed', identifier: id }];
|
|
109
|
+
if (!obs.viewResolved) {
|
|
110
|
+
return [{ kind: 'observe_view', identifier: id, prNumber: obs.summary.number }];
|
|
111
|
+
}
|
|
112
|
+
if (obs.view === null)
|
|
113
|
+
return [];
|
|
114
|
+
const view = obs.view;
|
|
115
|
+
if (view.state === 'MERGED' || view.state === 'CLOSED') {
|
|
116
|
+
return [
|
|
117
|
+
{ kind: 'delete_remote_branch', identifier: id, branch: obs.intent.branch },
|
|
118
|
+
{ kind: 'mark_completed', identifier: id },
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
// Open PR: close first, then gate branch deletion on close success. A
|
|
122
|
+
// failed close leaves the PR open on origin, so deleting the remote branch
|
|
123
|
+
// would orphan it — matching main's `runClosePr` which returned early on
|
|
124
|
+
// failure. The completion latch still fires (same as main) so a transient
|
|
125
|
+
// gh outage doesn't leave the close intent looping every pass.
|
|
126
|
+
if (!obs.closeAttempted) {
|
|
127
|
+
return [{ kind: 'close_pr', identifier: id, prNumber: view.number }];
|
|
128
|
+
}
|
|
129
|
+
if (obs.closeOutcome !== null && obs.closeOutcome.ok) {
|
|
130
|
+
return [
|
|
131
|
+
{ kind: 'delete_remote_branch', identifier: id, branch: obs.intent.branch },
|
|
132
|
+
{ kind: 'mark_completed', identifier: id },
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
return [{ kind: 'mark_completed', identifier: id }];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Conflict routing: append a notes block and move the issue back to the
|
|
139
|
+
* implementing state. No counter, no circuit breaker — the dispatched agent
|
|
140
|
+
* rebases onto a freshly-fetched `origin/<base>` and resolves the conflict
|
|
141
|
+
* as part of its normal Todo flow. Each round the PR flips back to
|
|
142
|
+
* MERGEABLE on the agent's force-push, the next reconcile pass arms
|
|
143
|
+
* auto-merge, and merging happens once checks pass.
|
|
144
|
+
*/
|
|
145
|
+
function decideConflict(obs) {
|
|
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`.
|
|
152
|
+
const view = obs.view;
|
|
153
|
+
return [
|
|
154
|
+
{
|
|
155
|
+
kind: 'route_conflict',
|
|
156
|
+
identifier: id,
|
|
157
|
+
fromState: obs.intent.state,
|
|
158
|
+
toState: obs.config.conflictRouteTo,
|
|
159
|
+
notes: buildConflictNotes({ intent: obs.intent, view }),
|
|
160
|
+
},
|
|
161
|
+
{ kind: 'reset_transient', identifier: id },
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Structured notes block appended to the issue file when a conflict route
|
|
166
|
+
* fires. Pure: every input is part of the observation. Lives here (not in the
|
|
167
|
+
* shell) so the route effect carries its rendered notes as data.
|
|
168
|
+
*/
|
|
169
|
+
export function buildConflictNotes(args) {
|
|
170
|
+
const { intent, view } = args;
|
|
171
|
+
const lines = [
|
|
172
|
+
'pr autopilot — PR is not mergeable against base',
|
|
173
|
+
'',
|
|
174
|
+
`GitHub reports PR #${view.number} (${view.url}) as \`mergeable: ${view.mergeable}\` against \`origin/${intent.base_branch}\`.`,
|
|
175
|
+
'',
|
|
176
|
+
`Routing the issue back to \`${intent.state}\` → implementing state. The next dispatch will fetch \`origin/${intent.base_branch}\` afresh into the workspace; the agent rebases \`${intent.branch}\` onto it as the first step of its normal Todo flow, resolves any conflicts in-tree, re-runs typecheck/tests, and hands back off to the reviewer. Once the rebased branch is force-pushed, this PR flips back to MERGEABLE and auto-merge is armed on the next reconcile pass.`,
|
|
177
|
+
];
|
|
178
|
+
return lines.join('\n');
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=pr-decide.js.map
|
|
@@ -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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"}
|