tumwater 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -108
- package/dist/build-info.json +2 -2
- package/dist/src/agent/agent-args.js +24 -0
- package/dist/src/agent/agent-backend.js +2 -2
- package/dist/src/agent/backend-traits.js +60 -0
- package/dist/src/agent/claude/claude-account.js +61 -8
- package/dist/src/agent/claude/claude-args.js +12 -15
- package/dist/src/agent/claude/claude-backend.js +51 -41
- package/dist/src/agent/claude/claude-env.js +7 -3
- package/dist/src/agent/claude/claude-stream.js +7 -16
- package/dist/src/agent/image-input.js +107 -0
- package/dist/src/agent/notes-shim.js +41 -0
- package/dist/src/agent/opencode/opencode-args.js +61 -0
- package/dist/src/agent/opencode/opencode-backend.js +255 -0
- package/dist/src/agent/opencode/opencode-catalog.js +184 -0
- package/dist/src/agent/opencode/opencode-config.js +188 -0
- package/dist/src/agent/opencode/opencode-env.js +36 -0
- package/dist/src/agent/opencode/opencode-session-id.js +37 -0
- package/dist/src/agent/opencode/opencode-stream.js +278 -0
- package/dist/src/agent/role-notes-write.js +16 -32
- package/dist/src/agent/run-agent.js +95 -18
- package/dist/src/agent/session-ledger.js +57 -1
- package/dist/src/backlog/backlog-archive.js +296 -0
- package/dist/src/backlog/backlog-cli.js +573 -0
- package/dist/src/backlog/backlog-commit.js +31 -0
- package/dist/src/backlog/backlog-eligibility.js +357 -33
- package/dist/src/backlog/backlog-md.js +98 -18
- package/dist/src/backlog/backlog-render.js +62 -11
- package/dist/src/backlog/backlog-structure.js +261 -58
- package/dist/src/backlog/backlog-write.js +197 -319
- package/dist/src/backlog/backlog.js +113 -16
- package/dist/src/backlog/question-answer.js +339 -0
- package/dist/src/baseline/main-baseline.js +75 -88
- package/dist/src/baseline/main-red.js +38 -30
- package/dist/src/brief/brief-edit.js +43 -0
- package/dist/src/{brief.js → brief/brief.js} +66 -10
- package/dist/src/budget/budget.js +32 -15
- package/dist/src/budget/fallback-breaker.js +8 -7
- package/dist/src/build/build-check-detect.js +8 -7
- package/dist/src/build/build-check-events.js +68 -22
- package/dist/src/build/build-check-report.js +22 -23
- package/dist/src/build/build-check-scoped.js +51 -62
- package/dist/src/build/build-check.js +15 -14
- package/dist/src/build/build-info.js +2 -1
- package/dist/src/build/build-stage.js +23 -22
- package/dist/src/build/dep-install.js +22 -21
- package/dist/src/build/host-sleep.js +1 -1
- package/dist/src/change/change-data.js +25 -14
- package/dist/src/change/change-render.js +11 -10
- package/dist/src/cli/brief-command.js +58 -0
- package/dist/src/cli/cli-args.js +25 -5
- package/dist/src/cli/cli-command-args.js +46 -14
- package/dist/src/cli/cli-editor.js +64 -0
- package/dist/src/cli/cli-flag-specs.js +54 -16
- package/dist/src/cli/cli-marker-commands.js +13 -10
- package/dist/src/cli/cli-output.js +9 -0
- package/dist/src/cli/cli-query-commands.js +458 -49
- package/dist/src/cli/cli-repo-gate.js +1 -1
- package/dist/src/cli/cli-run.js +208 -59
- package/dist/src/cli/completion.js +207 -0
- package/dist/src/cli/config-commands.js +14 -11
- package/dist/src/cli/help.js +305 -110
- package/dist/src/cli/log-commands.js +127 -21
- package/dist/src/cli/notify-command.js +33 -18
- package/dist/src/cli/question-commands.js +29 -224
- package/dist/src/cli.js +121 -40
- package/dist/src/collections.js +66 -16
- package/dist/src/concurrency/check-permit.js +16 -17
- package/dist/src/concurrency/lock.js +6 -5
- package/dist/src/concurrency/provider-lease.js +69 -0
- package/dist/src/concurrency/semaphore.js +258 -36
- package/dist/src/config/config-aliases.js +106 -0
- package/dist/src/config/config-editable-keys.js +3 -3
- package/dist/src/config/config-fallbacks.js +379 -0
- package/dist/src/config/config-field-checks.js +19 -10
- package/dist/src/config/config-keys.js +160 -0
- package/dist/src/config/config-live.js +64 -12
- package/dist/src/config/config-schema.js +34 -22
- package/dist/src/config/config-validation.js +132 -48
- package/dist/src/config/config-views.js +119 -337
- package/dist/src/config/config-write.js +138 -177
- package/dist/src/config/config.js +60 -49
- package/dist/src/config/model-selector.js +28 -2
- package/dist/src/doctor/doctor-backlog.js +546 -49
- package/dist/src/doctor/doctor-checks.js +534 -56
- package/dist/src/doctor/doctor-holds.js +193 -53
- package/dist/src/doctor/doctor-install.js +30 -0
- package/dist/src/doctor/doctor-launch-services.js +2 -2
- package/dist/src/doctor/doctor-model-checks.js +549 -157
- package/dist/src/doctor/doctor-notify.js +27 -0
- package/dist/src/doctor/doctor-orphans.js +10 -9
- package/dist/src/doctor/doctor-render.js +36 -9
- package/dist/src/doctor/doctor.js +80 -22
- package/dist/src/doctor/image-probe.js +244 -0
- package/dist/src/doctor/probe.js +64 -0
- package/dist/src/events/event-format.js +226 -102
- package/dist/src/events/event-labels.js +116 -0
- package/dist/src/events/event-legacy.js +140 -0
- package/dist/src/events/event-read.js +58 -22
- package/dist/src/events/event-window.js +27 -7
- package/dist/src/events/events.js +18 -14
- package/dist/src/events/notify.js +137 -38
- package/dist/src/failure/failure-cluster.js +12 -9
- package/dist/src/failure/failure-data.js +96 -48
- package/dist/src/failure/failure-render.js +69 -58
- package/dist/src/failure/failure-state-change.js +33 -26
- package/dist/src/failure/time-spend.js +79 -59
- package/dist/src/files/file-queue.js +16 -4
- package/dist/src/files/files.js +18 -6
- package/dist/src/files/json-object.js +18 -3
- package/dist/src/files/tail.js +1 -1
- package/dist/src/gates/bootstrap-gates.js +5 -4
- package/dist/src/gates/budget-gates.js +250 -34
- package/dist/src/gates/disk-gate.js +18 -18
- package/dist/src/gates/gate-polls.js +117 -69
- package/dist/src/gates/maintenance-quota.js +29 -29
- package/dist/src/gates/pause-gates.js +11 -11
- package/dist/src/gates/readiness.js +2 -1
- package/dist/src/gates/role-cap-gates.js +16 -21
- package/dist/src/gates/startup-gate.js +75 -31
- package/dist/src/gates/streak-gate.js +18 -16
- package/dist/src/git/commit-message.js +12 -5
- package/dist/src/git/git-diff.js +16 -16
- package/dist/src/git/git-run.js +8 -8
- package/dist/src/git/git.js +86 -55
- package/dist/src/git/slots-state.js +14 -5
- package/dist/src/git/worktree-pool.js +25 -18
- package/dist/src/git/worktree-use.js +15 -14
- package/dist/src/git/worktree.js +18 -18
- package/dist/src/gui/gui-args.js +10 -14
- package/dist/src/gui/gui-backlog-commands.js +273 -0
- package/dist/src/gui/gui-command.js +1 -1
- package/dist/src/gui/gui-config-commands.js +440 -0
- package/dist/src/gui/gui-endpoint-commands.js +16 -669
- package/dist/src/gui/gui-endpoint-common.js +49 -0
- package/dist/src/gui/gui-endpoints.js +116 -56
- package/dist/src/gui/gui-operator-commands.js +145 -0
- package/dist/src/gui/gui-prompt-commands.js +234 -0
- package/dist/src/gui/gui-server.js +28 -8
- package/dist/src/gui/gui-team-commands.js +164 -0
- package/dist/src/gui/http-body.js +17 -1
- package/dist/src/history/history-data.js +194 -98
- package/dist/src/history/history-render.js +76 -0
- package/dist/src/history/history.js +37 -58
- package/dist/src/inbox/inbox-attachments.js +75 -14
- package/dist/src/inbox/inbox-cancel.js +7 -5
- package/dist/src/inbox/inbox-edit.js +1 -1
- package/dist/src/inbox/inbox-submit.js +44 -4
- package/dist/src/inbox/inbox-top.js +83 -0
- package/dist/src/inbox/inbox.js +8 -2
- package/dist/src/inbox/pending-prompt.js +1 -1
- package/dist/src/inbox/prompt-commands.js +170 -80
- package/dist/src/init/init-templates.js +16 -14
- package/dist/src/init/init.js +12 -11
- package/dist/src/loop/leftover.js +28 -27
- package/dist/src/loop/loop-fallback.js +2 -2
- package/dist/src/loop/loop-pi.js +106 -52
- package/dist/src/loop/loop-recovery.js +15 -15
- package/dist/src/loop/loop-state.js +139 -13
- package/dist/src/loop/loop-tick.js +194 -86
- package/dist/src/loop/loop.js +72 -36
- package/dist/src/loop/model-fallback.js +3 -2
- package/dist/src/loop/revision.js +16 -7
- package/dist/src/merge/backlog-conflicts.js +155 -0
- package/dist/src/{landing/landing-batch.js → merge/merge-batch.js} +90 -89
- package/dist/src/{landing/landing-check-failures.js → merge/merge-check-failures.js} +87 -41
- package/dist/src/{landing/landing-core.js → merge/merge-core.js} +119 -95
- package/dist/src/{landing/landing-diff.js → merge/merge-diff.js} +1 -1
- package/dist/src/merge/merge-drain.js +212 -0
- package/dist/src/{landing/landing-git.js → merge/merge-git.js} +94 -21
- package/dist/src/merge/merge-pipeline.js +99 -0
- package/dist/src/{landing/landing-questions.js → merge/merge-questions.js} +9 -6
- package/dist/src/merge/merge-queue-render.js +75 -0
- package/dist/src/{landing/landing-queue.js → merge/merge-queue.js} +95 -36
- package/dist/src/merge/merge-slot.js +340 -0
- package/dist/src/{landing/landing-stack.js → merge/merge-stack.js} +66 -62
- package/dist/src/{landing/landing-merge.js → merge/merge-to-main.js} +72 -62
- package/dist/src/merge/merge-verify.js +212 -0
- package/dist/src/notes-cli.js +97 -0
- package/dist/src/operator/operator-commands.js +154 -47
- package/dist/src/operator/operator-intent.js +87 -49
- package/dist/src/operator/operator-requests.js +52 -52
- package/dist/src/operator/retire.js +62 -27
- package/dist/src/operator/revert.js +71 -0
- package/dist/src/orchestrator/orchestrator-launch.js +74 -14
- package/dist/src/orchestrator/orchestrator-scheduling.js +129 -44
- package/dist/src/orchestrator/orchestrator.js +158 -100
- package/dist/src/orchestrator/retention.js +29 -12
- package/dist/src/orchestrator/startup-migration-steps.js +51 -0
- package/dist/src/orchestrator/startup-migrations.js +40 -0
- package/dist/src/paths.js +128 -37
- package/dist/src/pi/pi-args.js +26 -3
- package/dist/src/pi/pi-backend.js +15 -23
- package/dist/src/pi/pi-bin.js +18 -12
- package/dist/src/pi/pi-event-line.js +17 -1
- package/dist/src/pi/pi-failure.js +87 -0
- package/dist/src/pi/pi-models.js +126 -38
- package/dist/src/pi/pi-run-result.js +1 -1
- package/dist/src/pi/pi-settings.js +86 -0
- package/dist/src/pi/pi-stream.js +131 -107
- package/dist/src/pi/pi-watchdogs.js +47 -43
- package/dist/src/pi-extension/bounded-output.js +20 -5
- package/dist/src/pi-extension/context-budget.js +3 -1
- package/dist/src/pi-extension/context-shake.js +54 -21
- package/dist/src/pi-extension/context-window.js +37 -0
- package/dist/src/pi-extension/full-output.js +2 -2
- package/dist/src/pi-extension/strip-thinking.js +80 -0
- package/dist/src/pi-extension/trim-system-prompt.js +38 -0
- package/dist/src/process/launch-services.js +11 -10
- package/dist/src/process/process-table.js +1 -1
- package/dist/src/process/process.js +7 -7
- package/dist/src/process/run-marker.js +29 -6
- package/dist/src/process/supervisor.js +47 -25
- package/dist/src/prompt/dialect.js +30 -10
- package/dist/src/prompt/gate-prompts.js +170 -67
- package/dist/src/prompt/principles.js +1 -0
- package/dist/src/prompt/prompt-followup.js +35 -20
- package/dist/src/prompt/prompt.js +249 -91
- package/dist/src/redeploy/redeploy-policy.js +10 -10
- package/dist/src/redeploy/redeploy.js +6 -4
- package/dist/src/redeploy/redeployer.js +63 -55
- package/dist/src/redeploy/self-reload.js +1 -1
- package/dist/src/report/report-data.js +264 -255
- package/dist/src/report/report-fold.js +353 -0
- package/dist/src/report/report-render.js +270 -33
- package/dist/src/request-timeouts.js +1 -1
- package/dist/src/review/known-flakes.js +34 -14
- package/dist/src/review/protected-edits.js +33 -0
- package/dist/src/review/review-followup.js +16 -4
- package/dist/src/review/review-precheck.js +14 -13
- package/dist/src/review/review-verdict.js +14 -0
- package/dist/src/review/review.js +81 -39
- package/dist/src/review/secret-leaks.js +127 -0
- package/dist/src/review/suite-rerun.js +4 -3
- package/dist/src/roles/legacy-role-ids.js +21 -0
- package/dist/src/roles/legacy-role-migration.js +62 -0
- package/dist/src/roles/loop-ids.js +19 -2
- package/dist/src/roles/role-catalog.js +125 -135
- package/dist/src/roles/role-guidance.js +64 -31
- package/dist/src/roles/role-labels.js +10 -0
- package/dist/src/roles/role-render.js +194 -18
- package/dist/src/roles/role-view.js +216 -17
- package/dist/src/roles/roles.js +18 -15
- package/dist/src/scheduling/backoff.js +29 -19
- package/dist/src/scheduling/claims.js +25 -9
- package/dist/src/scheduling/once-round.js +11 -11
- package/dist/src/scheduling/quiet-hours.js +25 -32
- package/dist/src/scheduling/scheduling.js +43 -24
- package/dist/src/scheduling/{work-landed-cache.js → work-merged-cache.js} +14 -14
- package/dist/src/status/status-budget.js +115 -0
- package/dist/src/status/status-data.js +77 -184
- package/dist/src/status/status-inbox.js +47 -0
- package/dist/src/status/status-install.js +27 -0
- package/dist/src/status/status-polls.js +68 -33
- package/dist/src/status/status-roles.js +105 -0
- package/dist/src/{fleet → team}/error-storm.js +10 -10
- package/dist/src/{fleet → team}/failure-spread.js +8 -8
- package/dist/src/{fleet → team}/orchestrator-info.js +86 -18
- package/dist/src/{fleet → team}/reclaim.js +5 -4
- package/dist/src/{fleet/fleet-hold.js → team/team-hold.js} +55 -21
- package/dist/src/{fleet/fleet-polls.js → team/team-polls.js} +116 -65
- package/dist/src/{fleet/fleet-state.js → team/team-state.js} +62 -37
- package/dist/src/text/datetime.js +42 -2
- package/dist/src/text/format.js +10 -1
- package/dist/src/text/markdown.js +1 -1
- package/dist/src/text/phrases.js +35 -34
- package/dist/src/text/suggest.js +3 -2
- package/dist/src/text/text.js +2 -2
- package/dist/src/tick/qa-coverage.js +2 -1
- package/dist/src/tick/stage-check.js +147 -26
- package/dist/src/tick/telemetry-digest.js +10 -9
- package/dist/src/tick/tick-apply.js +101 -72
- package/dist/src/tick/tick-detail-data.js +32 -18
- package/dist/src/tick/tick-detail.js +62 -21
- package/dist/src/tick/tick-finalize.js +29 -22
- package/dist/src/tick/tick-outcome.js +2 -1
- package/dist/src/tick/tick-prompt.js +94 -26
- package/dist/src/tick/tick-resume.js +29 -13
- package/dist/src/tick/tick-stage.js +91 -47
- package/dist/src/tick/tick-timing.js +60 -59
- package/dist/src/tick/tick-usage.js +53 -23
- package/dist/src/tick/tick-verdict.js +76 -10
- package/dist/src/ui/badges.js +118 -67
- package/dist/src/ui/gui/gui-client-boot.js +209 -30
- package/dist/src/ui/gui/gui-client-composer.js +102 -23
- package/dist/src/ui/gui/gui-client-drawer.js +330 -75
- package/dist/src/ui/gui/gui-client-history.js +96 -38
- package/dist/src/ui/gui/gui-client-labels.js +24 -0
- package/dist/src/ui/gui/gui-client-loops.js +94 -52
- package/dist/src/ui/gui/gui-client-markdown.js +1 -0
- package/dist/src/ui/gui/gui-client-model.js +63 -43
- package/dist/src/ui/gui/gui-client-operator.js +129 -39
- package/dist/src/ui/gui/gui-client-pending.js +36 -32
- package/dist/src/ui/gui/gui-client-report.js +339 -46
- package/dist/src/ui/gui/gui-client-settings.js +148 -14
- package/dist/src/ui/gui/gui-client-sound.js +2 -1
- package/dist/src/ui/gui/{gui-client-fleet.js → gui-client-team.js} +196 -72
- package/dist/src/ui/gui/gui-client.js +26 -20
- package/dist/src/ui/gui/gui-page.js +19 -19
- package/dist/src/ui/gui/gui-styles.js +12 -4
- package/dist/src/ui/progress-data.js +5 -3
- package/dist/src/ui/status-model.js +184 -122
- package/dist/src/ui/status-payload.js +119 -32
- package/dist/src/ui/status-render.js +122 -52
- package/dist/src/ui/team-alerts.js +341 -0
- package/dist/src/ui/tick-progress-model.js +14 -14
- package/dist/src/ui/tone.js +11 -8
- package/dist/src/ui/transcript-tail.js +1 -0
- package/dist/src/ui/transcript.js +23 -16
- package/dist/src/ui/tui/tui-app.js +1 -0
- package/dist/src/ui/tui/tui-backlog.js +85 -11
- package/dist/src/ui/tui/tui-editor-answer.js +97 -0
- package/dist/src/ui/tui/tui-editor-attach.js +107 -0
- package/dist/src/ui/tui/tui-editor-brief.js +107 -0
- package/dist/src/ui/tui/tui-editor-budget.js +155 -0
- package/dist/src/ui/tui/tui-editor-ctx.js +1 -0
- package/dist/src/ui/tui/tui-editor-entry.js +230 -0
- package/dist/src/ui/tui/tui-editor-interval.js +122 -0
- package/dist/src/ui/tui/tui-editor-notes.js +114 -0
- package/dist/src/ui/tui/tui-editor-pause.js +266 -0
- package/dist/src/ui/tui/tui-editor-prompt.js +95 -0
- package/dist/src/ui/tui/tui-editor-queued.js +98 -0
- package/dist/src/ui/tui/tui-editor-quiet.js +106 -0
- package/dist/src/ui/tui/tui-editor-retire.js +83 -0
- package/dist/src/ui/tui/tui-editor-search.js +73 -0
- package/dist/src/ui/tui/tui-editor-session.js +97 -0
- package/dist/src/ui/tui/tui-editors.js +152 -0
- package/dist/src/ui/tui/tui-frame.js +67 -55
- package/dist/src/ui/tui/tui-history.js +12 -7
- package/dist/src/ui/tui/tui-input.js +49 -44
- package/dist/src/ui/tui/tui-keymap.js +1 -0
- package/dist/src/ui/tui/tui-keys.js +91 -1704
- package/dist/src/ui/tui/tui-pane-activity.js +99 -0
- package/dist/src/ui/tui/tui-pane-backlog.js +224 -0
- package/dist/src/ui/tui/tui-pane-brief.js +30 -0
- package/dist/src/ui/tui/tui-pane-ctx.js +11 -0
- package/dist/src/ui/tui/tui-pane-health.js +124 -0
- package/dist/src/ui/tui/tui-pane-history.js +316 -0
- package/dist/src/ui/tui/tui-pane-pending.js +74 -0
- package/dist/src/ui/tui/tui-pane-queued.js +143 -0
- package/dist/src/ui/tui/tui-pane-report.js +122 -0
- package/dist/src/ui/tui/tui-pane-session.js +101 -0
- package/dist/src/ui/tui/tui-pane-transcript.js +150 -0
- package/dist/src/ui/tui/tui-pane.js +66 -28
- package/dist/src/ui/tui/tui-panes.js +294 -0
- package/dist/src/ui/tui/tui.js +45 -25
- package/dist/src/verdict/fix-claim.js +141 -38
- package/dist/src/verdict/no-change.js +19 -0
- package/dist/src/verdict/refusal.js +92 -8
- package/dist/src/verdict/reply-contract.js +17 -5
- package/dist/src/version.js +3 -2
- package/package.json +4 -2
- package/dist/src/agent/mcp/role-notes-server.js +0 -160
- package/dist/src/landing/backlog-conflicts.js +0 -116
- package/dist/src/landing/landing-drain.js +0 -204
- package/dist/src/landing/landing-pipeline.js +0 -96
- package/dist/src/landing/landing-queue-render.js +0 -31
- package/dist/src/landing/landing-slot.js +0 -246
- package/dist/src/landing/landing-vetting.js +0 -196
- package/dist/src/pi-extension/role-notes.js +0 -40
- package/dist/src/ui/fleet-alerts.js +0 -174
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
// vocabulary: plain
|
|
1
2
|
import { spawn } from "node:child_process";
|
|
3
|
+
import { TUMWATER_SOURCE } from "../events/events.js";
|
|
2
4
|
import { RESTART_EXIT_CODE } from "../redeploy/redeploy-policy.js";
|
|
3
5
|
import { childEnv, runOnAbort } from "./process.js";
|
|
4
6
|
/** The respawn loop behind `tumwater run`. The command runs as two processes: this supervisor (the
|
|
5
7
|
* one the operator started, holding the terminal) and a child that actually runs the orchestrator.
|
|
6
8
|
* When the child rebuilt dist/ onto a newer main (src/redeploy/redeployer.ts) it exits
|
|
7
9
|
* RESTART_EXIT_CODE and the supervisor respawns it — the same script path, now holding the new
|
|
8
|
-
* code — so a self-hosting
|
|
9
|
-
* other exit ends the supervisor with the child's code — and when nobody asked for it, the
|
|
10
|
-
* is down with nobody at the keyboard either, so that exit is recorded first (
|
|
10
|
+
* code — so a self-hosting team picks up its own changes without anyone at the keyboard. Any
|
|
11
|
+
* other exit ends the supervisor with the child's code — and when nobody asked for it, the team
|
|
12
|
+
* is down with nobody at the keyboard either, so that exit is recorded first (onTeamDown). Ctrl+C
|
|
11
13
|
* reaches both processes from the terminal (same foreground group), so the supervisor forwards only
|
|
12
14
|
* SIGTERM, which a plain `kill` delivers to it alone. */
|
|
13
15
|
/** Marks the child: `tumwater run` with this set runs the orchestrator instead of supervising. */
|
|
@@ -18,6 +20,13 @@ export const SUPERVISED_ENV = "TUMWATER_SUPERVISED";
|
|
|
18
20
|
* arms — still counts as gone (the dashboard's DASHBOARD_CHILD_ENV carries the same mark for its
|
|
19
21
|
* reload watch). */
|
|
20
22
|
export const SUPERVISOR_PID_ENV = "TUMWATER_SUPERVISOR_PID";
|
|
23
|
+
/** Marks a `run --for` window's start (epoch ms), set once by the supervisor and handed to every
|
|
24
|
+
* orchestrator generation, so a self-redeploy continues the window instead of opening a new one. */
|
|
25
|
+
export const RUN_WINDOW_START_ENV = "TUMWATER_RUN_WINDOW_START";
|
|
26
|
+
/** The exit code of a `run --once` round that finished and found failed ticks (cli-run.ts's
|
|
27
|
+
* onceFailures): an asked-for ending, so the supervisor passes it through without paging the
|
|
28
|
+
* team-down hook. */
|
|
29
|
+
export const ONCE_FAILED_EXIT_CODE = 3;
|
|
21
30
|
/** How often the supervised generation checks that its supervisor still lives (ms). */
|
|
22
31
|
const PARENT_POLL_MS = 5_000;
|
|
23
32
|
/** The default poll: `check` every `intervalMs`, on a timer unref'd so an idle watch never holds
|
|
@@ -32,10 +41,10 @@ function intervalPoll(intervalMs) {
|
|
|
32
41
|
/** Parent-death watch for the supervised generation. The supervisor forwards only SIGTERM —
|
|
33
42
|
* SIGKILL (the OOM killer, `kill -9`) cannot be trapped or forwarded, and an uncaught supervisor
|
|
34
43
|
* crash forwards nothing either — so a supervisor that dies outright leaves the generation
|
|
35
|
-
* reparented (on macOS to launchd) and ticking the
|
|
44
|
+
* reparented (on macOS to launchd) and ticking the team unattended, with nothing left to sweep
|
|
36
45
|
* it. The watch polls the parent pid on an interval: once it changes, the supervisor is gone
|
|
37
|
-
* without having stopped the
|
|
38
|
-
* would have run — a killed supervisor takes its
|
|
46
|
+
* without having stopped the team, and `onGone` runs the same graceful stop a forwarded SIGTERM
|
|
47
|
+
* would have run — a killed supervisor takes its team down with it. The timer is unref'd so it
|
|
39
48
|
* never holds the generation's event loop open past its real work. Returns the stop that
|
|
40
49
|
* disarms the watch (a no-op once it fired or was already stopped). */
|
|
41
50
|
export function startParentDeathWatch(onGone, opts = {}) {
|
|
@@ -91,12 +100,12 @@ export async function superviseRun(opts, signal) {
|
|
|
91
100
|
const now = opts.now ?? Date.now;
|
|
92
101
|
let generation = 1;
|
|
93
102
|
const recentRespawns = [];
|
|
94
|
-
const
|
|
103
|
+
const teamDown = async (down) => {
|
|
95
104
|
try {
|
|
96
|
-
await opts.
|
|
105
|
+
await opts.onTeamDown?.(down);
|
|
97
106
|
}
|
|
98
107
|
catch {
|
|
99
|
-
// Best-effort (see
|
|
108
|
+
// Best-effort (see onTeamDown): a trace that cannot be written must not change the exit.
|
|
100
109
|
}
|
|
101
110
|
};
|
|
102
111
|
try {
|
|
@@ -104,9 +113,11 @@ export async function superviseRun(opts, signal) {
|
|
|
104
113
|
const exit = await opts.spawnChild(signal);
|
|
105
114
|
if (exit.code !== RESTART_EXIT_CODE || opts.stopping()) {
|
|
106
115
|
// A clean exit (a child stopped by its own SIGTERM logs orchestrator_stop) and anything
|
|
107
|
-
// while the operator is stopping are asked-for endings
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
// while the operator is stopping are asked-for endings, and so is a once round that
|
|
117
|
+
// finished with failed ticks; everything else is the team dying.
|
|
118
|
+
const code = exitCodeOf(exit);
|
|
119
|
+
if (code !== 0 && code !== ONCE_FAILED_EXIT_CODE && !opts.stopping())
|
|
120
|
+
await teamDown({ generation, exit, crashLoop: false });
|
|
110
121
|
return exitCodeOf(exit);
|
|
111
122
|
}
|
|
112
123
|
const t = now();
|
|
@@ -115,7 +126,7 @@ export async function superviseRun(opts, signal) {
|
|
|
115
126
|
recentRespawns.push(t);
|
|
116
127
|
if (recentRespawns.length > MAX_RAPID_RESPAWNS) {
|
|
117
128
|
opts.onCrashLoop?.();
|
|
118
|
-
await
|
|
129
|
+
await teamDown({ generation, exit, crashLoop: true });
|
|
119
130
|
return 1;
|
|
120
131
|
}
|
|
121
132
|
generation += 1;
|
|
@@ -132,17 +143,17 @@ export async function superviseRun(opts, signal) {
|
|
|
132
143
|
}
|
|
133
144
|
}
|
|
134
145
|
}
|
|
135
|
-
/** The `supervisor_exit` event for a
|
|
146
|
+
/** The `supervisor_exit` event for a team that went down (see onTeamDown). `diagnosis` is the
|
|
136
147
|
* startup gate re-asked after the death (startup-gate.ts's runStartupProblem): the likeliest
|
|
137
148
|
* reason a generation dies right after a respawn is an environment that no longer boots, and the
|
|
138
149
|
* child's own message reached only the terminal. Null when every precondition passes — the event
|
|
139
150
|
* then carries no reason rather than a guess. A crash loop's reason is the guard itself. */
|
|
140
|
-
export function
|
|
151
|
+
export function teamDownEvent(down, diagnosis) {
|
|
141
152
|
const reason = down.crashLoop
|
|
142
153
|
? `restarted itself more than ${MAX_RAPID_RESPAWNS} times within ${RESPAWN_WINDOW_MS / 1000}s — giving up`
|
|
143
154
|
: diagnosis;
|
|
144
155
|
return {
|
|
145
|
-
|
|
156
|
+
source: TUMWATER_SOURCE,
|
|
146
157
|
type: "supervisor_exit",
|
|
147
158
|
generation: down.generation,
|
|
148
159
|
code: down.exit.code,
|
|
@@ -156,29 +167,40 @@ export function fleetDownEvent(down, diagnosis) {
|
|
|
156
167
|
* same branch) — stdio shared (the child's event stream is what the operator sees), and
|
|
157
168
|
* SUPERVISED_ENV set so it runs the orchestrator instead of supervising again, plus
|
|
158
169
|
* SUPERVISOR_PID_ENV naming this supervisor so the child's own parent-death watch fires even if
|
|
159
|
-
* this process is killed before the child reads its first ppid.
|
|
160
|
-
|
|
170
|
+
* this process is killed before the child reads its first ppid. `env` carries extra marks, e.g.
|
|
171
|
+
* RUN_WINDOW_START_ENV for a `--for` window. `stdio` defaults to `"inherit"` (the child's
|
|
172
|
+
* event stream is what a plain `run` operator sees); `run --tui` passes silent stdio instead,
|
|
173
|
+
* because the observer TUI owns the terminal and the child must not paint over its render. */
|
|
174
|
+
export function spawnRunChild(signal, extraArgs = [], env = {}, stdio = "inherit") {
|
|
175
|
+
// Spawn `run`, never `start`: the supervisor runs the build it started on, but each child
|
|
176
|
+
// loads dist/src/cli.js, which a redeploy replaces with main's newest build. Every build from
|
|
177
|
+
// the `start` rename on accepts `run`, and older builds accept only `run`, so `run` works
|
|
178
|
+
// against whatever build the child meets, even after a rollback; spawning `start` would make
|
|
179
|
+
// an updated supervisor's respawn fail with "unknown command" on a reverted build.
|
|
161
180
|
return spawnSupervised(["run", ...extraArgs], signal, {
|
|
162
181
|
[SUPERVISED_ENV]: "1",
|
|
163
182
|
[SUPERVISOR_PID_ENV]: String(process.pid),
|
|
164
|
-
|
|
183
|
+
...env,
|
|
184
|
+
}, stdio);
|
|
165
185
|
}
|
|
166
186
|
/** The production dashboard spawner for `run --gui`: a `tumwater gui` child on its defaults,
|
|
167
|
-
* stdio shared so a terminal Ctrl+C reaches it exactly as it reaches the orchestrator child
|
|
187
|
+
* stdio shared so a terminal Ctrl+C reaches it exactly as it reaches the orchestrator child —
|
|
188
|
+
* unless `--tui` is hosted, when the caller passes silent stdio so the dashboard's
|
|
189
|
+
* `tumwater gui at http://…` banner cannot paint over the observer TUI's full-screen render.
|
|
168
190
|
* `env` carries the caller's mark — in production DASHBOARD_CHILD_ENV naming this supervisor's
|
|
169
191
|
* pid — so the child's own reload watch (src/redeploy/self-reload.ts) both exits
|
|
170
192
|
* RESTART_EXIT_CODE for a fresh generation on a redeploy and exits on its own if this supervisor
|
|
171
193
|
* dies outright (SIGKILL, a crash), freeing the dashboard port. Deliberately not SUPERVISED_ENV:
|
|
172
|
-
* the child must run `gui`, not supervise a
|
|
194
|
+
* the child must run `gui`, not supervise a team. Resolves like spawnRunChild — a failed spawn
|
|
173
195
|
* is `{ code: 1, signal: null }` — so an EMFILE/ENOMEM here cannot throw an unhandled 'error'. */
|
|
174
|
-
export function spawnGuiChild(signal, env = {}) {
|
|
175
|
-
return spawnSupervised(["gui"], signal, env);
|
|
196
|
+
export function spawnGuiChild(signal, env = {}, stdio = "inherit") {
|
|
197
|
+
return spawnSupervised(["gui"], signal, env, stdio);
|
|
176
198
|
}
|
|
177
199
|
/** Spawn one supervised child (`commandArgs` after the cli.js script path) and resolve on its
|
|
178
200
|
* exit, with the abort signal wiring and spawn-failure handling shared by spawnRunChild and
|
|
179
201
|
* spawnGuiChild: the signal's abort sends SIGTERM, and a spawn that never starts resolves as a
|
|
180
202
|
* failed exit instead of emitting an unhandled 'error'. */
|
|
181
|
-
function spawnSupervised(commandArgs, signal, env) {
|
|
203
|
+
function spawnSupervised(commandArgs, signal, env, stdio = "inherit") {
|
|
182
204
|
return new Promise((resolve) => {
|
|
183
205
|
const script = process.argv[1];
|
|
184
206
|
if (!script) {
|
|
@@ -186,7 +208,7 @@ function spawnSupervised(commandArgs, signal, env) {
|
|
|
186
208
|
return;
|
|
187
209
|
}
|
|
188
210
|
const child = spawn(process.execPath, [script, ...commandArgs], {
|
|
189
|
-
stdio
|
|
211
|
+
stdio,
|
|
190
212
|
env: childEnv(env),
|
|
191
213
|
});
|
|
192
214
|
// runOnAbort closes the register/abort race: an already-fired signal kills the child
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// vocabulary: plain
|
|
1
2
|
/**
|
|
2
3
|
* The only backend-specific prompt text (plans/agent-backends.md "What the pi extensions did,
|
|
3
4
|
* per backend"). Everything else in the prompts already speaks in shell commands and "tool
|
|
@@ -10,26 +11,45 @@
|
|
|
10
11
|
* where its own tool surface does. Adding a backend means adding one dialect here, not editing
|
|
11
12
|
* every prompt builder.
|
|
12
13
|
*/
|
|
13
|
-
/** pi's dialect: the identity of the prompts before agent backends — its `
|
|
14
|
-
*
|
|
14
|
+
/** pi's dialect: the identity of the prompts before agent backends — its `read` tool's
|
|
15
|
+
* `offset`/`limit`, and its bundled head+tail marker. */
|
|
15
16
|
export const PI_DIALECT = {
|
|
16
|
-
notesTool: "role_notes",
|
|
17
17
|
readRange: "the read tool's offset/limit (or `sed -n 'A,Bp'`)",
|
|
18
18
|
oversizedOutput: `Oversized tool results come back as head+tail around a marker that names the omitted amount
|
|
19
19
|
and where the full output lives — follow the pointer (re-read with \`offset\`/\`limit\`, or open
|
|
20
20
|
the full-output file path) instead of retrying the same read.`,
|
|
21
21
|
};
|
|
22
|
-
/** claude's dialect: the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
/** claude's dialect: the Read tool takes `offset`/`limit`, and Claude Code truncates
|
|
23
|
+
* oversized Bash output and spills large results to a file it names (so it needs no head+tail
|
|
24
|
+
* marker). */
|
|
25
25
|
export const CLAUDE_DIALECT = {
|
|
26
|
-
notesTool: "mcp__tumwater__role_notes",
|
|
27
26
|
readRange: "the Read tool's offset/limit (or `sed -n 'A,Bp'`)",
|
|
28
27
|
oversizedOutput: `Oversized tool results are truncated and saved to a file the tool names — read that file
|
|
29
28
|
in ranges (the Read tool's offset/limit) instead of retrying the same read.`,
|
|
30
29
|
};
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
30
|
+
/** opencode's dialect (plans/opencode-backend.md §5): its read tool takes `offset`/`limit`,
|
|
31
|
+
* its oversized shell output spills to a named file (finding 17), and two backend rules tell
|
|
32
|
+
* the model how OpenCode's shell tool works: a 2-minute default timeout that `timeout`
|
|
33
|
+
* overrides, and no `background` (a backgrounded command dies when the run ends, finding 18). */
|
|
34
|
+
export const OPENCODE_DIALECT = {
|
|
35
|
+
readRange: "the read tool's offset/limit (or `sed -n 'A,Bp'`)",
|
|
36
|
+
oversizedOutput: `Oversized shell output keeps only its last lines, followed by a note naming the file with
|
|
37
|
+
the full output — read that file in ranges (the read tool's offset/limit) instead of
|
|
38
|
+
re-running the command.`,
|
|
39
|
+
backendRules: [
|
|
40
|
+
"Shell commands time out after 2 minutes unless you pass `timeout` in milliseconds; give the project's check a timeout that covers it (for example 900000).",
|
|
41
|
+
"Run every shell command in the foreground: never set `background`, because a background command is killed when your run ends.",
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
/** The dialect table keyed by backend id: every backend but claude speaks pi's dialect (and
|
|
45
|
+
* an unknown id falls back to pi because run-agent.ts routes an unregistered id to the pi
|
|
46
|
+
* backend). Adding a backend means one row here, not another branch. */
|
|
47
|
+
const DIALECTS = {
|
|
48
|
+
pi: PI_DIALECT,
|
|
49
|
+
claude: CLAUDE_DIALECT,
|
|
50
|
+
opencode: OPENCODE_DIALECT,
|
|
51
|
+
};
|
|
52
|
+
/** The dialect for an agent id, read from the per-backend table. */
|
|
33
53
|
export function dialectFor(agent) {
|
|
34
|
-
return agent
|
|
54
|
+
return DIALECTS[agent ?? "pi"] ?? PI_DIALECT;
|
|
35
55
|
}
|