create-walle 0.10.1 → 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 +7 -1
- package/lib/owner-write-safety.js +135 -0
- package/lib/public-runtime.js +13 -5
- package/lib/release-schema.json +3 -2
- package/lib/runtime-closure-policy.json +11 -8
- package/package.json +1 -1
- package/template/bin/deps-doctor.js +1 -1
- package/template/bin/node-bin.sh +11 -0
- package/template/coding-task-manager/api-prompts.js +55 -29
- package/template/coding-task-manager/bin/claude-hook.js +62 -4
- package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
- package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
- package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
- package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
- 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/lead-wait-census.js +1348 -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/bin/repair-foreign-clone.js +564 -0
- package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
- package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
- package/template/coding-task-manager/db.js +860 -317
- package/template/coding-task-manager/git-utils.js +44 -0
- 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 -7
- 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 +99 -1
- package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
- package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
- 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/host-stats.js +98 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +43 -12
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
- package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
- package/template/coding-task-manager/lib/api/machines.js +1150 -0
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +25 -5
- package/template/coding-task-manager/lib/api/providers.js +53 -6
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/resume-from-store.js +25 -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 +237 -59
- 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/transcript-history.js +17 -4
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/api/worktrees.js +38 -37
- package/template/coding-task-manager/lib/approval-drift.js +16 -1
- package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
- package/template/coding-task-manager/lib/approval-scope.js +68 -4
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-context.js +32 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +64 -1
- package/template/coding-task-manager/lib/auth-rules.js +474 -62
- 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 +7 -1
- package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
- package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-session-title.js +6 -30
- package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +69 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +55 -20
- package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
- package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
- package/template/coding-task-manager/lib/codex-paths.js +2 -1
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +48 -42
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +70 -4
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +24 -6
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +17 -0
- package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -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 +104 -13
- 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-boot-lifecycle.js +17 -1
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +8 -0
- package/template/coding-task-manager/lib/db-domains.js +22 -2
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -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 +6 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +5 -1
- 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 +61 -44
- package/template/coding-task-manager/lib/harness-history-transition.js +52 -11
- package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
- package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
- package/template/coding-task-manager/lib/headless-term-service.js +139 -25
- 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-control-dial.js +167 -0
- 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-orchestrator.js +16 -2
- package/template/coding-task-manager/lib/host-handoff.js +50 -15
- package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
- package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
- package/template/coding-task-manager/lib/host-stats.js +475 -0
- package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
- package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
- package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
- package/template/coding-task-manager/lib/hosted-sync-worker.js +141 -310
- 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 +12 -0
- package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
- package/template/coding-task-manager/lib/instance-manifest.js +18 -2
- package/template/coding-task-manager/lib/instance-sync-status.js +33 -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 +193 -8
- 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/launch-plan-worker.js +59 -2
- 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 +409 -72
- package/template/coding-task-manager/lib/lead-model-switch.js +115 -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 +85 -9
- 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/legacy-draft-cancellation-recovery.js +111 -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/login-tripwire.js +1 -0
- package/template/coding-task-manager/lib/machine-pairing.js +238 -0
- package/template/coding-task-manager/lib/machine-pool.js +409 -0
- package/template/coding-task-manager/lib/machine-registry.js +1494 -0
- package/template/coding-task-manager/lib/machine-self.js +66 -0
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +485 -57
- 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/media-journal-control-reader.js +473 -0
- package/template/coding-task-manager/lib/media-journal.js +84 -27
- package/template/coding-task-manager/lib/media-store-options.js +43 -15
- 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/v56-host-samples-and-machine-pool.js +76 -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/mirror-feed-sanitize.js +12 -3
- 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 +8 -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 +6 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
- 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/lead-worker-picks.js +25 -0
- package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
- package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
- package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -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/stream-accounting.js +205 -0
- package/template/coding-task-manager/lib/model-proxy/tokens.js +147 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +18 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +7 -5
- package/template/coding-task-manager/lib/native-lead-settings-client.js +46 -5
- package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +776 -75
- 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 +15 -1
- package/template/coding-task-manager/lib/painted-row-recorder.js +9 -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/prompt-submission-contract.js +21 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +264 -24
- package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
- package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
- package/template/coding-task-manager/lib/read-pool-client.js +94 -4
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +41 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +76 -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-command-context.js +12 -0
- package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
- package/template/coding-task-manager/lib/remote-machine-catalog.js +1357 -0
- package/template/coding-task-manager/lib/remote-machine-create.js +1233 -0
- package/template/coding-task-manager/lib/remote-machine-link.js +1426 -0
- package/template/coding-task-manager/lib/remote-machine-proxy.js +654 -0
- package/template/coding-task-manager/lib/remote-session-forward.js +364 -0
- package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
- 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/restart-outcome-truth.js +20 -3
- package/template/coding-task-manager/lib/restart-preflight.js +9 -2
- package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
- package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
- package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
- 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/resume-blocked-wire.js +62 -1
- package/template/coding-task-manager/lib/resume-cwd.js +13 -0
- package/template/coding-task-manager/lib/resume-from-store.js +12 -1
- package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
- package/template/coding-task-manager/lib/resume-preflight.js +21 -16
- package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
- package/template/coding-task-manager/lib/review-repo-registry.js +74 -18
- package/template/coding-task-manager/lib/root-delivery-runtime.js +74 -17
- package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
- package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +168 -34
- 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/scrollback-archive-store.js +7 -4
- package/template/coding-task-manager/lib/session-analysis-memory.js +2 -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/codex-native-provider-gate.js +218 -0
- package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +179 -20
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/identity.js +20 -1
- 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 +201 -9
- package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
- package/template/coding-task-manager/lib/session-create/provider-process.js +193 -64
- package/template/coding-task-manager/lib/session-create/response.js +37 -19
- 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 +14 -5
- 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 +50 -2
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
- package/template/coding-task-manager/lib/session-create/worker-observability.js +101 -9
- package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
- package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
- package/template/coding-task-manager/lib/session-host-manager.js +212 -206
- package/template/coding-task-manager/lib/session-jobs.js +20 -10
- package/template/coding-task-manager/lib/session-lifecycle.js +28 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +15 -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-resource-sampler.js +19 -9
- package/template/coding-task-manager/lib/session-standup.js +67 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +147 -6
- package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
- package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
- package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
- 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/startup-pointer-write.js +57 -0
- 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/state-sync/painted-frame-field.js +11 -0
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +25 -23
- 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/surviving-owner-bootstrap.js +7 -2
- package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
- 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-http-status.js +25 -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-archiver.js +229 -229
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +20 -5
- package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
- package/template/coding-task-manager/lib/transcript-link.js +77 -0
- package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
- package/template/coding-task-manager/lib/transcript-source.js +44 -7
- package/template/coding-task-manager/lib/transcript-store.js +49 -0
- package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
- package/template/coding-task-manager/lib/typing-interaction-trace.js +198 -3
- package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
- 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/visible-revision-watchdog.js +8 -12
- package/template/coding-task-manager/lib/wake-skip-reasons.js +47 -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 +130 -27
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
- 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 +125 -6
- package/template/coding-task-manager/lib/ws/terminal-attach.js +123 -1
- package/template/coding-task-manager/lib/ws-router.js +68 -1
- package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
- package/template/coding-task-manager/oauth-proxy.js +211 -170
- package/template/coding-task-manager/package-lock.json +34 -94
- package/template/coding-task-manager/package.json +7 -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/providers/codex-mcp-extract.js +121 -19
- package/template/coding-task-manager/providers/codex-mcp.js +14 -5
- package/template/coding-task-manager/public/css/app.css +449 -1
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +766 -465
- 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 +2572 -0
- package/template/coding-task-manager/public/js/app/models-tab.js +658 -73
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +191 -7
- package/template/coding-task-manager/public/js/background-work.js +203 -28
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +181 -13
- 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 +847 -5
- package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
- 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 +48 -4
- package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
- package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
- package/template/coding-task-manager/public/js/history-scroller.js +187 -9
- package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
- package/template/coding-task-manager/public/js/machine-pool-shared.js +991 -0
- 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/private-state-scope.js +31 -3
- package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
- package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
- 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/queue-panel-submission-reconcile.js +174 -1
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/reviews.js +7 -3
- package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
- package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
- package/template/coding-task-manager/public/js/row-join.js +4 -2
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +64 -21
- 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 +14 -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-02.js +16 -7
- package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
- package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
- 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 +60 -3
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +16 -12
- package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
- package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +211 -74
- package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
- package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +62 -5
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +15 -7
- package/template/coding-task-manager/public/js/walle-session.js +30 -7
- 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 +366 -8
- package/template/coding-task-manager/public/m/app.js +1006 -74
- package/template/coding-task-manager/public/m/index.html +55 -1
- package/template/coding-task-manager/public/m/machines.js +2147 -0
- package/template/coding-task-manager/public/m/pool-failover.js +391 -0
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
- package/template/coding-task-manager/public/m/sw.js +5 -0
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/queue-engine.js +13 -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/approvals.js +5 -6
- package/template/coding-task-manager/server/boot.js +136 -17
- package/template/coding-task-manager/server.js +2819 -11885
- package/template/coding-task-manager/session-integrity.js +71 -13
- package/template/coding-task-manager/workers/db-owner-worker.js +72 -9
- 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 +93 -12
- package/template/coding-task-manager/workers/session-host-pool-process.js +24 -10
- package/template/coding-task-manager/workers/session-host-process.js +19 -8
- package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +202 -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/scripts/conversation-storage-v2-migration.js +78 -11
- 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 +47 -6
- package/template/shared/fixtures/worker-status-payloads.json +392 -0
- package/template/shared/git-remote-key.js +83 -0
- package/template/shared/host-identity.js +98 -2
- 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/owner-write-safety.js +135 -0
- package/template/shared/public-runtime.js +13 -5
- package/template/shared/release-schema.json +3 -2
- package/template/shared/report-citations.js +14 -0
- package/template/shared/sqlite-write-lock.js +361 -223
- package/template/shared/storage/contract.js +38 -3
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +92 -4
- package/template/wall-e/api-walle.js +26 -1
- package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +14 -8
- 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/helper-rules-schema.js +129 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +91 -28
- package/template/wall-e/brain/model-deployment-facts.js +31 -1
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +39 -7
- package/template/wall-e/brain/schema-ensures.js +22 -0
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +172 -36
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/journal-dispatcher.js +51 -0
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/coding/session-journal.js +28 -40
- package/template/wall-e/coding-orchestrator.js +23 -26
- 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/auth.js +18 -1
- package/template/wall-e/http/blog-views-api.js +318 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +327 -0
- 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 +177 -2
- 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/http/telemetry-api.js +12 -0
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/blog-view-policy.js +88 -0
- package/template/wall-e/lib/blog-view-store.js +169 -0
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/client-config-lock.js +2 -1
- package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
- 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/error-kinds.js +10 -1
- package/template/wall-e/lib/feature-manifest.js +1 -1
- package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +398 -0
- package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
- package/template/wall-e/lib/helper-rules/grade.js +320 -0
- package/template/wall-e/lib/helper-rules/label.js +247 -0
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +555 -0
- package/template/wall-e/lib/helper-rules/store.js +669 -0
- 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 +63 -19
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/runtime-worker-pool.js +1 -0
- package/template/wall-e/lib/scheduler-worker-jobs.js +12 -4
- package/template/wall-e/lib/telemetry-db-schema.js +37 -0
- package/template/wall-e/lib/telemetry-process-client.js +76 -1
- package/template/wall-e/llm/default-fallback.js +4 -0
- 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-catalog.js +13 -4
- package/template/wall-e/llm/model-roles.js +7 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/portkey-http.js +150 -0
- package/template/wall-e/llm/portkey-sync.js +15 -145
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +117 -7
- package/template/wall-e/llm/worker-route.js +43 -1
- package/template/wall-e/loops/brain-custom-writes.js +64 -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 +77 -2
- package/template/wall-e/mcp-server.js +141 -31
- package/template/wall-e/mcp-worker-schemas.js +25 -7
- package/template/wall-e/memory/ctm-context-client.js +110 -5
- 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 +3 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/sqlite-write-lock.js +361 -223
- package/template/wall-e/shared/storage/contract.js +38 -3
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +13 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +11 -6
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +13 -8
- 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/tools/local-tools.js +6 -4
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +27 -4
- package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
- package/template/wall-e/workers/telemetry-worker.js +8 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-3 (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §6.3, D-6/D-9/D-13, §9 S-15/S-16/S-23):
|
|
4
|
+
// the BOX side of pairing — the two routes a joining member talks to.
|
|
5
|
+
//
|
|
6
|
+
// POST /api/machine-pairing/offers (admin + stepUp remote)
|
|
7
|
+
// -> 201 { ok, code:'XXXX-XXXX', expiresAt, pairingString, candidates }
|
|
8
|
+
// -> 409 { error:'pairing_offer_limit' } 3 unspent offers already exist
|
|
9
|
+
// -> 409 { error:'pool_member_exists' } this box is already IN a pool with members
|
|
10
|
+
//
|
|
11
|
+
// POST /api/machine-pairing/join (PRE-AUTH — phase 'api-cloudflare')
|
|
12
|
+
// { code, token, version, members, primary:{instanceId} }
|
|
13
|
+
// -> 201 { ok, instanceId, displayName, urls }
|
|
14
|
+
// -> 400 { error:'pool_token_invalid' } / 400 { error:'invalid_json' }
|
|
15
|
+
// -> 409 { error:'pool_member_exists' } this box is already somebody's member
|
|
16
|
+
// -> 410 { error:'pairing_code_invalid' } wrong / expired / already-used / burned
|
|
17
|
+
// -> 429 { error:'rate_limited' }
|
|
18
|
+
//
|
|
19
|
+
// GET /api/machine-pairing/identity (PRE-AUTH — phase 'api-cloudflare')
|
|
20
|
+
// -> 200 { ok, instanceId, displayName } a live code is showing on this box
|
|
21
|
+
// -> 404 { error:'pairing_offer_none' } no live code — not a pairing target right now
|
|
22
|
+
// -> 429 { error:'rate_limited' }
|
|
23
|
+
//
|
|
24
|
+
// WHY THE JOIN IS PRE-AUTH. The joining member does not hold this box's credential YET — the join
|
|
25
|
+
// request is the act that establishes it, and it carries the pool secret in the body precisely
|
|
26
|
+
// because there is nothing else to authenticate with. server.js dispatches phase 'api-cloudflare'
|
|
27
|
+
// BEFORE the /api auth wall (the same seam lib/api/microsoft-owner.js's public rows use), so this
|
|
28
|
+
// route never reaches lib/auth-rules.js and deliberately has NO row in HTTP_AUTH_RULES: a rule the
|
|
29
|
+
// dispatcher never consults is a lie in the table. Its defence is instead (a) possession of a live
|
|
30
|
+
// single-use code and (b) the `machine_pair` rate-limit bucket below (5/min, burst 5), keyed by
|
|
31
|
+
// REMOTE ADDRESS because there is no principal to key on.
|
|
32
|
+
//
|
|
33
|
+
// WHY THE IDENTITY PROBE IS PRE-AUTH TOO (D-9). Before it has paired, a member holds NO credential of
|
|
34
|
+
// this box, so it cannot read `/api/sync/manifest` (`sync`-scoped in lib/auth-rules.js) to find out
|
|
35
|
+
// whether it dialled the right machine — on a real LAN that 401s and the pair dies before it starts.
|
|
36
|
+
// The probe answers the smallest fact that makes a wrong address visible: "this box is showing a code
|
|
37
|
+
// right now", plus the name to compare against, and never a code, a token or a membership.
|
|
38
|
+
//
|
|
39
|
+
// WHAT IT NEVER DOES. Neither handler echoes, logs or persists a code or the token: the offer
|
|
40
|
+
// response is the ONE place a code exists in wire form (it is the box's own act of showing it to the
|
|
41
|
+
// operator), and the join response carries only this instance's identity and its own URLs.
|
|
42
|
+
|
|
43
|
+
const os = require('node:os');
|
|
44
|
+
const { registerApiRoutes } = require('../api-router');
|
|
45
|
+
const { TOKEN_PREFIX } = require('../machine-pool');
|
|
46
|
+
const { encodePairingString } = require('../machine-pairing');
|
|
47
|
+
|
|
48
|
+
let _deps = null;
|
|
49
|
+
|
|
50
|
+
function configure({
|
|
51
|
+
db,
|
|
52
|
+
pool,
|
|
53
|
+
pairing,
|
|
54
|
+
machineSelf,
|
|
55
|
+
registry,
|
|
56
|
+
selfUrls,
|
|
57
|
+
readJsonRequestBody,
|
|
58
|
+
sendJsonResponse,
|
|
59
|
+
rateLimit,
|
|
60
|
+
remoteIp,
|
|
61
|
+
logError = null,
|
|
62
|
+
ready = null,
|
|
63
|
+
} = {}) {
|
|
64
|
+
_deps = {
|
|
65
|
+
db, pool, pairing, machineSelf, registry, selfUrls,
|
|
66
|
+
readJsonRequestBody, sendJsonResponse, rateLimit, remoteIp, logError, ready,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** server.js injects its own (console) logger; the fallback keeps a bare harness truthful. */
|
|
71
|
+
function _logError(...args) {
|
|
72
|
+
if (_deps && typeof _deps.logError === 'function') return _deps.logError(...args);
|
|
73
|
+
console.error(...args);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The boot read's promise (server.js `_machinePoolReady`); both handlers here MUTATE the pool. */
|
|
77
|
+
function ready() {
|
|
78
|
+
return (_deps && _deps.ready) || Promise.resolve();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function _send(res, status, payload) {
|
|
82
|
+
if (_deps && typeof _deps.sendJsonResponse === 'function') return _deps.sendJsonResponse(res, status, payload);
|
|
83
|
+
const body = JSON.stringify(payload || {});
|
|
84
|
+
res.writeHead(status, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) });
|
|
85
|
+
res.end(body);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function _pool() {
|
|
89
|
+
return (_deps && _deps.pool) || require('../machine-pool').getMachinePool();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function _readJson(req) {
|
|
93
|
+
if (_deps && typeof _deps.readJsonRequestBody === 'function') return _deps.readJsonRequestBody(req);
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
const chunks = [];
|
|
96
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
97
|
+
req.on('end', () => {
|
|
98
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
99
|
+
if (!raw) return resolve({});
|
|
100
|
+
try { resolve(JSON.parse(raw)); } catch { reject(new Error('invalid_json')); }
|
|
101
|
+
});
|
|
102
|
+
req.on('error', reject);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** This machine's own minted id — '' rather than a throw before boot has primed identity. */
|
|
107
|
+
function _instanceId() {
|
|
108
|
+
try {
|
|
109
|
+
const identity = require('../instance-identity-access').getInstanceIdentity({ required: false });
|
|
110
|
+
return (identity && identity.instanceId) || '';
|
|
111
|
+
} catch {
|
|
112
|
+
return ''; // expected: instance identity is not ready yet (early boot / pre-initDb)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* D-4: the operator's label for this box, read from the machine-self store (the same source the
|
|
118
|
+
* manifest publishes), falling back to the host name. A pairing string with a label is what makes the
|
|
119
|
+
* operator's "which machine am I looking at" check possible on the far side.
|
|
120
|
+
*/
|
|
121
|
+
function _displayName() {
|
|
122
|
+
try {
|
|
123
|
+
const store = _deps && _deps.machineSelf;
|
|
124
|
+
const current = store && typeof store.current === 'function' ? store.current() : null;
|
|
125
|
+
const name = String((current && current.displayName) || '').trim();
|
|
126
|
+
if (name) return name;
|
|
127
|
+
} catch {
|
|
128
|
+
// expected: the machine-self cache is not configured (unit harness) — fall through to the host name
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
return String(os.hostname() || '').trim();
|
|
132
|
+
} catch {
|
|
133
|
+
return ''; // expected: no host name available — an empty label is truthful, never a failure
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** P-4: the dial list the pairing string advertises (injected — lib/api/machine-pool.js owns it). */
|
|
138
|
+
function _selfUrls() {
|
|
139
|
+
try {
|
|
140
|
+
const urls = _deps && typeof _deps.selfUrls === 'function' ? _deps.selfUrls() : [];
|
|
141
|
+
return Array.isArray(urls) ? urls.map((url) => String(url || '')).filter(Boolean) : [];
|
|
142
|
+
} catch {
|
|
143
|
+
return []; // expected: the URL getter is optional/unready — the operator can still type a URL
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The pre-auth defence both 'api-cloudflare' routes share (D-13): with no principal there is nothing
|
|
149
|
+
* to key a bucket on but the remote address, and the limiter is server.js's own singleton — the same
|
|
150
|
+
* instance every authorised route is charged to.
|
|
151
|
+
*/
|
|
152
|
+
function _allowed(req) {
|
|
153
|
+
const ip = _deps && typeof _deps.remoteIp === 'function' ? String(_deps.remoteIp(req) || '') : '';
|
|
154
|
+
const decision = _deps && typeof _deps.rateLimit === 'function'
|
|
155
|
+
? _deps.rateLimit('machine_pair', ip || 'anonymous')
|
|
156
|
+
: { ok: true };
|
|
157
|
+
return !!(decision && decision.ok);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function handleOffers(req, res) {
|
|
161
|
+
const pool = _pool();
|
|
162
|
+
await ready();
|
|
163
|
+
// §6.3 AC-3f: a box that already has a pool AND members is not "unpaired" — minting a code here
|
|
164
|
+
// would let a second, unrelated primary adopt a machine that is already somebody's member.
|
|
165
|
+
if (pool.hasPool() && pool.members().length > 0) {
|
|
166
|
+
return _send(res, 409, { ok: false, error: 'pool_member_exists' });
|
|
167
|
+
}
|
|
168
|
+
let result = null;
|
|
169
|
+
try {
|
|
170
|
+
result = await _deps.pairing.createOffer();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
// F5: REPORT the fault to the log; never echo it to the caller. The failure path still holds the
|
|
173
|
+
// offer's code (the store mints before it inserts), so a `detail` here would be the one place a
|
|
174
|
+
// live code could be copied out of a response body.
|
|
175
|
+
_logError('[machine-pairing] offer mint failed:', (error && error.message) || error);
|
|
176
|
+
return _send(res, 500, { ok: false, error: 'pairing_offer_failed' });
|
|
177
|
+
}
|
|
178
|
+
if (!result || !result.ok) {
|
|
179
|
+
// §6.3: 409 pairing_offer_limit (3 unspent offers already exist).
|
|
180
|
+
return _send(res, 409, { ok: false, error: (result && result.code) || 'pairing_offer_limit' });
|
|
181
|
+
}
|
|
182
|
+
const candidates = _selfUrls();
|
|
183
|
+
const instanceId = _instanceId();
|
|
184
|
+
return _send(res, 201, {
|
|
185
|
+
ok: true,
|
|
186
|
+
code: result.code,
|
|
187
|
+
expiresAt: result.expiresAt,
|
|
188
|
+
pairingString: encodePairingString({ instanceId, displayName: _displayName(), urls: candidates, code: result.code }),
|
|
189
|
+
candidates,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* D-9/F1: the PRE-AUTH identity probe (see the file header). A BOOLEAN, never a code: 200 while this
|
|
195
|
+
* box is showing at least one live offer, 404 the moment it is not. That is what lets a member aimed
|
|
196
|
+
* at the wrong address see "there is no pairing code here" instead of a 401 it cannot interpret.
|
|
197
|
+
*/
|
|
198
|
+
async function handleIdentity(req, res) {
|
|
199
|
+
if (!_allowed(req)) return _send(res, 429, { ok: false, error: 'rate_limited' });
|
|
200
|
+
await ready();
|
|
201
|
+
let live = false;
|
|
202
|
+
try {
|
|
203
|
+
live = !!(await _deps.pairing.hasLiveOffers());
|
|
204
|
+
} catch (error) {
|
|
205
|
+
_logError('[machine-pairing] identity probe failed:', (error && error.message) || error);
|
|
206
|
+
return _send(res, 500, { ok: false, error: 'pairing_identity_failed' });
|
|
207
|
+
}
|
|
208
|
+
if (!live) return _send(res, 404, { ok: false, error: 'pairing_offer_none' });
|
|
209
|
+
return _send(res, 200, { ok: true, instanceId: _instanceId(), displayName: _displayName() });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async function handleJoin(req, res) {
|
|
213
|
+
// PRE-AUTH: there is no principal, so the bucket is keyed by remote address (see _allowed).
|
|
214
|
+
if (!_allowed(req)) return _send(res, 429, { ok: false, error: 'rate_limited' });
|
|
215
|
+
|
|
216
|
+
let body = null;
|
|
217
|
+
try {
|
|
218
|
+
body = await _readJson(req);
|
|
219
|
+
} catch {
|
|
220
|
+
return _send(res, 400, { ok: false, error: 'invalid_json' });
|
|
221
|
+
}
|
|
222
|
+
const token = String((body && body.token) || '').trim();
|
|
223
|
+
if (!token.startsWith(TOKEN_PREFIX)) return _send(res, 400, { ok: false, error: 'pool_token_invalid' });
|
|
224
|
+
|
|
225
|
+
await ready();
|
|
226
|
+
const pool = _pool();
|
|
227
|
+
// F4: a box that already belongs to somebody must not be adoptable by a second, unrelated primary
|
|
228
|
+
// that happens to hold a code minted earlier (or to have brute-forced one). Same predicate as
|
|
229
|
+
// handleOffers, on the join side — and checked BEFORE the redeem so the attempt cannot spend a code.
|
|
230
|
+
if (pool.hasPool() && pool.members().length > 0) {
|
|
231
|
+
return _send(res, 409, { ok: false, error: 'pool_member_exists' });
|
|
232
|
+
}
|
|
233
|
+
const identity = _instanceId();
|
|
234
|
+
// §6.3 ordering: verify the code (hash compare) and burn it BEFORE the pool is touched, so a
|
|
235
|
+
// replay of an already-consumed code can never reach adopt().
|
|
236
|
+
const redeemed = await _deps.pairing.redeem(body && body.code, { by: identity });
|
|
237
|
+
if (!redeemed || !redeemed.ok) return _send(res, 410, { ok: false, error: 'pairing_code_invalid' });
|
|
238
|
+
|
|
239
|
+
// P-8: the PREVIOUS membership set, captured before adopt() — replaceRosterMachines may only
|
|
240
|
+
// delete rows for machines that WERE pool members. A legacy env-token row is never one, so this
|
|
241
|
+
// join can never drop it (the WP-2b fix; do not reintroduce the unguarded sweep).
|
|
242
|
+
const removable = pool.members();
|
|
243
|
+
// Two shapes, two consumers, and they are NOT interchangeable:
|
|
244
|
+
// - the POOL store holds instanceIds (P-8's per-target credential rule),
|
|
245
|
+
// - the REGISTRY takes the roster ENTRIES (db.replaceRosterMachines writes `url`/`urls_json` from
|
|
246
|
+
// each entry's dial list and SKIPS an entry with no URL). Handing it bare ids writes no row at
|
|
247
|
+
// all, which is how the membership silently failed to land: the box would answer 201 and then
|
|
248
|
+
// list nobody.
|
|
249
|
+
const entries = (Array.isArray(body && body.members) ? body.members : [])
|
|
250
|
+
.map((member) => ({
|
|
251
|
+
instanceId: String((member && (member.instanceId || member.instance_id)) || '').trim(),
|
|
252
|
+
urls: (Array.isArray(member && member.urls) ? member.urls : [])
|
|
253
|
+
.map((url) => String(url || '').trim().replace(/\/+$/, ''))
|
|
254
|
+
.filter(Boolean),
|
|
255
|
+
}))
|
|
256
|
+
.filter((member) => member.instanceId && member.instanceId !== identity);
|
|
257
|
+
const members = entries.map((member) => member.instanceId);
|
|
258
|
+
await pool.adopt({ token, roster: body && body.version, members });
|
|
259
|
+
await _deps.db.replaceRosterMachines({ members: entries, selfInstanceId: identity, removable });
|
|
260
|
+
if (_deps.registry && typeof _deps.registry.noteRegistryChanged === 'function') _deps.registry.noteRegistryChanged();
|
|
261
|
+
// F4: this box is somebody's member now, so every code that is still live dies here. Without it, a
|
|
262
|
+
// second primary holding an offer minted before this join could adopt the same box with the same
|
|
263
|
+
// code-less flow and take the pool secret with it. Best-effort after the fact: the adopt already
|
|
264
|
+
// succeeded and is what the caller was promised, so a burn failure is reported, never fatal.
|
|
265
|
+
try {
|
|
266
|
+
await _deps.pairing.burnAll();
|
|
267
|
+
} catch (error) {
|
|
268
|
+
_logError('[machine-pairing] burning the remaining offers after a join failed:', (error && error.message) || error);
|
|
269
|
+
}
|
|
270
|
+
// The token is deliberately NOT echoed — the caller already has it, and a response body is the
|
|
271
|
+
// easiest place for a secret to end up in a log or a proxy trace.
|
|
272
|
+
return _send(res, 201, { ok: true, instanceId: identity, displayName: _displayName(), urls: _selfUrls() });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function register() {
|
|
276
|
+
registerApiRoutes('machine-pairing', [
|
|
277
|
+
{ method: 'POST', path: '/api/machine-pairing/offers', handler: (req, res) => handleOffers(req, res) },
|
|
278
|
+
// PRE-AUTH (§6.3): dispatched before server.js's auth wall, so it carries no auth-rules row.
|
|
279
|
+
{ phase: 'api-cloudflare', method: 'POST', path: '/api/machine-pairing/join', handler: (req, res) => handleJoin(req, res) },
|
|
280
|
+
// PRE-AUTH (D-9/F1): same phase, same reason — an unpaired member holds no credential here.
|
|
281
|
+
{ phase: 'api-cloudflare', method: 'GET', path: '/api/machine-pairing/identity', handler: (req, res) => handleIdentity(req, res) },
|
|
282
|
+
]);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
module.exports = { configure, register, ready, handleOffers, handleJoin, handleIdentity };
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-2a (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §6.2, D-4/D-13, P-5/P-6, §9
|
|
4
|
+
// S-24/S-25/S-27): the pool + machine-self routes.
|
|
5
|
+
//
|
|
6
|
+
// GET /api/pool/roster (peerControl) -> { ok, poolId, version, members:[{instanceId, urls}] }
|
|
7
|
+
// `members` INCLUDES self (P-1: the roster a member
|
|
8
|
+
// pushes carries itself).
|
|
9
|
+
// POST /api/pool/roster (peerControl) P-5 receive side: a lower-revision push replaces this
|
|
10
|
+
// member's membership (upsert listed, delete unlisted,
|
|
11
|
+
// never self) and stores the version; an equal/higher
|
|
12
|
+
// revision is ignored and answered `{applied:false}`.
|
|
13
|
+
// POST /api/pool/rotate (peerControl) P-6 receive side: acceptRotation({token}).
|
|
14
|
+
// POST /api/pool/leave (admin+stepUp) leave() + drop every roster row.
|
|
15
|
+
// GET /api/machine-self (read, peerControl) D-4: this machine's own settings.
|
|
16
|
+
// POST /api/machine-self (admin+stepUp, peerControl) D-4 write.
|
|
17
|
+
//
|
|
18
|
+
// Like lib/api/machines.js (and unlike the lib/api/*.js extraction slices) this is NEW surface: the
|
|
19
|
+
// handler bodies live here, so there is no legacy handleApi branch to delete and
|
|
20
|
+
// tests-integration/api-router-parity.test.js's no-dual-dispatch rule is satisfied by construction.
|
|
21
|
+
//
|
|
22
|
+
// AUTH. lib/auth-rules.js carries the rows (D-13). The codebase expresses no "peer-only" rule
|
|
23
|
+
// mechanism — `peerControl: true` ADDS the peer bearer to a row's normal reach, it does not remove
|
|
24
|
+
// anyone — so the two roster rows and POST /api/pool/rotate are declared `admin` + `peerControl`
|
|
25
|
+
// and each handler REFUSES a non-peer principal itself with 403 `peer_only` (read off
|
|
26
|
+
// `req.ctmAuth`, the same place lib/api/access.js reads the principal). That is the "handler
|
|
27
|
+
// refuses" branch the brief names.
|
|
28
|
+
|
|
29
|
+
const os = require('node:os');
|
|
30
|
+
const { registerApiRoutes } = require('../api-router');
|
|
31
|
+
const { PEER_CONTROL_SCOPE } = require('../auth-rules');
|
|
32
|
+
const remoteMachineProxy = require('../remote-machine-proxy');
|
|
33
|
+
|
|
34
|
+
let _deps = null;
|
|
35
|
+
|
|
36
|
+
function configure({
|
|
37
|
+
db,
|
|
38
|
+
pool,
|
|
39
|
+
machineSelf,
|
|
40
|
+
registry,
|
|
41
|
+
readJsonRequestBody,
|
|
42
|
+
sendJsonResponse,
|
|
43
|
+
listenPort = 0,
|
|
44
|
+
publicOrigin = () => '',
|
|
45
|
+
ready = null,
|
|
46
|
+
} = {}) {
|
|
47
|
+
_deps = { db, pool, machineSelf, registry, readJsonRequestBody, sendJsonResponse, listenPort, publicOrigin, ready };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The boot read's promise (`_machinePoolReady` in server.js). server.js fires the pool load
|
|
52
|
+
* fire-and-forget, so a handler that MUTATES the pool awaits this first instead of racing a load
|
|
53
|
+
* still in flight; read-only handlers never need to. WP-3's pair/remove handlers await the same
|
|
54
|
+
* promise through their own configure() call.
|
|
55
|
+
*/
|
|
56
|
+
function ready() {
|
|
57
|
+
return (_deps && _deps.ready) || Promise.resolve();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function _send(res, status, payload) {
|
|
61
|
+
if (_deps && typeof _deps.sendJsonResponse === 'function') return _deps.sendJsonResponse(res, status, payload);
|
|
62
|
+
const body = JSON.stringify(payload || {});
|
|
63
|
+
res.writeHead(status, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) });
|
|
64
|
+
res.end(body);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function _pool() {
|
|
68
|
+
return (_deps && _deps.pool) || require('../machine-pool').getMachinePool();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** D-13: the peer-only gate. Returns true (and answers 403) for a non-peer principal. */
|
|
72
|
+
function _refuseNonPeer(req, res) {
|
|
73
|
+
const scopes = req && req.ctmAuth && req.ctmAuth.scopes;
|
|
74
|
+
const isPeer = !!scopes && (scopes instanceof Set ? scopes.has(PEER_CONTROL_SCOPE) : Array.isArray(scopes) && scopes.includes(PEER_CONTROL_SCOPE));
|
|
75
|
+
if (isPeer) return false;
|
|
76
|
+
_send(res, 403, { ok: false, error: 'peer_only' });
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* P-6: a pool MUTATION (roster push, rotate) must present this machine's CURRENT pool secret. The
|
|
82
|
+
* auth wall accepts the grace (previous) secret for ordinary calls, but a machine just removed from
|
|
83
|
+
* the pool still holds it — so on these two routes it is refused, as is an env peer token (a legacy
|
|
84
|
+
* env box is never a pool member and has no business rewriting the pool). Answers 403
|
|
85
|
+
* `pool_secret_stale`.
|
|
86
|
+
*/
|
|
87
|
+
function _refuseStaleSecret(req, res) {
|
|
88
|
+
const header = String((req && req.headers && req.headers.authorization) || '');
|
|
89
|
+
const match = /^Bearer\s+(\S+)$/i.exec(header.trim());
|
|
90
|
+
if (match && _pool().isCurrent(match[1])) return false;
|
|
91
|
+
_send(res, 403, { ok: false, error: 'pool_secret_stale' });
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** This machine's own minted id — '' rather than a throw before boot has primed identity. */
|
|
96
|
+
function _instanceId() {
|
|
97
|
+
try {
|
|
98
|
+
const identity = require('../instance-identity-access').getInstanceIdentity({ required: false });
|
|
99
|
+
return (identity && identity.instanceId) || '';
|
|
100
|
+
} catch {
|
|
101
|
+
return ''; // expected: identity is not ready yet (early boot / pre-initDb)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* An IPv4 a peer can dial: not the subnet's network address (host bits all zero) and not its
|
|
107
|
+
* broadcast address (host bits all one). macOS VM/container bridges (bridge101..105 on the lead's
|
|
108
|
+
* Mac, 2026-10-25) carry the bare network address, e.g. 192.168.215.0/24 — advertising it costs the
|
|
109
|
+
* redeeming member one dead identity probe per pairing. /31 and /32 have no such addresses.
|
|
110
|
+
*/
|
|
111
|
+
function isDialableIPv4(address, netmask) {
|
|
112
|
+
const toInt = (dotted) => String(dotted || '').split('.').reduce((acc, part) => ((acc << 8) | (Number(part) & 255)) >>> 0, 0);
|
|
113
|
+
const parts = String(address || '').split('.');
|
|
114
|
+
if (parts.length !== 4) return false;
|
|
115
|
+
const mask = toInt(netmask || '255.255.255.255');
|
|
116
|
+
const hostBits = (~mask) >>> 0;
|
|
117
|
+
if (hostBits <= 1) return true;
|
|
118
|
+
const host = (toInt(address) & hostBits) >>> 0;
|
|
119
|
+
return host !== 0 && host !== hostBits;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* P-4 self URLs: every dialable non-internal IPv4 of this host as `http://<ip>:<listen port>`, then
|
|
124
|
+
* executionHost.publicOrigin (`http://` added when the origin is bare host[:port]). De-duplicated,
|
|
125
|
+
* order preserved, empties dropped.
|
|
126
|
+
*/
|
|
127
|
+
function selfUrls() {
|
|
128
|
+
const port = Number(_deps && _deps.listenPort) || 0;
|
|
129
|
+
const out = [];
|
|
130
|
+
const ifaces = os.networkInterfaces();
|
|
131
|
+
for (const entries of Object.values(ifaces)) {
|
|
132
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
133
|
+
if (!entry || entry.internal) continue;
|
|
134
|
+
if (String(entry.family) !== 'IPv4' && String(entry.family) !== '4') continue;
|
|
135
|
+
if (!entry.address || !isDialableIPv4(entry.address, entry.netmask)) continue;
|
|
136
|
+
out.push(`http://${entry.address}:${port}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
let origin = '';
|
|
140
|
+
try {
|
|
141
|
+
origin = String((typeof _deps?.publicOrigin === 'function' ? _deps.publicOrigin() : _deps?.publicOrigin) || '').trim();
|
|
142
|
+
} catch {
|
|
143
|
+
origin = ''; // expected: the manifest origin getter is optional/unready — self URLs stay LAN-only
|
|
144
|
+
}
|
|
145
|
+
if (origin) out.push(/^https?:\/\//i.test(origin) ? origin : `http://${origin}`);
|
|
146
|
+
return [...new Set(out.filter(Boolean))];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* P-1: the roster lists every OTHER pool member plus self (last), each as {instanceId, urls}. Only
|
|
151
|
+
* POOL MEMBERS: a legacy env-token row (P-8) is a registry row but never a member, and a receiver
|
|
152
|
+
* that adopted it into its member set would dial it with the pool bearer and be refused. Exported so
|
|
153
|
+
* lib/api/machines.js's pair/remove pushes speak exactly this shape.
|
|
154
|
+
*/
|
|
155
|
+
function rosterMembers() {
|
|
156
|
+
const db = _deps && _deps.db;
|
|
157
|
+
const pool = _pool();
|
|
158
|
+
const rows = db && typeof db.listMachineRows === 'function' ? (db.listMachineRows() || []) : [];
|
|
159
|
+
const members = rows.filter((row) => pool.isMember(String(row.instanceId || ''))).map((row) => ({
|
|
160
|
+
instanceId: String(row.instanceId || ''),
|
|
161
|
+
urls: Array.isArray(row.urls) && row.urls.length ? row.urls : [String(row.url || '')].filter(Boolean),
|
|
162
|
+
})).filter((row) => row.instanceId);
|
|
163
|
+
const self = _instanceId();
|
|
164
|
+
if (self && !members.some((row) => row.instanceId === self)) members.push({ instanceId: self, urls: selfUrls() });
|
|
165
|
+
return members;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function _readJson(req) {
|
|
169
|
+
if (_deps && typeof _deps.readJsonRequestBody === 'function') return _deps.readJsonRequestBody(req);
|
|
170
|
+
return new Promise((resolve, reject) => {
|
|
171
|
+
const chunks = [];
|
|
172
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
173
|
+
req.on('end', () => {
|
|
174
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
175
|
+
if (!raw) return resolve({});
|
|
176
|
+
try { resolve(JSON.parse(raw)); } catch { reject(new Error('invalid_json')); }
|
|
177
|
+
});
|
|
178
|
+
req.on('error', reject);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function handleRosterGet(req, res) {
|
|
183
|
+
if (_refuseNonPeer(req, res)) return;
|
|
184
|
+
const pool = _pool();
|
|
185
|
+
return _send(res, 200, {
|
|
186
|
+
ok: true,
|
|
187
|
+
poolId: pool.poolId(),
|
|
188
|
+
version: pool.rosterVersion(),
|
|
189
|
+
members: rosterMembers(),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function handleRosterPost(req, res) {
|
|
194
|
+
if (_refuseNonPeer(req, res)) return;
|
|
195
|
+
if (_refuseStaleSecret(req, res)) return;
|
|
196
|
+
let body = null;
|
|
197
|
+
try {
|
|
198
|
+
body = await _readJson(req);
|
|
199
|
+
} catch {
|
|
200
|
+
return _send(res, 400, { ok: false, error: 'invalid_json' });
|
|
201
|
+
}
|
|
202
|
+
const pool = _pool();
|
|
203
|
+
const version = (body && body.version) || {};
|
|
204
|
+
const current = pool.rosterVersion();
|
|
205
|
+
if (!pool.isNewer(version, current)) {
|
|
206
|
+
return _send(res, 200, { ok: true, applied: false, version: current });
|
|
207
|
+
}
|
|
208
|
+
const self = _instanceId();
|
|
209
|
+
const pushed = Array.isArray(body && body.members) ? body.members : [];
|
|
210
|
+
// Only PREVIOUS pool members may be deleted (a legacy env-token row is never one, P-8).
|
|
211
|
+
const removable = typeof pool.members === 'function' ? pool.members() : [];
|
|
212
|
+
const result = await _deps.db.replaceRosterMachines({ members: pushed, selfInstanceId: self, removable });
|
|
213
|
+
await pool.setRosterVersion(version);
|
|
214
|
+
// P-8: the pushed roster IS this member's membership set, less itself — that is what makes the
|
|
215
|
+
// outbound bearer per target (a legacy env-token box is never in it and keeps getting the env one).
|
|
216
|
+
await pool.setMembers(pushed
|
|
217
|
+
.map((member) => String((member && member.instanceId) || ''))
|
|
218
|
+
.filter((id) => id && id !== self));
|
|
219
|
+
if (_deps.registry && typeof _deps.registry.noteRegistryChanged === 'function') _deps.registry.noteRegistryChanged();
|
|
220
|
+
return _send(res, 200, { ok: true, applied: true, version: pool.rosterVersion(), ...result });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function handleRotate(req, res) {
|
|
224
|
+
if (_refuseNonPeer(req, res)) return;
|
|
225
|
+
if (_refuseStaleSecret(req, res)) return;
|
|
226
|
+
let body = null;
|
|
227
|
+
try {
|
|
228
|
+
body = await _readJson(req);
|
|
229
|
+
} catch {
|
|
230
|
+
return _send(res, 400, { ok: false, error: 'invalid_json' });
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
await _pool().acceptRotation({ token: body && body.token });
|
|
234
|
+
} catch {
|
|
235
|
+
return _send(res, 400, { ok: false, error: 'token_required' });
|
|
236
|
+
}
|
|
237
|
+
return _send(res, 200, { ok: true });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function handleLeave(req, res) {
|
|
241
|
+
const pool = _pool();
|
|
242
|
+
// leave() drops the token AND (P-8) the membership set — a re-joined box must not keep dialling a
|
|
243
|
+
// stale pool with a secret it no longer holds.
|
|
244
|
+
await pool.leave();
|
|
245
|
+
const removed = await _deps.db.deleteAllMachineRows();
|
|
246
|
+
if (_deps.registry && typeof _deps.registry.noteRegistryChanged === 'function') _deps.registry.noteRegistryChanged();
|
|
247
|
+
return _send(res, 200, { ok: true, removed: Number(removed) || 0 });
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function handleMachineSelfGet(req, res) {
|
|
251
|
+
return _send(res, 200, { ok: true, self: _deps.machineSelf.current() });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function handleMachineSelfPost(req, res) {
|
|
255
|
+
let body = null;
|
|
256
|
+
try {
|
|
257
|
+
body = await _readJson(req);
|
|
258
|
+
} catch {
|
|
259
|
+
return _send(res, 400, { ok: false, error: 'invalid_json' });
|
|
260
|
+
}
|
|
261
|
+
const patch = {};
|
|
262
|
+
if (body && body.displayName !== undefined) {
|
|
263
|
+
const displayName = String(body.displayName || '').trim();
|
|
264
|
+
if (displayName.length > 80) return _send(res, 400, { ok: false, error: 'display_name_too_long' });
|
|
265
|
+
patch.displayName = displayName;
|
|
266
|
+
}
|
|
267
|
+
if (body && body.favorite !== undefined) patch.favorite = body.favorite ? 1 : 0;
|
|
268
|
+
if (body && body.hidden !== undefined) patch.hidden = body.hidden ? 1 : 0;
|
|
269
|
+
const self = await _deps.machineSelf.setSelf(patch, Date.now());
|
|
270
|
+
return _send(res, 200, { ok: true, self });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// D-4: a machine-self request that names ANOTHER machine (?machine= or X-CTM-Machine) is answered by
|
|
274
|
+
// that member over the peer bearer — the same wrapper shape lib/api/misc-ops.js:41 uses, applied per
|
|
275
|
+
// verb. A non-machine-routed request is the unchanged local handler.
|
|
276
|
+
function _machineRouted(route, local) {
|
|
277
|
+
return (req, res, url) => (remoteMachineProxy.isMachineRouted(req, url)
|
|
278
|
+
? remoteMachineProxy.maybeProxyMachineRequest(req, res, url, { route })
|
|
279
|
+
.then((handled) => (handled ? undefined : local(req, res, url)))
|
|
280
|
+
: local(req, res, url));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function register() {
|
|
284
|
+
registerApiRoutes('machine-pool', [
|
|
285
|
+
{ method: 'GET', path: '/api/pool/roster', handler: (req, res) => handleRosterGet(req, res) },
|
|
286
|
+
{ method: 'POST', path: '/api/pool/roster', handler: (req, res) => handleRosterPost(req, res) },
|
|
287
|
+
{ method: 'POST', path: '/api/pool/rotate', handler: (req, res) => handleRotate(req, res) },
|
|
288
|
+
{ method: 'POST', path: '/api/pool/leave', handler: (req, res) => handleLeave(req, res) },
|
|
289
|
+
{ method: 'GET', path: '/api/machine-self', handler: _machineRouted('GET /api/machine-self', (req, res) => handleMachineSelfGet(req, res)) },
|
|
290
|
+
{ method: 'POST', path: '/api/machine-self', handler: _machineRouted('POST /api/machine-self', (req, res) => handleMachineSelfPost(req, res)) },
|
|
291
|
+
]);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
module.exports = {
|
|
295
|
+
configure,
|
|
296
|
+
register,
|
|
297
|
+
ready,
|
|
298
|
+
handleRosterGet,
|
|
299
|
+
handleRosterPost,
|
|
300
|
+
handleRotate,
|
|
301
|
+
handleLeave,
|
|
302
|
+
handleMachineSelfGet,
|
|
303
|
+
handleMachineSelfPost,
|
|
304
|
+
selfUrls,
|
|
305
|
+
isDialableIPv4,
|
|
306
|
+
rosterMembers,
|
|
307
|
+
};
|