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,111 @@
|
|
|
1
|
+
// FCIS rewrite — pure `if:` predicate evaluation (ported from
|
|
2
|
+
// src/actions/predicates.ts + predicate-env.ts of the reference orchestrator).
|
|
3
|
+
//
|
|
4
|
+
// The reference `evaluatePredicate` was async because the branch_exists /
|
|
5
|
+
// file_present shapes reached IO through an injected `PredicateEnv`
|
|
6
|
+
// (git rev-parse / fs.stat). In the functional core that IO is FORBIDDEN, so
|
|
7
|
+
// this module is split into two pure, synchronous halves:
|
|
8
|
+
//
|
|
9
|
+
// 1. `evaluatePredicate(predicate, ctx, workspacePath)` decides AS DATA. It
|
|
10
|
+
// either RESOLVES immediately (null/undefined → true; string-truthy;
|
|
11
|
+
// empty-after-render → false) or EMITS a probe Effect the shell answers:
|
|
12
|
+
// - { branch_exists } → a `git.branch_exists` Effect, and
|
|
13
|
+
// - { file_present } → an `fs.path_exists` Effect.
|
|
14
|
+
// Unknown `$var` references surface as an ERROR decision (the reference
|
|
15
|
+
// threw a TemplateError; silent "" expansion masked operator typos).
|
|
16
|
+
//
|
|
17
|
+
// 2. `foldPredicateProbe(result)` folds the shell's EffectResult boolean back
|
|
18
|
+
// into the final predicate value once the probe has run.
|
|
19
|
+
//
|
|
20
|
+
// 100% SYNCHRONOUS. No async / await / Promise. No IO, no node: imports, no
|
|
21
|
+
// clock or randomness. Imports ONLY from src/types (and the sibling core
|
|
22
|
+
// templating module). (NodeNext ESM → .js extensions on relative imports.)
|
|
23
|
+
import { renderField } from './template.js';
|
|
24
|
+
import { joinPosix } from '../path.js';
|
|
25
|
+
// ─── template substitution ────────────────────────────────────────────────────
|
|
26
|
+
// Shared with the core planner via `renderField` (same $-grammar, same
|
|
27
|
+
// unknown-var error). `renderField` labels the error with the action-field name;
|
|
28
|
+
// here the relevant label IS the offending variable, which the reference's
|
|
29
|
+
// PredicateEnv surfaced. We re-label the returned TemplateError with the bad
|
|
30
|
+
// variable (parsed out of the message renderField already embeds) so callers see
|
|
31
|
+
// `field: "<varname>"`, matching the reference predicate-env behavior.
|
|
32
|
+
const BAD_VAR_RE = /unknown template variable "\$([A-Za-z_][A-Za-z0-9_]*)"/;
|
|
33
|
+
function render(template, ctx) {
|
|
34
|
+
const r = renderField('<predicate>', template, ctx);
|
|
35
|
+
if (r.ok)
|
|
36
|
+
return { ok: true, text: r.value };
|
|
37
|
+
const field = BAD_VAR_RE.exec(r.error.message)?.[1] ?? r.error.field;
|
|
38
|
+
return { ok: false, error: { field, message: r.error.message } };
|
|
39
|
+
}
|
|
40
|
+
// Path join is the canonical lexical `joinPosix` from core/path.ts (this module
|
|
41
|
+
// was the SUPERSET behaviour that became canonical — empty-base/absolute-rel
|
|
42
|
+
// handling). The reference used node:path, forbidden in the pure core.
|
|
43
|
+
/**
|
|
44
|
+
* Decide a predicate against the context, AS DATA.
|
|
45
|
+
*
|
|
46
|
+
* `null`/`undefined` → resolved true (no `if:` → run unconditionally).
|
|
47
|
+
*
|
|
48
|
+
* String form is a truthiness check on the rendered template: `if: $repo`
|
|
49
|
+
* resolves true iff `$repo` renders to non-empty after trimming. An empty (or
|
|
50
|
+
* empty-after-render) string is explicitly FALSE — the intent of `if: $repo`
|
|
51
|
+
* with `$repo` unset is "skip when the var is empty", not "always run".
|
|
52
|
+
*
|
|
53
|
+
* `{ branch_exists }` / `{ file_present }` render their argument, short-circuit
|
|
54
|
+
* to resolved-false on an empty ref/path, otherwise EMIT a probe Effect the
|
|
55
|
+
* shell runs; the boolean is folded back via `foldPredicateProbe`.
|
|
56
|
+
*
|
|
57
|
+
* An unknown `$var` anywhere returns a `{ kind: 'error' }` decision (the
|
|
58
|
+
* reference threw a TemplateError).
|
|
59
|
+
*/
|
|
60
|
+
export function evaluatePredicate(predicate, ctx, workspacePath) {
|
|
61
|
+
if (predicate === null || predicate === undefined) {
|
|
62
|
+
return { kind: 'resolved', value: true };
|
|
63
|
+
}
|
|
64
|
+
if (typeof predicate === 'string') {
|
|
65
|
+
const r = render(predicate, ctx);
|
|
66
|
+
if (!r.ok)
|
|
67
|
+
return { kind: 'error', error: r.error };
|
|
68
|
+
return { kind: 'resolved', value: r.text.trim().length > 0 };
|
|
69
|
+
}
|
|
70
|
+
if ('branch_exists' in predicate) {
|
|
71
|
+
const r = render(predicate.branch_exists, ctx);
|
|
72
|
+
if (!r.ok)
|
|
73
|
+
return { kind: 'error', error: r.error };
|
|
74
|
+
const ref = r.text.trim();
|
|
75
|
+
if (ref.length === 0)
|
|
76
|
+
return { kind: 'resolved', value: false };
|
|
77
|
+
return {
|
|
78
|
+
kind: 'probe',
|
|
79
|
+
effect: { family: 'git', kind: 'branch_exists', cwd: workspacePath, ref },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if ('file_present' in predicate) {
|
|
83
|
+
const r = render(predicate.file_present, ctx);
|
|
84
|
+
if (!r.ok)
|
|
85
|
+
return { kind: 'error', error: r.error };
|
|
86
|
+
const file = r.text.trim();
|
|
87
|
+
if (file.length === 0)
|
|
88
|
+
return { kind: 'resolved', value: false };
|
|
89
|
+
return {
|
|
90
|
+
kind: 'probe',
|
|
91
|
+
effect: { family: 'fs', kind: 'path_exists', path: joinPosix(workspacePath, file) },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// Unreachable for a well-typed ActionPredicate; mirror the reference's
|
|
95
|
+
// defensive `return false`.
|
|
96
|
+
return { kind: 'resolved', value: false };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Fold the shell's EffectResult for a `{ kind: 'probe' }` decision back into the
|
|
100
|
+
* final predicate boolean. Accepts the two probe result shapes this module can
|
|
101
|
+
* emit (`branch_exists` / `path_exists`); any other / failed result folds to
|
|
102
|
+
* `false` (a probe that could not run means "predicate not satisfied", matching
|
|
103
|
+
* the reference's missing-ref / fs-error → false behavior).
|
|
104
|
+
*/
|
|
105
|
+
export function foldPredicateProbe(result) {
|
|
106
|
+
if ('kind' in result && (result.kind === 'branch_exists' || result.kind === 'path_exists')) {
|
|
107
|
+
return result.exists;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=predicates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../../../src/core/actions/predicates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// FCIS rewrite — pure executor state machine for the typed-action DAG.
|
|
2
|
+
//
|
|
3
|
+
// Ported faithfully from the reference `src/actions/executor.ts`
|
|
4
|
+
// (`runEffects` + `runWithRetry` + `finalizeOutcome`/`finalizeFailure`). The
|
|
5
|
+
// reference was an async driver that AWAITED `applyAction`, slept on
|
|
6
|
+
// `node:timers/promises`, and called `log.warn` directly. In the functional
|
|
7
|
+
// core all of that becomes DATA:
|
|
8
|
+
//
|
|
9
|
+
// • IO (running the action attempt) happens in the shell. The shell applies
|
|
10
|
+
// one attempt, then hands the resulting `ActionOutcome` back to this fold.
|
|
11
|
+
// • The retry backoff `delay()` becomes a returned `timer.sleep` Effect plus a
|
|
12
|
+
// `retry` decision telling the shell to re-apply the same action.
|
|
13
|
+
// • The diagnostic `log.warn`/`log.debug` calls become `log.emit` Effects.
|
|
14
|
+
// • The ledger (bounded `ActionStatus[]`, most-recent-first) is THREADED
|
|
15
|
+
// through as plain data: each call takes the prior ledger and returns the
|
|
16
|
+
// next one.
|
|
17
|
+
//
|
|
18
|
+
// The shell drives this as a loop per action:
|
|
19
|
+
// 1. beginAction(...) → push an in_progress ledger row.
|
|
20
|
+
// 2. apply the action (IO) → produce an ActionOutcome.
|
|
21
|
+
// 3. foldActionOutcome(...) → decide retry / route / abort / done,
|
|
22
|
+
// emit Effects, and return the next ledger.
|
|
23
|
+
// 4. on `retry`, the shell sleeps (it already has the timer.sleep Effect),
|
|
24
|
+
// re-applies, and folds again with an incremented `attempt`.
|
|
25
|
+
//
|
|
26
|
+
// Predicate evaluation, template-render failures, and skip-on-`if=false` are
|
|
27
|
+
// handled by sibling core modules (`predicates.ts`, `template.ts`); the helpers
|
|
28
|
+
// here cover the "an attempt ran and produced an outcome" half of the loop plus
|
|
29
|
+
// the ledger bookkeeping the shell needs around it.
|
|
30
|
+
//
|
|
31
|
+
// 100% SYNCHRONOUS. No async / await / Promise. No IO, no node: imports, no
|
|
32
|
+
// wall clock or randomness (an ISO timestamp is injected as a plain string).
|
|
33
|
+
// Imports ONLY from src/types. (NodeNext ESM → .js extensions on relative
|
|
34
|
+
// imports.)
|
|
35
|
+
/**
|
|
36
|
+
* Most-recent-first slice length surfaced on the snapshot. The reference keeps
|
|
37
|
+
* twice this many rows internally (so a burst of in_progress→error→… updates
|
|
38
|
+
* doesn't evict still-relevant rows before they finalize) and slices to
|
|
39
|
+
* `MAX_ACTION_HISTORY` only when emitting.
|
|
40
|
+
*/
|
|
41
|
+
export const MAX_ACTION_HISTORY = 16;
|
|
42
|
+
const LEDGER_CAP = MAX_ACTION_HISTORY * 2;
|
|
43
|
+
// ─── ledger bookkeeping (pure; the reference's `push` / `upd` closures) ───────
|
|
44
|
+
/**
|
|
45
|
+
* Push a fresh in_progress row for an action attempt, most-recent-first, and
|
|
46
|
+
* cap the ledger at `LEDGER_CAP` rows. Returns the NEXT ledger (does not mutate
|
|
47
|
+
* the input).
|
|
48
|
+
*
|
|
49
|
+
* Mirrors the reference's `push` closure that `unshift`ed an in_progress row in
|
|
50
|
+
* `runOneEffect` before evaluating the predicate / applying the action.
|
|
51
|
+
*/
|
|
52
|
+
export function beginAction(ledger, input) {
|
|
53
|
+
const row = {
|
|
54
|
+
resource: input.resource,
|
|
55
|
+
action: input.action,
|
|
56
|
+
state: 'in_progress',
|
|
57
|
+
started_at: input.nowIso,
|
|
58
|
+
finished_at: null,
|
|
59
|
+
error: null,
|
|
60
|
+
};
|
|
61
|
+
const next = [row, ...ledger];
|
|
62
|
+
if (next.length > LEDGER_CAP)
|
|
63
|
+
next.length = LEDGER_CAP;
|
|
64
|
+
return next;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Mark the most-recent in_progress row for `action` with the given patch.
|
|
68
|
+
* Returns the NEXT ledger. Mirrors the reference's `upd` closure (find the
|
|
69
|
+
* first in_progress row keyed by action name; spread the patch onto it).
|
|
70
|
+
*
|
|
71
|
+
* When no matching in_progress row exists the ledger is returned unchanged
|
|
72
|
+
* (the reference's `upd` no-ops on a missing index).
|
|
73
|
+
*/
|
|
74
|
+
export function updateAction(ledger, action, patch) {
|
|
75
|
+
const idx = ledger.findIndex((a) => a.action === action && a.state === 'in_progress');
|
|
76
|
+
if (idx < 0)
|
|
77
|
+
return ledger.slice();
|
|
78
|
+
const next = ledger.slice();
|
|
79
|
+
next[idx] = { ...next[idx], ...patch };
|
|
80
|
+
return next;
|
|
81
|
+
}
|
|
82
|
+
// ─── retry / route / abort decision ───────────────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* Exponential backoff for the `attempt`-th (0-based) failed action attempt:
|
|
85
|
+
* `backoffMs * 2^attempt`. Mirrors the reference's
|
|
86
|
+
* `policy.retry.backoff_ms * Math.pow(2, attempt)`.
|
|
87
|
+
*/
|
|
88
|
+
export function actionBackoffMs(policy, attempt) {
|
|
89
|
+
return policy.backoffMs * Math.pow(2, attempt);
|
|
90
|
+
}
|
|
91
|
+
function warn(message, fields) {
|
|
92
|
+
return { family: 'log', kind: 'emit', level: 'warn', message, fields };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Fold one applied-action `ActionOutcome` against its `NormalizedActionPolicy`,
|
|
96
|
+
* threading the `ActionStatus` ledger and emitting the side effects as data.
|
|
97
|
+
*
|
|
98
|
+
* `attempt` is the 0-based number of the attempt that just produced `outcome`
|
|
99
|
+
* (0 for the first try). The reference's `runWithRetry` loop semantics:
|
|
100
|
+
*
|
|
101
|
+
* • `outcome.ok || outcome.route_to` short-circuits the retry loop. We never
|
|
102
|
+
* retry a routed failure — a routed handoff is clean, not a transient error.
|
|
103
|
+
* • otherwise, if `attempt < retryCount`, schedule a retry with
|
|
104
|
+
* `backoffMs * 2^attempt` backoff.
|
|
105
|
+
* • otherwise the retries are exhausted → finalize the failure.
|
|
106
|
+
*
|
|
107
|
+
* Finalization (the reference's `finalizeOutcome` / `finalizeFailure`):
|
|
108
|
+
* • success → `done`, ledger row finalized.
|
|
109
|
+
* • failure → route to `outcome.route_to` ?? (policy.then is an object ?
|
|
110
|
+
* policy.then.route_to : null). A non-null route → `route`; null → `abort`.
|
|
111
|
+
* Ledger row finalized to `error` with the failure reason either way.
|
|
112
|
+
*/
|
|
113
|
+
export function foldActionOutcome(input) {
|
|
114
|
+
const { action, outcome, policy, attempt, nowIso } = input;
|
|
115
|
+
// ── success ────────────────────────────────────────────────────────────
|
|
116
|
+
if (outcome.ok) {
|
|
117
|
+
return {
|
|
118
|
+
decision: { kind: 'done' },
|
|
119
|
+
ledger: updateAction(input.ledger, action, { state: 'done', finished_at: nowIso }),
|
|
120
|
+
effects: [],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const reason = outcome.reason ?? 'unknown';
|
|
124
|
+
// ── retry (only when NOT routed and retries remain) ──────────────────────
|
|
125
|
+
// A routed failure is a clean handoff and is never retried — mirrors the
|
|
126
|
+
// reference's `if (outcome.route_to) return outcome` short-circuit ahead of
|
|
127
|
+
// the retry-budget check.
|
|
128
|
+
if (!outcome.route_to && attempt < policy.retryCount) {
|
|
129
|
+
const backoffMs = actionBackoffMs(policy, attempt);
|
|
130
|
+
return {
|
|
131
|
+
decision: { kind: 'retry', attempt: attempt + 1, backoffMs },
|
|
132
|
+
// Leave the in_progress row in place: the attempt is still "running"
|
|
133
|
+
// from the dashboard's view until it ultimately succeeds or exhausts.
|
|
134
|
+
ledger: input.ledger.slice(),
|
|
135
|
+
effects: [
|
|
136
|
+
warn('action retrying', {
|
|
137
|
+
action,
|
|
138
|
+
attempt: attempt + 1,
|
|
139
|
+
next_backoff_ms: backoffMs,
|
|
140
|
+
error: outcome.reason,
|
|
141
|
+
}),
|
|
142
|
+
{ family: 'timer', kind: 'sleep', ms: backoffMs },
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ── terminal failure: route or abort ─────────────────────────────────────
|
|
147
|
+
const route = outcome.route_to ?? (typeof policy.then === 'object' ? policy.then.route_to : null);
|
|
148
|
+
const ledger = updateAction(input.ledger, action, {
|
|
149
|
+
state: 'error',
|
|
150
|
+
finished_at: nowIso,
|
|
151
|
+
error: reason,
|
|
152
|
+
});
|
|
153
|
+
if (route !== null) {
|
|
154
|
+
return {
|
|
155
|
+
decision: { kind: 'route', routeTo: route, reason },
|
|
156
|
+
ledger,
|
|
157
|
+
effects: [warn('action failed', { action, reason, route_to: route })],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
decision: { kind: 'abort', reason },
|
|
162
|
+
ledger,
|
|
163
|
+
effects: [warn('action failed', { action, reason, route_to: null })],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
// ─── render-failure / skip helpers (the non-retry ledger transitions) ─────────
|
|
167
|
+
/**
|
|
168
|
+
* Finalize the in_progress row for an action whose template render failed (the
|
|
169
|
+
* reference's `render_failed` Effect branch). Returns the next ledger and an
|
|
170
|
+
* `abort` decision — a render failure stops the cleanup loop, mirroring the
|
|
171
|
+
* reference returning `{ aborted: true }`.
|
|
172
|
+
*/
|
|
173
|
+
export function foldRenderFailed(input) {
|
|
174
|
+
const ledger = updateAction(input.ledger, input.action, {
|
|
175
|
+
state: 'error',
|
|
176
|
+
finished_at: input.nowIso,
|
|
177
|
+
error: input.error,
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
decision: { kind: 'abort', reason: input.error },
|
|
181
|
+
ledger,
|
|
182
|
+
effects: [warn('action template render failed', { action: input.action, error: input.error })],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Finalize the in_progress row for an action whose `if:` predicate resolved
|
|
187
|
+
* false (skip). The reference marked the row `done` (skips are not failures) and
|
|
188
|
+
* continued. Returns the next ledger and a `done` decision.
|
|
189
|
+
*/
|
|
190
|
+
export function foldSkipped(input) {
|
|
191
|
+
const ledger = updateAction(input.ledger, input.action, {
|
|
192
|
+
state: 'done',
|
|
193
|
+
finished_at: input.nowIso,
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
decision: { kind: 'done' },
|
|
197
|
+
ledger,
|
|
198
|
+
effects: [
|
|
199
|
+
{ family: 'log', kind: 'emit', level: 'debug', message: 'action skipped', fields: { action: input.action, reason: 'if=false' } },
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Finalize the in_progress row for an action whose `if:` predicate could not be
|
|
205
|
+
* evaluated (an error decision, e.g. an unknown `$var`). The reference treated
|
|
206
|
+
* this as an abort (it returned `{ aborted: true, reason }`).
|
|
207
|
+
*/
|
|
208
|
+
export function foldPredicateError(input) {
|
|
209
|
+
const ledger = updateAction(input.ledger, input.action, {
|
|
210
|
+
state: 'error',
|
|
211
|
+
finished_at: input.nowIso,
|
|
212
|
+
error: input.error,
|
|
213
|
+
});
|
|
214
|
+
return { decision: { kind: 'abort', reason: input.error }, ledger, effects: [] };
|
|
215
|
+
}
|
|
216
|
+
// ─── snapshot packing (the reference's `toActionsSnapshot`) ──────────────────
|
|
217
|
+
/**
|
|
218
|
+
* Aggregate a finished cleanup loop into the runner's result shape (the
|
|
219
|
+
* reference's `ActionExecResult`). `ok` is true iff the loop did not abort;
|
|
220
|
+
* `route_to`/`reason` carry the last route/abort decision the loop hit.
|
|
221
|
+
*
|
|
222
|
+
* Kept here (not in the snapshot packer) because the runner needs both the
|
|
223
|
+
* loop's terminal decision AND the bounded ledger.
|
|
224
|
+
*/
|
|
225
|
+
export function summarizeRun(input) {
|
|
226
|
+
return {
|
|
227
|
+
ok: input.abortReason === null,
|
|
228
|
+
reason: input.abortReason,
|
|
229
|
+
route_to: input.routeTo,
|
|
230
|
+
actions: input.ledger.slice(0, MAX_ACTION_HISTORY),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Pack a finished run into a `Snapshot`-shaped record the orchestrator surfaces
|
|
235
|
+
* alongside reconciler resources. `ready` mirrors the run's `ok`; `last_error`
|
|
236
|
+
* is the most-recent errored row's message. Mirrors the reference's
|
|
237
|
+
* `toActionsSnapshot`.
|
|
238
|
+
*/
|
|
239
|
+
export function toActionsSnapshot(id, result) {
|
|
240
|
+
const lastErr = result.actions.find((a) => a.state === 'error')?.error ?? null;
|
|
241
|
+
return {
|
|
242
|
+
id,
|
|
243
|
+
ready: result.ok,
|
|
244
|
+
last_error: lastErr,
|
|
245
|
+
actions: result.actions.slice(0, MAX_ACTION_HISTORY),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=run-fold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-fold.js","sourceRoot":"","sources":["../../../../src/core/actions/run-fold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// FCIS rewrite — strict template render.
|
|
2
|
+
//
|
|
3
|
+
// FUNCTIONAL CORE. Every function here is SYNCHRONOUS and pure: (data) -> data.
|
|
4
|
+
// No IO, no async, no clock, no randomness, no Effects. Imports ONLY from
|
|
5
|
+
// src/types. Ports the original behavior of src/actions/templating.ts
|
|
6
|
+
// ({renderTemplate, renderTree}) — $-substitution against the fixed
|
|
7
|
+
// ActionContext namespace, unknown-var = error.
|
|
8
|
+
//
|
|
9
|
+
// The behavioral change from the original, forced by the FCIS layout:
|
|
10
|
+
// TemplateError is DATA ({ field, message }, per src/types/actions.ts), not a
|
|
11
|
+
// thrown class. renderField returns a discriminated result; the caller (a future
|
|
12
|
+
// core planner) folds the error into an ActionOutcome instead of try/catch. The
|
|
13
|
+
// legacy "throw" shape is preserved only as the strict `renderOrThrow` helper for
|
|
14
|
+
// call-sites that still want it.
|
|
15
|
+
// ─── Template rendering ──────────────────────────────────────────────────────
|
|
16
|
+
// `$name` / `\$name` (escape). Matches the original VAR_RE exactly:
|
|
17
|
+
// group 1 = optional leading backslash (the escape)
|
|
18
|
+
// group 2 = the identifier
|
|
19
|
+
const VAR_RE = /(\\?)\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
20
|
+
/**
|
|
21
|
+
* Substitute `$name` references in `template` against the fixed ActionContext
|
|
22
|
+
* namespace. Faithful to src/actions/templating.ts:
|
|
23
|
+
* • `$name` → the named ActionContext field (null/undefined → "").
|
|
24
|
+
* • `\$name` → literal `$name` (escape).
|
|
25
|
+
* • `$` + non-word → left alone (regex only matches `$` + identifier).
|
|
26
|
+
* • unknown `$name` → ERROR (the original threw; silent "" expansion masks
|
|
27
|
+
* operator typos — the `$SYMPHONY_PR_TITTLE` bug).
|
|
28
|
+
*
|
|
29
|
+
* `field` is the action-field label (e.g. "title_from") carried into the
|
|
30
|
+
* TemplateError so a failure points at the offending field, matching the new
|
|
31
|
+
* TemplateError data shape in src/types/actions.ts.
|
|
32
|
+
*/
|
|
33
|
+
export function renderField(field, template, ctx) {
|
|
34
|
+
// Non-string passthrough is handled by renderTree; renderField is the
|
|
35
|
+
// string-typed leaf. A non-string here is a programming error, but we mirror
|
|
36
|
+
// the original's defensive passthrough rather than crash.
|
|
37
|
+
if (typeof template !== 'string') {
|
|
38
|
+
return { ok: true, value: template };
|
|
39
|
+
}
|
|
40
|
+
// `name in ctx` membership, typed without `any` (ActionContext is a plain
|
|
41
|
+
// object literal, so own + inherited enumerable keys coincide).
|
|
42
|
+
const vars = ctx;
|
|
43
|
+
let firstError = null;
|
|
44
|
+
const out = template.replace(VAR_RE, (_full, escape, name) => {
|
|
45
|
+
if (escape === '\\')
|
|
46
|
+
return `$${name}`;
|
|
47
|
+
if (!(name in vars)) {
|
|
48
|
+
firstError ??= {
|
|
49
|
+
field,
|
|
50
|
+
message: `unknown template variable "$${name}" (available: ${Object.keys(vars).join(', ')})`,
|
|
51
|
+
};
|
|
52
|
+
return ''; // value discarded; firstError short-circuits the return below.
|
|
53
|
+
}
|
|
54
|
+
const v = vars[name];
|
|
55
|
+
return v === null || v === undefined ? '' : String(v);
|
|
56
|
+
});
|
|
57
|
+
if (firstError !== null)
|
|
58
|
+
return { ok: false, error: firstError };
|
|
59
|
+
return { ok: true, value: out };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Strict variant matching the ORIGINAL throwing contract for the rare call-site
|
|
63
|
+
* that wants it. Prefer renderField (error-as-data) in core; this exists so the
|
|
64
|
+
* shell can keep a one-liner where a throw is the natural control flow.
|
|
65
|
+
*
|
|
66
|
+
* NOTE: throwing is acceptable here only because the thrown value carries the
|
|
67
|
+
* same TemplateError DATA — callers should catch and fold, not let it escape an
|
|
68
|
+
* effect boundary.
|
|
69
|
+
*/
|
|
70
|
+
export function renderOrThrow(template, ctx) {
|
|
71
|
+
const r = renderField('<template>', template, ctx);
|
|
72
|
+
if (!r.ok) {
|
|
73
|
+
const e = new Error(r.error.message);
|
|
74
|
+
e.name = 'TemplateError';
|
|
75
|
+
e.templateError = r.error;
|
|
76
|
+
throw e;
|
|
77
|
+
}
|
|
78
|
+
return r.value;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Render every string leaf of a value against the ActionContext, recursing into
|
|
82
|
+
* arrays and plain objects. Numbers / booleans / null pass through unchanged.
|
|
83
|
+
* Faithful to src/actions/templating.ts:renderTree, but returns the first
|
|
84
|
+
* TemplateError as data instead of throwing.
|
|
85
|
+
*
|
|
86
|
+
* `path` seeds the `field` label on errors (e.g. `cmd[1]`, `env.FOO`) so a
|
|
87
|
+
* failure deep in an action record still points at the offending leaf.
|
|
88
|
+
*/
|
|
89
|
+
export function renderTree(value, ctx, path = '') {
|
|
90
|
+
if (typeof value === 'string') {
|
|
91
|
+
const r = renderField(path || '<root>', value, ctx);
|
|
92
|
+
if (!r.ok)
|
|
93
|
+
return r;
|
|
94
|
+
return { ok: true, value: r.value };
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
const out = [];
|
|
98
|
+
for (let i = 0; i < value.length; i++) {
|
|
99
|
+
const r = renderTree(value[i], ctx, `${path}[${i}]`);
|
|
100
|
+
if (!r.ok)
|
|
101
|
+
return r;
|
|
102
|
+
out.push(r.value);
|
|
103
|
+
}
|
|
104
|
+
return { ok: true, value: out };
|
|
105
|
+
}
|
|
106
|
+
if (value && typeof value === 'object') {
|
|
107
|
+
const out = {};
|
|
108
|
+
for (const [k, v] of Object.entries(value)) {
|
|
109
|
+
const r = renderTree(v, ctx, path ? `${path}.${k}` : k);
|
|
110
|
+
if (!r.ok)
|
|
111
|
+
return r;
|
|
112
|
+
out[k] = r.value;
|
|
113
|
+
}
|
|
114
|
+
return { ok: true, value: out };
|
|
115
|
+
}
|
|
116
|
+
return { ok: true, value };
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../../../src/core/actions/template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// FCIS rewrite — pure CLI argument parsing for the `symphony` binary.
|
|
2
|
+
//
|
|
3
|
+
// Functional core: every export here is a pure, synchronous (data) -> data
|
|
4
|
+
// function. No IO, no clock, no randomness, no node: imports, no process.
|
|
5
|
+
// Imports ONLY from src/types.
|
|
6
|
+
//
|
|
7
|
+
// Ported from src/bin/cli-args.ts:parseCli. The original performed three side
|
|
8
|
+
// effects inline that violate the core contract and are RETURNED here instead:
|
|
9
|
+
// 1. `process.exit(2)` on a bad/unexpected arg → a returned `{ kind: 'error' }`
|
|
10
|
+
// directive carrying the message + exit code; the shell raises it.
|
|
11
|
+
// 2. `-h/--help` prints usage then `process.exit(0)` → a returned
|
|
12
|
+
// `{ kind: 'help' }` directive carrying the usage text + exit code 0.
|
|
13
|
+
// 3. `path.resolve(process.cwd(), 'WORKFLOW.yaml')` for the default workflow path
|
|
14
|
+
// → the CWD is INJECTED as a parameter and the join is a pure string op.
|
|
15
|
+
//
|
|
16
|
+
// The shell (composition root) calls `parseCli(argv, cwd)`, and on a
|
|
17
|
+
// non-`ok` result writes the directive's message to the matching stream and
|
|
18
|
+
// exits with the directive's code.
|
|
19
|
+
/** Default workflow filename used when no path argument is supplied. */
|
|
20
|
+
export const DEFAULT_WORKFLOW_FILENAME = 'WORKFLOW.yaml';
|
|
21
|
+
/** Usage text (ported verbatim from the original `-h/--help` branch). */
|
|
22
|
+
export const USAGE = `symphony [path-to-WORKFLOW.yaml] [--port PORT] [--verbose]\n` +
|
|
23
|
+
`symphony doctor [path-to-WORKFLOW.yaml] [--port PORT]\n` +
|
|
24
|
+
`symphony reconcile [path-to-WORKFLOW.yaml] [--force] [--port PORT]\n\n` +
|
|
25
|
+
`If path is omitted, ./WORKFLOW.yaml is used.\n` +
|
|
26
|
+
`\`doctor\` runs every adoption-prerequisite probe non-fatally, prints a\n` +
|
|
27
|
+
`PASS/FAIL line per check plus a one-line fix for each FAIL, and exits 0\n` +
|
|
28
|
+
`iff every check passes.\n` +
|
|
29
|
+
`\`reconcile --force\` requests an immediate reconcile pass (VM / workspace /\n` +
|
|
30
|
+
`PR janitors) at startup.\n` +
|
|
31
|
+
`\`--verbose\` (alias \`--foreground\`, \`-v\`) mirrors structured logs to the\n` +
|
|
32
|
+
`console; by default they go to the log file only so the console stays clean.\n`;
|
|
33
|
+
/** Pure path join: trailing-slash-tolerant `${cwd}/${name}`, no node:path. */
|
|
34
|
+
function joinDefaultWorkflow(cwd, name) {
|
|
35
|
+
const base = cwd.replace(/\/+$/, '');
|
|
36
|
+
// An empty/`/` cwd collapses to an absolute path at root; otherwise join.
|
|
37
|
+
return base === '' ? `/${name}` : `${base}/${name}`;
|
|
38
|
+
}
|
|
39
|
+
/** The `--port` invalid-value message, shared by both `--port V` and `--port=V`. */
|
|
40
|
+
const invalidPort = (raw) => ({ kind: 'error', message: `error: invalid --port value: ${raw}\n`, exitCode: 2 });
|
|
41
|
+
/**
|
|
42
|
+
* Parse `argv` (already sliced past `node script`) into a {@link CliResult}.
|
|
43
|
+
*
|
|
44
|
+
* `cwd` is injected (the original read `process.cwd()`); it is only used to
|
|
45
|
+
* resolve the default WORKFLOW.yaml path when no positional path is supplied.
|
|
46
|
+
*
|
|
47
|
+
* Faithful port of src/bin/cli-args.ts:parseCli — same subcommand detection,
|
|
48
|
+
* same flag handling, same precedence — but every `process.exit`/stream write
|
|
49
|
+
* is returned as a {@link CliHelp}/{@link CliError} directive for the shell.
|
|
50
|
+
*/
|
|
51
|
+
export function parseCli(argv, cwd) {
|
|
52
|
+
// Detect subcommands. `reconcile`/`doctor` share the parsed-args skeleton with
|
|
53
|
+
// the default `serve` mode; the subcommand is preserved verbatim (collapsing
|
|
54
|
+
// `reconcile`→`serve` would let the missing-workflow scaffold prompt fire on a
|
|
55
|
+
// `reconcile` invocation that has nothing to scaffold against).
|
|
56
|
+
let subcommand = 'serve';
|
|
57
|
+
let rest = argv;
|
|
58
|
+
if (argv[0] === 'reconcile') {
|
|
59
|
+
subcommand = 'reconcile';
|
|
60
|
+
rest = argv.slice(1);
|
|
61
|
+
}
|
|
62
|
+
else if (argv[0] === 'doctor') {
|
|
63
|
+
subcommand = 'doctor';
|
|
64
|
+
rest = argv.slice(1);
|
|
65
|
+
}
|
|
66
|
+
let workflow = null;
|
|
67
|
+
let port = null;
|
|
68
|
+
let reconcileForce = false;
|
|
69
|
+
let verbose = false;
|
|
70
|
+
for (let i = 0; i < rest.length; i++) {
|
|
71
|
+
const a = rest[i];
|
|
72
|
+
if (a === '--port' || a === '-p') {
|
|
73
|
+
const v = rest[++i];
|
|
74
|
+
if (v === undefined) {
|
|
75
|
+
return { kind: 'error', message: `error: --port requires a value\n`, exitCode: 2 };
|
|
76
|
+
}
|
|
77
|
+
const n = parseInt(v, 10);
|
|
78
|
+
if (!Number.isFinite(n) || n < 0)
|
|
79
|
+
return invalidPort(v);
|
|
80
|
+
port = n;
|
|
81
|
+
}
|
|
82
|
+
else if (a.startsWith('--port=')) {
|
|
83
|
+
const n = parseInt(a.slice('--port='.length), 10);
|
|
84
|
+
// The original interpolated the WHOLE arg (`--port=foo`) into the message.
|
|
85
|
+
if (!Number.isFinite(n) || n < 0)
|
|
86
|
+
return invalidPort(a);
|
|
87
|
+
port = n;
|
|
88
|
+
}
|
|
89
|
+
else if (subcommand === 'reconcile' && a === '--force') {
|
|
90
|
+
reconcileForce = true;
|
|
91
|
+
}
|
|
92
|
+
else if (a === '--verbose' || a === '-v' || a === '--foreground') {
|
|
93
|
+
verbose = true;
|
|
94
|
+
}
|
|
95
|
+
else if (a === '-h' || a === '--help') {
|
|
96
|
+
return { kind: 'help', message: USAGE, exitCode: 0 };
|
|
97
|
+
}
|
|
98
|
+
else if (workflow === null) {
|
|
99
|
+
workflow = a;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
return { kind: 'error', message: `error: unexpected argument: ${a}\n`, exitCode: 2 };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
kind: 'ok',
|
|
107
|
+
cli: {
|
|
108
|
+
subcommand,
|
|
109
|
+
workflow: workflow ?? joinDefaultWorkflow(cwd, DEFAULT_WORKFLOW_FILENAME),
|
|
110
|
+
port,
|
|
111
|
+
reconcileForce,
|
|
112
|
+
verbose,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../../src/core/cli/args.ts"],"names":[],"mappings":"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"}
|