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,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-0/WP-1 (docs/lead-switch-never-prompted-session-2026-10-30.html §5 D-1..D-4, §6): ONE history
|
|
4
|
+
// mode per transition — 'none' (this source lifetime has nothing to carry) or 'present' (today's
|
|
5
|
+
// behaviour) — decided ONCE before the switch claims its transition, carried on both recipes, and
|
|
6
|
+
// read back by every gate that used to re-derive (or silently assume) the answer.
|
|
7
|
+
//
|
|
8
|
+
// D-2, the rule that keeps this safe: 'none' is returned ONLY for a DEFINITE absence. The oracle is
|
|
9
|
+
// the same off-thread resume ladder park already consults (lib/park-fresh-relaunch.js
|
|
10
|
+
// `parkFindsNothingToResume`); a false answer, a thrown error, a timeout or an agent with no ladder
|
|
11
|
+
// all mean 'present'. "An unreadable store is not evidence that the conversation is gone"
|
|
12
|
+
// (superset-sh/superset#7144, adopted in §3 P-3), so a flaky ladder can only cost a refusal, never a
|
|
13
|
+
// lost conversation. A recipe written before this change carries no `historyMode` key and reads as
|
|
14
|
+
// 'present' — byte-for-byte today's path.
|
|
15
|
+
|
|
16
|
+
const { extractResumeTarget } = require('./session-history');
|
|
17
|
+
const { parkFindsNothingToResume } = require('./park-fresh-relaunch');
|
|
18
|
+
|
|
19
|
+
const HISTORY_MODES = Object.freeze(['none', 'present']);
|
|
20
|
+
// WP-2 D-6 (§5/§6): the only two spellings a source recipe's `modelOrigin` may carry.
|
|
21
|
+
const MODEL_ORIGINS = Object.freeze(['observed', 'cli-default']);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the SOURCE lifetime's history mode. NEVER throws (D-2): any error, rejection or timeout is
|
|
25
|
+
* 'present'.
|
|
26
|
+
*
|
|
27
|
+
* @param {object} input
|
|
28
|
+
* @param {'claude'|'codex'|string} input.agentType
|
|
29
|
+
* @param {string} input.ctmSessionId
|
|
30
|
+
* @param {string} input.jsonlPath claude: the transcript path park would stat; codex: the rollout path or ''
|
|
31
|
+
* @param {string} [input.resumeId] the source provider thread id
|
|
32
|
+
* @param {boolean} [input.resumeEvidence] true when park's own inputs already found a transcript/rollout ON DISK
|
|
33
|
+
* @param {(query: object) => Promise<{ rung?: string }>} input.resolveRung resolveResumeRungOffThread bound to dbPath
|
|
34
|
+
* @returns {Promise<'none'|'present'>}
|
|
35
|
+
*/
|
|
36
|
+
async function resolveSourceHistoryMode({ agentType, ctmSessionId, jsonlPath, resumeId, resumeEvidence = false, resolveRung } = {}) {
|
|
37
|
+
try {
|
|
38
|
+
// A transcript/rollout file already on disk is proof there IS something to resume, so the ladder
|
|
39
|
+
// is never consulted for it (park short-circuits the same way, lib/park-fresh-relaunch.js).
|
|
40
|
+
if (resumeEvidence === true) return 'present';
|
|
41
|
+
const nothingToResume = await parkFindsNothingToResume({ agentType, ctmSessionId, jsonlPath, resumeId, resolveRung });
|
|
42
|
+
return nothingToResume === true ? 'none' : 'present';
|
|
43
|
+
} catch {
|
|
44
|
+
// HANDLE: D-2 — an unreadable store, a rejected ladder or a timeout is never evidence of absence,
|
|
45
|
+
// so the refusal side of every gate keeps today's behaviour.
|
|
46
|
+
return 'present';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Recipe read with the D-2 default: a missing or unknown key is 'present'. */
|
|
51
|
+
function recipeHistoryMode(recipe) {
|
|
52
|
+
return recipe?.historyMode === 'none' ? 'none' : 'present';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* WP-2 D-6 (§5/§6): WHERE the source lifetime's model came from — recorded, never guessed.
|
|
57
|
+
*
|
|
58
|
+
* 'cli-default' means this source never named a model of its own: the mode is 'none' (nothing was
|
|
59
|
+
* ever prompted) AND `cliDefaultModel` (captured by the runtime's `getSessionInfo`) proved an empty
|
|
60
|
+
* `session.model_id`, no `--model`/`-m`/`--model=` in the captured launch argv and no
|
|
61
|
+
* `session_lead_model` pin row. Rolling such a source back must relaunch the ORIGINAL argv and pass
|
|
62
|
+
* NO one-shot model override at all, so the CLI's own default applies by construction (D-6 rejected
|
|
63
|
+
* both substituting `cli_default` as `--model` and re-reading the CLI's config file).
|
|
64
|
+
*
|
|
65
|
+
* Everything else is 'observed' — today's meaning: the model was read from the session/argv, and a
|
|
66
|
+
* rollback passes it as the one-shot override exactly as before. A recipe written before this change
|
|
67
|
+
* carries no `cliDefaultModel`, so it reads 'observed'.
|
|
68
|
+
*/
|
|
69
|
+
function sourceModelOrigin(source) {
|
|
70
|
+
return recipeHistoryMode(source) === 'none' && source?.cliDefaultModel === true ? 'cli-default' : 'observed';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** The value of a Claude argv's `--session-id <id>` / `--session-id=<id>`, or '' when absent. */
|
|
74
|
+
function claudeSessionIdArg(args) {
|
|
75
|
+
const list = Array.isArray(args) ? args.map(String) : [];
|
|
76
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
77
|
+
if (list[i] === '--session-id') return String(list[i + 1] || '');
|
|
78
|
+
if (list[i].startsWith('--session-id=')) return list[i].slice('--session-id='.length);
|
|
79
|
+
}
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The single thread clause shared by the pre-park planner check (D-4) and authorizeLiveTargetRestore
|
|
85
|
+
* (D-3) — one definition, so the two gates can never drift apart (§7).
|
|
86
|
+
*
|
|
87
|
+
* For 'present' it is EXACTLY the historical conjunct: the plan must resume the target recipe's own
|
|
88
|
+
* provider thread. For 'none' the plan must carry no resume selector at all, and a Claude plan's own
|
|
89
|
+
* `--session-id` must name the target recipe's thread: that argv is what the fresh process is given,
|
|
90
|
+
* so it is the thread its canonical owner will report.
|
|
91
|
+
*
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
function targetThreadClause({ source, target, launchPlan } = {}) {
|
|
95
|
+
const planThread = String(launchPlan?.resume?.sessionId || '');
|
|
96
|
+
const targetThread = String(target?.providerThreadId || '');
|
|
97
|
+
if (recipeHistoryMode(target) === 'present') return targetThread.length > 0 && planThread === targetThread;
|
|
98
|
+
// A 'none' target recipe is only meaningful with a 'none' SOURCE: the mode is one fact per
|
|
99
|
+
// transition, recorded twice.
|
|
100
|
+
if (recipeHistoryMode(source) !== 'none') return false;
|
|
101
|
+
if (planThread !== '') return false;
|
|
102
|
+
if (extractResumeTarget(launchPlan?.agentType, launchPlan?.args || [])) return false;
|
|
103
|
+
if (launchPlan?.agentType === 'claude') return targetThread.length > 0 && claudeSessionIdArg(launchPlan.args) === targetThread;
|
|
104
|
+
// codex: the new thread id is unknown until the thread links, so the owner check after launch
|
|
105
|
+
// binds it instead.
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = { HISTORY_MODES, MODEL_ORIGINS, resolveSourceHistoryMode, recipeHistoryMode,
|
|
110
|
+
sourceModelOrigin, claudeSessionIdArg, targetThreadClause };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// The CLI wire a lead agent speaks to CTM's model proxy. OpenCode leads and OpenCode's routed
|
|
3
|
+
// workers both use the Anthropic Messages face, so route servability is asked of 'claude'.
|
|
4
|
+
// This is the ONE rule: public/js/session-model-picker.js mirrors it as `leadWireAgent` for the
|
|
5
|
+
// Lead AND Delegate tabs, and tests pin the two bodies equal (docs/opencode-model-selection-round-2-shared-route-logic-2026-10-30.html §5 R-1, §6.1, §7).
|
|
6
|
+
function leadWireAgent(agent) { return agent === 'opencode' ? 'claude' : agent; }
|
|
7
|
+
module.exports = { leadWireAgent };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { createMediaJournalControlReader } = require('./media-journal-control-reader');
|
|
5
|
+
|
|
6
|
+
function unavailable(cause) {
|
|
7
|
+
return Object.assign(new Error('Pending image cancellation recovery is unavailable', { cause }), {
|
|
8
|
+
code: 'CTM_MEDIA_JOURNAL_UNAVAILABLE',
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// One recovery scope per logical DB handle and journal directory. No new SQL owner: the caller
|
|
13
|
+
// supplies the same worker projector used by the write-behind store. Neither journal nor cursor
|
|
14
|
+
// is advanced, because unrelated content must remain available to its ordinary replay owner.
|
|
15
|
+
function createLegacyDraftCancellationRecovery({ getDirectory, getContext, projectEntry }) {
|
|
16
|
+
for (const callback of [getDirectory, getContext, projectEntry]) {
|
|
17
|
+
if (typeof callback !== 'function') throw new TypeError('Cancellation recovery requires callbacks');
|
|
18
|
+
}
|
|
19
|
+
let scope = null;
|
|
20
|
+
let operation = null;
|
|
21
|
+
let retired = false;
|
|
22
|
+
let closing = null;
|
|
23
|
+
|
|
24
|
+
function binding() {
|
|
25
|
+
const context = getContext();
|
|
26
|
+
const directory = getDirectory();
|
|
27
|
+
if (!context || !directory) throw new Error('Cancellation recovery has no open storage context');
|
|
28
|
+
return { context, directory: path.resolve(directory) };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function assertCurrent(owner) {
|
|
32
|
+
if (retired || owner !== scope) throw new Error('Cancellation recovery scope is retired');
|
|
33
|
+
const current = binding();
|
|
34
|
+
if (current.context !== owner.context || current.directory !== owner.directory) {
|
|
35
|
+
throw new Error('Cancellation recovery storage context changed');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function closeReader(owner) {
|
|
40
|
+
if (!owner?.reader) return;
|
|
41
|
+
await owner.reader.close();
|
|
42
|
+
owner.reader = null; // Retain an unconfirmed resource owner on failure, not just its descriptor.
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function recover(current) {
|
|
46
|
+
await closeReader(scope);
|
|
47
|
+
const owner = scope = { ...current, reader: null, ready: false };
|
|
48
|
+
assertCurrent(owner);
|
|
49
|
+
const reader = owner.reader = createMediaJournalControlReader({
|
|
50
|
+
directory: owner.directory, assertCurrent: () => assertCurrent(owner),
|
|
51
|
+
});
|
|
52
|
+
let records;
|
|
53
|
+
let failed = false;
|
|
54
|
+
let failure;
|
|
55
|
+
try { records = await reader.read(); }
|
|
56
|
+
catch (error) { failed = true; failure = error; }
|
|
57
|
+
try { await closeReader(owner); }
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw failed
|
|
60
|
+
? new AggregateError([failure, error], 'Cancellation recovery and reader cleanup failed', { cause: failure })
|
|
61
|
+
: error;
|
|
62
|
+
}
|
|
63
|
+
if (failed) throw failure;
|
|
64
|
+
// Close every read handle BEFORE the first SQL projection. A partial projection remains
|
|
65
|
+
// idempotently retryable through applyMediaJournalEntry; it is never a completed recovery.
|
|
66
|
+
for (const { entry } of records) {
|
|
67
|
+
assertCurrent(owner);
|
|
68
|
+
const result = await projectEntry(entry, { urgent: true });
|
|
69
|
+
assertCurrent(owner);
|
|
70
|
+
if (typeof result?.cancelled !== 'boolean' || typeof result?.sessionEnded !== 'boolean'
|
|
71
|
+
|| result.cancelled === result.sessionEnded) {
|
|
72
|
+
throw new TypeError('Cancellation projection did not confirm a durable cancellation or ended session');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
assertCurrent(owner);
|
|
76
|
+
owner.ready = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function prepare() {
|
|
80
|
+
try {
|
|
81
|
+
if (retired) throw new Error('Cancellation recovery is closed');
|
|
82
|
+
const current = binding();
|
|
83
|
+
if (operation) return operation;
|
|
84
|
+
if (scope?.ready && scope.context === current.context && scope.directory === current.directory) {
|
|
85
|
+
return Promise.resolve();
|
|
86
|
+
}
|
|
87
|
+
operation = recover(current).catch(error => { throw unavailable(error); })
|
|
88
|
+
.finally(() => { operation = null; });
|
|
89
|
+
return operation;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return Promise.reject(unavailable(error));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function close() {
|
|
96
|
+
retired = true;
|
|
97
|
+
if (closing) return closing;
|
|
98
|
+
closing = (async () => {
|
|
99
|
+
// Already delivered operational errors are not shutdown failures. Unconfirmed handles
|
|
100
|
+
// remain owned and closeReader must still report them. No race against a timeout here.
|
|
101
|
+
if (operation) await operation.catch(() => { /* expected: admitted caller receives the failure */ });
|
|
102
|
+
await closeReader(scope);
|
|
103
|
+
scope = null;
|
|
104
|
+
})().finally(() => { closing = null; });
|
|
105
|
+
return closing;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { prepare, close };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = { createLegacyDraftCancellationRecovery };
|
|
@@ -49,7 +49,13 @@ function readJsonFileSafe(filePath) {
|
|
|
49
49
|
// that prompt entirely. Only a scope the USER wrote (top-level or `projects[cwd]` inside their
|
|
50
50
|
// own ~/.claude.json) may ever supply a command here.
|
|
51
51
|
function resolveCoreClaudeMcpServers(names, { homeDir = '', cwd = '' } = {}) {
|
|
52
|
-
|
|
52
|
+
return selectClaudeMcpServers(homeDir ? readJsonFileSafe(path.join(homeDir, '.claude.json')) : null, names, { cwd });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The pure half of resolveCoreClaudeMcpServers, shared with the async DeepSeek Harness reader
|
|
56
|
+
// (lib/session-create/dsh-session.js): the same two USER scopes, project scope winning. `names`
|
|
57
|
+
// null selects every declared server (the 'full' profile, which dsh must materialize itself).
|
|
58
|
+
function selectClaudeMcpServers(claudeJson, names, { cwd = '' } = {}) {
|
|
53
59
|
const userScope = claudeJson && typeof claudeJson.mcpServers === 'object' && claudeJson.mcpServers ? claudeJson.mcpServers : {};
|
|
54
60
|
const projectEntry = claudeJson && claudeJson.projects && typeof claudeJson.projects === 'object' && cwd
|
|
55
61
|
? claudeJson.projects[cwd]
|
|
@@ -57,7 +63,7 @@ function resolveCoreClaudeMcpServers(names, { homeDir = '', cwd = '' } = {}) {
|
|
|
57
63
|
const projectScope = projectEntry && typeof projectEntry.mcpServers === 'object' && projectEntry.mcpServers ? projectEntry.mcpServers : {};
|
|
58
64
|
|
|
59
65
|
const servers = {};
|
|
60
|
-
for (const name of names) {
|
|
66
|
+
for (const name of names || [...new Set([...Object.keys(userScope), ...Object.keys(projectScope)])]) {
|
|
61
67
|
const def = projectScope[name] || userScope[name];
|
|
62
68
|
if (def) servers[name] = def;
|
|
63
69
|
}
|
|
@@ -200,6 +206,7 @@ module.exports = {
|
|
|
200
206
|
codexMcpDisableArgs,
|
|
201
207
|
resolveMcpProfile,
|
|
202
208
|
normalizeMcpProfile,
|
|
209
|
+
selectClaudeMcpServers,
|
|
203
210
|
MCP_PROFILES,
|
|
204
211
|
MCP_PROFILE_FULL,
|
|
205
212
|
MCP_PROFILE_NONE,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-2 (live-defer-wake-adopted-host-death-2026-10-28.html §5 R-3/R-4/R-6/R-8): a LIVE defer
|
|
4
|
+
// (the process died under an open tab) used to announce nothing to the attached clients -- only
|
|
5
|
+
// `broadcastSessionList(true)`. The tab therefore kept its "current route proof" for the same
|
|
6
|
+
// socket generation, so selecting it never sent a `terminal-bootstrap` and the server's deferred
|
|
7
|
+
// wake never ran. The idle-park path already does it right (server.js park loop: iterate the
|
|
8
|
+
// session's clients, readyState 1, sendDeferredRestoreStatus). These are the PURE helpers for
|
|
9
|
+
// that announcement -- no server state, no requires, so both the adopted exit handler and the
|
|
10
|
+
// session-create exit handler can share one implementation.
|
|
11
|
+
|
|
12
|
+
// Which defer this exit is. WP-3a's dead-host path stamps `hostClosed: true` on the exit event it
|
|
13
|
+
// synthesizes (lib/adopted-host-redial.js `_emitExitOnce`), so the evidence is the event itself --
|
|
14
|
+
// never a process-liveness probe reconstructed at the defer site.
|
|
15
|
+
function liveDeferSource(exitEvent) {
|
|
16
|
+
return exitEvent?.hostClosed === true ? 'host-death' : 'crash-defer';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Announce the live defer to every client still attached. Returns the number of frames the caller's
|
|
20
|
+
// `send` accepted; a client that has gone away (readyState !== 1) is skipped, and a `send` that
|
|
21
|
+
// throws for one client must never stop the loop for the rest.
|
|
22
|
+
function announceLiveDefer({ clients, send } = {}) {
|
|
23
|
+
const list = clients || [];
|
|
24
|
+
let sent = 0;
|
|
25
|
+
for (const ws of list) {
|
|
26
|
+
if (ws?.readyState !== 1) continue;
|
|
27
|
+
try {
|
|
28
|
+
send(ws);
|
|
29
|
+
sent += 1;
|
|
30
|
+
} catch { /* expected: client disconnected during lifecycle broadcast */ }
|
|
31
|
+
}
|
|
32
|
+
return sent;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// WP-3b (R-8): the evidence a host death carries on its exit event, normalized for the diagnostic
|
|
36
|
+
// row. Booleans are strict, so an absent/undefined field reads as `false` -- never truthy garbage.
|
|
37
|
+
function hostDeathEvidence(exitEvent) {
|
|
38
|
+
return {
|
|
39
|
+
reason: String(exitEvent?.reason || ''),
|
|
40
|
+
hostRetired: exitEvent?.hostRetired === true,
|
|
41
|
+
hostPidAliveAtDeclare: exitEvent?.hostPidAliveAtDeclare === true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { liveDeferSource, announceLiveDefer, hostDeathEvidence };
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-3 (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §6.3, D-6/D-9, §9 S-15/S-16/S-23):
|
|
4
|
+
// the pairing code — the BOX side.
|
|
5
|
+
//
|
|
6
|
+
// A machine that wants to join a pool shows an 8-character code. The joining member posts the code
|
|
7
|
+
// plus the pool token to the box's PRE-AUTH `POST /api/machine-pairing/join`; the box verifies the
|
|
8
|
+
// code, burns it, and adopts the token. Rules that shape this module:
|
|
9
|
+
//
|
|
10
|
+
// * §6.3 verbatim — alphabet, length, TTL, the 3-live-offer ceiling and the 5-wrong-redeem burn.
|
|
11
|
+
// * The code is a BEARER secret for one redemption. It is NEVER stored and NEVER logged: the only
|
|
12
|
+
// thing that reaches the database is `sha256(normalizeCode(code))` hex (D-6, §11 anti-goals).
|
|
13
|
+
// * `redeem` compares hashes with crypto.timingSafeEqual over EQUAL-LENGTH buffers — the digest is
|
|
14
|
+
// fixed-width, so a length mismatch is a malformed row, never a timing oracle.
|
|
15
|
+
// * Expired and already-used offers answer the SAME `pairing_code_invalid` code: a wrong code, a
|
|
16
|
+
// stale offer and a burned one must be indistinguishable to the caller, or the endpoint becomes
|
|
17
|
+
// an oracle for "was there ever an offer here".
|
|
18
|
+
//
|
|
19
|
+
// LEAF module: node built-ins only. Everything is injectable (`now`, `randomBytes`, `db`) so the
|
|
20
|
+
// unit test never touches the real clock, the real CSPRNG or a real database (clock-free rule).
|
|
21
|
+
|
|
22
|
+
const crypto = require('node:crypto');
|
|
23
|
+
|
|
24
|
+
const CODE_ALPHABET = 'BCDFGHJKLMNPQRSTVWXZ'; // RFC 8628 §6.1 — no vowels, no 0/1/I/O look-alikes
|
|
25
|
+
const CODE_LENGTH = 8; // shown (and typed) as XXXX-XXXX
|
|
26
|
+
const OFFER_TTL_MS = 600_000;
|
|
27
|
+
const MAX_LIVE_OFFERS = 3;
|
|
28
|
+
const MAX_FAILED_REDEEMS = 5;
|
|
29
|
+
|
|
30
|
+
// The container the box prints/paints once: `ctmpair1:` + base64url(JSON).
|
|
31
|
+
const PAIRING_STRING_PREFIX = 'ctmpair1:';
|
|
32
|
+
|
|
33
|
+
// |CODE_ALPHABET| = 20 and 256 is NOT a multiple of 20, so `byte % 20` would favour the first four
|
|
34
|
+
// letters roughly 13% of the time. 240 = floor(256/20)*20 is the largest multiple of 20 that fits in
|
|
35
|
+
// a byte: every byte >= 240 is discarded and re-drawn (RFC 8628 §6.1 rejection sampling).
|
|
36
|
+
const REJECT_AT = Math.floor(256 / CODE_ALPHABET.length) * CODE_ALPHABET.length; // 240
|
|
37
|
+
// A batch per draw, and a hard ceiling on batches so a broken/scripted `randomBytes` cannot spin
|
|
38
|
+
// this loop forever — 32 batches of 16 bytes is a 1-in-10^22 tail, never a real event.
|
|
39
|
+
const DRAW_BATCH = CODE_LENGTH * 2;
|
|
40
|
+
const MAX_DRAW_BATCHES = 32;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* §6.3 verbatim: uppercase, then drop every character outside the alphabet. Hyphens and spaces are
|
|
44
|
+
* therefore formatting, not content — `wdjb-mjht`, `WDJB MJHT` and `WDJBMJHT` are one code.
|
|
45
|
+
*/
|
|
46
|
+
function normalizeCode(value) {
|
|
47
|
+
return String(value || '').toUpperCase().replace(/[^BCDFGHJKLMNPQRSTVWXZ]/g, '');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The display form the offer response carries: XXXX-XXXX (empty in => empty out). */
|
|
51
|
+
function formatCode(value) {
|
|
52
|
+
const code = normalizeCode(value);
|
|
53
|
+
if (code.length !== CODE_LENGTH) return code;
|
|
54
|
+
return `${code.slice(0, 4)}-${code.slice(4)}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** D-6: the ONLY representation of a code that is ever persisted. */
|
|
58
|
+
function hashCode(value) {
|
|
59
|
+
return crypto.createHash('sha256').update(normalizeCode(value), 'utf8').digest('hex');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Constant-time hash compare over equal-length buffers. Two sha256 digests are always 64 chars, so
|
|
64
|
+
* a mismatch in length means a malformed stored row — false, never a throw and never a compare.
|
|
65
|
+
*/
|
|
66
|
+
function codeHashEquals(left, right) {
|
|
67
|
+
const a = Buffer.from(String(left == null ? '' : left), 'utf8');
|
|
68
|
+
const b = Buffer.from(String(right == null ? '' : right), 'utf8');
|
|
69
|
+
if (!a.length || a.length !== b.length) return false;
|
|
70
|
+
return crypto.timingSafeEqual(a, b);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** `XXXX-XXXX` -> a batch of random letters, rejection-sampled (no modulo bias). */
|
|
74
|
+
function mintCode(randomBytes) {
|
|
75
|
+
const out = [];
|
|
76
|
+
for (let batch = 0; batch < MAX_DRAW_BATCHES && out.length < CODE_LENGTH; batch += 1) {
|
|
77
|
+
const bytes = randomBytes(DRAW_BATCH);
|
|
78
|
+
for (const byte of bytes) {
|
|
79
|
+
if (byte >= REJECT_AT) continue; // biased tail — re-draw, never fold
|
|
80
|
+
out.push(CODE_ALPHABET[byte % CODE_ALPHABET.length]);
|
|
81
|
+
if (out.length >= CODE_LENGTH) break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (out.length < CODE_LENGTH) throw new Error('machine-pairing: randomBytes did not yield an unbiased code');
|
|
85
|
+
return out.join('');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* §6.3: `'ctmpair1:' + base64url(JSON{v:1,i:instanceId,n:displayName,u:candidates,c:code})`.
|
|
90
|
+
* `c` is the DISPLAY form (XXXX-XXXX); `normalizeCode` strips the hyphen on the way back in.
|
|
91
|
+
*/
|
|
92
|
+
function encodePairingString({ instanceId, displayName, urls, code } = {}) {
|
|
93
|
+
const payload = JSON.stringify({
|
|
94
|
+
v: 1,
|
|
95
|
+
i: String(instanceId || ''),
|
|
96
|
+
n: String(displayName || ''),
|
|
97
|
+
u: (Array.isArray(urls) ? urls : []).map((url) => String(url || '')).filter(Boolean),
|
|
98
|
+
c: String(code || ''),
|
|
99
|
+
});
|
|
100
|
+
return `${PAIRING_STRING_PREFIX}${Buffer.from(payload, 'utf8').toString('base64url')}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The member side of the container. Returns null for anything that is not a v1 pairing string —
|
|
105
|
+
* a hand-edited or truncated string is a 400 (`pairing_string_invalid`), never a throw.
|
|
106
|
+
*/
|
|
107
|
+
function decodePairingString(value) {
|
|
108
|
+
const raw = String(value == null ? '' : value).trim();
|
|
109
|
+
if (!raw.startsWith(PAIRING_STRING_PREFIX)) return null;
|
|
110
|
+
let parsed = null;
|
|
111
|
+
try {
|
|
112
|
+
parsed = JSON.parse(Buffer.from(raw.slice(PAIRING_STRING_PREFIX.length), 'base64url').toString('utf8'));
|
|
113
|
+
} catch {
|
|
114
|
+
return null; // expected: a corrupted container is a client error, not a server fault
|
|
115
|
+
}
|
|
116
|
+
if (!parsed || typeof parsed !== 'object' || parsed.v !== 1) return null;
|
|
117
|
+
const code = normalizeCode(parsed.c);
|
|
118
|
+
if (code.length !== CODE_LENGTH) return null;
|
|
119
|
+
const urls = (Array.isArray(parsed.u) ? parsed.u : [])
|
|
120
|
+
.map((url) => String(url || '').trim().replace(/\/+$/, ''))
|
|
121
|
+
.filter(Boolean);
|
|
122
|
+
const instanceId = String(parsed.i || '').trim();
|
|
123
|
+
if (!instanceId && !urls.length) return null;
|
|
124
|
+
return { version: 1, instanceId, displayName: String(parsed.n || ''), urls, code };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* The box's pairing store.
|
|
129
|
+
*
|
|
130
|
+
* @param {{db: object, now?: () => number, randomBytes?: (n: number) => Buffer}} deps
|
|
131
|
+
* `db` must expose the four DB-owner ops: listLivePairingOffers, insertPairingOffer,
|
|
132
|
+
* markPairingOfferRedeemed, burnLivePairingOffers.
|
|
133
|
+
* @returns {{createOffer: () => Promise<object>, redeem: (code: string, options?: object) => Promise<object>,
|
|
134
|
+
* hasLiveOffers: () => Promise<boolean>, burnAll: () => Promise<object>}}
|
|
135
|
+
*/
|
|
136
|
+
function createMachinePairing({ db, now = () => Date.now(), randomBytes = (n) => crypto.randomBytes(n) } = {}) {
|
|
137
|
+
if (!db || typeof db.listLivePairingOffers !== 'function') {
|
|
138
|
+
throw new TypeError('machine-pairing: db.listLivePairingOffers is required');
|
|
139
|
+
}
|
|
140
|
+
// §6.3: in memory on purpose — a restart clearing the counter is fine (the offers themselves are
|
|
141
|
+
// single-use and TTL-bounded), while persisting it would put an attacker-controlled number in the
|
|
142
|
+
// DB. Five CONSECUTIVE failures burn everything live; one success resets it.
|
|
143
|
+
let failedRedeems = 0;
|
|
144
|
+
|
|
145
|
+
function _now() {
|
|
146
|
+
return Math.trunc(Number(now()) || 0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* §6.3 `POST /api/machine-pairing/offers`. At most MAX_LIVE_OFFERS unspent offers exist at any
|
|
151
|
+
* moment, so a walked-away browser cannot leave an unbounded set of valid codes behind.
|
|
152
|
+
*/
|
|
153
|
+
async function createOffer() {
|
|
154
|
+
const at = _now();
|
|
155
|
+
const live = await db.listLivePairingOffers({ at });
|
|
156
|
+
if (Array.isArray(live) && live.length >= MAX_LIVE_OFFERS) {
|
|
157
|
+
return { ok: false, code: 'pairing_offer_limit' };
|
|
158
|
+
}
|
|
159
|
+
const code = mintCode(randomBytes);
|
|
160
|
+
const expiresAt = at + OFFER_TTL_MS;
|
|
161
|
+
await db.insertPairingOffer({ id: crypto.randomUUID(), codeHash: hashCode(code), createdAt: at, expiresAt });
|
|
162
|
+
return { ok: true, code: formatCode(code), expiresAt };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* §6.3 ordering: hash-compare against the live set, then burn the one that matched. `by` is the
|
|
167
|
+
* redeeming machine's instance id and is the only thing recorded — never the code.
|
|
168
|
+
*
|
|
169
|
+
* SINGLE USE IS THE UPDATE, NOT THE READ (F3). The candidate was found by reading the live set, but
|
|
170
|
+
* that read is not a claim: two joins holding the same code would both find the row and both return
|
|
171
|
+
* ok from a read-then-trust redeem. `markPairingOfferRedeemed` carries the `redeemed_at IS NULL`
|
|
172
|
+
* predicate in its WHERE clause and reports how many rows it changed, so exactly one of the two
|
|
173
|
+
* callers sees `changes === 1` and the loser is told `pairing_code_invalid` — the same answer an
|
|
174
|
+
* already-used code gets, which is what keeps the endpoint from being an oracle. A lost claim is NOT
|
|
175
|
+
* a failed guess (the caller was holding a real code), so it must not count toward the burn.
|
|
176
|
+
*/
|
|
177
|
+
async function redeem(code, { by = '' } = {}) {
|
|
178
|
+
const at = _now();
|
|
179
|
+
const live = await db.listLivePairingOffers({ at });
|
|
180
|
+
const wanted = hashCode(code);
|
|
181
|
+
const offer = (Array.isArray(live) ? live : []).find((row) => codeHashEquals(row && row.codeHash, wanted));
|
|
182
|
+
if (!offer) {
|
|
183
|
+
failedRedeems += 1;
|
|
184
|
+
if (failedRedeems >= MAX_FAILED_REDEEMS) {
|
|
185
|
+
failedRedeems = 0;
|
|
186
|
+
// §6.3 AC-3c: the 5th consecutive miss burns EVERY live offer, so an attacker who is
|
|
187
|
+
// brute-forcing the 20^8 space loses the offers they were guessing against.
|
|
188
|
+
await db.burnLivePairingOffers({ at });
|
|
189
|
+
}
|
|
190
|
+
return { ok: false, code: 'pairing_code_invalid' };
|
|
191
|
+
}
|
|
192
|
+
const id = String(offer.id || '');
|
|
193
|
+
const changed = Number(await db.markPairingOfferRedeemed({
|
|
194
|
+
id,
|
|
195
|
+
at,
|
|
196
|
+
redeemedBy: String(by || '').slice(0, 200),
|
|
197
|
+
})) || 0;
|
|
198
|
+
if (changed !== 1) return { ok: false, code: 'pairing_code_invalid' };
|
|
199
|
+
// Only a claimed offer is a success, and only a success resets the consecutive-miss counter.
|
|
200
|
+
failedRedeems = 0;
|
|
201
|
+
return { ok: true, offer: { id, expiresAt: Number(offer.expiresAt) || 0 } };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** §6.3/D-9: is this box showing a live code right now? (the identity probe's yes/no, never a code) */
|
|
205
|
+
async function hasLiveOffers() {
|
|
206
|
+
const live = await db.listLivePairingOffers({ at: _now() });
|
|
207
|
+
return Array.isArray(live) && live.length > 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* F4: after a successful adopt this box belongs to somebody, so every OTHER live code must die —
|
|
212
|
+
* otherwise a second primary holding a code minted before the join could re-adopt the box and walk
|
|
213
|
+
* away with the pool secret. Also clears the failure counter: the box is no longer "unpaired".
|
|
214
|
+
*/
|
|
215
|
+
async function burnAll() {
|
|
216
|
+
failedRedeems = 0;
|
|
217
|
+
return db.burnLivePairingOffers({ at: _now() });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { createOffer, redeem, hasLiveOffers, burnAll };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
module.exports = {
|
|
224
|
+
CODE_ALPHABET,
|
|
225
|
+
CODE_LENGTH,
|
|
226
|
+
OFFER_TTL_MS,
|
|
227
|
+
MAX_LIVE_OFFERS,
|
|
228
|
+
MAX_FAILED_REDEEMS,
|
|
229
|
+
PAIRING_STRING_PREFIX,
|
|
230
|
+
normalizeCode,
|
|
231
|
+
formatCode,
|
|
232
|
+
hashCode,
|
|
233
|
+
codeHashEquals,
|
|
234
|
+
mintCode,
|
|
235
|
+
encodePairingString,
|
|
236
|
+
decodePairingString,
|
|
237
|
+
createMachinePairing,
|
|
238
|
+
};
|