create-walle 0.10.2 → 0.10.3
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 +3 -1
- package/lib/release-schema.json +2 -2
- package/lib/runtime-closure-policy.json +8 -7
- package/package.json +1 -1
- package/template/coding-task-manager/api-prompts.js +45 -7
- package/template/coding-task-manager/bin/claude-hook.js +55 -1
- package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
- package/template/coding-task-manager/bin/land.js +2069 -0
- package/template/coding-task-manager/bin/memory-census.js +4 -2
- package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
- package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
- package/template/coding-task-manager/db.js +156 -32
- package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
- package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
- package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
- package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
- package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
- package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
- package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
- package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
- package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
- package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
- package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
- package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
- package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
- package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
- package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
- package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
- package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
- package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
- package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
- package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
- package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
- package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
- package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
- package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
- package/template/coding-task-manager/lib/agent-definitions.js +19 -0
- package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
- package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
- package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
- package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
- package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
- package/template/coding-task-manager/lib/agent-presets.js +84 -1
- package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
- package/template/coding-task-manager/lib/agent-version-service.js +74 -11
- package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
- package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
- package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
- package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
- package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
- package/template/coding-task-manager/lib/api/fleet.js +118 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +9 -1
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machines.js +691 -2
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/session-attach.js +623 -0
- package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
- package/template/coding-task-manager/lib/api/sessions.js +77 -51
- package/template/coding-task-manager/lib/api/setup-network.js +544 -16
- package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
- package/template/coding-task-manager/lib/api/setup.js +829 -10
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
- package/template/coding-task-manager/lib/auth-rules.js +292 -21
- package/template/coding-task-manager/lib/background-stop.js +369 -0
- package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
- package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
- package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
- package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
- package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
- package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
- package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
- package/template/coding-task-manager/lib/conversation-sync.js +355 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
- package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
- package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
- package/template/coding-task-manager/lib/db-domains.js +1 -0
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
- package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
- package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +4 -0
- package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
- package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
- package/template/coding-task-manager/lib/fleet-hub.js +762 -0
- package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
- package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
- package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
- package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
- package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
- package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
- package/template/coding-task-manager/lib/fleet-update.js +798 -0
- package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
- package/template/coding-task-manager/lib/fs-watcher.js +58 -42
- package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
- package/template/coding-task-manager/lib/headless-term-service.js +84 -8
- package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
- package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
- package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
- package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
- package/template/coding-task-manager/lib/host-handoff.js +16 -19
- package/template/coding-task-manager/lib/host-stats.js +150 -3
- package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
- package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
- package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
- package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
- package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
- package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
- package/template/coding-task-manager/lib/hub-bridge.js +398 -0
- package/template/coding-task-manager/lib/idle-notify.js +491 -0
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
- package/template/coding-task-manager/lib/instance-manifest.js +5 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
- package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
- package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
- package/template/coding-task-manager/lib/landing/config.js +536 -0
- package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
- package/template/coding-task-manager/lib/landing/gate.js +360 -0
- package/template/coding-task-manager/lib/landing/git.js +344 -0
- package/template/coding-task-manager/lib/landing/lease.js +247 -0
- package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
- package/template/coding-task-manager/lib/landing/proof.js +223 -0
- package/template/coding-task-manager/lib/landing/queue.js +998 -0
- package/template/coding-task-manager/lib/landing/radar.js +489 -0
- package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
- package/template/coding-task-manager/lib/landing/state.js +263 -0
- package/template/coding-task-manager/lib/landing/stop.js +49 -0
- package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
- package/template/coding-task-manager/lib/landing/sync.js +456 -0
- package/template/coding-task-manager/lib/landing/train.js +885 -0
- package/template/coding-task-manager/lib/landing/window.js +57 -0
- package/template/coding-task-manager/lib/launch-environment.js +121 -0
- package/template/coding-task-manager/lib/launch-model-override.js +36 -10
- package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
- package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
- package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
- package/template/coding-task-manager/lib/lead-model-options.js +160 -3
- package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
- package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
- package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
- package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
- package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
- package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
- package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
- package/template/coding-task-manager/lib/machine-registry.js +750 -5
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
- package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
- package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
- package/template/coding-task-manager/lib/memory-join.js +337 -0
- package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
- package/template/coding-task-manager/lib/memory-sync.js +565 -0
- package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
- package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
- package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
- package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
- package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
- package/template/coding-task-manager/lib/model-availability.js +727 -0
- package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
- package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
- package/template/coding-task-manager/lib/model-id-rule.js +19 -0
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
- package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
- package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
- package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
- package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
- package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +6 -4
- package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
- package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
- package/template/coding-task-manager/lib/opencode-cli.js +480 -0
- package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
- package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
- package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
- package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
- package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
- package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
- package/template/coding-task-manager/lib/perf-summary.js +7 -0
- package/template/coding-task-manager/lib/perf-tracker.js +63 -2
- package/template/coding-task-manager/lib/project-config.js +7 -0
- package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/read-pool-client.js +89 -2
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
- package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
- package/template/coding-task-manager/lib/relay-client.js +57 -3
- package/template/coding-task-manager/lib/relink-audit.js +34 -5
- package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
- package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
- package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
- package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
- package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
- package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
- package/template/coding-task-manager/lib/restart-guard.js +18 -6
- package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
- package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
- package/template/coding-task-manager/lib/resume-admission.js +17 -3
- package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
- package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
- package/template/coding-task-manager/lib/runtime-contract.js +3 -1
- package/template/coding-task-manager/lib/schema-indexes.js +1 -0
- package/template/coding-task-manager/lib/session-context-locator.js +742 -0
- package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
- package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
- package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
- package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
- package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
- package/template/coding-task-manager/lib/session-create/response.js +7 -7
- package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
- package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
- package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
- package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
- package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-host-manager.js +60 -0
- package/template/coding-task-manager/lib/session-jobs.js +3 -1
- package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
- package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
- package/template/coding-task-manager/lib/session-park.js +738 -0
- package/template/coding-task-manager/lib/session-path-grant.js +13 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
- package/template/coding-task-manager/lib/session-transport.js +17 -0
- package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
- package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
- package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
- package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
- package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
- package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
- package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
- package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
- package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
- package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
- package/template/coding-task-manager/lib/submission-ack.js +90 -2
- package/template/coding-task-manager/lib/systemd-scope.js +115 -0
- package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
- package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
- package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
- package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
- package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
- package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
- package/template/coding-task-manager/lib/transcript-source.js +36 -4
- package/template/coding-task-manager/lib/transcript-store.js +9 -0
- package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
- package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
- package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
- package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
- package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
- package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
- package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
- package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
- package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
- package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
- package/template/coding-task-manager/lib/walle/turn.js +1 -1
- package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
- package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
- package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
- package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
- package/template/coding-task-manager/lib/walle-row-history.js +495 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
- package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
- package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
- package/template/coding-task-manager/lib/ws/misc.js +1 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
- package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
- package/template/coding-task-manager/oauth-proxy.js +112 -115
- package/template/coding-task-manager/package-lock.json +10 -94
- package/template/coding-task-manager/package.json +4 -3
- package/template/coding-task-manager/protocol/message-table.json +10 -0
- package/template/coding-task-manager/protocol/messages.js +10 -0
- package/template/coding-task-manager/protocol/ws-schema.json +20 -0
- package/template/coding-task-manager/protocol/ws-schema.md +2 -0
- package/template/coding-task-manager/public/css/app.css +170 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +473 -243
- package/template/coding-task-manager/public/js/agent-command.js +86 -0
- package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
- package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
- package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
- package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
- package/template/coding-task-manager/public/js/background-work.js +196 -27
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
- package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
- package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
- package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
- package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
- package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
- package/template/coding-task-manager/public/js/document-review-links.js +9 -1
- package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
- package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
- package/template/coding-task-manager/public/js/message-renderer.js +4 -3
- package/template/coding-task-manager/public/js/model-picker.js +3 -1
- package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
- package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
- package/template/coding-task-manager/public/js/pasted-content.js +236 -0
- package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
- package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
- package/template/coding-task-manager/public/js/prompts.js +11 -10
- package/template/coding-task-manager/public/js/protocol.js +10 -0
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
- package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
- package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
- package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
- package/template/coding-task-manager/public/js/stream-view.js +6 -5
- package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
- package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
- package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
- package/template/coding-task-manager/public/js/walle.js +6 -0
- package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
- package/template/coding-task-manager/public/m/app.css +140 -0
- package/template/coding-task-manager/public/m/app.js +507 -68
- package/template/coding-task-manager/public/m/index.html +17 -0
- package/template/coding-task-manager/public/m/machines.js +838 -4
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
- package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
- package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
- package/template/coding-task-manager/server.js +1950 -11679
- package/template/coding-task-manager/session-integrity.js +64 -4
- package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
- package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
- package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
- package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
- package/template/coding-task-manager/workers/session-host-process.js +5 -5
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +168 -33
- package/template/ctm-relay/lib/protocol.js +14 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/shared/backup-retention.js +82 -0
- package/template/shared/conversation-admission.js +2 -0
- package/template/shared/conversation-provenance.js +3 -7
- package/template/shared/conversation-storage-v2-contract.js +5 -0
- package/template/shared/linked-worktree.js +51 -0
- package/template/shared/macos-fda-target.js +57 -0
- package/template/shared/orphan-parents.js +55 -0
- package/template/shared/release-schema.json +2 -2
- package/template/shared/storage/contract.js +3 -0
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +71 -4
- package/template/wall-e/api-walle.js +21 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
- package/template/wall-e/brain/brain-join.js +859 -0
- package/template/wall-e/brain/brain-sync-membership.js +20 -0
- package/template/wall-e/brain/brain-sync-store.js +131 -77
- package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
- package/template/wall-e/brain/brain-sync-v2.js +578 -0
- package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
- package/template/wall-e/brain/deterministic-id.js +51 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +40 -6
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +23 -7
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +171 -35
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/config/main-loop-exemptions.json +2 -2
- package/template/wall-e/http/admin-api.js +37 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +7 -1
- package/template/wall-e/http/model-admin.js +8 -1
- package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
- package/template/wall-e/http/model-proxy-providers.js +174 -1
- package/template/wall-e/http/model-route-health.js +157 -0
- package/template/wall-e/http/sync-api.js +278 -464
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/ctm-data-dir.js +26 -0
- package/template/wall-e/lib/derivation-home.js +147 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
- package/template/wall-e/lib/helper-rules/grade.js +51 -8
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
- package/template/wall-e/lib/helper-rules/store.js +4 -2
- package/template/wall-e/lib/landing-mcp-tools.js +170 -0
- package/template/wall-e/lib/mcp-client-config.js +133 -14
- package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
- package/template/wall-e/lib/mcp-integration.js +58 -13
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
- package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
- package/template/wall-e/llm/delegate-vendor-default.js +12 -5
- package/template/wall-e/llm/model-roles.js +1 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +66 -17
- package/template/wall-e/loops/brain-custom-writes.js +19 -0
- package/template/wall-e/loops/ingest.js +17 -1
- package/template/wall-e/loops/think.js +19 -4
- package/template/wall-e/mcp-contract.js +222 -6
- package/template/wall-e/mcp-protocol-contract.js +40 -5
- package/template/wall-e/mcp-server.js +128 -29
- package/template/wall-e/mcp-worker-schemas.js +5 -5
- package/template/wall-e/memory/ctm-context-client.js +85 -0
- package/template/wall-e/memory/ctm-session-context.js +9 -3
- package/template/wall-e/memory/hub-bridge-client.js +388 -0
- package/template/wall-e/memory/replica-origin.js +56 -0
- package/template/wall-e/memory/session-pool.js +135 -0
- package/template/wall-e/runtime/live-capabilities.js +8 -3
- package/template/wall-e/server.js +4 -2
- package/template/wall-e/shared/release-schema.json +2 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/storage/contract.js +3 -0
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
- package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
- package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
- package/template/wall-e/tools/chrome-automation.js +6 -0
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +18 -4
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
|
@@ -42,6 +42,9 @@ const MACHINE_HEADER = 'x-ctm-machine';
|
|
|
42
42
|
const MACHINE_QUERY_PARAM = 'machine';
|
|
43
43
|
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
44
44
|
const BODY_LIMIT_BYTES = 1024 * 1024;
|
|
45
|
+
// D-5 (§6.4): a box mid fleet-update is silent for a minute or two. A bundle the hub sent inside
|
|
46
|
+
// this window is what lets a 502 name the update instead of leaving the user with "unreachable".
|
|
47
|
+
const FLEET_UPDATE_MAX_AGE_MS = 10 * 60 * 1000;
|
|
45
48
|
|
|
46
49
|
// The four routes this WP proxies (§9 S-9/S-10). Keyed `METHOD /pathname`, the same spelling the
|
|
47
50
|
// lead passes as `{ route }`.
|
|
@@ -72,6 +75,39 @@ const PROXIED_ROUTES = Object.freeze([
|
|
|
72
75
|
'GET /api/providers/login-state',
|
|
73
76
|
'POST /api/providers/:id/login',
|
|
74
77
|
'POST /api/providers/:id/login/code',
|
|
78
|
+
// WP-2 (docs/remote-box-model-access-2026-10-26.html §6.3, §5.1 R-4, §5.3 D-4): the picker's four
|
|
79
|
+
// lead-model calls for a MIRROR session are answered by the BOX that owns the session, through
|
|
80
|
+
// lib/remote-machine-catalog.js `forwardLeadModelRequest`, which names the REAL box path. Declared
|
|
81
|
+
// here so the box-routed route list stays the ONE inventory of what crosses the peer leg (the same
|
|
82
|
+
// `:id` spelling as the templated rows above).
|
|
83
|
+
'GET /api/sessions/:id/lead-model/options',
|
|
84
|
+
'POST /api/sessions/:id/lead-model',
|
|
85
|
+
'GET /api/sessions/:id/lead-model/request',
|
|
86
|
+
'DELETE /api/sessions/:id/lead-model/request',
|
|
87
|
+
// WP-3 (docs/remote-session-child-transcript-model-truth-and-restart-2026-10-27.html §5 D-4, §8
|
|
88
|
+
// WP-3): the Delegate pane's ladder read for a BOX-owned session is answered by the box that owns
|
|
89
|
+
// it, through lib/api/walle-bridge.js `handleProxy` → lib/remote-machine-catalog.js
|
|
90
|
+
// `forwardDelegatePrefsRequest` (a MIRROR lookup on the `ctm_session_id` query param, not a path
|
|
91
|
+
// id). Declared here so this list stays the ONE inventory of what crosses the peer leg.
|
|
92
|
+
'GET /api/models/delegate-prefs',
|
|
93
|
+
// WP-1 (docs/remote-session-delegate-pick-write-forward-2026-10-30.html D-1/D-2/D-7): the same
|
|
94
|
+
// forward carries the two WRITES that set a rung of that box's own ladder — a pick saved on the
|
|
95
|
+
// hub's Wall-E is one the box never reads. Same peer leg, same `ctm_session_id` ownership lookup.
|
|
96
|
+
'PUT /api/models/delegate-prefs',
|
|
97
|
+
'DELETE /api/models/delegate-prefs/:scope',
|
|
98
|
+
// WP-0 (docs/recent-sessions-follow-computer-filter-2026-10-31.html §5 D-2, §6): with a box
|
|
99
|
+
// selected the Recent list, its server-side search and the single-click review transcript all
|
|
100
|
+
// come from that box — the same ?machine= + peer-bearer leg as every row above, so the hub never
|
|
101
|
+
// has to mirror a box's sessions. The box already answers /api/recent-sessions and admits the
|
|
102
|
+
// peer bearer for it (lib/auth-rules.js); the other two rows gain the flag in the same change.
|
|
103
|
+
'GET /api/recent-sessions',
|
|
104
|
+
'GET /api/sessions/search',
|
|
105
|
+
'GET /api/session/messages',
|
|
106
|
+
// WP-4 (docs/fleet-session-lists-hub-search-2026-11-01.html §6.3, §9 S-15): the PE conversations
|
|
107
|
+
// list is fleet-wide (api-prompts.js wraps it with fleetRouted), so a stamped row's single-click
|
|
108
|
+
// view is answered by the BOX that owns the conversation — same `?machine=` + peer-bearer leg as
|
|
109
|
+
// the rows above, with lib/auth-rules.js admitting the peer bearer for both shapes.
|
|
110
|
+
'GET /api/conversations/:id',
|
|
75
111
|
]);
|
|
76
112
|
|
|
77
113
|
// S-10 mixed-request refusal: a create that names a REMOTE machine must carry the BOX-owned source
|
|
@@ -178,6 +214,63 @@ function _recencyScore(row, index) {
|
|
|
178
214
|
return index ? -index : 0;
|
|
179
215
|
}
|
|
180
216
|
|
|
217
|
+
// ---------------------------------------------------------------------------------------------
|
|
218
|
+
// WP-4 (D-5, §6.4): the failure trace and the "box is restarting for an update" name.
|
|
219
|
+
// ---------------------------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* D-5: ONE line per failed forward, so the next 02:20 has a record on the hub. `route`, `machine`
|
|
223
|
+
* and `status` are the only identifiers; `detail` is the refusal's own short reason. Headers,
|
|
224
|
+
* bodies and tokens are NEVER logged.
|
|
225
|
+
*/
|
|
226
|
+
function _logProxyFailure(route, machine, status, detail, startedAt) {
|
|
227
|
+
const elapsedMs = Math.max(0, Date.now() - (Number(startedAt) || Date.now()));
|
|
228
|
+
console.warn(`[remote-proxy] ${route} machine=${machine} status=${status} detail=${_string(detail, 300)} elapsedMs=${elapsedMs}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* D-5: the hub's persisted per-box fleet record -> `{ to, sentAt }` for a box the hub sent a
|
|
233
|
+
* bundle to inside the last 10 minutes, else null. Reads the normalized shape
|
|
234
|
+
* lib/fleet-hub.js `_normalizeHubState` produces: `{ inFlight: {instanceId, target, sentAt}|null,
|
|
235
|
+
* boxes: { [id]: { lastSentAt, attempts: { [target]: {sentAt, verdict, reason} } } } }`.
|
|
236
|
+
*/
|
|
237
|
+
function _fleetUpdateFromHubState(state, instanceId, now = Date.now()) {
|
|
238
|
+
const id = _string(instanceId, 160);
|
|
239
|
+
if (!state || !id) return null;
|
|
240
|
+
const fresh = (sentAt) => Number.isFinite(sentAt) && sentAt > 0 && now - sentAt < FLEET_UPDATE_MAX_AGE_MS;
|
|
241
|
+
const inFlight = state.inFlight;
|
|
242
|
+
if (inFlight && _string(inFlight.instanceId, 160) === id && fresh(Number(inFlight.sentAt))) {
|
|
243
|
+
return { to: _string(inFlight.target, 200), sentAt: Number(inFlight.sentAt) };
|
|
244
|
+
}
|
|
245
|
+
const box = state.boxes && typeof state.boxes === 'object' ? state.boxes[id] : null;
|
|
246
|
+
const attempts = box && box.attempts && typeof box.attempts === 'object' ? box.attempts : null;
|
|
247
|
+
if (!attempts) return null;
|
|
248
|
+
let best = null;
|
|
249
|
+
for (const [target, attempt] of Object.entries(attempts)) {
|
|
250
|
+
if (!attempt || typeof attempt !== 'object') continue;
|
|
251
|
+
if (String(attempt.verdict || '') !== 'sent') continue;
|
|
252
|
+
const sentAt = Number(attempt.sentAt);
|
|
253
|
+
if (!fresh(sentAt)) continue;
|
|
254
|
+
if (!best || sentAt > best.sentAt) best = { to: _string(target, 200), sentAt };
|
|
255
|
+
}
|
|
256
|
+
return best;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* D-5: the injected seam (`deps.fleetUpdateFor(instanceId)`), defaulting to the hub's own
|
|
261
|
+
* `<dataDir>/fleet-hub.json`. A lookup failure — no file, unreadable data dir, a throwing stub —
|
|
262
|
+
* is null and NOTHING else: naming an update may never change the proxy's own outcome.
|
|
263
|
+
*/
|
|
264
|
+
async function _fleetUpdateFor(deps, instanceId) {
|
|
265
|
+
try {
|
|
266
|
+
if (typeof deps.fleetUpdateFor === 'function') return await deps.fleetUpdateFor(instanceId);
|
|
267
|
+
const state = await require('./fleet-hub').readHubState(require('./data-dir').getDataDir());
|
|
268
|
+
return _fleetUpdateFromHubState(state, instanceId, Date.now());
|
|
269
|
+
} catch {
|
|
270
|
+
return null; /* expected: no fleet record yet (or an unreadable data dir) — the proxy still answers 502 */
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
181
274
|
/**
|
|
182
275
|
* The routing machine id, or '' when this request is not machine-routed at all.
|
|
183
276
|
* Query/header are consulted first so the common GET path never touches the request body.
|
|
@@ -197,6 +290,26 @@ function isMachineRouted(req, url) {
|
|
|
197
290
|
return !!_machineFromRequest(req, _resolveUrl(req, url));
|
|
198
291
|
}
|
|
199
292
|
|
|
293
|
+
/**
|
|
294
|
+
* WP-0 (docs/recent-sessions-follow-computer-filter-2026-10-31.html §5 D-2, §6): wrap a route
|
|
295
|
+
* handler so a picker request naming another machine (?machine= / X-CTM-Machine) is answered by
|
|
296
|
+
* that box and every other request is the unchanged local handler — the same shape
|
|
297
|
+
* lib/api/misc-ops.js's `_machineRouted` keeps for its own rows. Exported so lib/api/sessions.js
|
|
298
|
+
* can wrap its three rows without a fourth private copy (and without growing past its file-size
|
|
299
|
+
* ceiling). `local` runs exactly when the request is not machine-routed, or when the hook declines
|
|
300
|
+
* (a route it does not own) — the `handled === true` case never touches it.
|
|
301
|
+
*
|
|
302
|
+
* @param {string} route `'METHOD /pathname'`, the key PROXIED_ROUTES spells
|
|
303
|
+
* @param {(req: any, res: any, url: URL) => any} local
|
|
304
|
+
* @returns {(req: any, res: any, url: URL) => any}
|
|
305
|
+
*/
|
|
306
|
+
function machineRouted(route, local) {
|
|
307
|
+
return (req, res, url) => (isMachineRouted(req, url)
|
|
308
|
+
? maybeProxyMachineRequest(req, res, url, { route })
|
|
309
|
+
.then((handled) => (handled ? undefined : local(req, res, url)))
|
|
310
|
+
: local(req, res, url));
|
|
311
|
+
}
|
|
312
|
+
|
|
200
313
|
function _localInstanceId(deps) {
|
|
201
314
|
if (typeof deps.localInstanceId === 'string') return _string(deps.localInstanceId, 160);
|
|
202
315
|
try {
|
|
@@ -273,6 +386,9 @@ async function maybeProxyMachineRequest(req, res, url, options = {}) {
|
|
|
273
386
|
const isPost = route.startsWith('POST ');
|
|
274
387
|
const machine = _machineFromRequest(req, parsed);
|
|
275
388
|
if (!machine) return false;
|
|
389
|
+
// D-5: the clock every `[remote-proxy]` line reports against — the whole machine-routed
|
|
390
|
+
// handling, from the registry read to the box's answer.
|
|
391
|
+
const startedAt = Date.now();
|
|
276
392
|
let rawBody = null;
|
|
277
393
|
let parsedBody = null;
|
|
278
394
|
|
|
@@ -306,14 +422,22 @@ async function maybeProxyMachineRequest(req, res, url, options = {}) {
|
|
|
306
422
|
}
|
|
307
423
|
|
|
308
424
|
const machineName = _string(target.displayName, 200) || machine;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
machine,
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
425
|
+
// D-5: every 502 is logged once, and names the update the box is applying when the hub's fleet
|
|
426
|
+
// record says a bundle went to it inside the last 10 minutes.
|
|
427
|
+
const unreachable = async (extra = {}) => {
|
|
428
|
+
const status = 502;
|
|
429
|
+
_logProxyFailure(route, machine, status, extra.detail || extra.error || '', startedAt);
|
|
430
|
+
const update = await _fleetUpdateFor(deps, machine);
|
|
431
|
+
return _sendJson(res, status, {
|
|
432
|
+
ok: false,
|
|
433
|
+
code: 'machine_unreachable',
|
|
434
|
+
error: `Machine ${machineName} is unreachable`,
|
|
435
|
+
machine,
|
|
436
|
+
machineName,
|
|
437
|
+
...extra,
|
|
438
|
+
...(update && typeof update === 'object' ? { box_updating: { to: _string(update.to, 200) } } : {}),
|
|
439
|
+
});
|
|
440
|
+
};
|
|
317
441
|
|
|
318
442
|
// S-10: a create that mixes a hub-local worktree source with a remote machine is refused rather
|
|
319
443
|
// than silently creating a worktree on the hub (whose path the caller would then hand to the box).
|
|
@@ -358,6 +482,7 @@ async function maybeProxyMachineRequest(req, res, url, options = {}) {
|
|
|
358
482
|
// what it says: the box was dialled and did not answer.
|
|
359
483
|
if (!peerHeaders) {
|
|
360
484
|
const missing = _peerCredentialMissing(machineName);
|
|
485
|
+
_logProxyFailure(route, machine, 503, missing.code, startedAt);
|
|
361
486
|
return _sendJson(res, 503, {
|
|
362
487
|
ok: false,
|
|
363
488
|
code: missing.code,
|
|
@@ -430,7 +555,13 @@ async function maybeProxyMachineRequest(req, res, url, options = {}) {
|
|
|
430
555
|
if (res.headersSent) return true;
|
|
431
556
|
// The box's status and body are returned VERBATIM (§6.5): the picker parses the box's own
|
|
432
557
|
// payload shape, and a hub that re-shaped it would drift from the local case.
|
|
433
|
-
|
|
558
|
+
const upstreamStatus = Number(response.status) || 502;
|
|
559
|
+
// D-5: a non-2xx answer from the box is a failed forward like any other. The body is never
|
|
560
|
+
// logged — only "upstream", because the box's own payload may carry anything.
|
|
561
|
+
if (upstreamStatus < 200 || upstreamStatus >= 300) {
|
|
562
|
+
_logProxyFailure(route, machine, upstreamStatus, 'upstream', startedAt);
|
|
563
|
+
}
|
|
564
|
+
res.writeHead(upstreamStatus, {
|
|
434
565
|
'Content-Type': _string(response.headers && response.headers.get && response.headers.get('content-type'), 200)
|
|
435
566
|
|| 'application/json',
|
|
436
567
|
});
|
|
@@ -509,12 +640,15 @@ module.exports = {
|
|
|
509
640
|
MACHINE_HEADER,
|
|
510
641
|
MACHINE_QUERY_PARAM,
|
|
511
642
|
DEFAULT_TIMEOUT_MS,
|
|
643
|
+
FLEET_UPDATE_MAX_AGE_MS,
|
|
512
644
|
PROXIED_ROUTES,
|
|
513
645
|
configure,
|
|
514
646
|
isMachineRouted,
|
|
647
|
+
machineRouted,
|
|
515
648
|
maybeProxyMachineRequest,
|
|
516
649
|
forwardMachineHttp,
|
|
517
650
|
matchBoxProject,
|
|
518
651
|
normalizeGitRemote,
|
|
519
652
|
_recencyScore,
|
|
653
|
+
_fleetUpdateFromHubState,
|
|
520
654
|
};
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
// that owns the session — the bytes must land on the PTY host, because the CLI opens the delivered
|
|
13
13
|
// draft path on its own filesystem (§1 "Where the bytes must live").
|
|
14
14
|
//
|
|
15
|
-
// It is deliberately NOT a general reverse proxy
|
|
16
|
-
//
|
|
15
|
+
// It is deliberately NOT a general reverse proxy. Two dispatch lines use it today: WP-3's image-draft
|
|
16
|
+
// line in api-prompts.js, and WP-2's three terminal-history reads in lib/api/sessions.js (through
|
|
17
|
+
// `serveMirrorOrLocal` below):
|
|
17
18
|
//
|
|
18
19
|
// D-1 ownership is decided ONCE, by `catalog.getMirrorSessionMachine` — local sessions Map
|
|
19
20
|
// first (the 2026-10-23 relay-hijack fix), then the forwarded creates, the live catalog and
|
|
@@ -66,11 +67,24 @@ const FORWARDED_REQUEST_HEADERS = Object.freeze(['content-type', 'content-length
|
|
|
66
67
|
// keep its own retry hint; everything else (set-cookie, server, date) stays at the hop that owns it.
|
|
67
68
|
const FORWARDED_RESPONSE_HEADERS = Object.freeze(['content-type', 'content-length', 'etag', 'cache-control', 'retry-after', 'x-content-type-options']);
|
|
68
69
|
|
|
69
|
-
// D-3: the closed forwarded set. Each entry is [METHOD, RegExp on pathname]
|
|
70
|
-
// image-draft peer-control routes on the box (lib/auth-rules.js:164-179)
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
70
|
+
// D-3: the closed forwarded set — EIGHTEEN members. Each entry is [METHOD, RegExp on pathname]. The
|
|
71
|
+
// first ten mirror the image-draft peer-control routes on the box (lib/auth-rules.js:164-179)
|
|
72
|
+
// exactly; WP-1 of docs/composer-image-chip-stuck-submission-recovery-2026-10-30.html §5 R-1 adds the
|
|
73
|
+
// eleventh, `POST /api/sessions/<id>/image-refs` (image-ref recording, session-scoped so it can be
|
|
74
|
+
// forwarded); the next three are WP-2's box-owned terminal-history reads — the SINGULAR
|
|
75
|
+
// `/api/session/<id>/(history-window|scrollback|painted-rows)` GETs
|
|
76
|
+
// (docs/remote-session-history-reads-and-box-status-hooks-2026-10-26.html WP-2 / D-3), whose matching
|
|
77
|
+
// `peerControl` row is lib/auth-rules.js's single anchor regex; the fourteenth is WP-13's canonical
|
|
78
|
+
// conversation read for a BOX-OWNED session — the SINGULAR `/api/session/messages` GET, whose session
|
|
79
|
+
// id rides the `?id=` query (see the member's own comment below); the last three are WP-1's box-owned
|
|
80
|
+
// child-transcript routes — the native/worker review GETs and the native clear cutoff
|
|
81
|
+
// (docs/remote-session-child-transcript-model-truth-and-restart-2026-10-27.html §5 D-2/D-3), whose
|
|
82
|
+
// `peerControl` rows are lib/auth-rules.js:181/187/485. The
|
|
83
|
+
// pairing meta-test is tests/peer-control-auth.test.js → `forwarded-route pairing: every
|
|
84
|
+
// FORWARDED_SESSION_ROUTES member resolves to a peerControl HTTP rule with the same method`: it
|
|
85
|
+
// iterates this set and fails when a member here has no flagged row on the box. A member added here
|
|
86
|
+
// without that flag turns the hub's honest 503 into the box's 403 insufficient_scope (the
|
|
87
|
+
// incident-2/incident-3 class).
|
|
74
88
|
const FORWARDED_SESSION_ROUTES = Object.freeze([
|
|
75
89
|
['GET', /^\/api\/sessions\/[^/]+\/image-drafts$/],
|
|
76
90
|
['GET', /^\/api\/sessions\/[^/]+\/image-drafts\/[^/]+\/content$/],
|
|
@@ -82,6 +96,31 @@ const FORWARDED_SESSION_ROUTES = Object.freeze([
|
|
|
82
96
|
['POST', /^\/api\/sessions\/[^/]+\/image-drafts\/[^/]+\/freeze$/],
|
|
83
97
|
['POST', /^\/api\/sessions\/[^/]+\/image-drafts\/[^/]+\/submit$/],
|
|
84
98
|
['POST', /^\/api\/sessions\/[^/]+\/image-drafts\/[^/]+\/retry$/],
|
|
99
|
+
// WP-1 (§5 R-1, §6, §8 WP-1): image-ref RECORDING is session-scoped so it can be forwarded too —
|
|
100
|
+
// the draft it resolves lives on the box that owns a MIRROR session, and the hub's local resolver
|
|
101
|
+
// cannot see it (it answered CTM_SESSION_IMAGE_REF_UNRESOLVED until this row existed). The singular
|
|
102
|
+
// `/api/session/image-refs` path is REMOVED, not aliased, and lib/auth-rules.js carries the paired
|
|
103
|
+
// peerControl row.
|
|
104
|
+
['POST', /^\/api\/sessions\/[^/]+\/image-refs$/],
|
|
105
|
+
// WP-2/D-3: the box's terminal-history reads — SINGULAR `/api/session/`, not `/api/sessions/`.
|
|
106
|
+
['GET', /^\/api\/session\/[^/]+\/history-window$/],
|
|
107
|
+
['GET', /^\/api\/session\/[^/]+\/scrollback$/],
|
|
108
|
+
['GET', /^\/api\/session\/[^/]+\/painted-rows$/],
|
|
109
|
+
// WP-13 (docs/deepseek-harness-acp-agent-2026-10-28.html §5 D-25, §8 WP-13, §9 R-1, §10 T-23): the
|
|
110
|
+
// CANONICAL conversation read — the one the Conv view polls. It was local-only, so a box-owned
|
|
111
|
+
// session's Conv showed nothing on the hub for EVERY agent (Claude and Codex included, not just
|
|
112
|
+
// dsh): the hub holds no session row for a mirror id, so its own reader answered empty. There is
|
|
113
|
+
// ONE generic forward — no dsh-only route and no hub mirror file. The session id is the `?id=`
|
|
114
|
+
// QUERY parameter here (server.js's apiSessionMessages reads `url.searchParams.get('id')`), so the
|
|
115
|
+
// dispatch line in lib/api/sessions.js passes that value as serveMirrorOrLocal's encodedSessionId.
|
|
116
|
+
// The pathname is fixed, which is all this predicate needs (D-3 is purely lexical).
|
|
117
|
+
['GET', /^\/api\/session\/messages$/],
|
|
118
|
+
// WP-1 (docs/remote-session-child-transcript-model-truth-and-restart-2026-10-27.html §5 D-2):
|
|
119
|
+
// child-transcript reads and the clear cutoff are box-owned — the transcript and the native
|
|
120
|
+
// runtime live on the box; the hub has no row for a mirror id.
|
|
121
|
+
['GET', /^\/api\/sessions\/[^/]+\/native-subagents\/[^/]+\/messages$/],
|
|
122
|
+
['GET', /^\/api\/sessions\/[^/]+\/worker-transcript\/messages$/],
|
|
123
|
+
['POST', /^\/api\/sessions\/[^/]+\/native-subagents\/clear$/],
|
|
85
124
|
]);
|
|
86
125
|
|
|
87
126
|
function _string(value, max = 200) {
|
|
@@ -296,6 +335,24 @@ async function maybeForwardSessionRequest(req, res, url, sessionId, deps = {}) {
|
|
|
296
335
|
return true;
|
|
297
336
|
}
|
|
298
337
|
|
|
338
|
+
/**
|
|
339
|
+
* D-1/D-4: serve `localHandler` for a local or unclaimed id (same tick, request untouched), or forward a mirror id.
|
|
340
|
+
* @param {import('http').IncomingMessage} req
|
|
341
|
+
* @param {import('http').ServerResponse} res
|
|
342
|
+
* @param {URL} url
|
|
343
|
+
* @param {string} encodedSessionId the raw path segment (route param '1')
|
|
344
|
+
* @param {(req, res, url, encodedSessionId) => any} localHandler
|
|
345
|
+
* @param {object} [deps] passed through to isMirrorSessionRequest / maybeForwardSessionRequest
|
|
346
|
+
*/
|
|
347
|
+
function serveMirrorOrLocal(req, res, url, encodedSessionId, localHandler, deps = {}) {
|
|
348
|
+
let sessionId = '';
|
|
349
|
+
try { sessionId = decodeURIComponent(String(encodedSessionId || '')); }
|
|
350
|
+
catch { return localHandler(req, res, url, encodedSessionId); } // expected: a malformed id is the local handler's 4xx to give
|
|
351
|
+
if (!isMirrorSessionRequest(req, url, sessionId, deps)) return localHandler(req, res, url, encodedSessionId);
|
|
352
|
+
return maybeForwardSessionRequest(req, res, url, sessionId, deps)
|
|
353
|
+
.then((forwarded) => (forwarded ? undefined : localHandler(req, res, url, encodedSessionId)));
|
|
354
|
+
}
|
|
355
|
+
|
|
299
356
|
module.exports = {
|
|
300
357
|
FORWARDED_SESSION_ROUTES,
|
|
301
358
|
FORWARD_DEADLINE_MS,
|
|
@@ -303,4 +360,5 @@ module.exports = {
|
|
|
303
360
|
maybeForwardSessionRequest,
|
|
304
361
|
isForwardedSessionRoute,
|
|
305
362
|
isMirrorSessionRequest,
|
|
363
|
+
serveMirrorOrLocal,
|
|
306
364
|
};
|
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
const attemptOwners = new WeakMap();
|
|
4
4
|
|
|
5
|
+
// The delivery target's process identity: a PTY session's ptyProcess, or an ACP (DeepSeek Harness)
|
|
6
|
+
// session's `_acpProcess` token — set once per child by lib/session-create/dsh-session.js and cleared when
|
|
7
|
+
// the child exits — so a replaced or dead ACP child retires the target exactly like a replaced PTY.
|
|
8
|
+
function targetProcessOf(session) {
|
|
9
|
+
return session?.ptyProcess || session?._acpProcess || null;
|
|
10
|
+
}
|
|
11
|
+
|
|
5
12
|
function captureRemoteTerminalTarget(sessionId, session, sessionSource, getProcessGeneration) {
|
|
6
13
|
const getSession = typeof sessionSource === 'function' ? sessionSource : id => sessionSource?.get(id);
|
|
7
14
|
const originalSession = session && typeof session === 'object' ? session : null;
|
|
8
|
-
const originalPtyProcess = originalSession
|
|
15
|
+
const originalPtyProcess = targetProcessOf(originalSession);
|
|
9
16
|
const originalGeneration = originalSession && typeof getProcessGeneration === 'function'
|
|
10
17
|
? getProcessGeneration(originalSession)
|
|
11
18
|
: null;
|
|
@@ -19,7 +26,7 @@ function captureRemoteTerminalTarget(sessionId, session, sessionSource, getProce
|
|
|
19
26
|
}
|
|
20
27
|
const current = getSession(sessionId);
|
|
21
28
|
const matches = current === originalSession
|
|
22
|
-
&& current
|
|
29
|
+
&& targetProcessOf(current) === originalPtyProcess
|
|
23
30
|
&& typeof getProcessGeneration === 'function'
|
|
24
31
|
&& getProcessGeneration(current) === originalGeneration;
|
|
25
32
|
if (!matches) targetRetired = true;
|
|
@@ -81,13 +81,17 @@ function summarizeRestartGuard(sessions = [], options = {}) {
|
|
|
81
81
|
? normalizeWaitingReason(options.waitingReasonForSession(session))
|
|
82
82
|
: defaultWaitingReasonForSession(session);
|
|
83
83
|
const summary = restartSessionSummary(session, rawStatus, waitingForInput, waitingReason);
|
|
84
|
-
// WP-4 (pty-survival design doc, S-16)
|
|
85
|
-
// session's live process
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
84
|
+
// WP-4 (pty-survival design doc, S-16) + WP-2 (session-host-cgroup-survival design doc, D-5): a HOSTED
|
|
85
|
+
// session's live process survives a restart ONLY IF its host actually survives CTM's exit -- true under
|
|
86
|
+
// launchd (proven), and under systemd only when the host was moved out of ctm.service's cgroup
|
|
87
|
+
// (KillMode=control-group reaps everything else). `options.hostSurvivesRestart(session)` answers that at
|
|
88
|
+
// snapshot time; when absent it defaults to true (callers/tests that never knew about cgroups). A running or
|
|
89
|
+
// busy session whose host would NOT survive blocks like a non-hosted one. Approval/choice waits still
|
|
90
|
+
// block: those are a human decision left hanging mid-turn, not process survival.
|
|
89
91
|
const isHosted = typeof options.isHostedSession === 'function' ? !!options.isHostedSession(session) : false;
|
|
90
|
-
const
|
|
92
|
+
const survives = isHosted && (typeof options.hostSurvivesRestart === 'function' ? !!options.hostSurvivesRestart(session) : true);
|
|
93
|
+
summary.hostSurvives = isHosted ? survives : null;
|
|
94
|
+
const runningBlocked = BLOCKING_STATUSES.has(summary.status) && !survives;
|
|
91
95
|
const waitingBlocked = summary.status === 'waiting_input' &&
|
|
92
96
|
isBlockingWaitingSession(session, summary, waitingForInput, waitingReason, options);
|
|
93
97
|
if (runningBlocked || waitingBlocked) blockers.push(summary);
|
|
@@ -107,6 +111,14 @@ function summarizeRestartGuard(sessions = [], options = {}) {
|
|
|
107
111
|
blockers.push(summary);
|
|
108
112
|
}
|
|
109
113
|
|
|
114
|
+
// WP-3 (docs/session-create-box-restart-and-git-lane-starvation-2026-10-30.html §6.3/§8):
|
|
115
|
+
// an in-flight CREATE has no session row yet, so the loop above cannot see it — but a restart
|
|
116
|
+
// would still abort it. Each entry is appended VERBATIM (the caller owns the shape:
|
|
117
|
+
// `{ id, kind: 'create_in_progress', ... }`), and counts as a blocker. Absent/empty => unchanged.
|
|
118
|
+
for (const entry of options.pendingCreates || []) {
|
|
119
|
+
if (entry) blockers.push(entry);
|
|
120
|
+
}
|
|
121
|
+
|
|
110
122
|
return {
|
|
111
123
|
preflight,
|
|
112
124
|
totalCount: items.length,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-1 (docs/claude-restore-seed-alt-screen-trap-2026-10-27.html §5 R-1/R-2/R-5, §6, §8, §9):
|
|
4
|
+
// a restore seed fed to a NEW process's headless mirror must be CONTENT-ONLY. The persisted
|
|
5
|
+
// snapshot of a fullscreen Claude begins with `ESC[?1049h` (xterm SerializeAddon serializes an
|
|
6
|
+
// active alternate buffer that way). Fed to a newly-started Claude that renders INLINE -- which
|
|
7
|
+
// never emits `ESC[?1049l` because it never entered -- the mirror stays on the alternate buffer
|
|
8
|
+
// forever: DECSET 1049 disables scrollback while active, CTM strips mouse enables from snapshots,
|
|
9
|
+
// so the tab has no mouse and no history and the UI shows "Scrolling is off until this app
|
|
10
|
+
// reports its mouse mode". This module rewrites the seed so the NEW process alone decides the
|
|
11
|
+
// terminal modes:
|
|
12
|
+
// * every alternate-screen ENTER (`?1049h`/`?1047h`/`?47h`, including inside a multi-param
|
|
13
|
+
// DECSET such as `ESC[?2004;1049h`) is replaced by a push-out into normal-buffer history --
|
|
14
|
+
// the same shape lib/seed-push-out.js:17 (`seedPushOutSequence`) emits, with n = rows -- so
|
|
15
|
+
// the picture that followed the enter survives as scrollback instead of being covered;
|
|
16
|
+
// * every alternate-screen LEAVE (`?1049l`/`?1047l`/`?47l`, incl. inside a multi-param DECRST)
|
|
17
|
+
// is dropped (the new process never entered, so a leave is meaningless);
|
|
18
|
+
// * every mouse-tracking ENABLE (MOUSE_PARAMS with `h`) is dropped -- mouse truth must come only
|
|
19
|
+
// from the live process (R-2 / the read-only R-10 contract); mouse DISABLES (`l`) are kept.
|
|
20
|
+
// Pure: no I/O, no shared state. Applied to the WHOLE seed before slicing (R-5) so a DECSET is
|
|
21
|
+
// never torn across feedSliceChars chunks.
|
|
22
|
+
//
|
|
23
|
+
// NOT used by lib/host-handoff.js (R-3): a same-process handoff keeps the real alternate screen.
|
|
24
|
+
// The push-out is emitted once per DECSET that named at least one alt-screen param; the three
|
|
25
|
+
// counters each report the number of individual params removed.
|
|
26
|
+
|
|
27
|
+
const ALT_SCREEN_PARAMS = [1049, 1047, 47];
|
|
28
|
+
const MOUSE_PARAMS = [1000, 1002, 1003, 1005, 1006, 1015, 1016];
|
|
29
|
+
|
|
30
|
+
const ALT_SET = new Set(ALT_SCREEN_PARAMS);
|
|
31
|
+
const MOUSE_SET = new Set(MOUSE_PARAMS);
|
|
32
|
+
|
|
33
|
+
// A private DECSET/DECRST: `ESC [ ? <;params> h|l`. Params are decimal.
|
|
34
|
+
const DEC_MODE_RE = /\x1b\[\?([0-9;]*)([hl])/g;
|
|
35
|
+
|
|
36
|
+
// The push-out shape -- byte-identical to lib/seed-push-out.js:17 seedPushOutSequence with
|
|
37
|
+
// cursorY >= rows (n = rows): move to the bottom row, emit one LF per row (scrolling each seed
|
|
38
|
+
// row into history), then home the cursor.
|
|
39
|
+
function pushOutSequence(rows) {
|
|
40
|
+
return '\x1b[' + rows + ';1H' + '\n'.repeat(rows) + '\x1b[H';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function contentOnlyRestoreSeed(data, rows) {
|
|
44
|
+
if (typeof data !== 'string') {
|
|
45
|
+
return { data, altEntersConverted: 0, altLeavesDropped: 0, mouseEnablesDropped: 0 };
|
|
46
|
+
}
|
|
47
|
+
// Never guess a row count: anything that is not an integer >= 1 drops alt enters outright.
|
|
48
|
+
const validRows = Number.isInteger(rows) && rows >= 1;
|
|
49
|
+
let altEntersConverted = 0;
|
|
50
|
+
let altLeavesDropped = 0;
|
|
51
|
+
let mouseEnablesDropped = 0;
|
|
52
|
+
|
|
53
|
+
const out = data.replace(DEC_MODE_RE, (match, paramsStr, final) => {
|
|
54
|
+
if (!paramsStr) return match; // `ESC[?h` / `ESC[?l` name no mode -> leave untouched
|
|
55
|
+
const params = paramsStr.split(';');
|
|
56
|
+
const kept = [];
|
|
57
|
+
let altCount = 0;
|
|
58
|
+
let mouseCount = 0;
|
|
59
|
+
for (const param of params) {
|
|
60
|
+
const n = Number(param);
|
|
61
|
+
if (final === 'h' && ALT_SET.has(n)) { altCount += 1; continue; }
|
|
62
|
+
if (final === 'l' && ALT_SET.has(n)) { altLeavesDropped += 1; continue; }
|
|
63
|
+
if (final === 'h' && MOUSE_SET.has(n)) { mouseCount += 1; continue; }
|
|
64
|
+
kept.push(param);
|
|
65
|
+
}
|
|
66
|
+
if (final === 'l') {
|
|
67
|
+
// Alt leaves already dropped; keep the other params verbatim (or remove the DECRST).
|
|
68
|
+
return kept.length ? '\x1b[?' + kept.join(';') + 'l' : '';
|
|
69
|
+
}
|
|
70
|
+
// final === 'h'
|
|
71
|
+
mouseEnablesDropped += mouseCount;
|
|
72
|
+
if (altCount > 0) {
|
|
73
|
+
altEntersConverted += altCount;
|
|
74
|
+
const head = kept.length ? '\x1b[?' + kept.join(';') + 'h' : '';
|
|
75
|
+
return head + (validRows ? pushOutSequence(rows) : '');
|
|
76
|
+
}
|
|
77
|
+
if (mouseCount === 0) return match; // nothing matched -> preserve the exact bytes
|
|
78
|
+
return kept.length ? '\x1b[?' + kept.join(';') + 'h' : '';
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (altEntersConverted === 0 && altLeavesDropped === 0 && mouseEnablesDropped === 0) {
|
|
82
|
+
return { data, altEntersConverted, altLeavesDropped, mouseEnablesDropped };
|
|
83
|
+
}
|
|
84
|
+
return { data: out, altEntersConverted, altLeavesDropped, mouseEnablesDropped };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = { contentOnlyRestoreSeed, ALT_SCREEN_PARAMS, MOUSE_PARAMS };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { contentOnlyRestoreSeed } = require('./restore-seed-modes');
|
|
4
|
+
|
|
3
5
|
// Owns the restored-scrollback probe/feed transaction. The host supplies archive,
|
|
4
6
|
// worker, session, and diagnostic boundaries; this module owns ordering and policy.
|
|
5
7
|
function createRestoredScrollbackHydrationRuntime(deps = {}) {
|
|
@@ -80,6 +82,24 @@ function createRestoredScrollbackHydrationRuntime(deps = {}) {
|
|
|
80
82
|
return tail;
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
// WP-1 (docs/claude-restore-seed-alt-screen-trap-2026-10-27.html §5 R-1/R-2/R-5): strip the
|
|
86
|
+
// dead process's terminal modes from the seed so the NEW process alone decides the buffer and
|
|
87
|
+
// the mouse. Applied to the whole (already bounded) string so a DECSET is never split across
|
|
88
|
+
// feed slices. Idempotent, so hydrateInBackground (prepareSeed -> feed) records exactly one
|
|
89
|
+
// 'restore-seed-modes' diagnostic -- at whichever stage actually removed a mode.
|
|
90
|
+
function contentOnlySeed(sessionId, scrollData, seedRows) {
|
|
91
|
+
const cleaned = contentOnlyRestoreSeed(scrollData, seedRows);
|
|
92
|
+
if (cleaned.altEntersConverted || cleaned.altLeavesDropped || cleaned.mouseEnablesDropped) {
|
|
93
|
+
recordDiagnostic(sessionId, 'restore-seed-modes', {
|
|
94
|
+
altEntersConverted: cleaned.altEntersConverted,
|
|
95
|
+
altLeavesDropped: cleaned.altLeavesDropped,
|
|
96
|
+
mouseEnablesDropped: cleaned.mouseEnablesDropped,
|
|
97
|
+
seedRows: seedRows === undefined ? null : seedRows,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return cleaned.data;
|
|
101
|
+
}
|
|
102
|
+
|
|
83
103
|
async function prepareSeed(sessionId, scrollDataIn, opts = {}) {
|
|
84
104
|
let probe = { aligned: false, reason: 'flag-off', archiveLastRow: null };
|
|
85
105
|
if (alignedEnabled) {
|
|
@@ -103,7 +123,7 @@ function createRestoredScrollbackHydrationRuntime(deps = {}) {
|
|
|
103
123
|
drift: seam.drift,
|
|
104
124
|
});
|
|
105
125
|
return {
|
|
106
|
-
data: boundInput(sessionId, scrollDataIn, probe.aligned === true),
|
|
126
|
+
data: contentOnlySeed(sessionId, boundInput(sessionId, scrollDataIn, probe.aligned === true), opts.seedRows),
|
|
107
127
|
seedAligned: probe.aligned === true,
|
|
108
128
|
forwardDriftSeamRow: probe.mode === 'forward-drift' ? seam.recordedSeamRow : null,
|
|
109
129
|
};
|
|
@@ -114,7 +134,7 @@ function createRestoredScrollbackHydrationRuntime(deps = {}) {
|
|
|
114
134
|
const forwardDriftSeamRow = Number.isFinite(opts.forwardDriftSeamRow)
|
|
115
135
|
? opts.forwardDriftSeamRow
|
|
116
136
|
: null;
|
|
117
|
-
const scrollData = boundInput(sessionId, scrollDataIn, seedAligned);
|
|
137
|
+
const scrollData = contentOnlySeed(sessionId, boundInput(sessionId, scrollDataIn, seedAligned), opts.seedRows);
|
|
118
138
|
if (!sessionId || !scrollData) {
|
|
119
139
|
opts.onDone?.('empty');
|
|
120
140
|
return;
|
|
@@ -703,7 +703,7 @@ function classifyStartupTaskRestore(task, restoredOrdinal, fastSessionCount, ali
|
|
|
703
703
|
) {
|
|
704
704
|
return 'adopt';
|
|
705
705
|
}
|
|
706
|
-
if (task?.type === 'walle') return 'eager';
|
|
706
|
+
if (task?.type === 'walle') return 'eager'; if (task?.type === 'dsh') return 'defer'; // D-A (WP-5): dsh NEVER spawns at boot -- it is a childless deferred placeholder, started on attach/input by lib/session-create/dsh-session.js's restoreDshSession.
|
|
707
707
|
if (primary && task?._restoreInterruption?.interrupted) return 'eager'; // WP-2: resume an interrupted turn now
|
|
708
708
|
const ordinal = Number(restoredOrdinal) || 0;
|
|
709
709
|
const fastCount = Number(fastSessionCount) || 0;
|
|
@@ -790,12 +790,24 @@ function orderAutoResumeDeferredIds(deferredIds, priorityIds) {
|
|
|
790
790
|
|
|
791
791
|
function selectAutoResumeDeferredIds(deferredIds, priorityIds, policy) {
|
|
792
792
|
const ids = Array.isArray(deferredIds) ? deferredIds.filter(Boolean).map(String) : [];
|
|
793
|
-
|
|
793
|
+
// WP-2 (docs/external-causality-kill-session-loss-2026-10-27.html §6): the ONE escape from the
|
|
794
|
+
// boot cap, used by the explicit "Resume N sessions" control (POST /api/sessions/resume-deferred).
|
|
795
|
+
// `all` is read ONLY when present; with it absent every arm below is byte-identical to before.
|
|
796
|
+
const all = !!(policy && policy.all === true);
|
|
797
|
+
if (!ids.length) return [];
|
|
798
|
+
if (!all && (!policy || !policy.enabled || policy.limit <= 0)) return [];
|
|
794
799
|
const ordered = orderAutoResumeDeferredIds(ids, priorityIds);
|
|
795
|
-
if (!Number.isFinite(policy.limit)) return ordered;
|
|
800
|
+
if (all || !Number.isFinite(policy.limit)) return ordered;
|
|
796
801
|
return ordered.slice(0, Math.max(0, Math.floor(policy.limit)));
|
|
797
802
|
}
|
|
798
803
|
|
|
804
|
+
// WP-2 (§5 D-5, §6): the boot restore selector's cap as ONE object, so the adopted-host-death
|
|
805
|
+
// drain reuses the exact boot policy instead of inventing a second one. Same CTM_AUTO_RESUME_DEFERRED
|
|
806
|
+
// semantics resolveAutoResumeDeferredPolicy already applies at boot (mode 'off' ⇒ nothing drains).
|
|
807
|
+
function bootAutoResumePolicy(env = process.env) {
|
|
808
|
+
return resolveAutoResumeDeferredPolicy(env);
|
|
809
|
+
}
|
|
810
|
+
|
|
799
811
|
// WP-3 (design doc §5 D-4, §8 WP-3, §9 S-17/S-18): explicit all/wide numeric
|
|
800
812
|
// drains can still admit many eligible sessions, most-recent-first. The 2026-08-22
|
|
801
813
|
// incident measured 8 sessions (~2.5 GB) auto-resumed on a host already at 88%
|
|
@@ -914,6 +926,7 @@ const resumeAdmission = {
|
|
|
914
926
|
selectAutoResumeDeferredIds,
|
|
915
927
|
orderAutoResumeDeferredIds,
|
|
916
928
|
resolveAutoResumePolicy,
|
|
929
|
+
bootAutoResumePolicy,
|
|
917
930
|
DEFAULT_SESSION_FOOTPRINT_MB,
|
|
918
931
|
},
|
|
919
932
|
};
|
|
@@ -949,5 +962,6 @@ module.exports = {
|
|
|
949
962
|
selectAutoResumeDeferredIds,
|
|
950
963
|
orderAutoResumeDeferredIds,
|
|
951
964
|
resolveAutoResumePolicy,
|
|
965
|
+
bootAutoResumePolicy,
|
|
952
966
|
DEFAULT_SESSION_FOOTPRINT_MB,
|
|
953
967
|
};
|