smol-symphony 0.2.0 → 0.3.1
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/bin/symphony.js +22 -786
- package/dist/bin/symphony.js.map +1 -1
- package/dist/core/actions/context.js +109 -0
- package/dist/core/actions/context.js.map +1 -0
- package/dist/{actions/parsing.js → core/actions/parse.js} +33 -114
- package/dist/core/actions/parse.js.map +1 -0
- package/dist/core/actions/plan.js +197 -0
- package/dist/core/actions/plan.js.map +1 -0
- package/dist/core/actions/predicates.js +111 -0
- package/dist/core/actions/predicates.js.map +1 -0
- package/dist/core/actions/run-fold.js +248 -0
- package/dist/core/actions/run-fold.js.map +1 -0
- package/dist/core/actions/template.js +118 -0
- package/dist/core/actions/template.js.map +1 -0
- package/dist/core/cli/args.js +116 -0
- package/dist/core/cli/args.js.map +1 -0
- package/dist/core/coerce.js +75 -0
- package/dist/core/coerce.js.map +1 -0
- package/dist/core/credential/account-id.js +20 -0
- package/dist/core/credential/account-id.js.map +1 -0
- package/dist/core/credential/adapter-config.js +136 -0
- package/dist/core/credential/adapter-config.js.map +1 -0
- package/dist/core/credential/availability.js +98 -0
- package/dist/core/credential/availability.js.map +1 -0
- package/dist/core/credential/extract.js +228 -0
- package/dist/core/credential/extract.js.map +1 -0
- package/dist/core/credential/fake-creds.js +171 -0
- package/dist/core/credential/fake-creds.js.map +1 -0
- package/dist/core/credential/identity.js +125 -0
- package/dist/core/credential/identity.js.map +1 -0
- package/dist/core/credential/shape.js +230 -0
- package/dist/core/credential/shape.js.map +1 -0
- package/dist/core/credential/strings.js +15 -0
- package/dist/core/credential/strings.js.map +1 -0
- package/dist/core/doctor/checks.js +303 -0
- package/dist/core/doctor/checks.js.map +1 -0
- package/dist/core/git/result.js +107 -0
- package/dist/core/git/result.js.map +1 -0
- package/dist/core/http/decisions.js +225 -0
- package/dist/core/http/decisions.js.map +1 -0
- package/dist/{http.js → core/http/render.js} +472 -738
- package/dist/core/http/render.js.map +1 -0
- package/dist/{http-handlers.js → core/http/routes.js} +52 -87
- package/dist/core/http/routes.js.map +1 -0
- package/dist/core/http/views.js +181 -0
- package/dist/core/http/views.js.map +1 -0
- package/dist/core/image/managed-image.js +95 -0
- package/dist/core/image/managed-image.js.map +1 -0
- package/dist/core/issue/file.js +149 -0
- package/dist/core/issue/file.js.map +1 -0
- package/dist/core/issue/parse.js +210 -0
- package/dist/core/issue/parse.js.map +1 -0
- package/dist/core/mcp/dispatch.js +239 -0
- package/dist/core/mcp/dispatch.js.map +1 -0
- package/dist/core/mcp/post-move.js +92 -0
- package/dist/core/mcp/post-move.js.map +1 -0
- package/dist/core/mcp/protocol.js +293 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/url.js +162 -0
- package/dist/core/mcp/url.js.map +1 -0
- package/dist/core/path.js +63 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/reconcile/image-decide.js +48 -0
- package/dist/core/reconcile/image-decide.js.map +1 -0
- package/dist/core/reconcile/ledger.js +142 -0
- package/dist/core/reconcile/ledger.js.map +1 -0
- package/dist/core/reconcile/pr-classify.js +62 -0
- package/dist/core/reconcile/pr-classify.js.map +1 -0
- package/dist/{reconciler → core/reconcile}/pr-decide.js +25 -12
- package/dist/core/reconcile/pr-decide.js.map +1 -0
- package/dist/core/reconcile/pr-loop.js +161 -0
- package/dist/core/reconcile/pr-loop.js.map +1 -0
- package/dist/core/reconcile/pr-notes.js +35 -0
- package/dist/core/reconcile/pr-notes.js.map +1 -0
- package/dist/core/reconcile/vm-decide.js +70 -0
- package/dist/core/reconcile/vm-decide.js.map +1 -0
- package/dist/core/reconcile/vm-reap.js +207 -0
- package/dist/core/reconcile/vm-reap.js.map +1 -0
- package/dist/core/reconcile/workspace-decide.js +162 -0
- package/dist/core/reconcile/workspace-decide.js.map +1 -0
- package/dist/core/runlog/summary.js +231 -0
- package/dist/core/runlog/summary.js.map +1 -0
- package/dist/core/runner/dispatch-config.js +95 -0
- package/dist/core/runner/dispatch-config.js.map +1 -0
- package/dist/core/runner/injection.js +61 -0
- package/dist/core/runner/injection.js.map +1 -0
- package/dist/core/runner/mise.js +210 -0
- package/dist/core/runner/mise.js.map +1 -0
- package/dist/core/runner/prompt.js +720 -0
- package/dist/core/runner/prompt.js.map +1 -0
- package/dist/core/runner/turn.js +242 -0
- package/dist/core/runner/turn.js.map +1 -0
- package/dist/core/runner/vm-plan.js +390 -0
- package/dist/core/runner/vm-plan.js.map +1 -0
- package/dist/core/schedule/admission.js +123 -0
- package/dist/core/schedule/admission.js.map +1 -0
- package/dist/core/schedule/circuit-breaker.js +111 -0
- package/dist/core/schedule/circuit-breaker.js.map +1 -0
- package/dist/core/schedule/eligibility.js +83 -0
- package/dist/core/schedule/eligibility.js.map +1 -0
- package/dist/core/schedule/reconcile-issue.js +82 -0
- package/dist/core/schedule/reconcile-issue.js.map +1 -0
- package/dist/core/schedule/retry.js +96 -0
- package/dist/core/schedule/retry.js.map +1 -0
- package/dist/core/schedule/sleep-cycle.js +133 -0
- package/dist/core/schedule/sleep-cycle.js.map +1 -0
- package/dist/core/schedule/slots.js +124 -0
- package/dist/core/schedule/slots.js.map +1 -0
- package/dist/core/schedule/tick.js +553 -0
- package/dist/core/schedule/tick.js.map +1 -0
- package/dist/core/schedule/token-fold.js +181 -0
- package/dist/core/schedule/token-fold.js.map +1 -0
- package/dist/core/state-resolve.js +86 -0
- package/dist/core/state-resolve.js.map +1 -0
- package/dist/core/vm-guards.js +278 -0
- package/dist/core/vm-guards.js.map +1 -0
- package/dist/core/workflow/derive.js +107 -0
- package/dist/core/workflow/derive.js.map +1 -0
- package/dist/core/workflow/parse.js +687 -0
- package/dist/core/workflow/parse.js.map +1 -0
- package/dist/core/workflow/prompt-probe.js +78 -0
- package/dist/core/workflow/prompt-probe.js.map +1 -0
- package/dist/core/workflow/validate.js +189 -0
- package/dist/core/workflow/validate.js.map +1 -0
- package/dist/core/workspace-key.js +19 -0
- package/dist/core/workspace-key.js.map +1 -0
- package/dist/shell/actions-runner.js +356 -0
- package/dist/shell/actions-runner.js.map +1 -0
- package/dist/shell/adapter/adapter-registry.js +45 -0
- package/dist/shell/adapter/adapter-registry.js.map +1 -0
- package/dist/shell/adapter/clock-random.js +96 -0
- package/dist/shell/adapter/clock-random.js.map +1 -0
- package/dist/shell/adapter/gondolin-dispatch-helpers.js +158 -0
- package/dist/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
- package/dist/shell/adapter/gondolin-dispatch.js +385 -0
- package/dist/shell/adapter/gondolin-dispatch.js.map +1 -0
- package/dist/shell/adapter/gondolin-image-converter.js +233 -0
- package/dist/shell/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/shell/adapter/gondolin-image-fetch.js +180 -0
- package/dist/shell/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/shell/adapter/launcher-asset.js +57 -0
- package/dist/shell/adapter/launcher-asset.js.map +1 -0
- package/dist/shell/adapter/mise-config-asset.js +65 -0
- package/dist/shell/adapter/mise-config-asset.js.map +1 -0
- package/dist/shell/adapter/workflow-loader.js +304 -0
- package/dist/shell/adapter/workflow-loader.js.map +1 -0
- package/dist/shell/cli/doctor.js +268 -0
- package/dist/shell/cli/doctor.js.map +1 -0
- package/dist/shell/effect-interpreter-families.js +314 -0
- package/dist/shell/effect-interpreter-families.js.map +1 -0
- package/dist/shell/effect-interpreter.js +29 -0
- package/dist/shell/effect-interpreter.js.map +1 -0
- package/dist/shell/interp/acp-frame.js +137 -0
- package/dist/shell/interp/acp-frame.js.map +1 -0
- package/dist/shell/interp/acp-ws-conn.js +320 -0
- package/dist/shell/interp/acp-ws-conn.js.map +1 -0
- package/dist/shell/interp/acp-ws-frames.js +159 -0
- package/dist/shell/interp/acp-ws-frames.js.map +1 -0
- package/dist/shell/interp/acp-ws.js +197 -0
- package/dist/shell/interp/acp-ws.js.map +1 -0
- package/dist/shell/interp/acp.js +319 -0
- package/dist/shell/interp/acp.js.map +1 -0
- package/dist/shell/interp/credential-defaults.js +128 -0
- package/dist/shell/interp/credential-defaults.js.map +1 -0
- package/dist/shell/interp/credential-hooks.js +149 -0
- package/dist/shell/interp/credential-hooks.js.map +1 -0
- package/dist/shell/interp/credential-registry.js +226 -0
- package/dist/shell/interp/credential-registry.js.map +1 -0
- package/dist/shell/interp/credential.js +103 -0
- package/dist/shell/interp/credential.js.map +1 -0
- package/dist/shell/interp/gh.js +163 -0
- package/dist/shell/interp/gh.js.map +1 -0
- package/dist/shell/interp/git.js +28 -0
- package/dist/shell/interp/git.js.map +1 -0
- package/dist/shell/interp/log.js +213 -0
- package/dist/shell/interp/log.js.map +1 -0
- package/dist/shell/interp/process.js +178 -0
- package/dist/shell/interp/process.js.map +1 -0
- package/dist/shell/interp/runlog.js +193 -0
- package/dist/shell/interp/runlog.js.map +1 -0
- package/dist/shell/interp/timer.js +64 -0
- package/dist/shell/interp/timer.js.map +1 -0
- package/dist/shell/interp/tracker-disk.js +99 -0
- package/dist/shell/interp/tracker-disk.js.map +1 -0
- package/dist/shell/interp/tracker-parse.js +71 -0
- package/dist/shell/interp/tracker-parse.js.map +1 -0
- package/dist/shell/interp/tracker-scan.js +238 -0
- package/dist/shell/interp/tracker-scan.js.map +1 -0
- package/dist/shell/interp/tracker-write.js +91 -0
- package/dist/shell/interp/tracker-write.js.map +1 -0
- package/dist/shell/interp/tracker.js +41 -0
- package/dist/shell/interp/tracker.js.map +1 -0
- package/dist/shell/interp/tty.js +48 -0
- package/dist/shell/interp/tty.js.map +1 -0
- package/dist/shell/interp/vm.js +199 -0
- package/dist/shell/interp/vm.js.map +1 -0
- package/dist/shell/interp/workspace.js +310 -0
- package/dist/shell/interp/workspace.js.map +1 -0
- package/dist/shell/main-acp.js +78 -0
- package/dist/shell/main-acp.js.map +1 -0
- package/dist/shell/main-adapters.js +222 -0
- package/dist/shell/main-adapters.js.map +1 -0
- package/dist/shell/main-credential.js +122 -0
- package/dist/shell/main-credential.js.map +1 -0
- package/dist/shell/main-doctor.js +22 -0
- package/dist/shell/main-doctor.js.map +1 -0
- package/dist/shell/main-entry.js +46 -0
- package/dist/shell/main-entry.js.map +1 -0
- package/dist/shell/main-http-csrf.js +45 -0
- package/dist/shell/main-http-csrf.js.map +1 -0
- package/dist/shell/main-http-handler.js +389 -0
- package/dist/shell/main-http-handler.js.map +1 -0
- package/dist/shell/main-http-mcp.js +122 -0
- package/dist/shell/main-http-mcp.js.map +1 -0
- package/dist/shell/main-http-views.js +253 -0
- package/dist/shell/main-http-views.js.map +1 -0
- package/dist/shell/main-http.js +76 -0
- package/dist/shell/main-http.js.map +1 -0
- package/dist/shell/main-loops.js +130 -0
- package/dist/shell/main-loops.js.map +1 -0
- package/dist/shell/main-mcp.js +129 -0
- package/dist/shell/main-mcp.js.map +1 -0
- package/dist/shell/main-orchestrator.js +120 -0
- package/dist/shell/main-orchestrator.js.map +1 -0
- package/dist/shell/main-preflight.js +43 -0
- package/dist/shell/main-preflight.js.map +1 -0
- package/dist/shell/main-reconcilers-helpers.js +244 -0
- package/dist/shell/main-reconcilers-helpers.js.map +1 -0
- package/dist/shell/main-reconcilers-pr.js +148 -0
- package/dist/shell/main-reconcilers-pr.js.map +1 -0
- package/dist/shell/main-reconcilers.js +225 -0
- package/dist/shell/main-reconcilers.js.map +1 -0
- package/dist/shell/main-runner.js +355 -0
- package/dist/shell/main-runner.js.map +1 -0
- package/dist/shell/main-scaffold.js +116 -0
- package/dist/shell/main-scaffold.js.map +1 -0
- package/dist/shell/main-shutdown.js +115 -0
- package/dist/shell/main-shutdown.js.map +1 -0
- package/dist/shell/main-startup.js +48 -0
- package/dist/shell/main-startup.js.map +1 -0
- package/dist/shell/main-substrates.js +43 -0
- package/dist/shell/main-substrates.js.map +1 -0
- package/dist/shell/main.js +385 -0
- package/dist/shell/main.js.map +1 -0
- package/dist/shell/orchestrator-feedback.js +69 -0
- package/dist/shell/orchestrator-feedback.js.map +1 -0
- package/dist/shell/orchestrator-image.js +167 -0
- package/dist/shell/orchestrator-image.js.map +1 -0
- package/dist/shell/orchestrator-loop.js +468 -0
- package/dist/shell/orchestrator-loop.js.map +1 -0
- package/dist/shell/orchestrator-reconcile.js +36 -0
- package/dist/shell/orchestrator-reconcile.js.map +1 -0
- package/dist/shell/reconciler-loop.js +228 -0
- package/dist/shell/reconciler-loop.js.map +1 -0
- package/dist/shell/runner-loop-turn.js +301 -0
- package/dist/shell/runner-loop-turn.js.map +1 -0
- package/dist/shell/runner-loop.js +338 -0
- package/dist/shell/runner-loop.js.map +1 -0
- package/dist/shell/server/http.js +208 -0
- package/dist/shell/server/http.js.map +1 -0
- package/dist/shell/server/mcp-runtime-effects.js +237 -0
- package/dist/shell/server/mcp-runtime-effects.js.map +1 -0
- package/dist/shell/server/mcp-runtime.js +99 -0
- package/dist/shell/server/mcp-runtime.js.map +1 -0
- package/dist/shell/workspace-key.js +14 -0
- package/dist/shell/workspace-key.js.map +1 -0
- package/dist/types/acp.js +8 -0
- package/dist/types/acp.js.map +1 -0
- package/dist/types/actions/plan.js +6 -0
- package/dist/types/actions/plan.js.map +1 -0
- package/dist/types/actions/predicates.js +6 -0
- package/dist/types/actions/predicates.js.map +1 -0
- package/dist/types/actions/run-fold.js +8 -0
- package/dist/types/actions/run-fold.js.map +1 -0
- package/dist/types/actions.js +7 -0
- package/dist/types/actions.js.map +1 -0
- package/dist/types/adapter/clock-random.js +4 -0
- package/dist/types/adapter/clock-random.js.map +1 -0
- package/dist/types/adapter/gondolin-image-converter.js +5 -0
- package/dist/types/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/types/adapter/gondolin-image-fetch.js +5 -0
- package/dist/types/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/types/adapter/workflow-loader.js +4 -0
- package/dist/types/adapter/workflow-loader.js.map +1 -0
- package/dist/types/cli/args.js +8 -0
- package/dist/types/cli/args.js.map +1 -0
- package/dist/types/config.js +8 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/credential-interp.js +6 -0
- package/dist/types/credential-interp.js.map +1 -0
- package/dist/types/credentials.js +10 -0
- package/dist/types/credentials.js.map +1 -0
- package/dist/types/doctor.js +7 -0
- package/dist/types/doctor.js.map +1 -0
- package/dist/types/domain.js +7 -0
- package/dist/types/domain.js.map +1 -0
- package/dist/types/effect.js +15 -0
- package/dist/types/effect.js.map +1 -0
- package/dist/types/errors.js +39 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/http/decisions.js +6 -0
- package/dist/types/http/decisions.js.map +1 -0
- package/dist/types/http/render.js +10 -0
- package/dist/types/http/render.js.map +1 -0
- package/dist/types/http/views.js +6 -0
- package/dist/types/http/views.js.map +1 -0
- package/dist/types/http.js +9 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/image/managed-image.js +7 -0
- package/dist/types/image/managed-image.js.map +1 -0
- package/dist/types/interp/effect-interpreter.js +8 -0
- package/dist/types/interp/effect-interpreter.js.map +1 -0
- package/dist/types/interp/tracker.js +7 -0
- package/dist/types/interp/tracker.js.map +1 -0
- package/dist/types/issue/file.js +6 -0
- package/dist/types/issue/file.js.map +1 -0
- package/dist/types/issue/parse.js +8 -0
- package/dist/types/issue/parse.js.map +1 -0
- package/dist/types/main-acp.js +13 -0
- package/dist/types/main-acp.js.map +1 -0
- package/dist/types/main-adapters.js +5 -0
- package/dist/types/main-adapters.js.map +1 -0
- package/dist/types/main-credential.js +21 -0
- package/dist/types/main-credential.js.map +1 -0
- package/dist/types/main-doctor.js +6 -0
- package/dist/types/main-doctor.js.map +1 -0
- package/dist/types/main-http-handler.js +12 -0
- package/dist/types/main-http-handler.js.map +1 -0
- package/dist/types/main-http.js +5 -0
- package/dist/types/main-http.js.map +1 -0
- package/dist/types/main-loops.js +5 -0
- package/dist/types/main-loops.js.map +1 -0
- package/dist/types/main-mcp.js +12 -0
- package/dist/types/main-mcp.js.map +1 -0
- package/dist/types/main-orchestrator.js +5 -0
- package/dist/types/main-orchestrator.js.map +1 -0
- package/dist/types/main-reconcilers.js +11 -0
- package/dist/types/main-reconcilers.js.map +1 -0
- package/dist/types/main-runner.js +13 -0
- package/dist/types/main-runner.js.map +1 -0
- package/dist/types/main-startup.js +5 -0
- package/dist/types/main-startup.js.map +1 -0
- package/dist/types/main-substrates.js +5 -0
- package/dist/types/main-substrates.js.map +1 -0
- package/dist/types/mcp/dispatch.js +4 -0
- package/dist/types/mcp/dispatch.js.map +1 -0
- package/dist/types/mcp/post-move.js +7 -0
- package/dist/types/mcp/post-move.js.map +1 -0
- package/dist/types/mcp.js +9 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/ports.js +12 -0
- package/dist/types/ports.js.map +1 -0
- package/dist/types/reconcile/image-decide.js +5 -0
- package/dist/types/reconcile/image-decide.js.map +1 -0
- package/dist/types/reconcile/ledger.js +7 -0
- package/dist/types/reconcile/ledger.js.map +1 -0
- package/dist/types/reconcile/pr-loop.js +8 -0
- package/dist/types/reconcile/pr-loop.js.map +1 -0
- package/dist/types/reconcile/vm-reap.js +8 -0
- package/dist/types/reconcile/vm-reap.js.map +1 -0
- package/dist/types/reconcile/workspace-decide.js +7 -0
- package/dist/types/reconcile/workspace-decide.js.map +1 -0
- package/dist/types/reconcile.js +9 -0
- package/dist/types/reconcile.js.map +1 -0
- package/dist/types/runlog.js +7 -0
- package/dist/types/runlog.js.map +1 -0
- package/dist/types/runner/actions-runner.js +12 -0
- package/dist/types/runner/actions-runner.js.map +1 -0
- package/dist/types/runner/gondolin-dispatch.js +5 -0
- package/dist/types/runner/gondolin-dispatch.js.map +1 -0
- package/dist/types/runner/injection.js +6 -0
- package/dist/types/runner/injection.js.map +1 -0
- package/dist/types/runner/runner-loop.js +5 -0
- package/dist/types/runner/runner-loop.js.map +1 -0
- package/dist/types/runner/turn.js +4 -0
- package/dist/types/runner/turn.js.map +1 -0
- package/dist/types/runner/vm-plan.js +4 -0
- package/dist/types/runner/vm-plan.js.map +1 -0
- package/dist/types/runtime.js +9 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/schedule/admission.js +7 -0
- package/dist/types/schedule/admission.js.map +1 -0
- package/dist/types/schedule/circuit-breaker.js +2 -0
- package/dist/types/schedule/circuit-breaker.js.map +1 -0
- package/dist/types/schedule/eligibility.js +9 -0
- package/dist/types/schedule/eligibility.js.map +1 -0
- package/dist/types/schedule/orchestrator-loop.js +10 -0
- package/dist/types/schedule/orchestrator-loop.js.map +1 -0
- package/dist/types/schedule/sleep-cycle.js +4 -0
- package/dist/types/schedule/sleep-cycle.js.map +1 -0
- package/dist/types/schedule/slots.js +8 -0
- package/dist/types/schedule/slots.js.map +1 -0
- package/dist/types/schedule/tick.js +9 -0
- package/dist/types/schedule/tick.js.map +1 -0
- package/dist/types/server/mcp-runtime.js +8 -0
- package/dist/types/server/mcp-runtime.js.map +1 -0
- package/dist/types/workflow/parse.js +4 -0
- package/dist/types/workflow/parse.js.map +1 -0
- package/package.json +22 -10
- 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/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,92 @@
|
|
|
1
|
+
// FCIS rewrite — FUNCTIONAL CORE: MCP transition POST-move fold.
|
|
2
|
+
//
|
|
3
|
+
// Closes the decide→IO→decide loop for `symphony.transition`. The PRE-move
|
|
4
|
+
// decider (core/mcp/dispatch — written concurrently) validates the envelope,
|
|
5
|
+
// resolves the canonical target, and emits a `move_state` McpEffect. The SHELL
|
|
6
|
+
// performs the tracker file-move and hands the RESOLVED result back as an
|
|
7
|
+
// McpEffectResult. THIS module folds that resolved result into the post-move
|
|
8
|
+
// flags the original `performTransition` derived inline (impureCoreRisk fix):
|
|
9
|
+
//
|
|
10
|
+
// - the cleanup-on-exit gate (terminal role, minus PR-merge suppression),
|
|
11
|
+
// - the TransitionRecord stashed for the run-log `transition` event,
|
|
12
|
+
// - the notes header that the shell prepends when appending notes to the body.
|
|
13
|
+
//
|
|
14
|
+
// Pure + synchronous. The only nondeterministic input — the wall-clock ISO used
|
|
15
|
+
// in the notes header — is injected as a plain `nowIso` parameter (the shell
|
|
16
|
+
// passes Clock.iso()), never read here.
|
|
17
|
+
//
|
|
18
|
+
// Reference behavior (read-only): undefined/src/mcp.ts performTransition
|
|
19
|
+
// (post-move flag derivation) + undefined/src/trackers/local.ts
|
|
20
|
+
// buildNotesAppendedBody (notes header format).
|
|
21
|
+
/** Case-insensitive equality with explicit null handling (matches the original). */
|
|
22
|
+
function eqIgnoreCase(a, b) {
|
|
23
|
+
return b !== null && a.toLowerCase() === b.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build the notes-append header. Mirrors `buildNotesAppendedBody`'s header line
|
|
27
|
+
* exactly: `## <who> — <iso> — <from> → <to>`, with `who` defaulting to
|
|
28
|
+
* 'unknown' when the actor is null/empty.
|
|
29
|
+
*/
|
|
30
|
+
export function buildNotesHeader(actor, nowIso, fromState, toState) {
|
|
31
|
+
const who = actor && actor.length > 0 ? actor : 'unknown';
|
|
32
|
+
return `## ${who} — ${nowIso} — ${fromState} → ${toState}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fold the resolved tracker result into the post-move flags. Pure: returns a
|
|
36
|
+
* decision object; the shell mutates the running entry and folds the record into
|
|
37
|
+
* the run log. Failed / non-move results produce an inert decision (no terminal
|
|
38
|
+
* gate, no record) so the shell can leave the entry untouched and surface the
|
|
39
|
+
* error response the pre-move decider already shaped.
|
|
40
|
+
*/
|
|
41
|
+
export function foldPostMove(input) {
|
|
42
|
+
const { result, targetState, prMerge, fromState, notes, actor, nowIso } = input;
|
|
43
|
+
// Only a successful `move_state` (kind: 'moved') drives the post-move flags.
|
|
44
|
+
// `move_failed` and `written` (propose_issue) are no-ops here — the dispatch
|
|
45
|
+
// layer owns their responses; nothing transitioned, so no flags flip.
|
|
46
|
+
if (result.kind !== 'moved') {
|
|
47
|
+
return {
|
|
48
|
+
moved: false,
|
|
49
|
+
toState: null,
|
|
50
|
+
terminal: false,
|
|
51
|
+
cleanupWorkspaceOnExit: false,
|
|
52
|
+
suppressCleanupForMerge: false,
|
|
53
|
+
notesHeader: null,
|
|
54
|
+
transitionRecord: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Prefer the canonical declared name (operator-supplied casing) for the role
|
|
58
|
+
// lookup + downstream state resolution; fall back to the tracker's resolved
|
|
59
|
+
// toState when it no longer maps to a declared state (canonicalName === null).
|
|
60
|
+
const canonicalName = targetState !== null ? targetState.name : null;
|
|
61
|
+
const resolvedTo = canonicalName ?? result.toState;
|
|
62
|
+
const targetIsTerminal = targetState !== null && targetState.role === 'terminal';
|
|
63
|
+
// Issue 38/144 (mustFix): suppress terminal cleanup when the PR engine owns
|
|
64
|
+
// this state's workspace — the pr resource reaps it after the PR merges/closes.
|
|
65
|
+
// Other terminal states (Cancelled) still clean up immediately.
|
|
66
|
+
const suppressCleanupForMerge = targetIsTerminal &&
|
|
67
|
+
canonicalName !== null &&
|
|
68
|
+
prMerge.enabled &&
|
|
69
|
+
prMerge.mergeState !== null &&
|
|
70
|
+
eqIgnoreCase(canonicalName, prMerge.mergeState);
|
|
71
|
+
const cleanupWorkspaceOnExit = targetIsTerminal && !suppressCleanupForMerge;
|
|
72
|
+
const notesHeader = notes.length > 0 ? buildNotesHeader(actor, nowIso, fromState, resolvedTo) : null;
|
|
73
|
+
// Stash the transition for the shell-side run-log fold (issue 123). `from_state`
|
|
74
|
+
// is the tracker's resolved source; `to_state` is the canonical resolved target.
|
|
75
|
+
const transitionRecord = {
|
|
76
|
+
from_state: result.fromState,
|
|
77
|
+
to_state: resolvedTo,
|
|
78
|
+
notes,
|
|
79
|
+
actor,
|
|
80
|
+
terminal: targetIsTerminal,
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
moved: true,
|
|
84
|
+
toState: resolvedTo,
|
|
85
|
+
terminal: targetIsTerminal,
|
|
86
|
+
cleanupWorkspaceOnExit,
|
|
87
|
+
suppressCleanupForMerge,
|
|
88
|
+
notesHeader,
|
|
89
|
+
transitionRecord,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=post-move.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-move.js","sourceRoot":"","sources":["../../../src/core/mcp/post-move.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,iFAAiF;AACjF,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,wCAAwC;AACxC,EAAE;AACF,yEAAyE;AACzE,gEAAgE;AAChE,gDAAgD;AAShD,oFAAoF;AACpF,SAAS,YAAY,CAAC,CAAS,EAAE,CAAgB;IAC/C,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAoB,EACpB,MAAc,EACd,SAAiB,EACjB,OAAe;IAEf,MAAM,GAAG,GAAG,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,OAAO,MAAM,GAAG,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO,EAAE,CAAC;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,KAAoB;IAC/C,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAEhF,6EAA6E;IAC7E,6EAA6E;IAC7E,sEAAsE;IACtE,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,KAAK;YACf,sBAAsB,EAAE,KAAK;YAC7B,uBAAuB,EAAE,KAAK;YAC9B,WAAW,EAAE,IAAI;YACjB,gBAAgB,EAAE,IAAI;SACvB,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,4EAA4E;IAC5E,+EAA+E;IAC/E,MAAM,aAAa,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,MAAM,UAAU,GAAG,aAAa,IAAI,MAAM,CAAC,OAAO,CAAC;IAEnD,MAAM,gBAAgB,GAAG,WAAW,KAAK,IAAI,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC;IAEjF,4EAA4E;IAC5E,gFAAgF;IAChF,gEAAgE;IAChE,MAAM,uBAAuB,GAC3B,gBAAgB;QAChB,aAAa,KAAK,IAAI;QACtB,OAAO,CAAC,OAAO;QACf,OAAO,CAAC,UAAU,KAAK,IAAI;QAC3B,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAElD,MAAM,sBAAsB,GAAG,gBAAgB,IAAI,CAAC,uBAAuB,CAAC;IAE5E,MAAM,WAAW,GACf,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEnF,iFAAiF;IACjF,iFAAiF;IACjF,MAAM,gBAAgB,GAAqB;QACzC,UAAU,EAAE,MAAM,CAAC,SAAS;QAC5B,QAAQ,EAAE,UAAU;QACpB,KAAK;QACL,KAAK;QACL,QAAQ,EAAE,gBAAgB;KAC3B,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,UAAU;QACnB,QAAQ,EAAE,gBAAgB;QAC1B,sBAAsB;QACtB,uBAAuB;QACvB,WAAW;QACX,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// FCIS rewrite — pure MCP JSON-RPC framing.
|
|
2
|
+
//
|
|
3
|
+
// Functional-core port of the JSON-RPC *envelope* handling the original spread
|
|
4
|
+
// through `src/mcp.ts` (`isRpcRequest`, `getId`, `makeError`, `makeToolError`,
|
|
5
|
+
// `makeStructuredToolError`, the `PROTOCOL_VERSION`/`TOOL_LIST` catalog and the
|
|
6
|
+
// `initialize` / `tools/list` / `ping` / notification method routing inside
|
|
7
|
+
// `handleJsonRpc`).
|
|
8
|
+
//
|
|
9
|
+
// This module owns ONLY the framing — the parts that are a pure function of the
|
|
10
|
+
// inbound envelope and need neither the live `ActiveEntry` registry nor any IO:
|
|
11
|
+
//
|
|
12
|
+
// - validate the JSON-RPC request envelope (validateEnvelope)
|
|
13
|
+
// - extract the response id from arbitrary input (extractId)
|
|
14
|
+
// - the protocol-version + tool catalog (PROTOCOL_VERSION / TOOL_LIST)
|
|
15
|
+
// - the static `initialize` / `tools/list` / `ping` (routeFraming)
|
|
16
|
+
// results and the notification "no reply" decision
|
|
17
|
+
// - error / tool-error / structured-tool-error
|
|
18
|
+
// response shaping (makeError / makeToolError /
|
|
19
|
+
// makeStructuredToolError)
|
|
20
|
+
//
|
|
21
|
+
// What it deliberately does NOT do: the stateful `tools/call` dispatch
|
|
22
|
+
// (transition / propose_issue / request_human_steering). Those mutate the
|
|
23
|
+
// running entry and emit McpEffect[]; they belong to the registry decider
|
|
24
|
+
// (core/mcp/dispatch) which calls `routeFraming` first and only falls through to
|
|
25
|
+
// its own logic on a `tools/call` method.
|
|
26
|
+
//
|
|
27
|
+
// HARD CONSTRAINTS (gate-enforced):
|
|
28
|
+
// - 100% SYNCHRONOUS. No async/await/Promise anywhere (not even in a type).
|
|
29
|
+
// - No IO, no node: imports, no process/fetch, no wall clock, no randomness.
|
|
30
|
+
// - Imports ONLY from src/types/**.
|
|
31
|
+
//
|
|
32
|
+
// Behavior ported faithfully:
|
|
33
|
+
// - `isRpcRequest`: a body is a valid request iff it is a non-array object
|
|
34
|
+
// with `jsonrpc === '2.0'` and a string `method`.
|
|
35
|
+
// - `getId`: only string|number ids survive; everything else (including a
|
|
36
|
+
// literal null id, an array, a primitive body) collapses to `null`.
|
|
37
|
+
// - A notification is a request with NO `id` key at all (`id === undefined`);
|
|
38
|
+
// a present `id: null` is a request that still expects a response keyed null.
|
|
39
|
+
// - `initialize` / `tools/list` / `ping` as notifications get no reply (null);
|
|
40
|
+
// `notifications/*` always get no reply.
|
|
41
|
+
// - MCP convention: tool errors are NOT JSON-RPC `error` envelopes — they are
|
|
42
|
+
// successful results with `isError: true`; structured tool errors put the
|
|
43
|
+
// machine-readable payload on `structuredContent` (MCP 2025-06-18 has no
|
|
44
|
+
// `json` content-block type).
|
|
45
|
+
/** MCP protocol version advertised in the `initialize` result. */
|
|
46
|
+
export const PROTOCOL_VERSION = '2025-06-18';
|
|
47
|
+
/**
|
|
48
|
+
* The static tool catalog returned from `tools/list`. Verbatim from the
|
|
49
|
+
* original `src/mcp.ts:TOOL_LIST` (declaration order: steering, transition,
|
|
50
|
+
* propose_issue). Declared `as const` so callers cannot accidentally mutate the
|
|
51
|
+
* shared catalog.
|
|
52
|
+
*/
|
|
53
|
+
export const TOOL_LIST = [
|
|
54
|
+
{
|
|
55
|
+
name: 'request_human_steering',
|
|
56
|
+
description: 'Pause work and ask the human operator a question. Your current turn will end immediately after this returns; the human response will arrive as the prompt for your next turn. Use only when you cannot proceed without a decision a human must make.',
|
|
57
|
+
inputSchema: {
|
|
58
|
+
type: 'object',
|
|
59
|
+
properties: {
|
|
60
|
+
question: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
description: 'The question to ask the human. Be specific about what decision they need to make.',
|
|
63
|
+
},
|
|
64
|
+
context: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'Optional: relevant context the human needs to answer (file paths, options considered, etc.).',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
required: ['question'],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'transition',
|
|
74
|
+
description: 'Move this issue into another declared state, optionally appending notes to its body for the next agent. Use this for handoffs — implementer → reviewer, reviewer → implementer (rework), or implementer → terminal Done — rather than only at the very end of the work. Notes are appended to the issue file BEFORE the state move, so the next dispatch sees them in `issue.description` along with everything the previous agents wrote. `to_state` must be one of the states declared in WORKFLOW.yaml; if the current state declares `allowed_transitions`, `to_state` must also be in that list. On a terminal target, the workspace is removed after your turn ends and no further turns will be dispatched. On a non-terminal target, the same workspace and `agent/<id>` git branch survive into the next state.',
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {
|
|
78
|
+
to_state: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
description: 'Declared state to transition into (case-insensitive match against `states:` in WORKFLOW.yaml). Examples: "Review", "Done", "Todo".',
|
|
81
|
+
},
|
|
82
|
+
notes: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
description: 'Optional markdown notes to append to the issue body before the move. These become part of the issue description the next agent (in `to_state`) reads. Use this for review findings, rework instructions, or PR-body content on a terminal transition.',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
required: ['to_state'],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'propose_issue',
|
|
92
|
+
description: 'Propose a new issue for the human to triage. The orchestrator drops the proposal into a non-active "Triage" state directory and does NOT dispatch it — the operator approves (moves to the active queue) or discards it from the dashboard. Use this when you notice work that is out of scope for your current task: an unrelated bug, a follow-up the operator should size, a refactor a future agent could pick up. The parent issue you are working on is automatically recorded; do not paste it into the body.',
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
title: {
|
|
97
|
+
type: 'string',
|
|
98
|
+
description: 'Short single-line title in imperative voice (≤72 chars recommended). Example: "Fix race condition in workspace cleanup".',
|
|
99
|
+
},
|
|
100
|
+
description: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Optional multi-paragraph body for the issue. Explain what you observed, where (file paths), and why it is worth handling separately from your current task.',
|
|
103
|
+
},
|
|
104
|
+
labels: {
|
|
105
|
+
type: 'array',
|
|
106
|
+
items: { type: 'string' },
|
|
107
|
+
description: 'Optional list of label strings.',
|
|
108
|
+
},
|
|
109
|
+
priority: {
|
|
110
|
+
type: 'number',
|
|
111
|
+
description: 'Optional integer priority hint (tracker-defined meaning).',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
required: ['title'],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
/**
|
|
119
|
+
* JSON-RPC error codes used by the framing layer. Ported from the literals the
|
|
120
|
+
* original passed to `makeError`. Exposed as a const-object enum so callers (the
|
|
121
|
+
* shell router doing token/active checks) share one vocabulary.
|
|
122
|
+
*/
|
|
123
|
+
export const JsonRpcErrorCode = {
|
|
124
|
+
/** Reserved JSON-RPC: malformed request envelope. */
|
|
125
|
+
InvalidRequest: -32600,
|
|
126
|
+
/** Reserved JSON-RPC: unknown method (or unknown tool name). */
|
|
127
|
+
MethodNotFound: -32601,
|
|
128
|
+
/** Reserved JSON-RPC: handler threw. */
|
|
129
|
+
InternalError: -32603,
|
|
130
|
+
/** Implementation-defined: the issue identifier is not an active dispatch. */
|
|
131
|
+
IssueNotActive: -32001,
|
|
132
|
+
/** Implementation-defined: the bearer token did not match. */
|
|
133
|
+
InvalidToken: -32002,
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Validate the JSON-RPC request envelope. Faithful port of the original
|
|
137
|
+
* `isRpcRequest` type-guard: a body is a request iff it is a non-array object
|
|
138
|
+
* carrying `jsonrpc: '2.0'` and a string `method`. Used by the shell before
|
|
139
|
+
* routing; the `is` predicate narrows `body` for the caller.
|
|
140
|
+
*/
|
|
141
|
+
export function validateEnvelope(body) {
|
|
142
|
+
if (!body || typeof body !== 'object' || Array.isArray(body))
|
|
143
|
+
return false;
|
|
144
|
+
const rec = body;
|
|
145
|
+
return rec.jsonrpc === '2.0' && typeof rec.method === 'string';
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Extract the response id from an arbitrary (possibly malformed) body. Faithful
|
|
149
|
+
* port of the original `getId`: only a string or number `id` survives;
|
|
150
|
+
* everything else — a non-object body, an array, a missing id, or a literal
|
|
151
|
+
* `id: null` — collapses to `null`. This is the id used to key error envelopes
|
|
152
|
+
* for bodies that fail `validateEnvelope`.
|
|
153
|
+
*/
|
|
154
|
+
export function extractId(body) {
|
|
155
|
+
if (body && typeof body === 'object' && !Array.isArray(body)) {
|
|
156
|
+
const rec = body;
|
|
157
|
+
if (typeof rec.id === 'string' || typeof rec.id === 'number')
|
|
158
|
+
return rec.id;
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Is this validated request a notification (no reply expected)? In JSON-RPC a
|
|
164
|
+
* notification is a request with NO `id` member at all. The original keyed this
|
|
165
|
+
* off `body.id === undefined`; a present `id: null` is NOT a notification (it
|
|
166
|
+
* expects a response keyed `null`).
|
|
167
|
+
*/
|
|
168
|
+
export function isNotification(req) {
|
|
169
|
+
return req.id === undefined;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The response id for a validated request: the present id, or `null` when the
|
|
173
|
+
* request omitted it. Mirrors the original `const id = body.id ?? null;`.
|
|
174
|
+
*/
|
|
175
|
+
export function responseId(req) {
|
|
176
|
+
return req.id ?? null;
|
|
177
|
+
}
|
|
178
|
+
/** The static `initialize` result body (no id binding). */
|
|
179
|
+
function initializeResult() {
|
|
180
|
+
return {
|
|
181
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
182
|
+
capabilities: {
|
|
183
|
+
tools: { listChanged: false },
|
|
184
|
+
},
|
|
185
|
+
serverInfo: {
|
|
186
|
+
name: 'smol-symphony',
|
|
187
|
+
version: '0.1.0',
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Route the *framing* methods of a validated JSON-RPC request. Pure mirror of
|
|
193
|
+
* the method switch in the original `handleJsonRpc`, minus the stateful
|
|
194
|
+
* `tools/call` arms (collapsed into a `dispatch` outcome the caller forwards to
|
|
195
|
+
* the registry decider). The caller is responsible for the active-issue +
|
|
196
|
+
* token checks (which need the registry) BEFORE calling this; framing assumes
|
|
197
|
+
* the envelope is already validated.
|
|
198
|
+
*
|
|
199
|
+
* - notification (id omitted) -> { kind: 'none' } (HTTP 204)
|
|
200
|
+
* - notifications/initialized
|
|
201
|
+
* | notifications/cancelled
|
|
202
|
+
* | notifications/progress -> { kind: 'none' }
|
|
203
|
+
* - initialize -> static initialize result
|
|
204
|
+
* - tools/list -> static TOOL_LIST result
|
|
205
|
+
* - ping -> empty {} result
|
|
206
|
+
* - tools/call -> { kind: 'dispatch', id, toolName, args }
|
|
207
|
+
* - any other method -> MethodNotFound error
|
|
208
|
+
*/
|
|
209
|
+
export function routeFraming(req) {
|
|
210
|
+
const notification = isNotification(req);
|
|
211
|
+
const id = responseId(req);
|
|
212
|
+
switch (req.method) {
|
|
213
|
+
case 'notifications/initialized':
|
|
214
|
+
case 'notifications/cancelled':
|
|
215
|
+
case 'notifications/progress':
|
|
216
|
+
// These are always notifications; reply with nothing regardless of id.
|
|
217
|
+
return { kind: 'none' };
|
|
218
|
+
case 'initialize': {
|
|
219
|
+
if (notification)
|
|
220
|
+
return { kind: 'none' };
|
|
221
|
+
return { kind: 'respond', response: { jsonrpc: '2.0', id, result: initializeResult() } };
|
|
222
|
+
}
|
|
223
|
+
case 'tools/list': {
|
|
224
|
+
if (notification)
|
|
225
|
+
return { kind: 'none' };
|
|
226
|
+
return { kind: 'respond', response: { jsonrpc: '2.0', id, result: { tools: TOOL_LIST } } };
|
|
227
|
+
}
|
|
228
|
+
case 'ping': {
|
|
229
|
+
if (notification)
|
|
230
|
+
return { kind: 'none' };
|
|
231
|
+
return { kind: 'respond', response: { jsonrpc: '2.0', id, result: {} } };
|
|
232
|
+
}
|
|
233
|
+
case 'tools/call': {
|
|
234
|
+
if (notification)
|
|
235
|
+
return { kind: 'none' };
|
|
236
|
+
const params = (req.params ?? {});
|
|
237
|
+
return { kind: 'dispatch', id, toolName: params.name, args: params.arguments ?? {} };
|
|
238
|
+
}
|
|
239
|
+
default: {
|
|
240
|
+
if (notification)
|
|
241
|
+
return { kind: 'none' };
|
|
242
|
+
return {
|
|
243
|
+
kind: 'respond',
|
|
244
|
+
response: makeError(id, JsonRpcErrorCode.MethodNotFound, `unknown method: ${req.method}`),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Shape a JSON-RPC `error` envelope. Used for protocol-level failures
|
|
251
|
+
* (malformed envelope, unknown method, inactive issue, bad token, handler
|
|
252
|
+
* threw). Faithful port of the original module-level `makeError`.
|
|
253
|
+
*/
|
|
254
|
+
export function makeError(id, code, message) {
|
|
255
|
+
return { jsonrpc: '2.0', id, error: { code, message } };
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Shape an MCP *tool* error: a SUCCESSFUL JSON-RPC result whose payload carries
|
|
259
|
+
* `isError: true` and a single human-readable text block. Per MCP convention a
|
|
260
|
+
* tool's own failure is NOT a JSON-RPC `error` envelope — the SDK delivers it as
|
|
261
|
+
* a normal tool result the agent can read. Faithful port of `makeToolError`.
|
|
262
|
+
*/
|
|
263
|
+
export function makeToolError(id, message) {
|
|
264
|
+
return {
|
|
265
|
+
jsonrpc: '2.0',
|
|
266
|
+
id,
|
|
267
|
+
result: {
|
|
268
|
+
content: [{ type: 'text', text: message }],
|
|
269
|
+
isError: true,
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Shape an MCP tool error that also carries a machine-readable payload. The
|
|
275
|
+
* human-readable prose stays in `content[]`; the structured shape goes on
|
|
276
|
+
* `structuredContent` (MCP 2025-06-18's `CallToolResult.content` defines no
|
|
277
|
+
* `json` block, so structured data lives on the SDK-recognised slot). Used by
|
|
278
|
+
* `transition` rejections (`unknown_state` / `transition_not_allowed`) and
|
|
279
|
+
* `propose_issue`'s `no_holding_state`. Faithful port of
|
|
280
|
+
* `makeStructuredToolError`.
|
|
281
|
+
*/
|
|
282
|
+
export function makeStructuredToolError(id, text, json) {
|
|
283
|
+
return {
|
|
284
|
+
jsonrpc: '2.0',
|
|
285
|
+
id,
|
|
286
|
+
result: {
|
|
287
|
+
content: [{ type: 'text', text }],
|
|
288
|
+
isError: true,
|
|
289
|
+
structuredContent: json,
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/core/mcp/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// FCIS rewrite — pure MCP/ACP URL + state-name resolution.
|
|
2
|
+
//
|
|
3
|
+
// Functional core: every export here is a pure, synchronous (data) -> data
|
|
4
|
+
// function. No IO, no clock, no randomness, no node: imports. Imports ONLY
|
|
5
|
+
// from src/types. The original spread this logic across:
|
|
6
|
+
// - src/mcp.ts: McpRegistry.buildUrl (base resolution + path) and the
|
|
7
|
+
// module-private canonicalStateName (case-insensitive declared-name lookup).
|
|
8
|
+
// - src/agent/vm-acp-mapping.ts: the synthetic guest control-plane constants
|
|
9
|
+
// (MCP_GUEST_BASE_URL / ACP_WS_GUEST_URL), acpWsUrlFromExplicit,
|
|
10
|
+
// buildMcpTcpHostEntry — the Gondolin guest→host tunnel rewire.
|
|
11
|
+
// - src/agent/runner.ts: the `useSyntheticGuestHost` decision (when to dial
|
|
12
|
+
// the synthetic base vs. the explicit URL).
|
|
13
|
+
//
|
|
14
|
+
// All wall-clock / IO inputs the original read live (the bound HTTP port) are
|
|
15
|
+
// PARAMETERS here: `effectivePort` is passed in by the shell, never read.
|
|
16
|
+
import { resolveStateKey } from '../state-resolve.js';
|
|
17
|
+
// ── Synthetic guest control-plane constants (ported verbatim from vm-acp-mapping.ts) ──
|
|
18
|
+
//
|
|
19
|
+
// Gondolin blocks guest→host loopback by default. The supported rewire is a
|
|
20
|
+
// `tcp.hosts` mapping: the guest dials a synthetic hostname on a fixed port,
|
|
21
|
+
// Gondolin's synthetic per-host DNS resolves it, and the entry tunnels the flow
|
|
22
|
+
// to the host's unified HTTP server loopback. Both control planes (MCP HTTP +
|
|
23
|
+
// the `/acp` WebSocket) ride the SAME entry (`symphony-mcp:7001`).
|
|
24
|
+
/** The synthetic guest hostname the in-VM agent dials for the control plane (MCP + ACP). */
|
|
25
|
+
export const MCP_SYNTHETIC_HOST = 'symphony-mcp';
|
|
26
|
+
/**
|
|
27
|
+
* The fixed guest-side port the synthetic name is reached on. Both the MCP HTTP
|
|
28
|
+
* endpoint and the `/acp` WebSocket ride this one host:port (the unified HTTP
|
|
29
|
+
* server), so they share a single `tcp.hosts` entry.
|
|
30
|
+
*/
|
|
31
|
+
export const MCP_GUEST_PORT = 7001;
|
|
32
|
+
/** Guest-facing base URL the in-VM agent dials for MCP (the `/api/v1/...` path is appended). */
|
|
33
|
+
export const MCP_GUEST_BASE_URL = `http://${MCP_SYNTHETIC_HOST}:${MCP_GUEST_PORT}`;
|
|
34
|
+
/** Path the in-VM agent dials for the ACP control plane on the unified HTTP server. */
|
|
35
|
+
export const ACP_WS_PATH = '/acp';
|
|
36
|
+
/**
|
|
37
|
+
* Guest-facing WebSocket URL the in-VM agent dials for ACP: `ws://symphony-mcp:7001/acp`.
|
|
38
|
+
* ACP rides the SAME synthetic `tcp.hosts` entry MCP uses ({@link buildMcpTcpHostEntry});
|
|
39
|
+
* only the scheme (`ws`) and path (`/acp`) differ from the MCP base URL.
|
|
40
|
+
*/
|
|
41
|
+
export const ACP_WS_GUEST_URL = `ws://${MCP_SYNTHETIC_HOST}:${MCP_GUEST_PORT}${ACP_WS_PATH}`;
|
|
42
|
+
/** Trim trailing slashes from a URL base (mirror of `replace(/\/+$/, '')`). */
|
|
43
|
+
function trimTrailingSlashes(base) {
|
|
44
|
+
return base.replace(/\/+$/, '');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The MCP path appended to every base. Kept here so {@link buildUrl} and any
|
|
48
|
+
* caller deriving the per-issue endpoint agree on a single shape.
|
|
49
|
+
*/
|
|
50
|
+
export function mcpIssuePath(identifier) {
|
|
51
|
+
return `/api/v1/issues/${encodeURIComponent(identifier)}/mcp`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build the per-issue MCP URL the ACP agent will be told to POST to. Returns
|
|
55
|
+
* null when no HTTP server is available (`effectivePort === null`) and no
|
|
56
|
+
* explicit/override URL is configured; the runner uses that to skip MCP
|
|
57
|
+
* injection instead of advertising an unreachable endpoint.
|
|
58
|
+
*
|
|
59
|
+
* Base-resolution precedence (ported verbatim from McpRegistry.buildUrl):
|
|
60
|
+
* 1. `baseOverride` (e.g. the Gondolin guest synthetic base
|
|
61
|
+
* `http://symphony-mcp:7001`) — wins over everything: under Gondolin the
|
|
62
|
+
* guest cannot reach the host loopback directly.
|
|
63
|
+
* 2. `mcp.explicit_host_url` — a directly-reachable URL (no tunnel).
|
|
64
|
+
* 3. `http://${mcp.host}:${effectivePort}` — the bound HTTP server loopback.
|
|
65
|
+
*
|
|
66
|
+
* The original took `effectivePort` from live registry state (`this.effectivePort`);
|
|
67
|
+
* here it is an explicit parameter so the function stays pure.
|
|
68
|
+
*/
|
|
69
|
+
export function buildUrl(identifier, mcp, effectivePort, baseOverride) {
|
|
70
|
+
const base = baseOverride
|
|
71
|
+
? trimTrailingSlashes(baseOverride)
|
|
72
|
+
: mcp.explicit_host_url
|
|
73
|
+
? trimTrailingSlashes(mcp.explicit_host_url)
|
|
74
|
+
: effectivePort === null
|
|
75
|
+
? null
|
|
76
|
+
: `http://${mcp.host}:${effectivePort}`;
|
|
77
|
+
if (!base)
|
|
78
|
+
return null;
|
|
79
|
+
return `${base}${mcpIssuePath(identifier)}`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Decide whether the in-VM agent should dial the synthetic guest base (the
|
|
83
|
+
* Gondolin `tcp.hosts` tunnel) instead of an explicit URL / direct loopback.
|
|
84
|
+
*
|
|
85
|
+
* Ported from runner.ts `useSyntheticGuestHost`: true iff there is NO
|
|
86
|
+
* `explicit_host_url` (no direct reachability) AND the HTTP server is bound
|
|
87
|
+
* (a live tunnel target exists). The condition MUST match the tunnel-injection
|
|
88
|
+
* predicate so the advertised URL is always backed by a live `tcp.hosts` entry.
|
|
89
|
+
*/
|
|
90
|
+
export function useSyntheticGuestHost(mcp, effectivePort) {
|
|
91
|
+
return !mcp.explicit_host_url && effectivePort !== null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Resolve the guest-facing MCP URL the in-VM agent is told to use, applying the
|
|
95
|
+
* synthetic-base override when the tunnel is in play. Composes
|
|
96
|
+
* {@link useSyntheticGuestHost} + {@link buildUrl} the way the runner does:
|
|
97
|
+
* synthetic base when tunnelled, otherwise the explicit/loopback base.
|
|
98
|
+
*/
|
|
99
|
+
export function guestMcpUrl(identifier, mcp, effectivePort) {
|
|
100
|
+
const base = useSyntheticGuestHost(mcp, effectivePort) ? MCP_GUEST_BASE_URL : undefined;
|
|
101
|
+
return buildUrl(identifier, mcp, effectivePort, base);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolve the guest-facing ACP WebSocket URL.
|
|
105
|
+
* - No `explicit_host_url` → the synthetic tunnel URL `ws://symphony-mcp:7001/acp`.
|
|
106
|
+
* - `explicit_host_url` set → derive from it via {@link acpWsUrlFromExplicit}
|
|
107
|
+
* (direct reachability; null when the URL can't be parsed).
|
|
108
|
+
*
|
|
109
|
+
* Ported from runner.ts's ACP-back-dial derivation. Note: unlike the MCP path,
|
|
110
|
+
* the synthetic ACP URL does NOT depend on `effectivePort` — the constant tunnel
|
|
111
|
+
* URL is fixed and the runner gates the tunnel injection separately.
|
|
112
|
+
*/
|
|
113
|
+
export function guestAcpWsUrl(mcp) {
|
|
114
|
+
if (mcp.explicit_host_url)
|
|
115
|
+
return acpWsUrlFromExplicit(mcp.explicit_host_url);
|
|
116
|
+
return ACP_WS_GUEST_URL;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Derive the guest ACP WebSocket URL from an explicit MCP host URL (direct
|
|
120
|
+
* reachability — `mcp.explicit_host_url`). Swaps the `http(s)` scheme for
|
|
121
|
+
* `ws(s)` and points at `/acp`. Returns null when the URL can't be parsed.
|
|
122
|
+
*
|
|
123
|
+
* Ported verbatim from vm-acp-mapping.ts. `URL` is a JS-standard global
|
|
124
|
+
* (ECMAScript / WHATWG), not a node: import — pure and allowed in core.
|
|
125
|
+
*/
|
|
126
|
+
export function acpWsUrlFromExplicit(explicitHostUrl) {
|
|
127
|
+
try {
|
|
128
|
+
const u = new URL(explicitHostUrl);
|
|
129
|
+
const scheme = u.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
130
|
+
return `${scheme}//${u.host}${ACP_WS_PATH}`;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Build the `tcp.hosts` entry that tunnels the in-VM agent's control-plane
|
|
138
|
+
* traffic to the host's unified HTTP server loopback `mcpHost:mcpPort`. The
|
|
139
|
+
* channel carries only the per-dispatch bearer and is PORT-SPECIFIC so it can
|
|
140
|
+
* never be reused to reach another host-loopback service.
|
|
141
|
+
*
|
|
142
|
+
* Ported verbatim from vm-acp-mapping.ts. The caller pairs this entry with
|
|
143
|
+
* `dns: { mode: 'synthetic', syntheticHostMapping: 'per-host' }`.
|
|
144
|
+
*/
|
|
145
|
+
export function buildMcpTcpHostEntry(mcpHost, mcpPort) {
|
|
146
|
+
return { [`${MCP_SYNTHETIC_HOST}:${MCP_GUEST_PORT}`]: `${mcpHost}:${mcpPort}` };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Resolve a caller-supplied state name to its canonical declared form (the
|
|
150
|
+
* casing the operator wrote in `states:`). Comparison is case-insensitive to
|
|
151
|
+
* mirror the rest of symphony (eligibility, reconciliation, the local-tracker
|
|
152
|
+
* directory scan all compare lowercase). Returns null when no declared name
|
|
153
|
+
* matches.
|
|
154
|
+
*
|
|
155
|
+
* Thin alias over the canonical {@link resolveStateKey} (core/state-resolve.ts);
|
|
156
|
+
* kept exported here so MCP-URL importers keep their `core/mcp/url` specifier.
|
|
157
|
+
* Only the keys of `states` matter; the per-state config is unused.
|
|
158
|
+
*/
|
|
159
|
+
export function canonicalStateName(states, name) {
|
|
160
|
+
return resolveStateKey(states, name);
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/core/mcp/url.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,yDAAyD;AACzD,wEAAwE;AACxE,iFAAiF;AACjF,+EAA+E;AAC/E,qEAAqE;AACrE,oEAAoE;AACpE,8EAA8E;AAC9E,gDAAgD;AAChD,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAG1E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,yFAAyF;AACzF,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,gFAAgF;AAChF,8EAA8E;AAC9E,mEAAmE;AAEnE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAEjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,kBAAkB,IAAI,cAAc,EAAE,CAAC;AAEnF,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAElC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,kBAAkB,IAAI,cAAc,GAAG,WAAW,EAAE,CAAC;AAE7F,+EAA+E;AAC/E,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,OAAO,kBAAkB,kBAAkB,CAAC,UAAU,CAAC,MAAM,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,QAAQ,CACtB,UAAkB,EAClB,GAAuD,EACvD,aAA4B,EAC5B,YAAqB;IAErB,MAAM,IAAI,GAAG,YAAY;QACvB,CAAC,CAAC,mBAAmB,CAAC,YAAY,CAAC;QACnC,CAAC,CAAC,GAAG,CAAC,iBAAiB;YACrB,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAC5C,CAAC,CAAC,aAAa,KAAK,IAAI;gBACtB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,UAAU,GAAG,CAAC,IAAI,IAAI,aAAa,EAAE,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,GAAG,IAAI,GAAG,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAyC,EACzC,aAA4B;IAE5B,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,aAAa,KAAK,IAAI,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,UAAkB,EAClB,GAAuD,EACvD,aAA4B;IAE5B,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,OAAO,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,GAAyC;IACrE,IAAI,GAAG,CAAC,iBAAiB;QAAE,OAAO,oBAAoB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC9E,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,eAAuB;IAC1D,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QACxD,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,IAAI,GAAG,WAAW,EAAE,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,OAAe;IACnE,OAAO,EAAE,CAAC,GAAG,kBAAkB,IAAI,cAAc,EAAE,CAAC,EAAE,GAAG,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AAClF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAmC,EACnC,IAAY;IAEZ,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// FCIS rewrite — canonical LEXICAL POSIX path helpers for the functional core.
|
|
2
|
+
// Pure + synchronous; imports nothing. These replace the ~6 near-identical (and
|
|
3
|
+
// DRIFTING) inline `joinPosix`/`basename`/`posixDirname` copies that core may not
|
|
4
|
+
// satisfy via `node:path` (forbidden in the pure core).
|
|
5
|
+
//
|
|
6
|
+
// 100% PURE + SYNCHRONOUS. No IO, no node: imports, no clock/randomness.
|
|
7
|
+
//
|
|
8
|
+
// SCOPE: these are the simple LEXICAL helpers (one-shot join / strip a segment).
|
|
9
|
+
// They are deliberately NOT a `path.resolve` equivalent — the workflow `extends:`
|
|
10
|
+
// resolver in core/workflow/parse.ts keeps its own `.`/`..`-normalizing
|
|
11
|
+
// `joinPath`/`resolvePath`/`dirname` suite, which is a distinct concept.
|
|
12
|
+
//
|
|
13
|
+
// ─── Resolved drift (the reason this module exists) ──────────────────────────
|
|
14
|
+
// • joinPosix: core/vm-guards.ts had NO empty-base / absolute-rel handling
|
|
15
|
+
// while core/actions/predicates.ts did. The canonical adopts the SUPERSET
|
|
16
|
+
// (predicates form): an empty base or an absolute `rel` returns `rel`
|
|
17
|
+
// verbatim, else the trailing separator on `base` is collapsed to exactly
|
|
18
|
+
// one. This matches every vm-guards call site identically (they only ever
|
|
19
|
+
// pass a non-empty base + a relative rel) AND the predicates behaviour the
|
|
20
|
+
// existing file_present tests pin. Pinned by tests/core/path.test.ts.
|
|
21
|
+
const SEP = '/';
|
|
22
|
+
/**
|
|
23
|
+
* Lexical POSIX join of a base path and a relative segment. An empty `base` or
|
|
24
|
+
* an absolute `rel` (leading `/`) returns `rel` verbatim; otherwise a single
|
|
25
|
+
* trailing separator on `base` is collapsed so the result has exactly one `/`
|
|
26
|
+
* at the seam. No `.`/`..` normalization, no fs access.
|
|
27
|
+
*/
|
|
28
|
+
export function joinPosix(base, rel) {
|
|
29
|
+
if (base.length === 0 || rel.startsWith(SEP))
|
|
30
|
+
return rel;
|
|
31
|
+
const trimmedBase = base.endsWith(SEP) ? base.slice(0, -1) : base;
|
|
32
|
+
return `${trimmedBase}${SEP}${rel}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Variadic POSIX join over already-clean literal segments (the `node:path.join`
|
|
36
|
+
* shape the credential host-path builders need): empty parts are dropped, the
|
|
37
|
+
* rest are joined with `/`, and any run of 2+ separators is collapsed to one.
|
|
38
|
+
* No `.`/`..` normalization.
|
|
39
|
+
*/
|
|
40
|
+
export function joinPosixParts(...parts) {
|
|
41
|
+
return parts.filter((p) => p.length > 0).join(SEP).replace(/\/{2,}/g, SEP);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Pure basename: the final path segment, with any trailing `/` or `\` stripped
|
|
45
|
+
* first. Handles BOTH separators so a workflow path copied from any platform
|
|
46
|
+
* resolves to its filename. An input with no separator returns itself.
|
|
47
|
+
*/
|
|
48
|
+
export function basename(p) {
|
|
49
|
+
const trimmed = p.replace(/[/\\]+$/, '');
|
|
50
|
+
const idx = Math.max(trimmed.lastIndexOf('/'), trimmed.lastIndexOf('\\'));
|
|
51
|
+
return idx >= 0 ? trimmed.slice(idx + 1) : trimmed;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* POSIX dirname for an absolute `/`-separated path: everything before the final
|
|
55
|
+
* `/`. The root (and any path whose only `/` is leading) collapses to `/`.
|
|
56
|
+
*/
|
|
57
|
+
export function posixDirname(p) {
|
|
58
|
+
const idx = p.lastIndexOf(SEP);
|
|
59
|
+
if (idx <= 0)
|
|
60
|
+
return SEP;
|
|
61
|
+
return p.slice(0, idx);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/core/path.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gFAAgF;AAChF,kFAAkF;AAClF,wDAAwD;AACxD,EAAE;AACF,yEAAyE;AACzE,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,wEAAwE;AACxE,yEAAyE;AACzE,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;AAE1E,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,GAAW;IACjD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClE,OAAO,GAAG,WAAW,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAG,KAAe;IAC/C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IACzB,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACzB,CAAC"}
|