@cluesmith/codev 3.2.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard-dist/assets/index-BZRTEMtH.css +32 -0
- package/dashboard-dist/assets/{index-BZ1x7x1X.js → index-JCbkpAcV.js} +33 -33
- package/dashboard-dist/assets/index-JCbkpAcV.js.map +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +173 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/attach.js +2 -2
- package/dist/agent-farm/commands/attach.js.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +16 -0
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/inbox.d.ts +42 -0
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -0
- package/dist/agent-farm/commands/inbox.js +129 -0
- package/dist/agent-farm/commands/inbox.js.map +1 -0
- package/dist/agent-farm/commands/interrupt.d.ts +20 -0
- package/dist/agent-farm/commands/interrupt.d.ts.map +1 -0
- package/dist/agent-farm/commands/interrupt.js +65 -0
- package/dist/agent-farm/commands/interrupt.js.map +1 -0
- package/dist/agent-farm/commands/reset/constants.d.ts +52 -0
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/constants.js +52 -0
- package/dist/agent-farm/commands/reset/constants.js.map +1 -0
- package/dist/agent-farm/commands/reset/context.d.ts +230 -0
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/context.js +428 -0
- package/dist/agent-farm/commands/reset/context.js.map +1 -0
- package/dist/agent-farm/commands/reset/index.d.ts +192 -0
- package/dist/agent-farm/commands/reset/index.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/index.js +488 -0
- package/dist/agent-farm/commands/reset/index.js.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts +97 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.js +149 -0
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts +117 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.js +313 -0
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +19 -0
- package/dist/agent-farm/commands/reset.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset.js +292 -0
- package/dist/agent-farm/commands/reset.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts +2 -2
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +52 -11
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/setup.d.ts +4 -1
- package/dist/agent-farm/commands/setup.d.ts.map +1 -1
- package/dist/agent-farm/commands/setup.js +8 -4
- package/dist/agent-farm/commands/setup.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +116 -6
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +345 -74
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/commands/status.d.ts.map +1 -1
- package/dist/agent-farm/commands/status.js +105 -9
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/tower-sweep-husks.d.ts +6 -0
- package/dist/agent-farm/commands/tower-sweep-husks.d.ts.map +1 -0
- package/dist/agent-farm/commands/tower-sweep-husks.js +77 -0
- package/dist/agent-farm/commands/tower-sweep-husks.js.map +1 -0
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +34 -0
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/commands/whoami.d.ts +65 -0
- package/dist/agent-farm/commands/whoami.d.ts.map +1 -0
- package/dist/agent-farm/commands/whoami.js +196 -0
- package/dist/agent-farm/commands/whoami.js.map +1 -0
- package/dist/agent-farm/db/index.d.ts +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +80 -1
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/mailbox.d.ts +222 -0
- package/dist/agent-farm/db/mailbox.d.ts.map +1 -0
- package/dist/agent-farm/db/mailbox.js +304 -0
- package/dist/agent-farm/db/mailbox.js.map +1 -0
- package/dist/agent-farm/db/schema.d.ts +1 -1
- package/dist/agent-farm/db/schema.d.ts.map +1 -1
- package/dist/agent-farm/db/schema.js +35 -0
- package/dist/agent-farm/db/schema.js.map +1 -1
- package/dist/agent-farm/db/types.d.ts +45 -0
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +2 -2
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.d.ts +54 -0
- package/dist/agent-farm/lib/reconnect-backoff.d.ts.map +1 -0
- package/dist/agent-farm/lib/reconnect-backoff.js +47 -0
- package/dist/agent-farm/lib/reconnect-backoff.js.map +1 -0
- package/dist/agent-farm/lib/tower-client.d.ts +16 -6
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +37 -6
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts +69 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +218 -27
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/architect-session-holder.d.ts +133 -0
- package/dist/agent-farm/servers/architect-session-holder.d.ts.map +1 -0
- package/dist/agent-farm/servers/architect-session-holder.js +268 -0
- package/dist/agent-farm/servers/architect-session-holder.js.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts +72 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.js +80 -0
- package/dist/agent-farm/servers/cron-delivery.js.map +1 -0
- package/dist/agent-farm/servers/delayed-send.d.ts +85 -0
- package/dist/agent-farm/servers/delayed-send.d.ts.map +1 -0
- package/dist/agent-farm/servers/delayed-send.js +165 -0
- package/dist/agent-farm/servers/delayed-send.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +67 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.js +113 -0
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +370 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.js +617 -0
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +125 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.js +425 -0
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -0
- package/dist/agent-farm/servers/message-write.d.ts +53 -1
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +63 -0
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +23 -4
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/process-census.d.ts +41 -0
- package/dist/agent-farm/servers/process-census.d.ts.map +1 -0
- package/dist/agent-farm/servers/process-census.js +62 -0
- package/dist/agent-farm/servers/process-census.js.map +1 -0
- package/dist/agent-farm/servers/render-gate.d.ts +141 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -0
- package/dist/agent-farm/servers/render-gate.js +251 -0
- package/dist/agent-farm/servers/render-gate.js.map +1 -0
- package/dist/agent-farm/servers/session-log-sweep.d.ts +93 -0
- package/dist/agent-farm/servers/session-log-sweep.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-log-sweep.js +165 -0
- package/dist/agent-farm/servers/session-log-sweep.js.map +1 -0
- package/dist/agent-farm/servers/session-submit.d.ts +90 -0
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-submit.js +127 -0
- package/dist/agent-farm/servers/session-submit.js.map +1 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.d.ts +87 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.d.ts.map +1 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.js +129 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.js.map +1 -0
- package/dist/agent-farm/servers/tower-cron.d.ts +10 -7
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +58 -53
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -2
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +128 -19
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-messages.d.ts +38 -1
- package/dist/agent-farm/servers/tower-messages.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-messages.js +106 -1
- package/dist/agent-farm/servers/tower-messages.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts +16 -4
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +807 -99
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +241 -15
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +17 -2
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +139 -124
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +63 -4
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-types.d.ts +2 -1
- package/dist/agent-farm/servers/tower-types.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +99 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +242 -6
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +6 -21
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/servers/write-queue.d.ts +35 -0
- package/dist/agent-farm/servers/write-queue.d.ts.map +1 -0
- package/dist/agent-farm/servers/write-queue.js +56 -0
- package/dist/agent-farm/servers/write-queue.js.map +1 -0
- package/dist/agent-farm/state.d.ts +6 -1
- package/dist/agent-farm/state.d.ts.map +1 -1
- package/dist/agent-farm/state.js +5 -2
- package/dist/agent-farm/state.js.map +1 -1
- package/dist/agent-farm/types.d.ts +39 -0
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.d.ts +2 -2
- package/dist/agent-farm/utils/agent-names.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.js +3 -3
- package/dist/agent-farm/utils/agent-names.js.map +1 -1
- package/dist/agent-farm/utils/architect-name.d.ts +2 -2
- package/dist/agent-farm/utils/architect-name.d.ts.map +1 -1
- package/dist/agent-farm/utils/architect-name.js +3 -3
- package/dist/agent-farm/utils/architect-name.js.map +1 -1
- package/dist/agent-farm/utils/config.d.ts +13 -0
- package/dist/agent-farm/utils/config.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.js +33 -1
- package/dist/agent-farm/utils/config.js.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +103 -7
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +126 -19
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +3 -2
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +7 -6
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/consult/agy-auth-cache.d.ts +97 -0
- package/dist/commands/consult/agy-auth-cache.d.ts.map +1 -0
- package/dist/commands/consult/agy-auth-cache.js +320 -0
- package/dist/commands/consult/agy-auth-cache.js.map +1 -0
- package/dist/commands/consult/cli-options.d.ts +34 -0
- package/dist/commands/consult/cli-options.d.ts.map +1 -0
- package/dist/commands/consult/cli-options.js +67 -0
- package/dist/commands/consult/cli-options.js.map +1 -0
- package/dist/commands/consult/index.d.ts +56 -2
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +330 -27
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/metrics.d.ts +42 -0
- package/dist/commands/consult/metrics.d.ts.map +1 -1
- package/dist/commands/consult/metrics.js +129 -9
- package/dist/commands/consult/metrics.js.map +1 -1
- package/dist/commands/doctor.d.ts +28 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +258 -22
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +3 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +7 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +23 -0
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +60 -0
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/config.d.ts +20 -0
- package/dist/commands/porch/config.d.ts.map +1 -1
- package/dist/commands/porch/config.js +20 -0
- package/dist/commands/porch/config.js.map +1 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +32 -36
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +2 -41
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/commands/update.d.ts +4 -4
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +9 -11
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/config.d.ts +70 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +67 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/consult-lanes.d.ts +149 -0
- package/dist/lib/consult-lanes.d.ts.map +1 -0
- package/dist/lib/consult-lanes.js +360 -0
- package/dist/lib/consult-lanes.js.map +1 -0
- package/dist/lib/default-branch.d.ts +1 -1
- package/dist/lib/default-branch.js +1 -1
- package/dist/lib/github.js +1 -1
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/gitignore.d.ts +25 -2
- package/dist/lib/gitignore.d.ts.map +1 -1
- package/dist/lib/gitignore.js +70 -0
- package/dist/lib/gitignore.js.map +1 -1
- package/dist/lib/migration-backup-audit.d.ts +64 -0
- package/dist/lib/migration-backup-audit.d.ts.map +1 -0
- package/dist/lib/migration-backup-audit.js +145 -0
- package/dist/lib/migration-backup-audit.js.map +1 -0
- package/dist/lib/prompt-behavior-metrics.d.ts +67 -0
- package/dist/lib/prompt-behavior-metrics.d.ts.map +1 -0
- package/dist/lib/prompt-behavior-metrics.js +290 -0
- package/dist/lib/prompt-behavior-metrics.js.map +1 -0
- package/dist/lib/protocol-drift-audit.d.ts +118 -0
- package/dist/lib/protocol-drift-audit.d.ts.map +1 -0
- package/dist/lib/protocol-drift-audit.js +217 -0
- package/dist/lib/protocol-drift-audit.js.map +1 -0
- package/dist/lib/scaffold.d.ts +10 -3
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +29 -26
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/lib/skeleton.d.ts +22 -1
- package/dist/lib/skeleton.d.ts.map +1 -1
- package/dist/lib/skeleton.js +120 -0
- package/dist/lib/skeleton.js.map +1 -1
- package/dist/lib/test-env.d.ts +74 -0
- package/dist/lib/test-env.d.ts.map +1 -0
- package/dist/lib/test-env.js +92 -0
- package/dist/lib/test-env.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts +9 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +32 -6
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +156 -4
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +307 -42
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/ring-buffer.d.ts +39 -6
- package/dist/terminal/ring-buffer.d.ts.map +1 -1
- package/dist/terminal/ring-buffer.js +74 -6
- package/dist/terminal/ring-buffer.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +129 -0
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +337 -44
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +91 -0
- package/dist/terminal/session-screen.d.ts.map +1 -0
- package/dist/terminal/session-screen.js +135 -0
- package/dist/terminal/session-screen.js.map +1 -0
- package/dist/terminal/shellper-client.d.ts +19 -4
- package/dist/terminal/shellper-client.d.ts.map +1 -1
- package/dist/terminal/shellper-client.js +70 -8
- package/dist/terminal/shellper-client.js.map +1 -1
- package/dist/terminal/shellper-main.js +2 -1
- package/dist/terminal/shellper-main.js.map +1 -1
- package/dist/terminal/shellper-process.d.ts +1 -1
- package/dist/terminal/shellper-process.d.ts.map +1 -1
- package/dist/terminal/shellper-process.js +33 -9
- package/dist/terminal/shellper-process.js.map +1 -1
- package/dist/terminal/shellper-protocol.d.ts +40 -2
- package/dist/terminal/shellper-protocol.d.ts.map +1 -1
- package/dist/terminal/shellper-protocol.js +72 -5
- package/dist/terminal/shellper-protocol.js.map +1 -1
- package/dist/terminal/shellper-replay-buffer.d.ts +69 -7
- package/dist/terminal/shellper-replay-buffer.d.ts.map +1 -1
- package/dist/terminal/shellper-replay-buffer.js +167 -31
- package/dist/terminal/shellper-replay-buffer.js.map +1 -1
- package/package.json +11 -9
- package/skeleton/.claude/skills/afx/SKILL.md +27 -1
- package/skeleton/.claude/skills/arch-init/SKILL.md +135 -0
- package/skeleton/.claude/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.claude/skills/codev/SKILL.md +33 -2
- package/skeleton/.claude/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/.codex/skills/afx/SKILL.md +170 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +135 -0
- package/skeleton/.codex/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.codex/skills/codev/SKILL.md +90 -0
- package/skeleton/.codex/skills/consult/SKILL.md +96 -0
- package/skeleton/.codex/skills/generate-image/SKILL.md +45 -0
- package/skeleton/.codex/skills/porch/SKILL.md +60 -0
- package/skeleton/.codex/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/.codex/skills/update-arch-docs/SKILL.md +132 -0
- package/skeleton/protocols/air/builder-prompt.md +28 -47
- package/skeleton/protocols/air/consult-types/impl-review.md +17 -34
- package/skeleton/protocols/air/consult-types/pr-review.md +14 -37
- package/skeleton/protocols/air/prompts/implement.md +20 -73
- package/skeleton/protocols/air/prompts/pr.md +22 -54
- package/skeleton/protocols/air/protocol.md +40 -71
- package/skeleton/protocols/aspir/builder-prompt.md +29 -66
- package/skeleton/protocols/aspir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/aspir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/aspir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/aspir/prompts/implement.md +27 -196
- package/skeleton/protocols/aspir/prompts/plan.md +21 -85
- package/skeleton/protocols/aspir/prompts/review.md +29 -228
- package/skeleton/protocols/aspir/prompts/specify.md +25 -111
- package/skeleton/protocols/aspir/protocol.json +10 -0
- package/skeleton/protocols/aspir/protocol.md +36 -82
- package/skeleton/protocols/bugfix/builder-prompt.md +23 -45
- package/skeleton/protocols/bugfix/consult-types/impl-review.md +21 -45
- package/skeleton/protocols/bugfix/consult-types/pr-review.md +18 -52
- package/skeleton/protocols/bugfix/prompts/fix.md +16 -61
- package/skeleton/protocols/bugfix/prompts/investigate.md +18 -62
- package/skeleton/protocols/bugfix/prompts/pr.md +22 -57
- package/skeleton/protocols/bugfix/protocol.md +44 -50
- package/skeleton/protocols/experiment/builder-prompt.md +25 -58
- package/skeleton/protocols/experiment/protocol.md +22 -188
- package/skeleton/protocols/experiment/templates/notes.md +11 -71
- package/skeleton/protocols/maintain/builder-prompt.md +24 -45
- package/skeleton/protocols/maintain/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/maintain/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/maintain/prompts/maintain.md +1 -1
- package/skeleton/protocols/maintain/protocol.md +32 -266
- package/skeleton/protocols/maintain/templates/maintenance-run.md +11 -0
- package/skeleton/protocols/pir/builder-prompt.md +30 -64
- package/skeleton/protocols/pir/consult-types/impl-review.md +17 -50
- package/skeleton/protocols/pir/consult-types/pr-review.md +11 -40
- package/skeleton/protocols/pir/prompts/implement.md +1 -2
- package/skeleton/protocols/pir/prompts/plan.md +0 -3
- package/skeleton/protocols/pir/prompts/review.md +1 -1
- package/skeleton/protocols/pir/protocol.md +54 -177
- package/skeleton/protocols/research/builder-prompt.md +27 -58
- package/skeleton/protocols/research/protocol.md +28 -153
- package/skeleton/protocols/spike/builder-prompt.md +30 -48
- package/skeleton/protocols/spike/protocol.md +24 -107
- package/skeleton/protocols/spike/templates/findings.md +9 -39
- package/skeleton/protocols/spir/builder-prompt.md +33 -62
- package/skeleton/protocols/spir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/spir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/spir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/spir/prompts/implement.md +26 -195
- package/skeleton/protocols/spir/prompts/plan.md +20 -84
- package/skeleton/protocols/spir/prompts/review.md +28 -227
- package/skeleton/protocols/spir/prompts/specify.md +24 -110
- package/skeleton/protocols/spir/protocol.json +10 -0
- package/skeleton/protocols/spir/protocol.md +84 -633
- package/skeleton/protocols/spir/templates/plan.md +28 -147
- package/skeleton/protocols/spir/templates/review.md +21 -80
- package/skeleton/protocols/spir/templates/spec.md +24 -118
- package/skeleton/resources/commands/agent-farm.md +348 -0
- package/skeleton/resources/commands/codev.md +5 -0
- package/skeleton/resources/commands/consult.md +262 -8
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/roles/architect.md +67 -306
- package/skeleton/roles/builder.md +77 -191
- package/skeleton/templates/AGENTS.md +2 -0
- package/skeleton/templates/CLAUDE.md +2 -0
- package/templates/tower.html +39 -2
- package/dashboard-dist/assets/index-BZ1x7x1X.js.map +0 -1
- package/dashboard-dist/assets/index-DB1KBSNE.css +0 -32
- package/dist/agent-farm/servers/send-buffer.d.ts +0 -59
- package/dist/agent-farm/servers/send-buffer.d.ts.map +0 -1
- package/dist/agent-farm/servers/send-buffer.js +0 -103
- package/dist/agent-farm/servers/send-buffer.js.map +0 -1
- package/skeleton/porch/prompts/defend.md +0 -108
- package/skeleton/porch/prompts/diagnose.md +0 -70
- package/skeleton/porch/prompts/evaluate.md +0 -132
- package/skeleton/porch/prompts/fix.md +0 -59
- package/skeleton/porch/prompts/implement.md +0 -88
- package/skeleton/porch/prompts/plan.md +0 -74
- package/skeleton/porch/prompts/pr.md +0 -84
- package/skeleton/porch/prompts/review.md +0 -249
- package/skeleton/porch/prompts/specify.md +0 -53
- package/skeleton/porch/prompts/test.md +0 -63
- package/skeleton/protocols/aspir/templates/plan.md +0 -184
- package/skeleton/protocols/aspir/templates/review.md +0 -120
- package/skeleton/protocols/aspir/templates/spec.md +0 -154
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architect-session-holder.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/architect-session-holder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAM5D;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAG/E;AAsBD,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAc5F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,EAAE,CAgBnD;AAED,MAAM,WAAW,2BAA2B;IAC1C,gFAAgF;IAChF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,YAAY,EAAE,CAAC;CAC7B,GAAG,2BAA2B,CAqB9B;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,YAAY,EAAE,CAAC;CAC7B,GAAG,MAAM,EAAE,CAcX;AA6BD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,CAAC,EAAE;IACL,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;IACrD,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAE1F;;;;;;;;;;GAUG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,YAAY,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C,GAAG,OAAO,CAAC;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA4B/D"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue #1224: detect and reclaim live processes that hold an architect's
|
|
3
|
+
* conversation session id, so an architect launch never bakes a colliding
|
|
4
|
+
* `claude --resume <id>` into a permanent crash loop.
|
|
5
|
+
*
|
|
6
|
+
* Two holder classes were observed after a workspace restart (forensic timeline
|
|
7
|
+
* on the issue):
|
|
8
|
+
* 1. OUR OWN superseded shellper for the same architect identity — a remnant
|
|
9
|
+
* from before the restart, or a previous crash-looping instance. Its claude
|
|
10
|
+
* child dies within seconds of every respawn, so the child is absent most
|
|
11
|
+
* of the time; the durable evidence is the *shellper parent's* argv, which
|
|
12
|
+
* carries the session id in its JSON config (`"--session-id","<id>"`).
|
|
13
|
+
* 2. A FOREIGN process — e.g. an interactive `claude` the user started by hand
|
|
14
|
+
* on their own tty (holder case in incident 3). This must NEVER be touched:
|
|
15
|
+
* it is not ours to kill.
|
|
16
|
+
*
|
|
17
|
+
* The policy: reclaim (kill + resume) only OUR OWN superseded shellper, proven
|
|
18
|
+
* by shellper-main.js + matching session id + matching cwd + matching
|
|
19
|
+
* CODEV_ARCHITECT_NAME. Anything else that holds the id is foreign → mint fresh.
|
|
20
|
+
*/
|
|
21
|
+
import { execFileSync } from 'node:child_process';
|
|
22
|
+
import { realpathSync } from 'node:fs';
|
|
23
|
+
/** Marker identifying a Codev shellper process in a `ps` command line. */
|
|
24
|
+
const SHELLPER_MARKER = 'shellper-main.js';
|
|
25
|
+
/**
|
|
26
|
+
* The session-flag needle forms a live holder's argv can carry the id in:
|
|
27
|
+
* - `--session-id <id>` / `--resume <id>` — a claude CHILD's shell argv
|
|
28
|
+
* - `--session-id=<id>` / `--resume=<id>` — the `=`-joined shell variant
|
|
29
|
+
* - `"--session-id","<id>"` / `"--resume","<id>"` — the shellper PARENT's
|
|
30
|
+
* JSON config argv (Issue #1224: catches a remnant shellper whose child is
|
|
31
|
+
* dead between crash-loop respawns).
|
|
32
|
+
*/
|
|
33
|
+
export function sessionIdNeedles(sessionId) {
|
|
34
|
+
return ['--session-id', '--resume'].flatMap((flag) => [
|
|
35
|
+
`${flag} ${sessionId}`,
|
|
36
|
+
`${flag}=${sessionId}`,
|
|
37
|
+
`"${flag}","${sessionId}"`,
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
/** True when a process's argv references `sessionId` as a session-flag argument. */
|
|
41
|
+
export function cmdlineHoldsSession(cmdline, sessionId) {
|
|
42
|
+
const needles = sessionIdNeedles(sessionId);
|
|
43
|
+
return needles.some((needle) => cmdline.includes(needle));
|
|
44
|
+
}
|
|
45
|
+
/** Canonicalize a path for comparison; fall back to the input when realpath fails. */
|
|
46
|
+
function realpathOrSelf(p) {
|
|
47
|
+
try {
|
|
48
|
+
return realpathSync(p);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract a `"key":"value"` string field from a shellper's JSON config as it
|
|
56
|
+
* appears verbatim in the `ps` argv. Regex rather than JSON.parse: the config
|
|
57
|
+
* embeds the full process env, so the blob is large and a partial/edge `ps`
|
|
58
|
+
* line must degrade to "field absent" rather than throw.
|
|
59
|
+
*/
|
|
60
|
+
function extractJsonStringField(cmdline, key) {
|
|
61
|
+
const m = cmdline.match(new RegExp(`"${key}"\\s*:\\s*"([^"]+)"`));
|
|
62
|
+
return m ? m[1] : null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* True when `cmdline` is one of OUR OWN shellper processes for `identity`:
|
|
66
|
+
* a `shellper-main.js` whose JSON config carries the matching workspace cwd and
|
|
67
|
+
* `CODEV_ARCHITECT_NAME`. The cwd match tolerates symlink variants (macOS
|
|
68
|
+
* `/tmp` vs `/private/tmp`), mirroring verifySessionOwnership.
|
|
69
|
+
*
|
|
70
|
+
* This is the airtight-identity gate before any kill: if any field cannot be
|
|
71
|
+
* positively confirmed, this returns false and the caller must not reclaim.
|
|
72
|
+
*/
|
|
73
|
+
export function isOwnArchitectShellper(cmdline, identity) {
|
|
74
|
+
if (!cmdline.includes(SHELLPER_MARKER))
|
|
75
|
+
return false;
|
|
76
|
+
const cfgName = extractJsonStringField(cmdline, 'CODEV_ARCHITECT_NAME');
|
|
77
|
+
if (cfgName !== identity.architectName)
|
|
78
|
+
return false;
|
|
79
|
+
const cfgCwd = extractJsonStringField(cmdline, 'cwd');
|
|
80
|
+
if (!cfgCwd)
|
|
81
|
+
return false;
|
|
82
|
+
const wanted = new Set([identity.workspacePath, realpathOrSelf(identity.workspacePath)]);
|
|
83
|
+
const got = new Set([cfgCwd, realpathOrSelf(cfgCwd)]);
|
|
84
|
+
const cwdMatches = [...got].some((g) => wanted.has(g));
|
|
85
|
+
if (!cwdMatches)
|
|
86
|
+
return false;
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Snapshot every running process as {pid, cmdline}. `ps -ww` prevents argv
|
|
91
|
+
* truncation (the shellper config blob is large) on both BSD and coreutils.
|
|
92
|
+
* Throws on `ps` failure; callers decide how to degrade.
|
|
93
|
+
*/
|
|
94
|
+
export function listProcessEntries() {
|
|
95
|
+
const out = execFileSync('ps', ['-ww', '-eo', 'pid=,args='], {
|
|
96
|
+
encoding: 'utf-8',
|
|
97
|
+
timeout: 5000,
|
|
98
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
99
|
+
});
|
|
100
|
+
const entries = [];
|
|
101
|
+
for (const line of out.split('\n')) {
|
|
102
|
+
const trimmed = line.trimStart();
|
|
103
|
+
const sp = trimmed.indexOf(' ');
|
|
104
|
+
if (sp <= 0)
|
|
105
|
+
continue;
|
|
106
|
+
const pid = parseInt(trimmed.slice(0, sp), 10);
|
|
107
|
+
if (Number.isNaN(pid) || pid <= 0)
|
|
108
|
+
continue;
|
|
109
|
+
entries.push({ pid, cmdline: trimmed.slice(sp + 1) });
|
|
110
|
+
}
|
|
111
|
+
return entries;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Classify every live holder of `sessionId` into reclaimable-own vs foreign.
|
|
115
|
+
* A holder is reclaimable only when it is one of our own architect shellpers
|
|
116
|
+
* (identity-matched); any other holder (a bare `claude`, a shellper for a
|
|
117
|
+
* different identity, an unparseable match) is foreign.
|
|
118
|
+
*
|
|
119
|
+
* On `ps` failure returns `{reclaimable: [], foreign: false}` — no positive
|
|
120
|
+
* evidence, so the caller resumes as it would have before this guard existed.
|
|
121
|
+
*/
|
|
122
|
+
export function classifyArchitectSessionHolder(opts) {
|
|
123
|
+
const list = opts.list ?? listProcessEntries;
|
|
124
|
+
let entries;
|
|
125
|
+
try {
|
|
126
|
+
entries = list();
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return { reclaimable: [], foreign: false };
|
|
130
|
+
}
|
|
131
|
+
const reclaimable = [];
|
|
132
|
+
let foreign = false;
|
|
133
|
+
for (const { pid, cmdline } of entries) {
|
|
134
|
+
if (opts.selfPid !== undefined && pid === opts.selfPid)
|
|
135
|
+
continue;
|
|
136
|
+
if (!cmdlineHoldsSession(cmdline, opts.sessionId))
|
|
137
|
+
continue;
|
|
138
|
+
if (isOwnArchitectShellper(cmdline, opts.identity)) {
|
|
139
|
+
reclaimable.push(pid);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
foreign = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return { reclaimable, foreign };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Find PIDs of OUR OWN architect shellpers for `identity`, regardless of which
|
|
149
|
+
* session they hold. Used by remove-architect to reap a live-process-without-a-
|
|
150
|
+
* registry-row zombie (Issue #1224 symptom B) — there is no stored session id to
|
|
151
|
+
* key on, so identity (shellper-main.js + cwd + CODEV_ARCHITECT_NAME) is the key.
|
|
152
|
+
*/
|
|
153
|
+
export function findOwnArchitectShellpers(opts) {
|
|
154
|
+
const list = opts.list ?? listProcessEntries;
|
|
155
|
+
let entries;
|
|
156
|
+
try {
|
|
157
|
+
entries = list();
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
const pids = [];
|
|
163
|
+
for (const { pid, cmdline } of entries) {
|
|
164
|
+
if (opts.selfPid !== undefined && pid === opts.selfPid)
|
|
165
|
+
continue;
|
|
166
|
+
if (isOwnArchitectShellper(cmdline, opts.identity))
|
|
167
|
+
pids.push(pid);
|
|
168
|
+
}
|
|
169
|
+
return pids;
|
|
170
|
+
}
|
|
171
|
+
/** Whether a pid is still alive (signal 0 probe). */
|
|
172
|
+
function pidAlive(pid) {
|
|
173
|
+
try {
|
|
174
|
+
process.kill(pid, 0);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
// ESRCH → gone; EPERM → alive but not ours to signal (treat as alive).
|
|
179
|
+
return err.code === 'EPERM';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Kill a shellper's whole process group (leader is detached), best-effort. */
|
|
183
|
+
function killProcessGroup(pid, signal) {
|
|
184
|
+
try {
|
|
185
|
+
process.kill(-pid, signal);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Group gone or not permitted — fall back to the single pid.
|
|
189
|
+
try {
|
|
190
|
+
process.kill(pid, signal);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
/* already dead */
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
198
|
+
/**
|
|
199
|
+
* Reap the given superseded-shellper PIDs: SIGTERM the process group, poll for
|
|
200
|
+
* death, then SIGKILL any survivor. Resolves once every pid is gone (or the
|
|
201
|
+
* SIGKILL grace elapses). The wait matters: the killed shellper's child must
|
|
202
|
+
* release the session lock before the caller's fresh `claude --resume` runs,
|
|
203
|
+
* else the collision recurs.
|
|
204
|
+
*
|
|
205
|
+
* Seams (`isAlive`, `kill`, `wait`) keep it unit-testable without real signals.
|
|
206
|
+
*/
|
|
207
|
+
export async function reapShellpers(pids, opts) {
|
|
208
|
+
if (pids.length === 0)
|
|
209
|
+
return;
|
|
210
|
+
const isAlive = opts?.isAlive ?? pidAlive;
|
|
211
|
+
const kill = opts?.kill ?? killProcessGroup;
|
|
212
|
+
const wait = opts?.wait ?? sleep;
|
|
213
|
+
const graceMs = opts?.graceMs ?? 3000;
|
|
214
|
+
const killGraceMs = opts?.killGraceMs ?? 2000;
|
|
215
|
+
const pollMs = opts?.pollMs ?? 100;
|
|
216
|
+
const pollUntilDead = async (deadlineMs) => {
|
|
217
|
+
let waited = 0;
|
|
218
|
+
while (waited < deadlineMs && pids.some((pid) => isAlive(pid))) {
|
|
219
|
+
await wait(pollMs);
|
|
220
|
+
waited += pollMs;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
for (const pid of pids)
|
|
224
|
+
kill(pid, 'SIGTERM');
|
|
225
|
+
await pollUntilDead(graceMs);
|
|
226
|
+
const survivors = pids.filter((pid) => isAlive(pid));
|
|
227
|
+
if (survivors.length > 0) {
|
|
228
|
+
for (const pid of survivors)
|
|
229
|
+
kill(pid, 'SIGKILL');
|
|
230
|
+
// Confirm SIGKILL actually took effect before returning: the caller resumes
|
|
231
|
+
// `claude --resume <id>` next, and a holder still in the kernel's exit path
|
|
232
|
+
// has not yet released the session lock — returning early would re-open the
|
|
233
|
+
// very collision race this reap exists to close (codex review, Issue #1224).
|
|
234
|
+
await pollUntilDead(killGraceMs);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Reconcile a stored architect session id against the live process table before
|
|
239
|
+
* launch, resolving whether the caller may resume it.
|
|
240
|
+
*
|
|
241
|
+
* - A FOREIGN holder → `{ foreignHolder: true }`: the caller must mint fresh
|
|
242
|
+
* (the session is genuinely in use by something we must not touch).
|
|
243
|
+
* - Only OUR OWN superseded shellper(s) hold it → reap them and return
|
|
244
|
+
* `{ foreignHolder: false }`: the session is now free, resume it (mint-or-
|
|
245
|
+
* RECLAIM, preserving the conversation instead of abandoning it).
|
|
246
|
+
* - No holder → `{ foreignHolder: false }`: resume as usual.
|
|
247
|
+
*/
|
|
248
|
+
export async function reconcileArchitectSessionHolder(opts) {
|
|
249
|
+
const { reclaimable, foreign } = classifyArchitectSessionHolder({
|
|
250
|
+
sessionId: opts.sessionId,
|
|
251
|
+
identity: opts.identity,
|
|
252
|
+
selfPid: opts.selfPid,
|
|
253
|
+
list: opts.list,
|
|
254
|
+
});
|
|
255
|
+
const shortId = opts.sessionId.slice(0, 8);
|
|
256
|
+
if (foreign) {
|
|
257
|
+
opts.log?.('WARN', `Architect '${opts.identity.architectName}' session ${shortId}… is held by a foreign process; minting a fresh session (holder left untouched) in ${opts.identity.workspacePath}`);
|
|
258
|
+
return { foreignHolder: true, reclaimedPids: [] };
|
|
259
|
+
}
|
|
260
|
+
if (reclaimable.length === 0) {
|
|
261
|
+
return { foreignHolder: false, reclaimedPids: [] };
|
|
262
|
+
}
|
|
263
|
+
opts.log?.('WARN', `Architect '${opts.identity.architectName}' session ${shortId}… is held by our own superseded shellper(s) [${reclaimable.join(', ')}]; reaping to reclaim the conversation in ${opts.identity.workspacePath}`);
|
|
264
|
+
const reap = opts.reap ?? ((pids) => reapShellpers(pids));
|
|
265
|
+
await reap(reclaimable);
|
|
266
|
+
return { foreignHolder: false, reclaimedPids: reclaimable };
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=architect-session-holder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architect-session-holder.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/architect-session-holder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron message delivery through the mailbox + gate (Spec 1313, Phase 6).
|
|
3
|
+
*
|
|
4
|
+
* Cron is today the most unguarded message writer: it wrote straight to the PTY with
|
|
5
|
+
* no idle check and logged "delivered" unconditionally. This phase makes it an
|
|
6
|
+
* ordinary mailbox sender — every cron notification is persisted and then delivered
|
|
7
|
+
* through the SAME single gated path (`deliverAgentMailSerialized`) that `handleSend`
|
|
8
|
+
* and the backstop drainer use, so a cron message can never land mid-draft or fuse
|
|
9
|
+
* with a human's half-typed line. There is no force path: a busy/menu/wrapper screen
|
|
10
|
+
* holds the message for the backstop, exactly like any other send.
|
|
11
|
+
*
|
|
12
|
+
* Two cron-specific twists on top of the shared path:
|
|
13
|
+
* - **Supersede key = task name** (Baked Decision 6): a newer run of a task replaces
|
|
14
|
+
* its own older *held* row instead of queueing a backlog. Supersede keys are
|
|
15
|
+
* cron-only in this project — no non-cron send ever supplies one.
|
|
16
|
+
* - **Honest run outcome**: the caller logs the real fate (`delivered` / `held` /
|
|
17
|
+
* `superseded`) rather than an unconditional "delivered".
|
|
18
|
+
*
|
|
19
|
+
* This module holds the registry-free orchestration core behind the Phase-4
|
|
20
|
+
* {@link DeliveryPorts} seam, so it is unit-testable against a real mailbox DB with
|
|
21
|
+
* fake edges (no live Tower). The identity resolution that needs the live routing
|
|
22
|
+
* registry (`resolveTarget` + the architect reverse-map + the dead-session registry
|
|
23
|
+
* fallback) lives in `tower-routes.ts`'s `deliverCronMessage`, which calls this.
|
|
24
|
+
*/
|
|
25
|
+
import type Database from 'better-sqlite3';
|
|
26
|
+
import type { MailboxReason } from '../db/types.js';
|
|
27
|
+
import { type DeliveryPorts } from './mailbox-delivery.js';
|
|
28
|
+
/** The pseudo-agent identity every cron notification is sent as. */
|
|
29
|
+
export declare const CRON_SENDER = "af-cron";
|
|
30
|
+
/** The real fate of one cron run's message (what the run log records). */
|
|
31
|
+
export type CronOutcome = 'delivered' | 'held' | 'superseded' | 'unresolved';
|
|
32
|
+
/** Outcome of routing a cron notification through the mailbox + gate. */
|
|
33
|
+
export interface CronDeliveryResult {
|
|
34
|
+
/**
|
|
35
|
+
* `delivered` — written to a render-verified empty prompt now; `held` — this run's
|
|
36
|
+
* message is held for the backstop (line busy / menu / no profile / no live PTY);
|
|
37
|
+
* `superseded` — held, and it replaced a still-held row from an earlier run of the
|
|
38
|
+
* same task (no backlog); `unresolved` — the target could not be resolved at all
|
|
39
|
+
* (nothing persisted).
|
|
40
|
+
*/
|
|
41
|
+
outcome: CronOutcome;
|
|
42
|
+
/** Why held, when `held`/`superseded`; null when `delivered`/`unresolved`. */
|
|
43
|
+
reason: MailboxReason | null;
|
|
44
|
+
/** The persisted row id (audit); null only when `unresolved`. */
|
|
45
|
+
mailboxId: string | null;
|
|
46
|
+
}
|
|
47
|
+
/** A resolved cron recipient plus the bytes to persist. */
|
|
48
|
+
export interface CronTarget {
|
|
49
|
+
workspacePath: string;
|
|
50
|
+
/** Canonical recipient agent id (a builder id or a specific architect name). */
|
|
51
|
+
toAgent: string;
|
|
52
|
+
/** Last-known PTY hint; null when the recipient has no live terminal. */
|
|
53
|
+
terminalId: string | null;
|
|
54
|
+
/** Raw message body (never logged). */
|
|
55
|
+
body: string;
|
|
56
|
+
/** Exact bytes written to the PTY on delivery. */
|
|
57
|
+
formattedMessage: string;
|
|
58
|
+
/** Per-task coalescing key (Baked Decision 6) — the task name. */
|
|
59
|
+
supersedeKey: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Persist a cron notification (superseding any still-held row from an earlier run of
|
|
63
|
+
* the same task) and attempt one gated delivery, returning the run's real outcome.
|
|
64
|
+
*
|
|
65
|
+
* The corruption-safety is entirely inherited from {@link deliverAgentMailSerialized}:
|
|
66
|
+
* the body is only ever written to a render-verified empty prompt, and the per-agent
|
|
67
|
+
* serializer means a concurrent send can never interleave with this write. A busy or
|
|
68
|
+
* unclassifiable screen simply leaves the row held for the backstop — there is no
|
|
69
|
+
* force path here, by construction.
|
|
70
|
+
*/
|
|
71
|
+
export declare function deliverCronMail(ports: DeliveryPorts, db: Database.Database, target: CronTarget): Promise<CronDeliveryResult>;
|
|
72
|
+
//# sourceMappingURL=cron-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-delivery.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/cron-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEvF,oEAAoE;AACpE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;AAE7E,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB,8EAA8E;IAC9E,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,iEAAiE;IACjE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,2DAA2D;AAC3D,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAgD7B"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron message delivery through the mailbox + gate (Spec 1313, Phase 6).
|
|
3
|
+
*
|
|
4
|
+
* Cron is today the most unguarded message writer: it wrote straight to the PTY with
|
|
5
|
+
* no idle check and logged "delivered" unconditionally. This phase makes it an
|
|
6
|
+
* ordinary mailbox sender — every cron notification is persisted and then delivered
|
|
7
|
+
* through the SAME single gated path (`deliverAgentMailSerialized`) that `handleSend`
|
|
8
|
+
* and the backstop drainer use, so a cron message can never land mid-draft or fuse
|
|
9
|
+
* with a human's half-typed line. There is no force path: a busy/menu/wrapper screen
|
|
10
|
+
* holds the message for the backstop, exactly like any other send.
|
|
11
|
+
*
|
|
12
|
+
* Two cron-specific twists on top of the shared path:
|
|
13
|
+
* - **Supersede key = task name** (Baked Decision 6): a newer run of a task replaces
|
|
14
|
+
* its own older *held* row instead of queueing a backlog. Supersede keys are
|
|
15
|
+
* cron-only in this project — no non-cron send ever supplies one.
|
|
16
|
+
* - **Honest run outcome**: the caller logs the real fate (`delivered` / `held` /
|
|
17
|
+
* `superseded`) rather than an unconditional "delivered".
|
|
18
|
+
*
|
|
19
|
+
* This module holds the registry-free orchestration core behind the Phase-4
|
|
20
|
+
* {@link DeliveryPorts} seam, so it is unit-testable against a real mailbox DB with
|
|
21
|
+
* fake edges (no live Tower). The identity resolution that needs the live routing
|
|
22
|
+
* registry (`resolveTarget` + the architect reverse-map + the dead-session registry
|
|
23
|
+
* fallback) lives in `tower-routes.ts`'s `deliverCronMessage`, which calls this.
|
|
24
|
+
*/
|
|
25
|
+
import { supersede, getById, countHeldWithKey } from '../db/mailbox.js';
|
|
26
|
+
import { deliverAgentMailSerialized } from './mailbox-delivery.js';
|
|
27
|
+
/** The pseudo-agent identity every cron notification is sent as. */
|
|
28
|
+
export const CRON_SENDER = 'af-cron';
|
|
29
|
+
/**
|
|
30
|
+
* Persist a cron notification (superseding any still-held row from an earlier run of
|
|
31
|
+
* the same task) and attempt one gated delivery, returning the run's real outcome.
|
|
32
|
+
*
|
|
33
|
+
* The corruption-safety is entirely inherited from {@link deliverAgentMailSerialized}:
|
|
34
|
+
* the body is only ever written to a render-verified empty prompt, and the per-agent
|
|
35
|
+
* serializer means a concurrent send can never interleave with this write. A busy or
|
|
36
|
+
* unclassifiable screen simply leaves the row held for the backstop — there is no
|
|
37
|
+
* force path here, by construction.
|
|
38
|
+
*/
|
|
39
|
+
export async function deliverCronMail(ports, db, target) {
|
|
40
|
+
const { workspacePath, toAgent, supersedeKey } = target;
|
|
41
|
+
// Did an earlier run of this task leave a row still held? Read it BEFORE the
|
|
42
|
+
// supersede, with no await between, so the pair is atomic on the synchronous DB
|
|
43
|
+
// handle (see countHeldWithKey). This only informs the log word — the "no backlog"
|
|
44
|
+
// correctness comes from supersede() being atomic regardless.
|
|
45
|
+
const replacedPrior = countHeldWithKey(db, workspacePath, supersedeKey) > 0;
|
|
46
|
+
const row = supersede(db, workspacePath, supersedeKey, {
|
|
47
|
+
workspacePath,
|
|
48
|
+
toAgent,
|
|
49
|
+
terminalId: target.terminalId,
|
|
50
|
+
body: target.body,
|
|
51
|
+
formattedMessage: target.formattedMessage,
|
|
52
|
+
fromAgent: CRON_SENDER,
|
|
53
|
+
fromWorkspace: workspacePath,
|
|
54
|
+
}, ports.now());
|
|
55
|
+
// The held set changed (a new row enqueued, possibly replacing a prior held one) →
|
|
56
|
+
// refresh the indicator count (Spec 1313, Phase 7). A clean delivery below fires it
|
|
57
|
+
// again when the row leaves the set; both are cheap, idempotent refetch triggers.
|
|
58
|
+
ports.onHeldStateChange();
|
|
59
|
+
try {
|
|
60
|
+
await deliverAgentMailSerialized(ports, db, workspacePath, toAgent);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
// A gate/write error leaves the row HELD (markDelivered only runs on a completed
|
|
64
|
+
// write); the backstop drainer retries. Mirrors handleSend — never throws upward.
|
|
65
|
+
ports.log(`[cron] delivery attempt errored for ${toAgent} (row ${row.id.slice(0, 8)}… stays held): ${String(err)}`);
|
|
66
|
+
}
|
|
67
|
+
const stored = getById(db, row.id);
|
|
68
|
+
if (stored?.status === 'delivered') {
|
|
69
|
+
return { outcome: 'delivered', reason: null, mailboxId: row.id };
|
|
70
|
+
}
|
|
71
|
+
// Held. `reason` is set by the delivery pass when it holds; default to `busy` for
|
|
72
|
+
// the rare case where an older row for the same agent delivered first and left ours
|
|
73
|
+
// queued behind it (its Enter makes the line busy for the next pass anyway).
|
|
74
|
+
return {
|
|
75
|
+
outcome: replacedPrior ? 'superseded' : 'held',
|
|
76
|
+
reason: stored?.reason ?? 'busy',
|
|
77
|
+
mailboxId: row.id,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=cron-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-delivery.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/cron-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,0BAA0B,EAAsB,MAAM,uBAAuB,CAAC;AAEvF,oEAAoE;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAoCrC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAoB,EACpB,EAAqB,EACrB,MAAkB;IAElB,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAExD,6EAA6E;IAC7E,gFAAgF;IAChF,mFAAmF;IACnF,8DAA8D;IAC9D,MAAM,aAAa,GAAG,gBAAgB,CAAC,EAAE,EAAE,aAAa,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAG,SAAS,CACnB,EAAE,EACF,aAAa,EACb,YAAY,EACZ;QACE,aAAa;QACb,OAAO;QACP,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,SAAS,EAAE,WAAW;QACtB,aAAa,EAAE,aAAa;KAC7B,EACD,KAAK,CAAC,GAAG,EAAE,CACZ,CAAC;IACF,mFAAmF;IACnF,oFAAoF;IACpF,kFAAkF;IAClF,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAE1B,IAAI,CAAC;QACH,MAAM,0BAA0B,CAAC,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iFAAiF;QACjF,kFAAkF;QAClF,KAAK,CAAC,GAAG,CAAC,uCAAuC,OAAO,SAAS,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,kBAAkB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACnC,IAAI,MAAM,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IACnE,CAAC;IACD,kFAAkF;IAClF,oFAAoF;IACpF,6EAA6E;IAC7E,OAAO;QACL,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM;QAC9C,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM;QAChC,SAAS,EAAE,GAAG,CAAC,EAAE;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Due-time timer for the delayed `afx send --delay --interrupt` path (Spec 1307,
|
|
3
|
+
* reshaped by Spec 1313 round 3).
|
|
4
|
+
*
|
|
5
|
+
* ## What this module does NOW (and no longer does)
|
|
6
|
+
*
|
|
7
|
+
* The message *body* of every `--delay` send is persisted to the durable mailbox
|
|
8
|
+
* at REQUEST time, with a `not_before` due time, by `handleDelayedSend` in
|
|
9
|
+
* tower-routes.ts — NOT here, and NOT at fire time. The gated backstop drainer
|
|
10
|
+
* delivers that row once `not_before` passes, so a plain `--delay` keeps no timer
|
|
11
|
+
* at all and survives a Tower restart by construction.
|
|
12
|
+
*
|
|
13
|
+
* This module holds a due-time timer used by ONE caller: the delayed-`--interrupt`
|
|
14
|
+
* path. When it fires it writes only the Ctrl+C that ends the current turn — no
|
|
15
|
+
* message body, and it marks nothing `delivered`. The body then lands through the
|
|
16
|
+
* same render gate every send uses, after the ^C ends the turn.
|
|
17
|
+
*
|
|
18
|
+
* ## Why the registry exists at all
|
|
19
|
+
*
|
|
20
|
+
* A bare `setTimeout` would work until Tower shuts down, at which point the
|
|
21
|
+
* process would either hang on a pending timer or exit with a ^C half-scheduled
|
|
22
|
+
* and no record of it. The registry makes shutdown explicit.
|
|
23
|
+
*
|
|
24
|
+
* ## Shutdown drops the ^C nudge, never the message
|
|
25
|
+
*
|
|
26
|
+
* A pre-due `--delay` message is a persisted mailbox row: it survives a restart
|
|
27
|
+
* and delivers when the target's prompt is next clean. Only the in-memory ^C
|
|
28
|
+
* nudge is dropped on shutdown — recoverable (a human re-interrupts if it matters),
|
|
29
|
+
* and matching the documented "only the interrupt semantics gracefully degrade"
|
|
30
|
+
* boundary. This is the CONSCIOUS reversal of Spec 1307's original body-drop-on-
|
|
31
|
+
* restart trade (see review 1313): the render gate now supplies the protection that
|
|
32
|
+
* trade wanted — a post-restart delivery still only lands on a render-verified empty
|
|
33
|
+
* prompt, and a stale pending row is visible and cancellable in `afx inbox`.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* Upper bound on `--delay`, in seconds.
|
|
37
|
+
*
|
|
38
|
+
* One hour. Not a meaningful workflow limit — it exists so a typo (`--delay
|
|
39
|
+
* 1500` when 15 was meant) cannot park a message far in the future unnoticed.
|
|
40
|
+
* Under Spec 1313 round 3 a parked send IS listable and cancellable via
|
|
41
|
+
* `afx inbox` / `afx inbox dismiss` (it is a durable mailbox row), but the
|
|
42
|
+
* ceiling stays as a cheap guard against the typo case.
|
|
43
|
+
*/
|
|
44
|
+
export declare const MAX_DELAY_SECONDS = 3600;
|
|
45
|
+
/**
|
|
46
|
+
* Validate a delay in seconds, returning null when acceptable or an error
|
|
47
|
+
* string naming the problem.
|
|
48
|
+
*
|
|
49
|
+
* `Number.isInteger` rather than a bare comparison chain: `NaN > 0` and
|
|
50
|
+
* `NaN <= 0` are both false, so a NaN slips through any single comparison
|
|
51
|
+
* written the obvious way and yields a `setTimeout` that fires immediately —
|
|
52
|
+
* silently converting a delayed send into an immediate one. Infinity is
|
|
53
|
+
* rejected for the same class of reason.
|
|
54
|
+
*/
|
|
55
|
+
export declare function validateDelaySeconds(value: unknown): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Schedule `deliver` to run after `delaySeconds`.
|
|
58
|
+
*
|
|
59
|
+
* The callback is responsible for re-resolving the session and re-deciding how
|
|
60
|
+
* to deliver; this module guarantees only *when* it is invoked, and that it is
|
|
61
|
+
* invoked at most once.
|
|
62
|
+
*/
|
|
63
|
+
export declare function scheduleDelayedSend(delaySeconds: number, terminalId: string,
|
|
64
|
+
/**
|
|
65
|
+
* Invoked when the send comes due. Receives `isStillLive`, which it must
|
|
66
|
+
* re-check at the moment it actually writes (inside the submission lock): a
|
|
67
|
+
* delivery can acquire the lock only AFTER a shutdown that fired while it
|
|
68
|
+
* queued, and the generation check below only guards the moment BEFORE it
|
|
69
|
+
* enters the lock. Return value is ignored.
|
|
70
|
+
*/
|
|
71
|
+
deliver: (isStillLive: () => boolean) => unknown): void;
|
|
72
|
+
/**
|
|
73
|
+
* Cancel every pending delayed send without delivering. Returns the count of
|
|
74
|
+
* still-timing sends dropped, so shutdown can log it rather than losing
|
|
75
|
+
* messages silently.
|
|
76
|
+
*
|
|
77
|
+
* Covers two states: sends still on their timer (cleared here) and sends whose
|
|
78
|
+
* timer has fired but whose delivery has not started — invalidated by bumping
|
|
79
|
+
* `generation`, which the delivery callback re-checks. A delivery already
|
|
80
|
+
* writing when this runs is NOT interrupted; see `generation`'s note.
|
|
81
|
+
*/
|
|
82
|
+
export declare function shutdownDelayedSends(): number;
|
|
83
|
+
/** Number of pending delayed sends. Diagnostics and tests. */
|
|
84
|
+
export declare function pendingDelayedSendCount(): number;
|
|
85
|
+
//# sourceMappingURL=delayed-send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delayed-send.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/delayed-send.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAwCH;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAWlE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM;AAClB;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,OAAO,KAAK,OAAO,GAC/C,IAAI,CAmCN;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAQ7C;AAED,8DAA8D;AAC9D,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD"}
|