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,10 @@
|
|
|
1
|
+
// FCIS rewrite — the dependency contract the orchestrator poll/dispatch loop
|
|
2
|
+
// driver (src/shell/orchestrator-loop.ts) receives from the composition root.
|
|
3
|
+
//
|
|
4
|
+
// The loop itself is an imperative shell value (the OrchestratorLoop class lives
|
|
5
|
+
// in src/shell); only the *shapes* it is wired with live here (the
|
|
6
|
+
// exported-types-live-in-src/types invariant). The shell re-exports
|
|
7
|
+
// `OrchestratorLoopDeps` so importers (the composition root) keep their original
|
|
8
|
+
// specifier.
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=orchestrator-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator-loop.js","sourceRoot":"","sources":["../../../src/types/schedule/orchestrator-loop.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,EAAE;AACF,iFAAiF;AACjF,mEAAmE;AACnE,oEAAoE;AACpE,iFAAiF;AACjF,aAAa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep-cycle.js","sourceRoot":"","sources":["../../../src/types/schedule/sleep-cycle.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,0EAA0E"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// FCIS rewrite — types for src/core/schedule/slots.ts (pure slot accounting).
|
|
2
|
+
//
|
|
3
|
+
// Pure declarations only (the exported-types-live-in-src/types invariant). The
|
|
4
|
+
// slot-accounting DECISIONS live in src/core/schedule/slots.ts, which re-exports
|
|
5
|
+
// these types so existing importers (tick.ts, the unit test) keep the original
|
|
6
|
+
// specifier.
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.js","sourceRoot":"","sources":["../../../src/types/schedule/slots.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAC/E,aAAa"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// FCIS rewrite — data types for the orchestrator scheduler reducer
|
|
2
|
+
// (src/core/schedule/tick.ts).
|
|
3
|
+
//
|
|
4
|
+
// The reducer in core is pure runtime (it produces these shapes); the shapes
|
|
5
|
+
// themselves live here so core/shell only declare values, not exported types
|
|
6
|
+
// (the exported-types-live-in-src/types invariant). The core module re-exports
|
|
7
|
+
// these so importers keep their original specifier.
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=tick.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tick.js","sourceRoot":"","sources":["../../../src/types/schedule/tick.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,+BAA+B;AAC/B,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,oDAAoD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// FCIS rewrite — types mirror for the per-issue MCP runtime (shell slice
|
|
2
|
+
// src/shell/server/mcp-runtime.ts). Declarations only; the runtime + effect
|
|
3
|
+
// interpreter live in the shell. Kept here so the "exported types belong in
|
|
4
|
+
// src/types" gate holds and the composition root + interpreter share one
|
|
5
|
+
// vocabulary. The shell modules re-export these so importers keep their
|
|
6
|
+
// `server/mcp-runtime` specifier.
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=mcp-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-runtime.js","sourceRoot":"","sources":["../../../src/types/server/mcp-runtime.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,4EAA4E;AAC5E,4EAA4E;AAC5E,yEAAyE;AACzE,wEAAwE;AACxE,kCAAkC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/types/workflow/parse.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mFAAmF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smol-symphony",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "TypeScript orchestrator that runs coding agents (Claude, Codex, OpenCode) in per-issue Gondolin microVMs over ACP.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"orchestrator",
|
|
@@ -29,26 +29,37 @@
|
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"dist/",
|
|
32
|
-
"
|
|
33
|
-
"WORKFLOW.
|
|
32
|
+
"patches/",
|
|
33
|
+
"WORKFLOW.yaml",
|
|
34
|
+
"WORKFLOW.minimal.yaml",
|
|
35
|
+
"WORKFLOW.template.yaml",
|
|
36
|
+
"assets/",
|
|
37
|
+
"prompts/",
|
|
38
|
+
"prompts-minimal/",
|
|
34
39
|
"AGENTS.md",
|
|
35
40
|
"SPEC.md",
|
|
36
41
|
"PRODUCT.md",
|
|
37
42
|
"DESIGN.md",
|
|
43
|
+
"scripts/postinstall.mjs",
|
|
38
44
|
"scripts/vm-agent.mjs",
|
|
39
45
|
"README.md",
|
|
40
46
|
"LICENSE"
|
|
41
47
|
],
|
|
42
48
|
"scripts": {
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
49
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
50
|
+
"build": "tsc -p tsconfig.build.json",
|
|
51
|
+
"start": "tsx src/shell/main.ts",
|
|
52
|
+
"symphony": "tsx src/shell/main.ts WORKFLOW.yaml",
|
|
53
|
+
"dev": "tsx watch src/shell/main.ts",
|
|
47
54
|
"typecheck": "tsc --noEmit",
|
|
48
|
-
"test": "node --test --import tsx tests/*.test.ts",
|
|
49
|
-
"prepublishOnly": "npm run typecheck && npm test && npm run build",
|
|
50
55
|
"lint": "eslint src --max-warnings 0",
|
|
51
|
-
"lint:arch": "depcruise src --ts-config tsconfig.json
|
|
56
|
+
"lint:arch": "depcruise src --ts-config tsconfig.json",
|
|
57
|
+
"check:ratio": "node scripts/check-core-ratio.mjs",
|
|
58
|
+
"check:pokes": "node scripts/check-state-pokes.mjs",
|
|
59
|
+
"check:io": "node scripts/check-shell-io.mjs",
|
|
60
|
+
"test": "node --test --import tsx $(find tests -name '*.test.ts')",
|
|
61
|
+
"verify": "npm run typecheck && npm run lint && npm run lint:arch && npm run check:ratio && npm run check:pokes && npm run check:io && npm test",
|
|
62
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build && node -e \"require('node:fs').accessSync('dist/bin/symphony.js')\"",
|
|
52
63
|
"build:image": "bash images/agents/build-image-oci.sh"
|
|
53
64
|
},
|
|
54
65
|
"dependencies": {
|
|
@@ -56,6 +67,7 @@
|
|
|
56
67
|
"@earendil-works/gondolin": "^0.12.0",
|
|
57
68
|
"chokidar": "^4.0.3",
|
|
58
69
|
"liquidjs": "^10.21.1",
|
|
70
|
+
"patch-package": "^8.0.1",
|
|
59
71
|
"yaml": "^2.6.1"
|
|
60
72
|
},
|
|
61
73
|
"devDependencies": {
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
diff --git a/node_modules/@earendil-works/gondolin/dist/src/qemu/network-stack.js b/node_modules/@earendil-works/gondolin/dist/src/qemu/network-stack.js
|
|
2
|
+
index f08a11f..b8603bd 100644
|
|
3
|
+
--- a/node_modules/@earendil-works/gondolin/dist/src/qemu/network-stack.js
|
|
4
|
+
+++ b/node_modules/@earendil-works/gondolin/dist/src/qemu/network-stack.js
|
|
5
|
+
@@ -10,6 +10,35 @@ const IP_PROTO_ICMP = 1;
|
|
6
|
+
function makeTcpNatKey(srcIP, srcPort, dstIP, dstPort) {
|
|
7
|
+
return `TCP:${srcIP}:${srcPort}:${dstIP}:${dstPort}`;
|
|
8
|
+
}
|
|
9
|
+
+// TCP sequence and acknowledgement numbers are 32 bits wide and wrap at 2^32.
|
|
10
|
+
+// We keep every stored counter (mySeq/myAck/vmSeq/vmAck) masked into [0, 2^32)
|
|
11
|
+
+// and compare them with RFC 1982 serial-number arithmetic instead of raw </>,
|
|
12
|
+
+// which break across the wrap boundary. Skipping either half re-introduces the
|
|
13
|
+
+// `writeUInt32BE` overflow crash or silent reassembly desync near 0xFFFFFFFF.
|
|
14
|
+
+/** Fold a value into the 32-bit TCP sequence space [0, 2^32). */
|
|
15
|
+
+function wrapSeq(value) {
|
|
16
|
+
+ return value >>> 0;
|
|
17
|
+
+}
|
|
18
|
+
+/**
|
|
19
|
+
+ * Signed RFC 1982 distance between two sequence numbers: > 0 when `a` is "after"
|
|
20
|
+
+ * `b`, < 0 when "before", 0 when equal. ToInt32 (`| 0`) folds the difference into
|
|
21
|
+
+ * the [-2^31, 2^31) serial window so comparisons stay correct across wrap.
|
|
22
|
+
+ */
|
|
23
|
+
+function seqDistance(a, b) {
|
|
24
|
+
+ return (a - b) | 0;
|
|
25
|
+
+}
|
|
26
|
+
+/** `a` is strictly after `b` in serial-number order. */
|
|
27
|
+
+function seqGt(a, b) {
|
|
28
|
+
+ return seqDistance(a, b) > 0;
|
|
29
|
+
+}
|
|
30
|
+
+/** `a` is strictly before `b` in serial-number order. */
|
|
31
|
+
+function seqLt(a, b) {
|
|
32
|
+
+ return seqDistance(a, b) < 0;
|
|
33
|
+
+}
|
|
34
|
+
+/** `a` is at or before `b` in serial-number order. */
|
|
35
|
+
+function seqLe(a, b) {
|
|
36
|
+
+ return seqDistance(a, b) <= 0;
|
|
37
|
+
+}
|
|
38
|
+
const HTTP_METHODS = [
|
|
39
|
+
"GET",
|
|
40
|
+
"POST",
|
|
41
|
+
@@ -503,7 +532,7 @@ export class NetworkStack extends EventEmitter {
|
|
42
|
+
vmSeq: seq,
|
|
43
|
+
vmAck: ack,
|
|
44
|
+
mySeq: Math.floor(Math.random() * 0x0fffffff),
|
|
45
|
+
- myAck: seq + 1,
|
|
46
|
+
+ myAck: wrapSeq(seq + 1),
|
|
47
|
+
peerWindow: window,
|
|
48
|
+
pendingOutbound: Buffer.alloc(0),
|
|
49
|
+
endPending: false,
|
|
50
|
+
@@ -527,14 +556,14 @@ export class NetworkStack extends EventEmitter {
|
|
51
|
+
}
|
|
52
|
+
if (!session) {
|
|
53
|
+
if (!SYN) {
|
|
54
|
+
- this.sendTCP(srcIP, srcPort, dstIP, dstPort, 0, seq + (payload.length || 1), 0x04);
|
|
55
|
+
+ this.sendTCP(srcIP, srcPort, dstIP, dstPort, 0, wrapSeq(seq + (payload.length || 1)), 0x04);
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const prevPeerWindow = session.peerWindow;
|
|
60
|
+
session.peerWindow = window;
|
|
61
|
+
let shouldDrainOutbound = false;
|
|
62
|
+
- if (ack > session.vmAck && ack <= session.mySeq) {
|
|
63
|
+
+ if (seqGt(ack, session.vmAck) && seqLe(ack, session.mySeq)) {
|
|
64
|
+
session.vmAck = ack;
|
|
65
|
+
shouldDrainOutbound = true;
|
|
66
|
+
}
|
|
67
|
+
@@ -553,12 +582,12 @@ export class NetworkStack extends EventEmitter {
|
|
68
|
+
// This matters for SSH in particular: duplicating bytes can desync the
|
|
69
|
+
// protocol and trigger errors like "Bad packet length".
|
|
70
|
+
const expectedSeq = session.myAck;
|
|
71
|
+
- if (seq > expectedSeq) {
|
|
72
|
+
+ if (seqGt(seq, expectedSeq)) {
|
|
73
|
+
// Out-of-order: re-ACK what we've already seen.
|
|
74
|
+
this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, session.mySeq, session.myAck, 0x10);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
- const skip = Math.max(0, expectedSeq - seq);
|
|
78
|
+
+ const skip = Math.max(0, seqDistance(expectedSeq, seq));
|
|
79
|
+
if (skip >= payload.length) {
|
|
80
|
+
// Pure retransmit (or segment contains only already-acked bytes)
|
|
81
|
+
this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, session.mySeq, session.myAck, 0x10);
|
|
82
|
+
@@ -568,7 +597,7 @@ export class NetworkStack extends EventEmitter {
|
|
83
|
+
}
|
|
84
|
+
const newPayload = payload.subarray(skip);
|
|
85
|
+
let sendBuffer = null;
|
|
86
|
+
- const nextAck = expectedSeq + newPayload.length;
|
|
87
|
+
+ const nextAck = wrapSeq(expectedSeq + newPayload.length);
|
|
88
|
+
if (!session.flowProtocol) {
|
|
89
|
+
session.pendingData = Buffer.concat([session.pendingData, newPayload]);
|
|
90
|
+
if (session.allowRawTcp) {
|
|
91
|
+
@@ -635,20 +664,20 @@ export class NetworkStack extends EventEmitter {
|
|
92
|
+
if (FIN) {
|
|
93
|
+
// FIN consumes one sequence number, so only accept it once the sequence
|
|
94
|
+
// space up to the FIN is fully received.
|
|
95
|
+
- const finSeq = seq + payload.length;
|
|
96
|
+
- if (finSeq > session.myAck) {
|
|
97
|
+
+ const finSeq = wrapSeq(seq + payload.length);
|
|
98
|
+
+ if (seqGt(finSeq, session.myAck)) {
|
|
99
|
+
// Out-of-order FIN: keep ACKing the last in-order byte.
|
|
100
|
+
this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, session.mySeq, session.myAck, 0x10);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
- if (finSeq < session.myAck) {
|
|
104
|
+
+ if (seqLt(finSeq, session.myAck)) {
|
|
105
|
+
// Duplicate FIN (already acked)
|
|
106
|
+
this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, session.mySeq, session.myAck, 0x10);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// finSeq === session.myAck
|
|
110
|
+
this.callbacks.onTcpClose({ key, destroy: false });
|
|
111
|
+
- session.myAck++;
|
|
112
|
+
+ session.myAck = wrapSeq(session.myAck + 1);
|
|
113
|
+
this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, session.mySeq, session.myAck, 0x10);
|
|
114
|
+
if (session.state === "CLOSED_BY_REMOTE" ||
|
|
115
|
+
session.state === "FIN_WAIT") {
|
|
116
|
+
@@ -664,8 +693,10 @@ export class NetworkStack extends EventEmitter {
|
|
117
|
+
const header = Buffer.alloc(20);
|
|
118
|
+
header.writeUInt16BE(srcPort, 0);
|
|
119
|
+
header.writeUInt16BE(dstPort, 2);
|
|
120
|
+
- header.writeUInt32BE(seq, 4);
|
|
121
|
+
- header.writeUInt32BE(ack, 8);
|
|
122
|
+
+ // Counters are kept wrapped at their mutation sites; mask again here so the
|
|
123
|
+
+ // serialization boundary can never emit an out-of-range uint32 (the crash).
|
|
124
|
+
+ header.writeUInt32BE(wrapSeq(seq), 4);
|
|
125
|
+
+ header.writeUInt32BE(wrapSeq(ack), 8);
|
|
126
|
+
header[12] = 0x50;
|
|
127
|
+
header[13] = flags;
|
|
128
|
+
header.writeUInt16BE(65535, 14);
|
|
129
|
+
@@ -925,7 +956,7 @@ export class NetworkStack extends EventEmitter {
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
- const inFlight = Math.max(0, session.mySeq - session.vmAck);
|
|
134
|
+
+ const inFlight = Math.max(0, seqDistance(session.mySeq, session.vmAck));
|
|
135
|
+
const maxInFlight = Math.max(0, Math.min(session.peerWindow, this.TCP_MAX_IN_FLIGHT_BYTES));
|
|
136
|
+
if (inFlight < maxInFlight) {
|
|
137
|
+
this.txFlowPaused.delete(key);
|
|
138
|
+
@@ -945,7 +976,7 @@ export class NetworkStack extends EventEmitter {
|
|
139
|
+
}
|
|
140
|
+
const MSS = 1460;
|
|
141
|
+
let bytesBurstThisTick = 0;
|
|
142
|
+
- let inFlight = Math.max(0, session.mySeq - session.vmAck);
|
|
143
|
+
+ let inFlight = Math.max(0, seqDistance(session.mySeq, session.vmAck));
|
|
144
|
+
const maxInFlight = Math.max(0, Math.min(session.peerWindow, this.TCP_MAX_IN_FLIGHT_BYTES));
|
|
145
|
+
while (session.pendingOutbound.length > 0 &&
|
|
146
|
+
inFlight < maxInFlight &&
|
|
147
|
+
@@ -963,7 +994,7 @@ export class NetworkStack extends EventEmitter {
|
|
148
|
+
if (!isLiveSession()) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
- session.mySeq += chunk.length;
|
|
152
|
+
+ session.mySeq = wrapSeq(session.mySeq + chunk.length);
|
|
153
|
+
inFlight += chunk.length;
|
|
154
|
+
bytesBurstThisTick += chunk.length;
|
|
155
|
+
}
|
|
156
|
+
@@ -990,7 +1021,7 @@ export class NetworkStack extends EventEmitter {
|
|
157
|
+
if (!isLiveSession()) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
- session.mySeq++;
|
|
161
|
+
+ session.mySeq = wrapSeq(session.mySeq + 1);
|
|
162
|
+
session.state = "FIN_WAIT";
|
|
163
|
+
session.endPending = false;
|
|
164
|
+
inFlight += 1;
|
|
165
|
+
@@ -1012,7 +1043,7 @@ export class NetworkStack extends EventEmitter {
|
|
166
|
+
return;
|
|
167
|
+
session.state = "ESTABLISHED";
|
|
168
|
+
this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, session.mySeq, session.myAck, 0x12);
|
|
169
|
+
- session.mySeq++;
|
|
170
|
+
+ session.mySeq = wrapSeq(session.mySeq + 1);
|
|
171
|
+
}
|
|
172
|
+
handleTcpData(message) {
|
|
173
|
+
const session = this.natTable.get(message.key);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
You are the **reflector** running symphony's *sleep cycle*. You are not
|
|
2
|
+
implementing or reviewing a product change. Your job: mine symphony's own
|
|
3
|
+
finished work for *recurring* friction in **how it runs work**, distil concrete
|
|
4
|
+
lessons, and file one harness-improvement proposal per lesson into Triage —
|
|
5
|
+
where a human operator decides whether to adopt it. Then close out this cycle.
|
|
6
|
+
|
|
7
|
+
You are a single-run, ephemeral reflection issue: you were spawned for this one
|
|
8
|
+
cycle, you run once, and you terminate in `Reflected`. There is no parked ticket
|
|
9
|
+
to re-arm — the orchestrator mints a fresh reflection issue for the next cycle.
|
|
10
|
+
|
|
11
|
+
This is a self-modifying loop: you read agent-authored transcripts and then
|
|
12
|
+
propose changes to *your own* operating instructions. The guardrails below are
|
|
13
|
+
load-bearing — follow them exactly.
|
|
14
|
+
|
|
15
|
+
**What you can read** (read-only mounts present only in this state):
|
|
16
|
+
|
|
17
|
+
- `/symphony/issues/` — every issue file across every state directory. The
|
|
18
|
+
richest signal is `/symphony/issues/Done/*.md`: each file is the full handoff
|
|
19
|
+
thread (every `symphony.transition` notes block from implementer → reviewer →
|
|
20
|
+
approval is appended to the body), so a Done file shows how the work actually
|
|
21
|
+
went, not just the final result. `Triage/`, `Cancelled/`, and the active
|
|
22
|
+
state dirs are visible too.
|
|
23
|
+
- `/symphony/logs/<id>.jsonl` — the per-issue run log: every ACP frame, adapter
|
|
24
|
+
stderr line, typed-action output, and orchestrator lifecycle event for that issue.
|
|
25
|
+
This is where stalls, turn-budget exhaustion, retries, and timeouts show up
|
|
26
|
+
in detail.
|
|
27
|
+
- Your workspace is a clone of the symphony repo, so you can read `WORKFLOW.yaml`,
|
|
28
|
+
`WORKFLOW.template.yaml`, `src/`, `images/agents/`, etc. to ground each proposal
|
|
29
|
+
in the concrete knob it would change.
|
|
30
|
+
|
|
31
|
+
If structured per-issue run summaries exist (companion issue #123), start from
|
|
32
|
+
those as an index; otherwise skim `Done/*.md` and open the
|
|
33
|
+
`/symphony/logs/<id>.jsonl` for the issues that look anomalous.
|
|
34
|
+
|
|
35
|
+
**What to look for — *recurring* patterns, not one-offs.** One bad run is
|
|
36
|
+
noise; the same failure shape across several issues is signal. For example:
|
|
37
|
+
|
|
38
|
+
- repeated `Review → Todo` rejects with the same root cause (the reviewer keeps
|
|
39
|
+
catching the same class of mistake the implementer prompt doesn't prevent);
|
|
40
|
+
- turn-budget exhaustion (a state hits `max_turns` before it can transition);
|
|
41
|
+
- stalls / timeouts (`stall_timeout_ms` / `prompt_timeout_ms` trips);
|
|
42
|
+
- rebase / merge-conflict churn on re-dispatch;
|
|
43
|
+
- credential re-login loops;
|
|
44
|
+
- acceptance-criteria misses a sharper prompt or checklist would have caught;
|
|
45
|
+
- prompt ambiguity that forced `request_human_steering`.
|
|
46
|
+
|
|
47
|
+
**For each distilled lesson, file exactly one `symphony.propose_issue` call**
|
|
48
|
+
(one per fix — never batch multiple fixes into one proposal; Triage is
|
|
49
|
+
per-item). Each proposal must:
|
|
50
|
+
|
|
51
|
+
- name a single concrete change to the **harness / operating config**: a
|
|
52
|
+
per-state `prompt_file`, a per-state `model` / `max_turns` /
|
|
53
|
+
`allowed_transitions` / `effort` / `actions`, the `gondolin` image config, an
|
|
54
|
+
acceptance criterion, or a timeout;
|
|
55
|
+
- include a **before → after** (what the config/prompt says now, what you'd
|
|
56
|
+
change it to);
|
|
57
|
+
- cite the **evidence** — the issue ids (and, where useful, the log lines or
|
|
58
|
+
Done-file quotes) that motivated it — so the operator can check the lesson
|
|
59
|
+
against the trajectories rather than trusting your summary.
|
|
60
|
+
|
|
61
|
+
**Hard guardrails — a proposal that violates any of these must NOT be filed:**
|
|
62
|
+
|
|
63
|
+
- Propose changes to the **harness only** — `WORKFLOW.yaml` /
|
|
64
|
+
`WORKFLOW.template.yaml`, per-state config (including `actions:`), the `gondolin`
|
|
65
|
+
image config, acceptance criteria, timeouts. Do **not** propose edits to product/source code under
|
|
66
|
+
`src/` as a "fix" for a trajectory; if a genuine product bug is the root
|
|
67
|
+
cause, that is an ordinary `propose_issue` for an implementer, not a harness
|
|
68
|
+
change, and you should frame it that way.
|
|
69
|
+
- Never propose anything that **weakens a quality gate.** Do not weaken or
|
|
70
|
+
remove the Review state, the `npm run typecheck` / `npm test` /
|
|
71
|
+
`npm run lint:arch` / `npm run lint` gates, or the Triage human-approval gate
|
|
72
|
+
itself. The whole point of this loop is that a human stays in it; proposals
|
|
73
|
+
that would let the loop dispatch its own changes without review are
|
|
74
|
+
forbidden, even if the trajectories seem to "justify" them.
|
|
75
|
+
- One fix per proposal, each with cited evidence. No proposal without issue ids.
|
|
76
|
+
|
|
77
|
+
When you have filed your proposals — or concluded there is no recurring pattern
|
|
78
|
+
worth acting on this cycle — hand off by terminating in `Reflected`:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
symphony.transition({
|
|
82
|
+
to_state: "Reflected",
|
|
83
|
+
notes: "<one-paragraph log of this cycle: how many issues you reviewed, the
|
|
84
|
+
patterns you found, and the proposal titles you filed (or 'no
|
|
85
|
+
actionable pattern this cycle')>"
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Then end your turn; do not call any further tools. This issue is archived in the
|
|
90
|
+
`Reflected` column as a per-cycle audit trail; the orchestrator mints a fresh
|
|
91
|
+
reflection issue for the next cycle.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
You are the **reviewer**. The implementer has committed work to the per-issue
|
|
2
|
+
branch (`agent/{{ issue.identifier }}`) and handed off. Their summary is in
|
|
3
|
+
the issue description above. Your job: decide whether the work is correct and
|
|
4
|
+
either approve (→ Done) or send it back (→ Todo) with specific findings.
|
|
5
|
+
|
|
6
|
+
1. Read the implementer's notes in the issue description carefully — title,
|
|
7
|
+
summary, files claimed touched. (Follow-ups belong in `propose_issue`,
|
|
8
|
+
not the notes; if you see a "Follow-ups not done" section in the notes,
|
|
9
|
+
reject and ask the implementer to file each item as a separate
|
|
10
|
+
`propose_issue` call instead.)
|
|
11
|
+
2. Inspect the diff against the freshly-fetched base. The host fetched
|
|
12
|
+
`origin/main` (or whatever base branch `SYMPHONY_BASE_BRANCH` names — `main`
|
|
13
|
+
is the default here) into this workspace before the dispatch, and the
|
|
14
|
+
implementer rebased onto it, so `origin/main` is the true base:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
git log --oneline origin/main..HEAD
|
|
18
|
+
git diff origin/main..HEAD
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Diff against `origin/main`, **not** the local `main` ref: your workspace's
|
|
22
|
+
local `main` is frozen at clone time and goes **stale** as sibling PRs merge
|
|
23
|
+
— `origin/main` advances but local `main` does not. Diffing `main..HEAD` then
|
|
24
|
+
surfaces commits already on base as if they were the implementer's change,
|
|
25
|
+
and can make a correctly-based branch look like it *reverts* recently-landed
|
|
26
|
+
work. (Local-only mode — no `origin` remote — has no such drift, so `main`
|
|
27
|
+
stays the correct base there.) If `HEAD`'s merge-base is behind `origin/main`
|
|
28
|
+
(e.g. `git merge-tree --write-tree HEAD origin/main` reports conflicts),
|
|
29
|
+
reject to `Todo` asking the implementer to rebase onto `origin/main` — don't
|
|
30
|
+
agonize over an apparent revert.
|
|
31
|
+
|
|
32
|
+
Look at each file the implementer claimed to touch. Spot-check tests and
|
|
33
|
+
typecheck pass:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
npm run typecheck
|
|
37
|
+
npm test
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
3. Placement check — is the change on the right side of the seam?
|
|
41
|
+
|
|
42
|
+
The orchestrator (`src/agent/runner.ts`, `src/mcp.ts`, `src/orchestrator.ts`)
|
|
43
|
+
owns the state machine and tracker. Repo-local glue (`git push`, `gh pr
|
|
44
|
+
create`, rescuing artifacts) lives in a state's typed `actions:` block
|
|
45
|
+
(or a `run_in_vm` action for arbitrary guest commands). Reject when the
|
|
46
|
+
diff crosses that line:
|
|
47
|
+
|
|
48
|
+
- An action implements a new state transition, or mutates the tracker
|
|
49
|
+
filesystem the orchestrator owns (e.g. `mv issues/<state>/<id>.md
|
|
50
|
+
issues/<other-state>/<id>.md`).
|
|
51
|
+
- An action mutates runtime state the orchestrator committed earlier (e.g.
|
|
52
|
+
undoing a cleanup flag) and the runner now has to re-detect what the
|
|
53
|
+
action did via a post-action scan.
|
|
54
|
+
- A new `SYMPHONY_*` env var is added so an action can reach into
|
|
55
|
+
orchestrator-owned state. The contract is growing because the logic is
|
|
56
|
+
on the wrong side; surface it as a typed call in the runner/MCP layer
|
|
57
|
+
instead.
|
|
58
|
+
|
|
59
|
+
If any of the above fires, reject with a pointer to the right home
|
|
60
|
+
(runner, MCP tool, or orchestrator). Action-only diffs that stay within
|
|
61
|
+
repo-local glue (push/PR/format-patch) are fine — this check is
|
|
62
|
+
about state-machine logic leaking into a state's `actions:`.
|
|
63
|
+
|
|
64
|
+
4. Decide:
|
|
65
|
+
|
|
66
|
+
- **Approve**: the change is correct, tests pass, no blocking issues. Call
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
symphony.transition({
|
|
70
|
+
to_state: "Done",
|
|
71
|
+
notes: "<approval rationale; this becomes the PR body>"
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Your notes are appended to the issue body and feed straight into the PR
|
|
76
|
+
description the host opens against the base branch. Be specific about
|
|
77
|
+
what you verified.
|
|
78
|
+
|
|
79
|
+
- **Reject**: the change is wrong, incomplete, or has issues that need
|
|
80
|
+
rework. Call
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
symphony.transition({
|
|
84
|
+
to_state: "Todo",
|
|
85
|
+
notes: "<specific findings: file paths, line numbers, what's wrong,
|
|
86
|
+
what needs to change. Be concrete — the implementer will see
|
|
87
|
+
this as their next prompt.>"
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The issue goes back to Todo with your findings appended. The same
|
|
92
|
+
workspace and `agent/{{ issue.identifier }}` branch survive the round
|
|
93
|
+
trip, so the next implementer dispatch sees both your notes and their
|
|
94
|
+
prior commits.
|
|
95
|
+
|
|
96
|
+
Either way, end your turn after the transition call. Do not call any
|
|
97
|
+
further tools.
|
package/prompts/Todo.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
You are the **implementer**. Your job: turn the issue into a working change on
|
|
2
|
+
the per-issue branch, then hand off to the reviewer.
|
|
3
|
+
|
|
4
|
+
1. **Rebase onto a fresh base first.** Symphony has just fetched
|
|
5
|
+
`origin/main` into your workspace (or whatever base branch
|
|
6
|
+
`SYMPHONY_BASE_BRANCH` names — `main` is the default and matches this
|
|
7
|
+
project). The very first thing to do is rebase your branch onto it:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
git rebase origin/main
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- On a fresh issue this is a no-op (you're already on top of base).
|
|
14
|
+
- On a re-dispatch where base has advanced this picks up the new commits.
|
|
15
|
+
- If `git rebase` reports conflicts, **resolve them in-tree as part of
|
|
16
|
+
this turn** (reconcile your change with what landed on base), `git add`
|
|
17
|
+
the resolved files, and `git rebase --continue` (repeat per replayed
|
|
18
|
+
commit). Then proceed to step 2. There is no separate conflict state
|
|
19
|
+
to route to — handling the conflict is part of normal implementation
|
|
20
|
+
work, just like any other rebase you'd do on your own machine.
|
|
21
|
+
2. Read enough of the codebase to understand the change you need to make.
|
|
22
|
+
3. Decide where the change belongs before writing it. The orchestrator
|
|
23
|
+
(`src/agent/runner.ts`, `src/mcp.ts`, `src/orchestrator.ts`) owns the
|
|
24
|
+
state machine and the tracker. Repo-local glue (`git push`, `gh pr
|
|
25
|
+
create`, rescuing artifacts) lives in a state's typed `actions:` block
|
|
26
|
+
(or, for arbitrary guest commands, a `run_in_vm` action); workspace
|
|
27
|
+
setup is the orchestrator's `setupWorkspaceDir`, and per-VM tooling is
|
|
28
|
+
baked into the agent image. State-machine behavior (new transitions,
|
|
29
|
+
anything that mutates tracker files or runtime entry state) belongs in
|
|
30
|
+
the orchestrator with typed APIs and tests — not in an action. If you
|
|
31
|
+
find yourself adding a `SYMPHONY_*` env var so an action can reach into
|
|
32
|
+
orchestrator state, or writing an action that the runner then has to
|
|
33
|
+
re-detect via a post-action scan, that is the signal you are on the wrong
|
|
34
|
+
side of the seam: stop and put the logic in the runner/MCP layer
|
|
35
|
+
instead. The issue body may sketch a shell-shaped solution; treat that
|
|
36
|
+
as one option, not a directive.
|
|
37
|
+
4. Make the smallest correct change for the issue's stated scope, and keep it
|
|
38
|
+
focused. If you notice work beyond what the issue states, call
|
|
39
|
+
`symphony.propose_issue` for it rather than expanding this change to swallow
|
|
40
|
+
follow-up work. Add or update tests where the change is testable. Before
|
|
41
|
+
handing off, run `npm run typecheck`, `npm test`, `npm run lint:arch`, and
|
|
42
|
+
`npm run lint` — all must pass. `node_modules` may be absent on dispatch;
|
|
43
|
+
if you `npm install` to run those gates, the image's npm can rewrite
|
|
44
|
+
`package-lock.json` (e.g. bumping the root package `engines.node` from
|
|
45
|
+
`>=20` to `>=23.6.0`). That drift is unrelated to your change — before
|
|
46
|
+
handing off, run `git status` and `git checkout -- package-lock.json` to
|
|
47
|
+
drop any incidental lockfile churn you did not intend. The handoff tree
|
|
48
|
+
must be clean.
|
|
49
|
+
**Do NOT edit the `--max-warnings` ratchet in `package.json`** — leave that line
|
|
50
|
+
exactly as-is. It is tightened in one pass at the end of the burn-down. Your change
|
|
51
|
+
only needs to keep `npm run lint` green at the *current* ratchet (it will, as long
|
|
52
|
+
as you reduce or hold the warning count). Lowering it yourself just collides with
|
|
53
|
+
every other in-flight issue's `package.json` and forces manual conflict resolution.
|
|
54
|
+
5. Commit your work to the per-issue branch with a short message.
|
|
55
|
+
6. **Re-read the issue's Acceptance criteria and confirm your diff satisfies
|
|
56
|
+
every bullet before handing off.** An acceptance bullet you've left unmet —
|
|
57
|
+
because closing it would touch a path outside the stated `allowed_paths`, or
|
|
58
|
+
because you'd rather defer it to a `symphony.propose_issue` follow-up — means
|
|
59
|
+
the issue is **not done**. `allowed_paths` describes where the change
|
|
60
|
+
*normally* lands; it is not license to hand off an unmet acceptance bullet.
|
|
61
|
+
Satisfy the criterion (touch the extra path and say why in your notes — the
|
|
62
|
+
way you would for a required `CHANGELOG.md` edit), and do **not**
|
|
63
|
+
`symphony.propose_issue` work the acceptance criteria require of *this*
|
|
64
|
+
issue. If a criterion genuinely cannot be met within scope (it conflicts
|
|
65
|
+
with another constraint, or needs a decision only a human can make), call
|
|
66
|
+
`symphony.request_human_steering` rather than handing off a partial change
|
|
67
|
+
with the gap described in the notes. (If satisfying a bullet here means new
|
|
68
|
+
edits, re-run the gates from step 4 and amend your commit before handing
|
|
69
|
+
off.)
|
|
70
|
+
7. Hand off to the reviewer by calling:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
symphony.transition({
|
|
74
|
+
to_state: "Review",
|
|
75
|
+
notes: "# <imperative-voice title, ≤72 chars>\n\n<one- to three-paragraph
|
|
76
|
+
summary of what you changed, why, files touched, and tests added>"
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The notes describe **this change**. Out-of-scope items you noticed —
|
|
81
|
+
unrelated bugs, refactors, follow-ups, a future ticket someone should
|
|
82
|
+
size — go through `symphony.propose_issue` (see the shared section below).
|
|
83
|
+
Do not park them in a "Follow-ups not done" section in the notes; that
|
|
84
|
+
surface dies in `Done/<id>.md` and no agent ever sees it again.
|
|
85
|
+
|
|
86
|
+
Don't include a verification section restating that
|
|
87
|
+
`npm run typecheck` / `npm test` / `npm run build` passed — that's an
|
|
88
|
+
AGENTS.md requirement and the reviewer re-runs them. Mention test count
|
|
89
|
+
or extra commands only when something is atypical (test count dropped,
|
|
90
|
+
you ran a smoke against a live service, etc.).
|
|
91
|
+
|
|
92
|
+
The notes block is appended to the issue body **before** the file moves to
|
|
93
|
+
`Review/`, so the reviewer sees it as part of `issue.description` on the
|
|
94
|
+
next dispatch. Write it as if it were the PR body — because if the reviewer
|
|
95
|
+
approves, the entire issue body (including this block) becomes the PR
|
|
96
|
+
description. Then end your turn; do not call any further tools.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
If you genuinely cannot proceed — ambiguous requirements, missing context that
|
|
2
|
+
only a human can supply, a design decision that needs human input — call
|
|
3
|
+
`symphony.request_human_steering({ question, context })` instead of guessing.
|
|
4
|
+
Your turn will end immediately and the human's response will arrive as your
|
|
5
|
+
next prompt.
|
|
6
|
+
|
|
7
|
+
Steering tips:
|
|
8
|
+
|
|
9
|
+
- The operator's dashboard already shows the original issue title and body
|
|
10
|
+
alongside your question. Do **not** restate or paraphrase the issue body in
|
|
11
|
+
`question`; ask the specific thing you need answered.
|
|
12
|
+
- Use `context` for facts the operator wouldn't otherwise see: what you've
|
|
13
|
+
inspected, what you've already tried, what constraint is forcing the
|
|
14
|
+
question.
|
|
15
|
+
|
|
16
|
+
If during your work you notice something worth fixing that is **out of scope**
|
|
17
|
+
for your current task — an unrelated bug, a follow-up the operator should
|
|
18
|
+
size, a refactor a future agent could pick up — call
|
|
19
|
+
`symphony.propose_issue({ title, description?, labels?, priority? })`. The
|
|
20
|
+
proposal lands in a Triage state directory that the orchestrator does **not**
|
|
21
|
+
dispatch; the operator approves or discards it from the dashboard. Your
|
|
22
|
+
current issue is automatically recorded as the proposal's parent — do not
|
|
23
|
+
paste it into the body. Use this instead of grafting unrelated changes onto
|
|
24
|
+
your current task; keep your branch focused.
|
|
25
|
+
|
|
26
|
+
File **one `propose_issue` call per follow-up**, not a batched call with
|
|
27
|
+
multiple items in one body. Triage is per-item triage; the operator's
|
|
28
|
+
approve/discard verb is per-issue, so a batched proposal forces an
|
|
29
|
+
all-or-nothing decision and loses the individual sizing/priority each
|
|
30
|
+
follow-up deserves. The "Follow-ups not done" pattern of writing a bulleted
|
|
31
|
+
list in the handoff notes is the wrong surface — those notes ride into the
|
|
32
|
+
PR and then die in `Done/<id>.md`; only `propose_issue` puts the items in
|
|
33
|
+
front of the operator on the dashboard.
|
|
34
|
+
|
|
35
|
+
{% if attempt -%}
|
|
36
|
+
This is continuation/retry attempt {{ attempt }}. Inspect the workspace before
|
|
37
|
+
making new edits; your previous run may have left commits on the branch. Check
|
|
38
|
+
`git log agent/{{ issue.identifier }}` to see what's there. If the work is
|
|
39
|
+
already complete in the current state, call `symphony.transition` with the
|
|
40
|
+
appropriate next state and notes summarising what was already done, then stop.
|
|
41
|
+
{%- endif %}
|