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,565 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-3 (docs/shared-memory-every-machine-2026-10-31.html §5 D-1/D-2/D-9/D-12, §6.6): the hub side
|
|
4
|
+
// of the v2 brain replica in the existing star.
|
|
5
|
+
//
|
|
6
|
+
// syncMemberBrainOnce(member, deps) -> { ok, member, state, pulled, pushed, error? }
|
|
7
|
+
// runBrainMemberRound(deps) -> { ok, members: [...], pruned }
|
|
8
|
+
// memorySyncStatus() -> { lastRoundAt, members: [...] }
|
|
9
|
+
//
|
|
10
|
+
// D-1: membership is PAIRING, not `CTM_SYNC_PEERS`. The members are this host's machine-registry
|
|
11
|
+
// rows with `enabled = 1` and `health === 'reachable'` (the hub owns liveness, machine-registry
|
|
12
|
+
// D-4) — the same credential the probe uses reaches them (`peerHeadersFor`, the pool secret for a
|
|
13
|
+
// member). D-2: only the hub dials; each round exchanges both directions with every reachable
|
|
14
|
+
// member and there is no box↔box link. D-12: the member's CTM fronts its own loopback Wall-E at
|
|
15
|
+
// `/api/sync/brain/v2/*`; the local leg talks to THIS host's Wall-E with the local CTM token.
|
|
16
|
+
//
|
|
17
|
+
// The per-member state Map (failure backoff, last verdict) is MODULE state by design, exactly like
|
|
18
|
+
// machine-registry's probe bookkeeping: it describes the last round this process ran, dies with the
|
|
19
|
+
// process, and a stale copy must never look like durable truth.
|
|
20
|
+
|
|
21
|
+
const { boolFlag, createEnvFlags } = require('./env-flags');
|
|
22
|
+
const machineRegistry = require('./machine-registry');
|
|
23
|
+
const { advanceMemberJoin } = require('./memory-join');
|
|
24
|
+
const conversationStore = require('./conversation-store-v2');
|
|
25
|
+
const conversationSync = require('./conversation-sync');
|
|
26
|
+
|
|
27
|
+
const DEFAULT_PAGE_LIMIT = 500; // D-9: one page is at most 500 clock rows
|
|
28
|
+
const DEFAULT_MAX_PAGES = 20; // D-9: at most 20 pages per member per round
|
|
29
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
|
|
30
|
+
const DEFAULT_FAILURE_BACKOFF_MS = 15_000;
|
|
31
|
+
const DEFAULT_FAILURE_BACKOFF_MAX_MS = 60_000;
|
|
32
|
+
|
|
33
|
+
// WP-4 (§5 D-6, §6.7): the non-error join states a member can report while it is taking the hub's
|
|
34
|
+
// snapshot. 'join_failed' is deliberately absent — a broken join is a fault, not progress.
|
|
35
|
+
const JOIN_PROGRESS_STATES = new Set(['join_snapshot', 'join_transfer', 'join_import', 'join_done']);
|
|
36
|
+
|
|
37
|
+
// The box CTM's front routes (D-12). Each forwards verbatim to the box's own Wall-E.
|
|
38
|
+
const MEMBER_PATHS = Object.freeze({
|
|
39
|
+
vector: '/api/sync/brain/v2/vector',
|
|
40
|
+
changes: '/api/sync/brain/v2/changes',
|
|
41
|
+
apply: '/api/sync/brain/v2/apply',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// The hub's LOCAL Wall-E v2 routes (already loopback + CTM token).
|
|
45
|
+
const LOCAL_PATHS = Object.freeze({
|
|
46
|
+
vector: '/api/walle/sync/v2/vector',
|
|
47
|
+
changes: '/api/walle/sync/v2/changes',
|
|
48
|
+
apply: '/api/walle/sync/v2/apply',
|
|
49
|
+
memberVector: '/api/walle/sync/v2/member-vector',
|
|
50
|
+
pruneTombstones: '/api/walle/sync/v2/prune-tombstones',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// WP-5 (§5 D-3, §6.8): the conversation-history front routes a member's CTM serves itself — no
|
|
54
|
+
// Wall-E hop, because transcription history lives in task-manager.db.
|
|
55
|
+
const CONVERSATION_PATHS = Object.freeze({
|
|
56
|
+
vector: '/api/sync/conversation/v2/vector',
|
|
57
|
+
changes: '/api/sync/conversation/v2/changes',
|
|
58
|
+
apply: '/api/sync/conversation/v2/apply',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// instanceId -> { attempts, nextAt, state }. Module state (see the header).
|
|
62
|
+
const _memberState = new Map();
|
|
63
|
+
// The one in-flight round, or null. A second call joins/reports it, never starts a second round.
|
|
64
|
+
let _inFlight = null;
|
|
65
|
+
let _lastRound = null;
|
|
66
|
+
|
|
67
|
+
function _string(value, max = 160) {
|
|
68
|
+
if (typeof value === 'string') return value.trim().slice(0, max);
|
|
69
|
+
return value == null ? '' : String(value).trim().slice(0, max);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function _now(deps = {}) {
|
|
73
|
+
return typeof deps.now === 'function' ? Number(deps.now()) || Date.now() : Date.now();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// D-1 flag. Default ON; only '0'/'false'/'no'/'off' disables. `deps.env` is injected so a test can
|
|
77
|
+
// flip it without touching process.env (H-1), and so a member Wall-E's own kill switch is honoured
|
|
78
|
+
// on the local leg (503 brain_sync_disabled -> 'disabled').
|
|
79
|
+
function _brainSyncEnabled(env) {
|
|
80
|
+
if (!env || env === process.env) return boolFlag('CTM_SYNC_BRAIN_ENABLED', true);
|
|
81
|
+
return createEnvFlags({ env }).boolFlag('CTM_SYNC_BRAIN_ENABLED', true);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function _memberUrls(member = {}) {
|
|
85
|
+
const list = (Array.isArray(member.urls) ? member.urls : []).map((u) => _string(u, 1000)).filter(Boolean);
|
|
86
|
+
if (list.length) return list;
|
|
87
|
+
const pinned = _string(member.url, 1000);
|
|
88
|
+
return pinned ? [pinned] : [];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function _joinUrl(base, pathname) {
|
|
92
|
+
return `${String(base).replace(/\/+$/, '')}${pathname}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// One member request, with the AbortController + unref'd timer shape machine-registry's _getJsonBox
|
|
96
|
+
// uses, so a hung box can never hold the tick open past the timeout. Never throws: a transport fault
|
|
97
|
+
// is reported as `{ status: 0 }` and mapped by the caller to 'unreachable'.
|
|
98
|
+
async function _memberRequest(fetchImpl, url, pathname, { method = 'GET', body = null, headers = {} } = {}) {
|
|
99
|
+
const fetchFn = fetchImpl || global.fetch;
|
|
100
|
+
if (typeof fetchFn !== 'function') return { status: 0, json: null, error: 'fetch_unavailable' };
|
|
101
|
+
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
102
|
+
const timer = controller ? setTimeout(() => controller.abort(), DEFAULT_REQUEST_TIMEOUT_MS) : null;
|
|
103
|
+
if (timer && typeof timer.unref === 'function') timer.unref();
|
|
104
|
+
try {
|
|
105
|
+
const payload = body == null ? null : JSON.stringify(body);
|
|
106
|
+
const res = await fetchFn(_joinUrl(url, pathname), {
|
|
107
|
+
method,
|
|
108
|
+
headers: {
|
|
109
|
+
...headers,
|
|
110
|
+
...(payload ? { 'Content-Type': 'application/json' } : {}),
|
|
111
|
+
Accept: 'application/json',
|
|
112
|
+
},
|
|
113
|
+
...(payload ? { body: payload } : {}),
|
|
114
|
+
signal: controller ? controller.signal : undefined,
|
|
115
|
+
});
|
|
116
|
+
let json = null;
|
|
117
|
+
try { json = await res.json(); } catch { json = null; /* expected: a non-JSON body is degraded, mapped by the caller */ }
|
|
118
|
+
return { status: Number(res && res.status) || 0, json };
|
|
119
|
+
} catch (err) {
|
|
120
|
+
return { status: 0, json: null, error: err?.message || String(err) };
|
|
121
|
+
} finally {
|
|
122
|
+
if (timer) clearTimeout(timer);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// One local Wall-E call. walle.requestJson resolves { status, json } for any answer and rejects only
|
|
127
|
+
// on a transport fault — the caller maps both.
|
|
128
|
+
async function _walleRequest(walle, pathname, { method = 'GET', body = null } = {}) {
|
|
129
|
+
try {
|
|
130
|
+
const res = await walle.requestJson(pathname, body == null ? { method } : { method, body });
|
|
131
|
+
return { status: Number(res && res.status) || 0, json: (res && res.json) || null };
|
|
132
|
+
} catch (err) {
|
|
133
|
+
return { status: 0, json: null, error: err?.message || String(err) };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function _isDisabled(res) {
|
|
138
|
+
return res && res.status === 503 && res.json && res.json.error === 'brain_sync_disabled';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// The first URL that ANSWERS (any HTTP status) owns the rest of the exchange, so a member is never
|
|
142
|
+
// half-dialled across two origins inside one round. No answer at all -> status 0 ('unreachable').
|
|
143
|
+
async function _dialMember(fetchImpl, urls, pathname, options) {
|
|
144
|
+
let last = { status: 0, json: null, error: 'member_has_no_url' };
|
|
145
|
+
for (const url of urls) {
|
|
146
|
+
const res = await _memberRequest(fetchImpl, url, pathname, options);
|
|
147
|
+
if (res.status > 0) return { ...res, url };
|
|
148
|
+
last = { ...res, url };
|
|
149
|
+
}
|
|
150
|
+
return last;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* One bidirectional exchange with one member (D-2, D-9). Returns a state from
|
|
155
|
+
* 'synced' | 'seed_pending' | 'disabled' | 'unreachable' | 'error', or — for a member that has
|
|
156
|
+
* never taken the hub's origin — one of lib/memory-join.js's join states ('seed_pending' |
|
|
157
|
+
* 'join_snapshot' | 'join_transfer' | 'join_import' | 'join_done' | 'join_failed').
|
|
158
|
+
*
|
|
159
|
+
* @param {{instanceId: string, urls?: string[], url?: string}} member
|
|
160
|
+
* @param {object} deps { fetchImpl, peerHeadersFor, walle, env, now, pageLimit, maxPages,
|
|
161
|
+
* chunksPerTick, readChunk }
|
|
162
|
+
*/
|
|
163
|
+
async function syncMemberBrainOnce(member = {}, deps = {}) {
|
|
164
|
+
const fetchImpl = deps.fetchImpl || global.fetch;
|
|
165
|
+
const walle = deps.walle;
|
|
166
|
+
const env = deps.env || process.env;
|
|
167
|
+
const pageLimit = Number(deps.pageLimit) || DEFAULT_PAGE_LIMIT;
|
|
168
|
+
const maxPages = Number(deps.maxPages) || DEFAULT_MAX_PAGES;
|
|
169
|
+
const instanceId = _string(member.instanceId);
|
|
170
|
+
const base = { ok: true, member: instanceId, state: 'error', pulled: 0, pushed: 0 };
|
|
171
|
+
if (!walle || typeof walle.requestJson !== 'function') return { ...base, ok: false, error: 'walle_client_missing' };
|
|
172
|
+
if (!instanceId) return { ...base, ok: false, error: 'member_instance_required' };
|
|
173
|
+
const urls = _memberUrls(member);
|
|
174
|
+
if (!urls.length) return { ...base, ok: false, state: 'unreachable', error: 'member_has_no_url' };
|
|
175
|
+
const headers = typeof deps.peerHeadersFor === 'function' ? (deps.peerHeadersFor(instanceId) || {}) : {};
|
|
176
|
+
|
|
177
|
+
// 1. both ends' vectors.
|
|
178
|
+
const localRes = await _walleRequest(walle, LOCAL_PATHS.vector);
|
|
179
|
+
if (_isDisabled(localRes)) return { ...base, ok: false, state: 'disabled' };
|
|
180
|
+
if (localRes.status === 0 || !localRes.json) return { ...base, ok: false, state: 'unreachable', error: localRes.error || 'local_walle_unreachable' };
|
|
181
|
+
const local = localRes.json;
|
|
182
|
+
const memberRes = await _dialMember(fetchImpl, urls, MEMBER_PATHS.vector, { method: 'GET', headers });
|
|
183
|
+
if (_isDisabled(memberRes)) return { ...base, ok: false, state: 'disabled' };
|
|
184
|
+
if (memberRes.status === 0 || !memberRes.json) return { ...base, ok: false, state: 'unreachable', error: memberRes.error || 'member_unreachable' };
|
|
185
|
+
const memberUrl = memberRes.url;
|
|
186
|
+
const mv = memberRes.json;
|
|
187
|
+
|
|
188
|
+
// 2. D-9: a node whose WP-0 clock walk has not finished cannot exchange a feed. No traffic.
|
|
189
|
+
if (local.clockSeedDone !== true || mv.clockSeedDone !== true) {
|
|
190
|
+
return { ...base, ok: false, state: 'seed_pending' };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const localInstanceId = _string(local.instanceId) || _string(env.CTM_INSTANCE_ID || env.CTM_INSTANCE_TAG);
|
|
194
|
+
const localVector = (local.vector && typeof local.vector === 'object') ? { ...local.vector } : {};
|
|
195
|
+
const memberVector = (mv.vector && typeof mv.vector === 'object') ? { ...mv.vector } : {};
|
|
196
|
+
|
|
197
|
+
// 3. D-1/§6.6: a member that has never taken the hub's origin cannot exchange a feed yet —
|
|
198
|
+
// pushing its orphaned legacy rows at the hub now would flood identity conflicts. WP-4 (§5 D-6,
|
|
199
|
+
// §6.7) turns that idle 'join_required' into the join state machine: the hub ships its consistent
|
|
200
|
+
// snapshot in chunks, the member imports it, and only then does the normal feed resume.
|
|
201
|
+
if (Object.keys(localVector).length > 0 && localInstanceId && !Object.prototype.hasOwnProperty.call(memberVector, localInstanceId)) {
|
|
202
|
+
const join = await advanceMemberJoin(member, {
|
|
203
|
+
localInstanceId,
|
|
204
|
+
walle,
|
|
205
|
+
fetchImpl,
|
|
206
|
+
headers,
|
|
207
|
+
memberUrl,
|
|
208
|
+
now: deps.now,
|
|
209
|
+
chunksPerTick: deps.chunksPerTick,
|
|
210
|
+
readChunk: deps.readChunk,
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
...base,
|
|
214
|
+
ok: join.state === 'join_done',
|
|
215
|
+
state: join.state,
|
|
216
|
+
pulled: 0,
|
|
217
|
+
pushed: 0,
|
|
218
|
+
...(join.detail ? { detail: join.detail } : {}),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let pulled = 0;
|
|
223
|
+
let pushed = 0;
|
|
224
|
+
let pullVector = localVector;
|
|
225
|
+
let pushVector = memberVector;
|
|
226
|
+
|
|
227
|
+
// 4. pull: member /changes -> local /apply, page by page.
|
|
228
|
+
for (let page = 0; page < maxPages; page += 1) {
|
|
229
|
+
const changes = await _memberRequest(fetchImpl, memberUrl, MEMBER_PATHS.changes, {
|
|
230
|
+
method: 'POST', headers, body: { since: pullVector, limit: pageLimit },
|
|
231
|
+
});
|
|
232
|
+
if (_isDisabled(changes)) return { ...base, ok: false, state: 'disabled' };
|
|
233
|
+
if (changes.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed, error: changes.error || 'member_unreachable' };
|
|
234
|
+
if (changes.status === 409) return { ...base, ok: false, state: 'seed_pending', pulled, pushed };
|
|
235
|
+
if (changes.status < 200 || changes.status >= 300 || !changes.json) {
|
|
236
|
+
return { ...base, ok: false, state: 'error', pulled, pushed, error: `member_changes_http_${changes.status}` };
|
|
237
|
+
}
|
|
238
|
+
const entries = Array.isArray(changes.json.entries) ? changes.json.entries : [];
|
|
239
|
+
if (entries.length) {
|
|
240
|
+
const applied = await _walleRequest(walle, LOCAL_PATHS.apply, { method: 'POST', body: { sourceInstanceId: instanceId, entries } });
|
|
241
|
+
if (_isDisabled(applied)) return { ...base, ok: false, state: 'disabled' };
|
|
242
|
+
if (applied.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed, error: 'local_walle_unreachable' };
|
|
243
|
+
if (applied.status < 200 || applied.status >= 300 || !applied.json) {
|
|
244
|
+
return { ...base, ok: false, state: 'error', pulled, pushed, error: `local_apply_http_${applied.status}` };
|
|
245
|
+
}
|
|
246
|
+
pulled += Number(applied.json.applied) || entries.length;
|
|
247
|
+
pullVector = (applied.json.vector && typeof applied.json.vector === 'object') ? applied.json.vector : pullVector;
|
|
248
|
+
}
|
|
249
|
+
if (changes.json.more !== true) break;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// 5. push: local /changes -> member /apply, page by page.
|
|
253
|
+
for (let page = 0; page < maxPages; page += 1) {
|
|
254
|
+
const changes = await _walleRequest(walle, LOCAL_PATHS.changes, { method: 'POST', body: { since: pushVector, limit: pageLimit } });
|
|
255
|
+
if (_isDisabled(changes)) return { ...base, ok: false, state: 'disabled', pulled, pushed };
|
|
256
|
+
if (changes.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed, error: 'local_walle_unreachable' };
|
|
257
|
+
if (changes.status === 409) return { ...base, ok: false, state: 'seed_pending', pulled, pushed };
|
|
258
|
+
if (changes.status < 200 || changes.status >= 300 || !changes.json) {
|
|
259
|
+
return { ...base, ok: false, state: 'error', pulled, pushed, error: `local_changes_http_${changes.status}` };
|
|
260
|
+
}
|
|
261
|
+
const entries = Array.isArray(changes.json.entries) ? changes.json.entries : [];
|
|
262
|
+
if (entries.length) {
|
|
263
|
+
const applied = await _memberRequest(fetchImpl, memberUrl, MEMBER_PATHS.apply, {
|
|
264
|
+
// D-5: name this node as the member's home so the member stops running derived producers.
|
|
265
|
+
method: 'POST', headers: { ...headers, 'X-CTM-Memory-Sync-Home': localInstanceId }, body: { sourceInstanceId: localInstanceId, entries },
|
|
266
|
+
});
|
|
267
|
+
if (_isDisabled(applied)) return { ...base, ok: false, state: 'disabled', pulled, pushed };
|
|
268
|
+
if (applied.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed, error: applied.error || 'member_unreachable' };
|
|
269
|
+
if (applied.status < 200 || applied.status >= 300 || !applied.json) {
|
|
270
|
+
return { ...base, ok: false, state: 'error', pulled, pushed, error: `member_apply_http_${applied.status}` };
|
|
271
|
+
}
|
|
272
|
+
pushed += Number(applied.json.applied) || entries.length;
|
|
273
|
+
pushVector = (applied.json.vector && typeof applied.json.vector === 'object') ? applied.json.vector : pushVector;
|
|
274
|
+
}
|
|
275
|
+
if (changes.json.more !== true) break;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 6. tell the hub's Wall-E what the member last reported (feeds tombstone pruning).
|
|
279
|
+
const recorded = await _walleRequest(walle, LOCAL_PATHS.memberVector, {
|
|
280
|
+
method: 'POST', body: { memberInstanceId: instanceId, vector: pushVector },
|
|
281
|
+
});
|
|
282
|
+
if (_isDisabled(recorded)) return { ...base, ok: false, state: 'disabled', pulled, pushed };
|
|
283
|
+
if (recorded.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed, error: 'local_walle_unreachable' };
|
|
284
|
+
if (recorded.status < 200 || recorded.status >= 300) {
|
|
285
|
+
return { ...base, ok: false, state: 'error', pulled, pushed, error: `local_member_vector_http_${recorded.status}` };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return { ok: true, member: instanceId, state: 'synced', pulled, pushed };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// WP-5 (§5 D-3, §6.8) flag. Its own switch: the brain leg's CTM_SYNC_BRAIN_ENABLED must not take
|
|
292
|
+
// transcription history down with it (and vice versa). Default ON.
|
|
293
|
+
function _conversationSyncEnabled(env) {
|
|
294
|
+
if (!env || env === process.env) return boolFlag('CTM_SYNC_CONVERSATION_ENABLED', true);
|
|
295
|
+
return createEnvFlags({ env }).boolFlag('CTM_SYNC_CONVERSATION_ENABLED', true);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* The raw statement interface for CTM's own store. The worker is handed the db MODULE
|
|
300
|
+
* (server.js passes `db-owner-client`), whose proxies expose `getDb()` rather than
|
|
301
|
+
* `prepare`/`exec`; a db object with no readable handle at all — a push-only worker stub — has no
|
|
302
|
+
* conversation store to exchange, so the leg is skipped rather than reported as a member error.
|
|
303
|
+
*
|
|
304
|
+
* @param {object|null} db the round's injected db module
|
|
305
|
+
* @returns {object|null} a better-sqlite3 handle, or null when this node cannot serve the feed
|
|
306
|
+
*/
|
|
307
|
+
function _conversationDb(db) {
|
|
308
|
+
if (!db) return null;
|
|
309
|
+
if (typeof db.prepare === 'function') return db;
|
|
310
|
+
if (typeof db.getDb === 'function') {
|
|
311
|
+
try { return db.getDb() || null; } catch { return null; /* REPORT: no readable store handle — the leg is skipped */ }
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* One bidirectional exchange of conversation-clock changes with one member (D-3 over transcription
|
|
318
|
+
* history). Runs AFTER the brain leg and independently of its verdict: the conversation feed needs
|
|
319
|
+
* no join snapshot, so a member mid-join still exchanges items. Returns
|
|
320
|
+
* { ok, state, pulled, pushed } with a state from 'synced' | 'seed_pending' | 'disabled' |
|
|
321
|
+
* 'unreachable' | 'error'.
|
|
322
|
+
*
|
|
323
|
+
* @param {{instanceId: string, urls?: string[], url?: string}} member
|
|
324
|
+
* @param {object} deps { db, fetchImpl, peerHeadersFor, env, pageLimit, maxPages }
|
|
325
|
+
*/
|
|
326
|
+
async function syncMemberConversationOnce(member = {}, deps = {}) {
|
|
327
|
+
const db = _conversationDb(deps.db);
|
|
328
|
+
const fetchImpl = deps.fetchImpl || global.fetch;
|
|
329
|
+
const env = deps.env || process.env;
|
|
330
|
+
const pageLimit = Number(deps.pageLimit) || DEFAULT_PAGE_LIMIT;
|
|
331
|
+
const maxPages = Number(deps.maxPages) || DEFAULT_MAX_PAGES;
|
|
332
|
+
const instanceId = _string(member.instanceId);
|
|
333
|
+
const base = { ok: true, state: 'error', pulled: 0, pushed: 0 };
|
|
334
|
+
if (!db) return { ...base, ok: false, error: 'db_required' };
|
|
335
|
+
if (!instanceId) return { ...base, ok: false, error: 'member_instance_required' };
|
|
336
|
+
const urls = _memberUrls(member);
|
|
337
|
+
if (!urls.length) return { ...base, ok: false, state: 'unreachable', error: 'member_has_no_url' };
|
|
338
|
+
const headers = typeof deps.peerHeadersFor === 'function' ? (deps.peerHeadersFor(instanceId) || {}) : {};
|
|
339
|
+
|
|
340
|
+
// 1. this node's own seed advances one bounded page per round (never at boot, §6.8).
|
|
341
|
+
try {
|
|
342
|
+
conversationStore.seedConversationClockPage(db, {});
|
|
343
|
+
} catch {
|
|
344
|
+
return { ...base, ok: false, state: 'error', error: 'conversation_seed_failed' };
|
|
345
|
+
}
|
|
346
|
+
const local = conversationSync.readConversationVector(db);
|
|
347
|
+
if (local.seedDone !== true) return { ...base, ok: true, state: 'seed_pending' };
|
|
348
|
+
|
|
349
|
+
// 2. the member's vector. Its /vector call advances the member's own seed page too.
|
|
350
|
+
const memberRes = await _dialMember(fetchImpl, urls, CONVERSATION_PATHS.vector, { method: 'GET', headers });
|
|
351
|
+
if (memberRes.status === 0 || !memberRes.json) {
|
|
352
|
+
return { ...base, ok: false, state: 'unreachable', error: memberRes.error || 'member_unreachable' };
|
|
353
|
+
}
|
|
354
|
+
if (memberRes.status < 200 || memberRes.status >= 300) {
|
|
355
|
+
return { ...base, ok: false, state: 'error', error: `member_vector_http_${memberRes.status}` };
|
|
356
|
+
}
|
|
357
|
+
const memberUrl = memberRes.url;
|
|
358
|
+
if (memberRes.json.seedDone !== true) return { ...base, ok: true, state: 'seed_pending' };
|
|
359
|
+
|
|
360
|
+
const localInstanceId = _string(local.instanceId)
|
|
361
|
+
|| _string(env.CTM_INSTANCE_ID || env.CTM_INSTANCE_TAG);
|
|
362
|
+
let pullVector = (local.vector && typeof local.vector === 'object') ? { ...local.vector } : {};
|
|
363
|
+
let pushVector = (memberRes.json.vector && typeof memberRes.json.vector === 'object') ? { ...memberRes.json.vector } : {};
|
|
364
|
+
|
|
365
|
+
// 3. pull: member /changes -> local apply.
|
|
366
|
+
let pulled = 0;
|
|
367
|
+
for (let page = 0; page < maxPages; page += 1) {
|
|
368
|
+
const changes = await _memberRequest(fetchImpl, memberUrl, CONVERSATION_PATHS.changes, {
|
|
369
|
+
method: 'POST', headers, body: { since: pullVector, limit: pageLimit },
|
|
370
|
+
});
|
|
371
|
+
if (changes.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed: 0, error: changes.error || 'member_unreachable' };
|
|
372
|
+
if (changes.status < 200 || changes.status >= 300 || !changes.json) {
|
|
373
|
+
return { ...base, ok: false, state: 'error', pulled, pushed: 0, error: `member_changes_http_${changes.status}` };
|
|
374
|
+
}
|
|
375
|
+
const entries = Array.isArray(changes.json.entries) ? changes.json.entries : [];
|
|
376
|
+
if (entries.length) {
|
|
377
|
+
try {
|
|
378
|
+
const result = conversationSync.applyConversationChanges(db, { sourceInstanceId: instanceId, entries });
|
|
379
|
+
pulled += Number(result.applied) || 0;
|
|
380
|
+
pullVector = result.vector || pullVector;
|
|
381
|
+
} catch {
|
|
382
|
+
return { ...base, ok: false, state: 'error', pulled, pushed: 0, error: 'local_apply_failed' };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (changes.json.more !== true) break;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// 4. push: local changes -> member /apply, page by page.
|
|
389
|
+
let pushed = 0;
|
|
390
|
+
for (let page = 0; page < maxPages; page += 1) {
|
|
391
|
+
const page2 = conversationSync.conversationChangesSince(db, { since: pushVector, limit: pageLimit });
|
|
392
|
+
const entries = page2.entries;
|
|
393
|
+
if (entries.length) {
|
|
394
|
+
const applied = await _memberRequest(fetchImpl, memberUrl, CONVERSATION_PATHS.apply, {
|
|
395
|
+
method: 'POST', headers, body: { sourceInstanceId: localInstanceId, entries },
|
|
396
|
+
});
|
|
397
|
+
if (applied.status === 0) return { ...base, ok: false, state: 'unreachable', pulled, pushed, error: applied.error || 'member_unreachable' };
|
|
398
|
+
if (applied.status < 200 || applied.status >= 300 || !applied.json) {
|
|
399
|
+
return { ...base, ok: false, state: 'error', pulled, pushed, error: `member_apply_http_${applied.status}` };
|
|
400
|
+
}
|
|
401
|
+
pushed += Number(applied.json.applied) || entries.length;
|
|
402
|
+
pushVector = (applied.json.vector && typeof applied.json.vector === 'object') ? applied.json.vector : pushVector;
|
|
403
|
+
}
|
|
404
|
+
if (page2.more !== true) break;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return { ...base, ok: true, state: 'synced', pulled, pushed };
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Exponential backoff with jitter, mirroring hosted-sync-worker's _failureDelayMs so a member that
|
|
411
|
+
// just failed is not re-dialled every tick.
|
|
412
|
+
function _failureDelayMs(env, attempt, options = {}) {
|
|
413
|
+
const base = Math.max(1000, Number(env.CTM_SYNC_FAILURE_BACKOFF_MS || options.failureBackoffMs || DEFAULT_FAILURE_BACKOFF_MS) || DEFAULT_FAILURE_BACKOFF_MS);
|
|
414
|
+
const max = Math.max(base, Number(env.CTM_SYNC_FAILURE_BACKOFF_MAX_MS || options.failureBackoffMaxMs || DEFAULT_FAILURE_BACKOFF_MAX_MS) || DEFAULT_FAILURE_BACKOFF_MAX_MS);
|
|
415
|
+
const exp = Math.min(max, base * Math.max(1, 2 ** Math.max(0, attempt - 1)));
|
|
416
|
+
const jitter = Math.floor(exp * 0.2 * Math.random());
|
|
417
|
+
return Math.min(max, exp + jitter);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function _resolveSelfInstanceId(deps = {}, env = process.env) {
|
|
421
|
+
const source = deps.selfInstanceId;
|
|
422
|
+
if (typeof source === 'function') {
|
|
423
|
+
try { return _string(source()); } catch { return ''; }
|
|
424
|
+
}
|
|
425
|
+
if (source) return _string(source);
|
|
426
|
+
return _string(env.CTM_INSTANCE_ID || env.CTM_INSTANCE_TAG || '');
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function _candidateMembers(db, selfInstanceId) {
|
|
430
|
+
const { machines } = machineRegistry.listMachines({ db });
|
|
431
|
+
return (machines || []).filter((m) => m
|
|
432
|
+
&& m.enabled
|
|
433
|
+
&& m.health === 'reachable'
|
|
434
|
+
&& m.instanceId
|
|
435
|
+
&& m.instanceId !== selfInstanceId);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* One hub round: every reachable registered member, sequentially (D-2 — only the hub dials, and a
|
|
440
|
+
* slow member must not fan out into concurrent dials). A member inside its failure-backoff window is
|
|
441
|
+
* skipped (and its last state reported) so it never delays the others. After the round, tombstones
|
|
442
|
+
* are pruned only when every member that was attempted ended 'synced'.
|
|
443
|
+
*
|
|
444
|
+
* @param {object} deps { db, fetchImpl, env, peerHeadersFor, walle, now, selfInstanceId }
|
|
445
|
+
*/
|
|
446
|
+
async function runBrainMemberRound(deps = {}) {
|
|
447
|
+
if (_inFlight) return { ok: true, skipped: 'in_flight', members: [], pruned: 0 };
|
|
448
|
+
const env = deps.env || process.env;
|
|
449
|
+
if (!_brainSyncEnabled(env)) {
|
|
450
|
+
return { ok: true, disabled: true, members: [], pruned: 0 };
|
|
451
|
+
}
|
|
452
|
+
_inFlight = _runRound(deps).finally(() => { _inFlight = null; });
|
|
453
|
+
return _inFlight;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async function _runRound(deps = {}) {
|
|
457
|
+
const env = deps.env || process.env;
|
|
458
|
+
const nowMs = _now(deps);
|
|
459
|
+
const selfInstanceId = _resolveSelfInstanceId(deps, env);
|
|
460
|
+
const walle = deps.walle || require('./walle-client');
|
|
461
|
+
const candidates = _candidateMembers(deps.db, selfInstanceId);
|
|
462
|
+
// WP-5: resolved once per round — the CTM store handle the conversation feed reads (see
|
|
463
|
+
// _conversationDb). Null means this node has no conversation store to exchange, and the leg is
|
|
464
|
+
// skipped without a per-member `conversation` verdict.
|
|
465
|
+
const conversationEnabled = _conversationSyncEnabled(env);
|
|
466
|
+
const conversationDb = conversationEnabled ? _conversationDb(deps.db) : null;
|
|
467
|
+
const members = [];
|
|
468
|
+
for (const member of candidates) {
|
|
469
|
+
const instanceId = _string(member.instanceId);
|
|
470
|
+
const prior = _memberState.get(instanceId);
|
|
471
|
+
if (prior && prior.nextAt > nowMs) {
|
|
472
|
+
members.push({ instanceId, state: prior.state || 'unreachable', pulled: 0, pushed: 0, backoff: true });
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
let result;
|
|
476
|
+
try {
|
|
477
|
+
result = await syncMemberBrainOnce(member, {
|
|
478
|
+
fetchImpl: deps.fetchImpl,
|
|
479
|
+
peerHeadersFor: deps.peerHeadersFor,
|
|
480
|
+
walle,
|
|
481
|
+
env,
|
|
482
|
+
now: deps.now,
|
|
483
|
+
pageLimit: deps.pageLimit,
|
|
484
|
+
maxPages: deps.maxPages,
|
|
485
|
+
// WP-4 (§5 D-6): the join state machine's own seams. Absent -> memory-join's defaults.
|
|
486
|
+
chunksPerTick: deps.chunksPerTick,
|
|
487
|
+
readChunk: deps.readChunk,
|
|
488
|
+
});
|
|
489
|
+
} catch (err) {
|
|
490
|
+
result = { ok: false, member: instanceId, state: 'error', pulled: 0, pushed: 0, error: err?.message || String(err) };
|
|
491
|
+
}
|
|
492
|
+
// WP-5 (§5 D-3, §6.8): the conversation-history leg runs AFTER the brain leg and is
|
|
493
|
+
// independent of its verdict — a member mid-join still exchanges items (no snapshot needed),
|
|
494
|
+
// and a broken conversation leg must never turn a green brain leg red.
|
|
495
|
+
let conversation = null;
|
|
496
|
+
if (conversationDb) {
|
|
497
|
+
try {
|
|
498
|
+
conversation = await syncMemberConversationOnce(member, {
|
|
499
|
+
db: conversationDb,
|
|
500
|
+
fetchImpl: deps.fetchImpl,
|
|
501
|
+
peerHeadersFor: deps.peerHeadersFor,
|
|
502
|
+
env,
|
|
503
|
+
pageLimit: deps.pageLimit,
|
|
504
|
+
maxPages: deps.maxPages,
|
|
505
|
+
});
|
|
506
|
+
} catch (err) {
|
|
507
|
+
conversation = { ok: false, state: 'error', pulled: 0, pushed: 0, error: err?.message || String(err) };
|
|
508
|
+
}
|
|
509
|
+
} else if (!conversationEnabled) {
|
|
510
|
+
conversation = { ok: true, state: 'disabled', pulled: 0, pushed: 0 };
|
|
511
|
+
}
|
|
512
|
+
members.push({
|
|
513
|
+
instanceId,
|
|
514
|
+
state: result.state,
|
|
515
|
+
pulled: result.pulled,
|
|
516
|
+
pushed: result.pushed,
|
|
517
|
+
...(result.error ? { error: result.error } : {}),
|
|
518
|
+
...(result.detail ? { detail: result.detail } : {}),
|
|
519
|
+
...(conversation ? { conversation } : {}),
|
|
520
|
+
});
|
|
521
|
+
if (result.state === 'unreachable' || result.state === 'error') {
|
|
522
|
+
const attempt = ((prior && Number(prior.attempts)) || 0) + 1;
|
|
523
|
+
_memberState.set(instanceId, { attempts: attempt, nextAt: nowMs + _failureDelayMs(env, attempt, deps), state: result.state });
|
|
524
|
+
} else {
|
|
525
|
+
_memberState.delete(instanceId);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
let pruned = 0;
|
|
530
|
+
if (members.length > 0 && members.every((m) => m.state === 'synced')) {
|
|
531
|
+
try {
|
|
532
|
+
const res = await _walleRequest(walle, LOCAL_PATHS.pruneTombstones, { method: 'POST', body: {} });
|
|
533
|
+
if (res.json && Number.isFinite(Number(res.json.pruned))) pruned = Number(res.json.pruned) || 0;
|
|
534
|
+
} catch {
|
|
535
|
+
pruned = 0; // REPORT: prune is best-effort; a failure leaves the tombstones and the next round retries
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
_lastRound = { at: new Date(nowMs).toISOString(), members };
|
|
540
|
+
// A member mid-join is not an error (it is making progress); only a broken exchange flips `ok`.
|
|
541
|
+
return { ok: members.every((m) => JOIN_PROGRESS_STATES.has(m.state) || m.state === 'synced' || m.state === 'seed_pending'), members, pruned };
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** Observability only (no route in this WP): the last round's verdict per member. */
|
|
545
|
+
function memorySyncStatus() {
|
|
546
|
+
return {
|
|
547
|
+
lastRoundAt: _lastRound ? _lastRound.at : null,
|
|
548
|
+
members: _lastRound ? _lastRound.members : [],
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/** Test seam: forget the per-member backoff + last round (module state survives a process). */
|
|
553
|
+
function _resetMemorySyncStateForTests() {
|
|
554
|
+
_memberState.clear();
|
|
555
|
+
_lastRound = null;
|
|
556
|
+
_inFlight = null;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
module.exports = {
|
|
560
|
+
syncMemberBrainOnce,
|
|
561
|
+
syncMemberConversationOnce,
|
|
562
|
+
runBrainMemberRound,
|
|
563
|
+
memorySyncStatus,
|
|
564
|
+
_resetMemorySyncStateForTests,
|
|
565
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-1 (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §5 D-4/D-7/D-11, §6.1, §8 WP-1,
|
|
4
|
+
// §9 S-3): the machine-pool schema, in one migration because every piece of it lands with the same
|
|
5
|
+
// reader (lib/host-stats.js today; WP-2/WP-3 for the pairing/self tables).
|
|
6
|
+
//
|
|
7
|
+
// host_samples D-11 — the box owns its own 24 h time series (one row per 60 s tick;
|
|
8
|
+
// ≤1440 rows/machine). No hub-side samples table exists.
|
|
9
|
+
// machine_self D-4 rev 2 — this machine's OWN user settings (display name, favorite,
|
|
10
|
+
// hidden). Exactly one row, id = 1.
|
|
11
|
+
// machine_pairing_offers D-6 — the RFC 8628-shaped code a joining member redeems. The plaintext
|
|
12
|
+
// code is never stored, only its hash.
|
|
13
|
+
// machines.urls_json P-1/P-4 rev 2 — the member's dialable URLs in dial order.
|
|
14
|
+
//
|
|
15
|
+
// Rev 2 deliberately has NO peer_credentials table: D-7 is one shared pool secret in
|
|
16
|
+
// machine-pool.json, never in the DB.
|
|
17
|
+
//
|
|
18
|
+
// The shape follows v55-agent-origin-backfill.js: a narrow dependency object, idempotent SQL, and
|
|
19
|
+
// the version stamp LAST so a failure leaves the ladder where it was. ALTER TABLE has no
|
|
20
|
+
// `IF NOT EXISTS` in SQLite, so the column add is guarded by its own PRAGMA read — which also
|
|
21
|
+
// makes a re-run (a restored snapshot, a partially upgraded file) a no-op rather than an error.
|
|
22
|
+
|
|
23
|
+
const TABLES_DDL = `
|
|
24
|
+
CREATE TABLE IF NOT EXISTS host_samples (
|
|
25
|
+
at INTEGER PRIMARY KEY,
|
|
26
|
+
sample_json TEXT NOT NULL
|
|
27
|
+
);
|
|
28
|
+
CREATE TABLE IF NOT EXISTS machine_self (
|
|
29
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
30
|
+
display_name TEXT NOT NULL DEFAULT '',
|
|
31
|
+
favorite INTEGER NOT NULL DEFAULT 0,
|
|
32
|
+
hidden INTEGER NOT NULL DEFAULT 0,
|
|
33
|
+
updated_at INTEGER NOT NULL DEFAULT 0
|
|
34
|
+
);
|
|
35
|
+
CREATE TABLE IF NOT EXISTS machine_pairing_offers (
|
|
36
|
+
id TEXT PRIMARY KEY,
|
|
37
|
+
code_hash TEXT NOT NULL UNIQUE,
|
|
38
|
+
created_at INTEGER NOT NULL,
|
|
39
|
+
expires_at INTEGER NOT NULL,
|
|
40
|
+
redeemed_at INTEGER,
|
|
41
|
+
redeemed_by TEXT
|
|
42
|
+
);
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
function _tableExists(db, table) {
|
|
46
|
+
try {
|
|
47
|
+
return !!db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);
|
|
48
|
+
} catch {
|
|
49
|
+
return false; // expected: a handle that cannot read sqlite_master (pre-boot) has nothing to alter
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _tableHasColumn(db, table, column) {
|
|
54
|
+
try {
|
|
55
|
+
return db.prepare(`PRAGMA table_info(${table})`).all().some((c) => c.name === column);
|
|
56
|
+
} catch {
|
|
57
|
+
return false; // expected: no such table on an old/partial database -> nothing to alter
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function migrateToV56({ getDb, setSchemaVersion, log = console } = {}) {
|
|
62
|
+
if (typeof getDb !== 'function' || typeof setSchemaVersion !== 'function') throw new TypeError('migration dependencies are required');
|
|
63
|
+
const db = getDb();
|
|
64
|
+
db.exec(TABLES_DDL);
|
|
65
|
+
// S-3: existing databases get the column by ALTER; db.js's machines CREATE literal carries the
|
|
66
|
+
// same column for a fresh file, and the two must stay in the same ordinal position.
|
|
67
|
+
let altered = 0;
|
|
68
|
+
if (_tableExists(db, 'machines') && !_tableHasColumn(db, 'machines', 'urls_json')) {
|
|
69
|
+
db.exec("ALTER TABLE machines ADD COLUMN urls_json TEXT NOT NULL DEFAULT '[]'");
|
|
70
|
+
altered = 1;
|
|
71
|
+
}
|
|
72
|
+
setSchemaVersion(56);
|
|
73
|
+
log.log(`[db] Schema migrated to v56 (host samples + machine pool): ${altered} column(s) added`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = { migrateToV56 };
|