create-walle 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/lib/release-schema.json +2 -2
- package/lib/runtime-closure-policy.json +8 -7
- package/package.json +1 -1
- package/template/coding-task-manager/api-prompts.js +45 -7
- package/template/coding-task-manager/bin/claude-hook.js +55 -1
- package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
- package/template/coding-task-manager/bin/land.js +2069 -0
- package/template/coding-task-manager/bin/memory-census.js +4 -2
- package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
- package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
- package/template/coding-task-manager/db.js +156 -32
- package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
- package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
- package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
- package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
- package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
- package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
- package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
- package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
- package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
- package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
- package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
- package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
- package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
- package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
- package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
- package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
- package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
- package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
- package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
- package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
- package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
- package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
- package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
- package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
- package/template/coding-task-manager/lib/agent-definitions.js +19 -0
- package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
- package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
- package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
- package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
- package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
- package/template/coding-task-manager/lib/agent-presets.js +84 -1
- package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
- package/template/coding-task-manager/lib/agent-version-service.js +74 -11
- package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
- package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
- package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
- package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
- package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
- package/template/coding-task-manager/lib/api/fleet.js +118 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +9 -1
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machines.js +691 -2
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/session-attach.js +623 -0
- package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
- package/template/coding-task-manager/lib/api/sessions.js +77 -51
- package/template/coding-task-manager/lib/api/setup-network.js +544 -16
- package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
- package/template/coding-task-manager/lib/api/setup.js +829 -10
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
- package/template/coding-task-manager/lib/auth-rules.js +292 -21
- package/template/coding-task-manager/lib/background-stop.js +369 -0
- package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
- package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
- package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
- package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
- package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
- package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
- package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
- package/template/coding-task-manager/lib/conversation-sync.js +355 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
- package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
- package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
- package/template/coding-task-manager/lib/db-domains.js +1 -0
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
- package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
- package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +4 -0
- package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
- package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
- package/template/coding-task-manager/lib/fleet-hub.js +762 -0
- package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
- package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
- package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
- package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
- package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
- package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
- package/template/coding-task-manager/lib/fleet-update.js +798 -0
- package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
- package/template/coding-task-manager/lib/fs-watcher.js +58 -42
- package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
- package/template/coding-task-manager/lib/headless-term-service.js +84 -8
- package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
- package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
- package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
- package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
- package/template/coding-task-manager/lib/host-handoff.js +16 -19
- package/template/coding-task-manager/lib/host-stats.js +150 -3
- package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
- package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
- package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
- package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
- package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
- package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
- package/template/coding-task-manager/lib/hub-bridge.js +398 -0
- package/template/coding-task-manager/lib/idle-notify.js +491 -0
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
- package/template/coding-task-manager/lib/instance-manifest.js +5 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
- package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
- package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
- package/template/coding-task-manager/lib/landing/config.js +536 -0
- package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
- package/template/coding-task-manager/lib/landing/gate.js +360 -0
- package/template/coding-task-manager/lib/landing/git.js +344 -0
- package/template/coding-task-manager/lib/landing/lease.js +247 -0
- package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
- package/template/coding-task-manager/lib/landing/proof.js +223 -0
- package/template/coding-task-manager/lib/landing/queue.js +998 -0
- package/template/coding-task-manager/lib/landing/radar.js +489 -0
- package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
- package/template/coding-task-manager/lib/landing/state.js +263 -0
- package/template/coding-task-manager/lib/landing/stop.js +49 -0
- package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
- package/template/coding-task-manager/lib/landing/sync.js +456 -0
- package/template/coding-task-manager/lib/landing/train.js +885 -0
- package/template/coding-task-manager/lib/landing/window.js +57 -0
- package/template/coding-task-manager/lib/launch-environment.js +121 -0
- package/template/coding-task-manager/lib/launch-model-override.js +36 -10
- package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
- package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
- package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
- package/template/coding-task-manager/lib/lead-model-options.js +160 -3
- package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
- package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
- package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
- package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
- package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
- package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
- package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
- package/template/coding-task-manager/lib/machine-registry.js +750 -5
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
- package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
- package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
- package/template/coding-task-manager/lib/memory-join.js +337 -0
- package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
- package/template/coding-task-manager/lib/memory-sync.js +565 -0
- package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
- package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
- package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
- package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
- package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
- package/template/coding-task-manager/lib/model-availability.js +727 -0
- package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
- package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
- package/template/coding-task-manager/lib/model-id-rule.js +19 -0
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
- package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
- package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
- package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
- package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
- package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +6 -4
- package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
- package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
- package/template/coding-task-manager/lib/opencode-cli.js +480 -0
- package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
- package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
- package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
- package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
- package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
- package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
- package/template/coding-task-manager/lib/perf-summary.js +7 -0
- package/template/coding-task-manager/lib/perf-tracker.js +63 -2
- package/template/coding-task-manager/lib/project-config.js +7 -0
- package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/read-pool-client.js +89 -2
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
- package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
- package/template/coding-task-manager/lib/relay-client.js +57 -3
- package/template/coding-task-manager/lib/relink-audit.js +34 -5
- package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
- package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
- package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
- package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
- package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
- package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
- package/template/coding-task-manager/lib/restart-guard.js +18 -6
- package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
- package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
- package/template/coding-task-manager/lib/resume-admission.js +17 -3
- package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
- package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
- package/template/coding-task-manager/lib/runtime-contract.js +3 -1
- package/template/coding-task-manager/lib/schema-indexes.js +1 -0
- package/template/coding-task-manager/lib/session-context-locator.js +742 -0
- package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
- package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
- package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
- package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
- package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
- package/template/coding-task-manager/lib/session-create/response.js +7 -7
- package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
- package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
- package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
- package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
- package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-host-manager.js +60 -0
- package/template/coding-task-manager/lib/session-jobs.js +3 -1
- package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
- package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
- package/template/coding-task-manager/lib/session-park.js +738 -0
- package/template/coding-task-manager/lib/session-path-grant.js +13 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
- package/template/coding-task-manager/lib/session-transport.js +17 -0
- package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
- package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
- package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
- package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
- package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
- package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
- package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
- package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
- package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
- package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
- package/template/coding-task-manager/lib/submission-ack.js +90 -2
- package/template/coding-task-manager/lib/systemd-scope.js +115 -0
- package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
- package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
- package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
- package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
- package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
- package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
- package/template/coding-task-manager/lib/transcript-source.js +36 -4
- package/template/coding-task-manager/lib/transcript-store.js +9 -0
- package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
- package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
- package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
- package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
- package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
- package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
- package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
- package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
- package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
- package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
- package/template/coding-task-manager/lib/walle/turn.js +1 -1
- package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
- package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
- package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
- package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
- package/template/coding-task-manager/lib/walle-row-history.js +495 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
- package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
- package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
- package/template/coding-task-manager/lib/ws/misc.js +1 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
- package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
- package/template/coding-task-manager/oauth-proxy.js +112 -115
- package/template/coding-task-manager/package-lock.json +10 -94
- package/template/coding-task-manager/package.json +4 -3
- package/template/coding-task-manager/protocol/message-table.json +10 -0
- package/template/coding-task-manager/protocol/messages.js +10 -0
- package/template/coding-task-manager/protocol/ws-schema.json +20 -0
- package/template/coding-task-manager/protocol/ws-schema.md +2 -0
- package/template/coding-task-manager/public/css/app.css +170 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +473 -243
- package/template/coding-task-manager/public/js/agent-command.js +86 -0
- package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
- package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
- package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
- package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
- package/template/coding-task-manager/public/js/background-work.js +196 -27
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
- package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
- package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
- package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
- package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
- package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
- package/template/coding-task-manager/public/js/document-review-links.js +9 -1
- package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
- package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
- package/template/coding-task-manager/public/js/message-renderer.js +4 -3
- package/template/coding-task-manager/public/js/model-picker.js +3 -1
- package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
- package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
- package/template/coding-task-manager/public/js/pasted-content.js +236 -0
- package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
- package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
- package/template/coding-task-manager/public/js/prompts.js +11 -10
- package/template/coding-task-manager/public/js/protocol.js +10 -0
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
- package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
- package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
- package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
- package/template/coding-task-manager/public/js/stream-view.js +6 -5
- package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
- package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
- package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
- package/template/coding-task-manager/public/js/walle.js +6 -0
- package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
- package/template/coding-task-manager/public/m/app.css +140 -0
- package/template/coding-task-manager/public/m/app.js +507 -68
- package/template/coding-task-manager/public/m/index.html +17 -0
- package/template/coding-task-manager/public/m/machines.js +838 -4
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
- package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
- package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
- package/template/coding-task-manager/server.js +1950 -11679
- package/template/coding-task-manager/session-integrity.js +64 -4
- package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
- package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
- package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
- package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
- package/template/coding-task-manager/workers/session-host-process.js +5 -5
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +168 -33
- package/template/ctm-relay/lib/protocol.js +14 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/shared/backup-retention.js +82 -0
- package/template/shared/conversation-admission.js +2 -0
- package/template/shared/conversation-provenance.js +3 -7
- package/template/shared/conversation-storage-v2-contract.js +5 -0
- package/template/shared/linked-worktree.js +51 -0
- package/template/shared/macos-fda-target.js +57 -0
- package/template/shared/orphan-parents.js +55 -0
- package/template/shared/release-schema.json +2 -2
- package/template/shared/storage/contract.js +3 -0
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +71 -4
- package/template/wall-e/api-walle.js +21 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
- package/template/wall-e/brain/brain-join.js +859 -0
- package/template/wall-e/brain/brain-sync-membership.js +20 -0
- package/template/wall-e/brain/brain-sync-store.js +131 -77
- package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
- package/template/wall-e/brain/brain-sync-v2.js +578 -0
- package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
- package/template/wall-e/brain/deterministic-id.js +51 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +40 -6
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +23 -7
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +171 -35
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/config/main-loop-exemptions.json +2 -2
- package/template/wall-e/http/admin-api.js +37 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +7 -1
- package/template/wall-e/http/model-admin.js +8 -1
- package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
- package/template/wall-e/http/model-proxy-providers.js +174 -1
- package/template/wall-e/http/model-route-health.js +157 -0
- package/template/wall-e/http/sync-api.js +278 -464
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/ctm-data-dir.js +26 -0
- package/template/wall-e/lib/derivation-home.js +147 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
- package/template/wall-e/lib/helper-rules/grade.js +51 -8
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
- package/template/wall-e/lib/helper-rules/store.js +4 -2
- package/template/wall-e/lib/landing-mcp-tools.js +170 -0
- package/template/wall-e/lib/mcp-client-config.js +133 -14
- package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
- package/template/wall-e/lib/mcp-integration.js +58 -13
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
- package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
- package/template/wall-e/llm/delegate-vendor-default.js +12 -5
- package/template/wall-e/llm/model-roles.js +1 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +66 -17
- package/template/wall-e/loops/brain-custom-writes.js +19 -0
- package/template/wall-e/loops/ingest.js +17 -1
- package/template/wall-e/loops/think.js +19 -4
- package/template/wall-e/mcp-contract.js +222 -6
- package/template/wall-e/mcp-protocol-contract.js +40 -5
- package/template/wall-e/mcp-server.js +128 -29
- package/template/wall-e/mcp-worker-schemas.js +5 -5
- package/template/wall-e/memory/ctm-context-client.js +85 -0
- package/template/wall-e/memory/ctm-session-context.js +9 -3
- package/template/wall-e/memory/hub-bridge-client.js +388 -0
- package/template/wall-e/memory/replica-origin.js +56 -0
- package/template/wall-e/memory/session-pool.js +135 -0
- package/template/wall-e/runtime/live-capabilities.js +8 -3
- package/template/wall-e/server.js +4 -2
- package/template/wall-e/shared/release-schema.json +2 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/storage/contract.js +3 -0
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
- package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
- package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
- package/template/wall-e/tools/chrome-automation.js +6 -0
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +18 -4
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-5 (docs/shared-memory-every-machine-2026-10-31.html §5 D-3, D-11, §6.8): the storage half of
|
|
4
|
+
// the conversation-history change feed — a version-vector addressed feed over
|
|
5
|
+
// `conversation_item_clock` plus the one transaction that applies a page of it. Deliberately the
|
|
6
|
+
// same shape as wall-e's brain replica (the Wall-E brain replica's brain-sync-v2 module), because D-3 is one
|
|
7
|
+
// protocol over two stores.
|
|
8
|
+
//
|
|
9
|
+
// readConversationVector(db) -> { instanceId, vector, seedDone }
|
|
10
|
+
// conversationChangesSince(db, { since, limit }) -> { entries, more, seedDone }
|
|
11
|
+
// applyConversationChanges(db, { sourceInstanceId, entries }) -> { ok, applied, skipped, vector }
|
|
12
|
+
//
|
|
13
|
+
// The entries are the SENDER's clock rows: the receiver keeps the sender's (origin, origin_seq)
|
|
14
|
+
// verbatim, so a box-1 row relayed by the hub to box-2 still reads as box-1's, and a node never
|
|
15
|
+
// takes its own rows back (it asks with its own maximum, and `origin === local` is skipped).
|
|
16
|
+
//
|
|
17
|
+
// The item half is committed through the store's OWN writer (commitConversationBatchV2) with
|
|
18
|
+
// `replication: { origin, originSeqByKey }` — so the FTS triggers, the placement table, the
|
|
19
|
+
// `conversation_projection_outbox_v2` event and the session generation bookkeeping all run exactly
|
|
20
|
+
// as they do for a locally ingested item, which is what makes Wall-E's existing subscriber project
|
|
21
|
+
// a replicated item with no subscriber change (AC-5b). Tombstones instead go through
|
|
22
|
+
// deleteConversationItemsByStableKeyV2, which records the conversation_projection_deletes_v2 row
|
|
23
|
+
// the subscriber's delete feed reads.
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
commitConversationBatchV2,
|
|
27
|
+
ensureConversationStoreV2,
|
|
28
|
+
} = require('./conversation-store-v2');
|
|
29
|
+
// WP-5 §6.8: the clock's read/stamp API lives in lib/conversation-item-clock.js (no DDL there).
|
|
30
|
+
const {
|
|
31
|
+
localConversationInstanceId,
|
|
32
|
+
readConversationClockVector,
|
|
33
|
+
bumpConversationVv,
|
|
34
|
+
stampIncomingConversationClockV2,
|
|
35
|
+
conversationSeedState,
|
|
36
|
+
} = require('./conversation-item-clock');
|
|
37
|
+
// The receiver's delete lives beside purgeConversationV2 (the pinned item-table writer).
|
|
38
|
+
const { deleteConversationItemsByStableKeyV2 } = require('./prompt-purge-v2');
|
|
39
|
+
const { admitDurableText } = require('../../shared/conversation-admission');
|
|
40
|
+
|
|
41
|
+
const DEFAULT_CHANGES_LIMIT = 2_000; // §6.8: one page is at most 2000 clock rows
|
|
42
|
+
const MAX_CHANGES_LIMIT = 2_000;
|
|
43
|
+
const MAX_APPLY_ENTRIES = 2_000;
|
|
44
|
+
// The synthetic origin of the receiver path's ingest cursor. §6.8 names it `peer-sync:<origin>:<session>`.
|
|
45
|
+
const PEER_SYNC_SOURCE_PREFIX = 'peer-sync:';
|
|
46
|
+
const PEER_SYNC_SOURCE_FINGERPRINT = 'peer-sync';
|
|
47
|
+
const PEER_SYNC_PARSER_VERSION = 1;
|
|
48
|
+
|
|
49
|
+
function _string(value, max = 400) {
|
|
50
|
+
if (typeof value === 'string') return value.slice(0, max);
|
|
51
|
+
return value == null ? '' : String(value).slice(0, max);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function _parseSeq(value) {
|
|
55
|
+
const n = Number(value);
|
|
56
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function _ensure(db) {
|
|
60
|
+
ensureConversationStoreV2(db);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _itemExists(db, sessionId, stableKey) {
|
|
64
|
+
return db.prepare(
|
|
65
|
+
'SELECT turn_id, kind, text, provenance, provider, model, created_at_ms, content_version, updated_at_ms,'
|
|
66
|
+
+ ' source_event_digest, provider_message_digest FROM conversation_text_items_v2 WHERE session_id=? AND stable_key=?',
|
|
67
|
+
).get(sessionId, stableKey) || null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// A hidden placement (a superseded/tombstoned incumbent) is a delete on the wire: shipping its
|
|
71
|
+
// tombstone position key would make the receiver store a live row at a position it never owned.
|
|
72
|
+
function _positionOf(db, sessionId, stableKey) {
|
|
73
|
+
const row = db.prepare(
|
|
74
|
+
'SELECT position_key, visible FROM conversation_item_placement_v2 WHERE session_id=? AND stable_key=?',
|
|
75
|
+
).get(sessionId, stableKey);
|
|
76
|
+
if (!row || Number(row.visible) !== 1) return null;
|
|
77
|
+
return row.position_key;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** GET /api/sync/conversation/v2/vector — this node's id, its vector, and its seed verdict. */
|
|
81
|
+
function readConversationVector(db) {
|
|
82
|
+
_ensure(db);
|
|
83
|
+
return {
|
|
84
|
+
instanceId: localConversationInstanceId(db),
|
|
85
|
+
vector: readConversationClockVector(db),
|
|
86
|
+
seedDone: conversationSeedState(db).done,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function _feedEntry(db, row) {
|
|
91
|
+
const origin = _string(row.origin_instance_id, 160);
|
|
92
|
+
const deleted = Number(row.deleted) ? 1 : 0;
|
|
93
|
+
const stableKey = _string(row.stable_key, 200);
|
|
94
|
+
const sessionId = _string(row.session_id, 200);
|
|
95
|
+
const item = deleted ? null : _itemExists(db, sessionId, stableKey);
|
|
96
|
+
// A clock that says "live" for a row that is gone is a race with a local delete: ship it as a
|
|
97
|
+
// delete. The peer's apply is idempotent, so the tombstone is harmless when it is already gone.
|
|
98
|
+
const isDeleted = deleted === 1 || !item;
|
|
99
|
+
return {
|
|
100
|
+
stableKey,
|
|
101
|
+
sessionId,
|
|
102
|
+
origin,
|
|
103
|
+
originSeq: Number(row.origin_seq) || 0,
|
|
104
|
+
deleted: isDeleted ? 1 : 0,
|
|
105
|
+
updatedAtMs: Number(row.updated_at_ms) || 0,
|
|
106
|
+
item: isDeleted ? null : {
|
|
107
|
+
turnId: item.turn_id,
|
|
108
|
+
kind: item.kind,
|
|
109
|
+
text: item.text,
|
|
110
|
+
provenance: item.provenance == null ? '' : item.provenance,
|
|
111
|
+
provider: item.provider,
|
|
112
|
+
model: item.model,
|
|
113
|
+
createdAtMs: Number(item.created_at_ms),
|
|
114
|
+
contentVersion: Number(item.content_version) || 1,
|
|
115
|
+
updatedAtMs: item.updated_at_ms == null ? null : Number(item.updated_at_ms),
|
|
116
|
+
sourceEventDigest: item.source_event_digest || '',
|
|
117
|
+
providerMessageDigest: item.provider_message_digest || '',
|
|
118
|
+
positionKey: _positionOf(db, sessionId, stableKey),
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Every clock row whose origin_seq is beyond `since`, ascending by (origin, origin_seq), filling one
|
|
124
|
+
// page. Origin '' (a row this host could not address) is never shipped. `more` is true when ANY
|
|
125
|
+
// origin still holds rows past this page.
|
|
126
|
+
function conversationChangesSince(db, { since = {}, limit = DEFAULT_CHANGES_LIMIT } = {}) {
|
|
127
|
+
_ensure(db);
|
|
128
|
+
const requested = Math.floor(Number(limit) || 0) || DEFAULT_CHANGES_LIMIT;
|
|
129
|
+
const budget = Math.max(1, Math.min(MAX_CHANGES_LIMIT, requested));
|
|
130
|
+
const sinceMap = since && typeof since === 'object' && !Array.isArray(since) ? since : {};
|
|
131
|
+
const origins = db.prepare('SELECT origin_instance_id FROM conversation_vv ORDER BY origin_instance_id ASC').all()
|
|
132
|
+
.map((row) => String(row.origin_instance_id))
|
|
133
|
+
.filter((origin) => origin !== '');
|
|
134
|
+
const select = db.prepare(`
|
|
135
|
+
SELECT stable_key, session_id, origin_instance_id, origin_seq, updated_at_ms, deleted
|
|
136
|
+
FROM conversation_item_clock
|
|
137
|
+
WHERE origin_instance_id = ? AND origin_seq > ?
|
|
138
|
+
ORDER BY origin_seq ASC
|
|
139
|
+
LIMIT ?
|
|
140
|
+
`);
|
|
141
|
+
const probe = db.prepare('SELECT 1 AS hit FROM conversation_item_clock WHERE origin_instance_id = ? AND origin_seq > ? LIMIT 1');
|
|
142
|
+
const entries = [];
|
|
143
|
+
let pending = null;
|
|
144
|
+
for (const origin of origins) {
|
|
145
|
+
const after = Math.max(0, _parseSeq(sinceMap[origin]));
|
|
146
|
+
const remaining = budget - entries.length;
|
|
147
|
+
if (remaining <= 0) { pending = { origin, after }; break; }
|
|
148
|
+
const rows = select.all(origin, after, remaining);
|
|
149
|
+
for (const row of rows) entries.push(_feedEntry(db, row));
|
|
150
|
+
if (rows.length < remaining) continue; // this origin drained
|
|
151
|
+
const lastSeq = rows.length ? Number(rows[rows.length - 1].origin_seq) : after;
|
|
152
|
+
if (probe.get(origin, lastSeq)) { pending = { origin, after: lastSeq }; break; }
|
|
153
|
+
}
|
|
154
|
+
let more = false;
|
|
155
|
+
if (pending) {
|
|
156
|
+
const startAt = origins.indexOf(pending.origin);
|
|
157
|
+
for (let index = startAt; index < origins.length && !more; index += 1) {
|
|
158
|
+
const origin = origins[index];
|
|
159
|
+
const after = index === startAt ? pending.after : Math.max(0, _parseSeq(sinceMap[origin]));
|
|
160
|
+
more = !!probe.get(origin, after);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return { entries, more, seedDone: conversationSeedState(db).done };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// The wire item, reduced to exactly the keys admission accepts. `contentVersion`/`updatedAtMs`
|
|
167
|
+
// travel on the entry (below) for observability; admitDurableText rejects unknown item fields.
|
|
168
|
+
function _commitItem(entry) {
|
|
169
|
+
const item = entry.item || {};
|
|
170
|
+
return {
|
|
171
|
+
stableKey: _string(entry.stableKey, 200),
|
|
172
|
+
sessionId: _string(entry.sessionId, 200),
|
|
173
|
+
turnId: _string(item.turnId, 400),
|
|
174
|
+
kind: item.kind,
|
|
175
|
+
text: typeof item.text === 'string' ? item.text : String(item.text == null ? '' : item.text),
|
|
176
|
+
provenance: item.provenance == null ? '' : String(item.provenance),
|
|
177
|
+
provider: item.provider,
|
|
178
|
+
model: item.model == null ? null : String(item.model),
|
|
179
|
+
createdAtMs: Number(item.createdAtMs),
|
|
180
|
+
positionKey: _string(item.positionKey, 400),
|
|
181
|
+
sourceEventDigest: _string(item.sourceEventDigest, 64),
|
|
182
|
+
providerMessageDigest: _string(item.providerMessageDigest, 64),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function _isAdmissible(item) {
|
|
187
|
+
// Mirror the store's own pre-admission strip (conversation-store-v2 `_normalizeItems`): the two
|
|
188
|
+
// digests are recomputed/kept by the store and are NOT part of admission's item shape.
|
|
189
|
+
const probe = { ...item };
|
|
190
|
+
delete probe.sourceEventDigest;
|
|
191
|
+
delete probe.providerMessageDigest;
|
|
192
|
+
return admitDurableText(probe).action === 'persist_text';
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* POST /api/sync/conversation/v2/apply — one IMMEDIATE transaction for the whole page. Entries the
|
|
197
|
+
* vector already covers, this node's own origin, and malformed entries are skipped (and counted as
|
|
198
|
+
* "considered" so the sender stops re-offering them). Live entries are grouped by session and
|
|
199
|
+
* committed through the store's writer with `replication` set; tombstones are deleted with the
|
|
200
|
+
* Wall-E delete-feed row. The vector advances only inside this transaction.
|
|
201
|
+
*/
|
|
202
|
+
function applyConversationChanges(db, { sourceInstanceId, entries } = {}) {
|
|
203
|
+
_ensure(db);
|
|
204
|
+
const source = _string(sourceInstanceId, 160).trim();
|
|
205
|
+
if (!source) {
|
|
206
|
+
const error = new Error('conversation_sync_source_instance_required');
|
|
207
|
+
error.code = 'CONVERSATION_SYNC_SOURCE_REQUIRED';
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
const list = Array.isArray(entries) ? entries : [];
|
|
211
|
+
if (list.length > MAX_APPLY_ENTRIES) {
|
|
212
|
+
const error = new Error('conversation_sync_entries_too_large');
|
|
213
|
+
error.code = 'CONVERSATION_SYNC_ENTRIES_TOO_LARGE';
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
const localId = localConversationInstanceId(db);
|
|
217
|
+
const nowMs = Date.now();
|
|
218
|
+
let applied = 0;
|
|
219
|
+
let skipped = 0;
|
|
220
|
+
db.transaction(() => {
|
|
221
|
+
const seenThrough = db.prepare('SELECT max_seq FROM conversation_vv WHERE origin_instance_id = ?');
|
|
222
|
+
// Dedupe by stable key keeping the highest seq: a page is a compacted log, so one row per key.
|
|
223
|
+
const byKey = new Map();
|
|
224
|
+
for (const entry of list) {
|
|
225
|
+
const stableKey = _string(entry?.stableKey, 200).trim();
|
|
226
|
+
const sessionId = _string(entry?.sessionId, 200).trim();
|
|
227
|
+
const origin = _string(entry?.origin, 160).trim();
|
|
228
|
+
const originSeq = _parseSeq(entry?.originSeq);
|
|
229
|
+
if (!stableKey || !sessionId || !origin || !originSeq) { skipped += 1; continue; }
|
|
230
|
+
if (origin === localId) { skipped += 1; continue; } // echo guard (D-3): never take our own rows back
|
|
231
|
+
const seen = seenThrough.get(origin);
|
|
232
|
+
if (seen && Number(seen.max_seq) >= originSeq) { skipped += 1; continue; }
|
|
233
|
+
const prior = byKey.get(stableKey);
|
|
234
|
+
if (prior && prior.originSeq >= originSeq) { skipped += 1; continue; }
|
|
235
|
+
byKey.set(stableKey, { stableKey, sessionId, origin, originSeq, deleted: Number(entry?.deleted) ? 1 : 0, item: entry?.item || null });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const liveBySession = new Map(); // `${origin}\0${sessionId}` -> { origin, sessionId, items[], originSeqByKey }
|
|
239
|
+
const tombstonesBySession = new Map(); // `${origin}\0${sessionId}` -> { sessionId, keys[] }
|
|
240
|
+
const considered = new Map(); // origin -> highest seq considered
|
|
241
|
+
for (const entry of byKey.values()) {
|
|
242
|
+
considered.set(entry.origin, Math.max(considered.get(entry.origin) || 0, entry.originSeq));
|
|
243
|
+
if (entry.deleted) {
|
|
244
|
+
const key = `${entry.origin}\0${entry.sessionId}`;
|
|
245
|
+
if (!tombstonesBySession.has(key)) tombstonesBySession.set(key, { sessionId: entry.sessionId, keys: [] });
|
|
246
|
+
tombstonesBySession.get(key).keys.push(entry.stableKey);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const item = _commitItem(entry);
|
|
250
|
+
if (!_isAdmissible(item)) { skipped += 1; continue; }
|
|
251
|
+
const key = `${entry.origin}\0${entry.sessionId}`;
|
|
252
|
+
if (!liveBySession.has(key)) {
|
|
253
|
+
liveBySession.set(key, { origin: entry.origin, sessionId: entry.sessionId, provider: item.provider, items: [], originSeqByKey: {}, maxSeq: 0 });
|
|
254
|
+
}
|
|
255
|
+
const group = liveBySession.get(key);
|
|
256
|
+
group.items.push(item);
|
|
257
|
+
group.originSeqByKey[item.stableKey] = entry.originSeq;
|
|
258
|
+
group.maxSeq = Math.max(group.maxSeq, entry.originSeq);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
for (const group of liveBySession.values()) {
|
|
262
|
+
const cursor = {
|
|
263
|
+
sourceId: `${PEER_SYNC_SOURCE_PREFIX}${group.origin}:${group.sessionId}`,
|
|
264
|
+
provider: group.provider,
|
|
265
|
+
sourceFingerprint: PEER_SYNC_SOURCE_FINGERPRINT,
|
|
266
|
+
byteOffset: group.maxSeq,
|
|
267
|
+
sourceSize: group.maxSeq,
|
|
268
|
+
parserVersion: PEER_SYNC_PARSER_VERSION,
|
|
269
|
+
};
|
|
270
|
+
const result = commitConversationBatchV2(db, {
|
|
271
|
+
items: group.items,
|
|
272
|
+
cursor,
|
|
273
|
+
replication: { origin: group.origin, originSeqByKey: group.originSeqByKey },
|
|
274
|
+
nowMs,
|
|
275
|
+
});
|
|
276
|
+
applied += Number(result.inserted || 0) + Number(result.corrected || 0);
|
|
277
|
+
}
|
|
278
|
+
for (const group of tombstonesBySession.values()) {
|
|
279
|
+
applied += deleteConversationItemsByStableKeyV2(db, { sessionId: group.sessionId, stableKeys: group.keys, nowMs });
|
|
280
|
+
}
|
|
281
|
+
// A tombstone keeps its SENDER's (origin, seq) so it stays addressable in that origin's stream
|
|
282
|
+
// and relays onward — including in the case where the receiver never held the item, which is
|
|
283
|
+
// exactly when compaction must still record "origin X has moved past this key".
|
|
284
|
+
for (const entry of byKey.values()) {
|
|
285
|
+
if (!entry.deleted) continue;
|
|
286
|
+
stampIncomingConversationClockV2(db, {
|
|
287
|
+
stableKey: entry.stableKey, sessionId: entry.sessionId, origin: entry.origin,
|
|
288
|
+
originSeq: entry.originSeq, nowMs,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
// D-3 "seen through": every entry this call considered is now behind the vector, whether it was
|
|
292
|
+
// written, skipped as stale, or refused as malformed — re-offering it next tick would only grow
|
|
293
|
+
// the page budget.
|
|
294
|
+
for (const [origin, seq] of considered) bumpConversationVv(db, origin, seq);
|
|
295
|
+
}).immediate();
|
|
296
|
+
return { ok: true, applied, skipped, vector: readConversationClockVector(db) };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ── WP-3 (docs/join-sync-followups-2-2026-11-01.html §5 R-10, §8 WP-3) ──────────────────────
|
|
300
|
+
// The OWNER-side entry points for the three /api/sync/conversation/v2/* handlers. Every one of
|
|
301
|
+
// them is a pure function of a DB handle: the route calls it via db.js's closed
|
|
302
|
+
// DB_OWNER_MUTATION_ACTIONS map (runMutation -> workers/db-owner-worker.js), so the seed page,
|
|
303
|
+
// the store DDL (`_ensure`) and the reads/writes all run on the owner worker's own connection
|
|
304
|
+
// instead of the request thread — which the request-zone guard forbids
|
|
305
|
+
// (lib/main-db-census.js, CTM_MAIN_DB_REQUEST_FORBIDDEN). That is the whole reason these exist:
|
|
306
|
+
// /vector and /changes seeded synchronously on the main handle and 500'd on every member (I-2).
|
|
307
|
+
// The payload shapes are unchanged (R-11); only where the work runs changed.
|
|
308
|
+
|
|
309
|
+
// One bounded seed page per call, on the owner's handle. Never throws: a seed fault must not
|
|
310
|
+
// take the feed down (the next call retries from the same cursor).
|
|
311
|
+
function _seedOwnerPage(db, seedPageLimit) {
|
|
312
|
+
try {
|
|
313
|
+
return require('./conversation-store-v2').seedConversationClockPage(db, { limit: seedPageLimit });
|
|
314
|
+
} catch (error) {
|
|
315
|
+
// REPORT: seed fault — the feed still answers, and the next call retries from the same cursor.
|
|
316
|
+
console.warn('[conversation-sync] seed page failed: ' + (error && error.message ? error.message : error));
|
|
317
|
+
return { seeded: 0, done: false, afterItemId: 0 };
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** GET /api/sync/conversation/v2/vector owner half — seed one page, then this node's vector. */
|
|
322
|
+
function ownerVector(db, { seedPageLimit } = {}) {
|
|
323
|
+
_seedOwnerPage(db, seedPageLimit);
|
|
324
|
+
return readConversationVector(db);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** POST /api/sync/conversation/v2/changes owner half — seed one page, then one feed page. */
|
|
328
|
+
function ownerChanges(db, { since, limit, seedPageLimit } = {}) {
|
|
329
|
+
_seedOwnerPage(db, seedPageLimit);
|
|
330
|
+
return conversationChangesSince(db, { since, limit });
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* POST /api/sync/conversation/v2/apply owner half. The over-cap case still throws with
|
|
335
|
+
* `code = 'CONVERSATION_SYNC_ENTRIES_TOO_LARGE'` (applyConversationChanges' own contract): the
|
|
336
|
+
* DB-owner transport carries `error.code` back verbatim (workers/db-owner-worker.js's
|
|
337
|
+
* _serializeError -> lib/db-owner-worker-client.js's _finishRequest), so the route can keep
|
|
338
|
+
* mapping it to 413 without a second in-band flag.
|
|
339
|
+
*/
|
|
340
|
+
function ownerApply(db, { sourceInstanceId, entries } = {}) {
|
|
341
|
+
return applyConversationChanges(db, { sourceInstanceId, entries });
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
module.exports = {
|
|
345
|
+
DEFAULT_CHANGES_LIMIT,
|
|
346
|
+
MAX_CHANGES_LIMIT,
|
|
347
|
+
MAX_APPLY_ENTRIES,
|
|
348
|
+
PEER_SYNC_SOURCE_PREFIX,
|
|
349
|
+
readConversationVector,
|
|
350
|
+
conversationChangesSince,
|
|
351
|
+
applyConversationChanges,
|
|
352
|
+
ownerVector,
|
|
353
|
+
ownerChanges,
|
|
354
|
+
ownerApply,
|
|
355
|
+
};
|
|
@@ -51,17 +51,19 @@ const { locateClaudeSettingsArg } = require('../native-lead-settings-argv');
|
|
|
51
51
|
const codexSandboxArgs = require('../codex-sandbox-args');
|
|
52
52
|
const codexLaunchHealth = require('../codex-launch-health');
|
|
53
53
|
const dbModule = require('../../db-owner-client');
|
|
54
|
-
const { buildTelemetryEnv, sanitizeInheritedAgentEnv } = require('../agent-presets');
|
|
54
|
+
const { buildTelemetryEnv, sanitizeInheritedAgentEnv, buildClaudeRendererLaunchEnv } = require('../agent-presets');
|
|
55
55
|
const { sanitizeAnthropicAuth } = require('../sanitize-anthropic-auth');
|
|
56
56
|
const { sanitizeOpenAiAuth } = require('../sanitize-openai-auth');
|
|
57
57
|
// WP-2 (S-6): the D-1/D-2 sandbox env builder for a non-primary instance's launch env.
|
|
58
58
|
const { buildSandboxCliEnv } = require('../../../shared/sandbox-cli-env');
|
|
59
59
|
const { getPrivateSourceRecoveryEnvironment } = require('../lead-model-restore-reconciliation');
|
|
60
|
+
// WP-2b: the ONE Claude `--session-id` reader, shared with the source runtime (D-5/D-6).
|
|
61
|
+
const { claudeSessionIdArg } = require('../lead-switch-history-mode');
|
|
60
62
|
const { getSession } = require('../../server-state');
|
|
61
63
|
const { claudeMcpConfigArgs } = require('../lifecycle-wake-experiment');
|
|
62
64
|
const { buildWorkerRoleArgs, WORKER_PROFILES } = require('./worker-role-profile');
|
|
63
65
|
const {
|
|
64
|
-
workerDeniedToolsArgs, codexWorkerDenyArgs, workerClaudeSettingsArgs, workerSandboxArgs,
|
|
66
|
+
workerDeniedToolsArgs, codexWorkerDenyArgs, workerClaudeSettingsArgs, workerSandboxArgs, dshWorkerSandbox,
|
|
65
67
|
} = require('../session-create/worker-launch-sandbox');
|
|
66
68
|
|
|
67
69
|
function resolveCreateLaunchParams(ctx) {
|
|
@@ -174,6 +176,35 @@ function resolveCreateLaunchParams(ctx) {
|
|
|
174
176
|
console.warn('[native-model-args] skipped:', e.message);
|
|
175
177
|
}
|
|
176
178
|
}
|
|
179
|
+
|
|
180
|
+
// --- OpenCode 2.x launch shape (R-1, R-2) ---
|
|
181
|
+
// docs/opencode-v2-model-switch-standalone-plugin-2026-10-30.html §5.1: a plain 2.x TUI attaches to a
|
|
182
|
+
// shared background service that ignores the tab's env/OPENCODE_CONFIG_CONTENT, so EVERY 2.x
|
|
183
|
+
// launch (fresh AND restore — a restore's argv comes from preparedLaunchPlan.args, built by
|
|
184
|
+
// lib/agent-capabilities.js's resumeSpec) runs its own private server via `--standalone`.
|
|
185
|
+
// R-2: CTM also chooses the 2.x session id, `ses_<CTM session UUID without dashes>`, the twin of
|
|
186
|
+
// Claude's deterministic `--session-id` injection below, so a restore has a precise `--session`.
|
|
187
|
+
// The line is the same peek rule as the model-args gate above (R-6): server.js's handleCreate
|
|
188
|
+
// has already awaited primeOpencodeLine() for an OpenCode launch before this argv is built, so
|
|
189
|
+
// this read is sync and fs-free. A v1 or null line leaves `args` byte-identical to before.
|
|
190
|
+
let _injectedOpencodeSessionId = null;
|
|
191
|
+
if (normalizeAgentType(createAgentType) === 'opencode') {
|
|
192
|
+
try {
|
|
193
|
+
const cli = require('../opencode-cli');
|
|
194
|
+
if (cli.peekOpencodeLine() === 'v2') {
|
|
195
|
+
if (!args.includes('--standalone')) args = ['--standalone', ...args];
|
|
196
|
+
const hasSessionArg = args.some(a => a === '--session' || a === '-s' || a === '--continue' || a === '-c'
|
|
197
|
+
|| (typeof a === 'string' && a.startsWith('--session=')));
|
|
198
|
+
if (!hasSessionArg && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id)) {
|
|
199
|
+
const minted = `ses_${id.replace(/-/g, '')}`;
|
|
200
|
+
args = [...args, '--session', minted];
|
|
201
|
+
_injectedOpencodeSessionId = minted;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.warn('[opencode-v2-launch] skipped:', e.message);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
177
208
|
if (createAgentType === 'codex' && codexResumeCwdGuardEnabled) {
|
|
178
209
|
args = withCodexResumeCd(args, cwd);
|
|
179
210
|
}
|
|
@@ -352,10 +383,23 @@ function resolveCreateLaunchParams(ctx) {
|
|
|
352
383
|
const resume = preparedLaunchPlan?.resume || {};
|
|
353
384
|
const providerThreadId = resume.providerResumeId || resume.providerResumeID || resume.sessionId || resume.agentSessionId || '';
|
|
354
385
|
const routeId = msg._launchLeadRoute?.routeId || null;
|
|
386
|
+
// WP-2b (§5 D-5/D-6): a FRESH rollback of a never-prompted source is the one shape that carries
|
|
387
|
+
// neither a resume selector nor a model override. `freshRelaunch` is the record's own fact, so an
|
|
388
|
+
// older record (absent -> false) keeps today's exact resume-shaped rule -- including the empty
|
|
389
|
+
// provider thread it could never have matched.
|
|
390
|
+
const freshRelaunch = sourceRecoveryEnvironment.freshRelaunch === true;
|
|
391
|
+
// The launch's resolved thread: for a fresh rollback the plan has no resume selector at all, so ''
|
|
392
|
+
// is acceptable -- but the argv must then name the SOURCE's own thread through `--session-id`.
|
|
393
|
+
const threadMatches = freshRelaunch
|
|
394
|
+
? providerThreadId === '' || providerThreadId === sourceRecoveryEnvironment.providerThreadId
|
|
395
|
+
: providerThreadId === sourceRecoveryEnvironment.providerThreadId;
|
|
396
|
+
const argvThreadMatches = !freshRelaunch || createAgentType !== 'claude'
|
|
397
|
+
|| claudeSessionIdArg(args) === sourceRecoveryEnvironment.providerThreadId;
|
|
355
398
|
if (!msg._isRestore || msg._leadModelTransition || sourceRecoveryEnvironment.ctmSessionId !== id
|
|
356
399
|
|| sourceRecoveryEnvironment.agent !== createAgentType
|
|
357
|
-
||
|
|
358
|
-
|| sourceRecoveryEnvironment.modelId !== msg._launchModelOverride
|
|
400
|
+
|| !threadMatches
|
|
401
|
+
|| sourceRecoveryEnvironment.modelId !== String(msg._launchModelOverride || '')
|
|
402
|
+
|| !argvThreadMatches
|
|
359
403
|
|| sourceRecoveryEnvironment.routeId !== routeId) {
|
|
360
404
|
throw Object.assign(new Error('Captured source environment does not match the prepared recovery owner.'), {
|
|
361
405
|
code: 'source_recovery_environment_owner_mismatch',
|
|
@@ -396,6 +440,12 @@ function resolveCreateLaunchParams(ctx) {
|
|
|
396
440
|
// This adds OTEL_EXPORTER_OTLP_ENDPOINT → http://localhost:<PORT> for agents
|
|
397
441
|
// that emit OTLP logs, plus CTM_SESSION_ID for our hook scripts to read.
|
|
398
442
|
Object.assign(env, buildTelemetryEnv(id, cmd, PORT, env));
|
|
443
|
+
// WP-2 (docs/claude-restore-seed-alt-screen-trap-2026-10-27.html R-4, §8 WP-2): restate the
|
|
444
|
+
// user's own Claude renderer choice through Claude's own override, so a CTM crash-restore
|
|
445
|
+
// storm cannot silently flip it via the fullscreen boot canary. Runs AFTER the non-primary
|
|
446
|
+
// sandbox env rebuild above, so a dev/test instance reads the sandbox HOME's settings, never
|
|
447
|
+
// the real user's.
|
|
448
|
+
Object.assign(env, buildClaudeRendererLaunchEnv(cmd, env));
|
|
399
449
|
if (createAgentType === 'codex') {
|
|
400
450
|
try {
|
|
401
451
|
const launchHealth = preparedLaunchPlan.maintenance?.codexHealth || { args, mcpReport: { disabled: [] } };
|
|
@@ -466,13 +516,10 @@ function resolveCreateLaunchParams(ctx) {
|
|
|
466
516
|
&& msg.titleIntent !== 'default' && !!requestedTitle;
|
|
467
517
|
let title = requestedTitle;
|
|
468
518
|
if (!title) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
: cmd.includes('cursor') ? 'Cursor'
|
|
474
|
-
: cmd.includes('aider') ? 'Aider'
|
|
475
|
-
: null;
|
|
519
|
+
// S-3 (D-5): the product-facing title comes from the ONE detector; 'aider' stays a local fallback
|
|
520
|
+
// ('walle' and 'shell' still title as `Shell: <cwd>`, unchanged).
|
|
521
|
+
const AGENT_TITLE = { dsh: 'DeepSeek Harness', claude: 'Claude Code', codex: 'Codex', gemini: 'Gemini', opencode: 'OpenCode', cursor: 'Cursor' };
|
|
522
|
+
const agentName = AGENT_TITLE[detectAgentType(cmd)] || (cmd.includes('aider') ? 'Aider' : null);
|
|
476
523
|
if (agentName) {
|
|
477
524
|
const shortCwd = cwd.replace(serverConfig.HOME || '', '~');
|
|
478
525
|
title = `${agentName}: ${shortCwd}`;
|
|
@@ -506,6 +553,9 @@ function resolveCreateLaunchParams(ctx) {
|
|
|
506
553
|
claudeResumeId,
|
|
507
554
|
isResumeLaunch,
|
|
508
555
|
_injectedSessionId,
|
|
556
|
+
// R-2: deliberately NOT `_injectedSessionId` — that one drives Claude-only JSONL/project-dir
|
|
557
|
+
// side effects downstream in lib/session-create/provider-process.js. Only one can ever be set.
|
|
558
|
+
_injectedOpencodeSessionId,
|
|
509
559
|
_approvalHookEnabled,
|
|
510
560
|
_approvalHookToken,
|
|
511
561
|
restoreSeedSnapshot,
|
|
@@ -696,7 +746,7 @@ function resolveWorkerLaunchParams(opts = {}) {
|
|
|
696
746
|
agent, alias, model, token, proxyPort,
|
|
697
747
|
briefPath, cwd, reportPath,
|
|
698
748
|
} = opts;
|
|
699
|
-
if (agent !== 'claude' && agent !== 'codex') {
|
|
749
|
+
if (agent !== 'claude' && agent !== 'codex' && agent !== 'dsh') {
|
|
700
750
|
throw new TypeError(`resolveWorkerLaunchParams: unsupported agent "${agent}"`);
|
|
701
751
|
}
|
|
702
752
|
if (!alias) throw new TypeError('resolveWorkerLaunchParams: alias required');
|
|
@@ -715,6 +765,40 @@ function resolveWorkerLaunchParams(opts = {}) {
|
|
|
715
765
|
throw new TypeError(`resolveWorkerLaunchParams: unsupported worker profile "${workerProfile}"`);
|
|
716
766
|
}
|
|
717
767
|
const prompt = typeof opts.prompt === 'string' ? opts.prompt : buildWorkerPrompt({ briefPath, cwd, reportPath, profile: workerProfile });
|
|
768
|
+
// WP-14 (docs/deepseek-harness-acp-agent-2026-10-28.html §9b W-2): a dsh worker has NO argv. It is
|
|
769
|
+
// ONE ACP child (lib/acp/dsh-session-runtime.js) started from the create request's own resolved
|
|
770
|
+
// launch env (server.js `buildLaunchEnv` -> lib/session-create/dsh-session.js) and spoken to over
|
|
771
|
+
// ACP, so this branch returns the ACP START PARAMS instead of an argv:
|
|
772
|
+
// * `env` — the worker's own proxy credential (ANTHROPIC_AUTH_TOKEN, the one key pi-ai's built-in
|
|
773
|
+
// anthropic provider turns into `Authorization: Bearer …`, §6.6 OQ-1) plus the worker mark the
|
|
774
|
+
// env strip reads (agent-presets.js) and the child's permission mode (W-9). The routed baseURL
|
|
775
|
+
// is deliberately NOT here: the dsh route patch declares it (D-21/§6.6) and the runtime strips
|
|
776
|
+
// the inherited provider keys, so the credential and the mark are all that travel.
|
|
777
|
+
// * `acp` — the brief as the FIRST PROMPT, the report path, the routed pick and the MCP set
|
|
778
|
+
// (WP-10 already materializes `mcpServers`; the dsh create path converts them to ACP entries).
|
|
779
|
+
// Sits BEFORE `workerSandboxArgs` precisely because that table's harness ternary is claude/codex only.
|
|
780
|
+
if (agent === 'dsh') {
|
|
781
|
+
const mcpServers = (opts.mcpServers && typeof opts.mcpServers === 'object' && !Array.isArray(opts.mcpServers))
|
|
782
|
+
? opts.mcpServers
|
|
783
|
+
: {};
|
|
784
|
+
const { permissionMode } = dshWorkerSandbox({ profile: workerProfile });
|
|
785
|
+
return {
|
|
786
|
+
cmd: 'dsh',
|
|
787
|
+
args: [],
|
|
788
|
+
env: {
|
|
789
|
+
CTM_WORKER_AGENT: agent,
|
|
790
|
+
CTM_WORKER_TOKEN: token,
|
|
791
|
+
ANTHROPIC_AUTH_TOKEN: token,
|
|
792
|
+
DSH_PERMISSION_MODE: permissionMode,
|
|
793
|
+
},
|
|
794
|
+
acp: {
|
|
795
|
+
prompt, briefPath, cwd, reportPath,
|
|
796
|
+
routeAlias: alias, model,
|
|
797
|
+
mcpServers,
|
|
798
|
+
permissionMode,
|
|
799
|
+
},
|
|
800
|
+
};
|
|
801
|
+
}
|
|
718
802
|
const port = Number(proxyPort);
|
|
719
803
|
// WP-4 (delegate-codex-lessons §5 D-29): the lead posture's launch half. Absent posture =
|
|
720
804
|
// today's argv exactly (no sandbox key, no extra args); a resolved posture adds the
|
|
@@ -21,12 +21,12 @@ function normalizeWorkerRequest(opts = {}) {
|
|
|
21
21
|
const invalid = (code, message) => { const error = new Error(message); error.code = code; throw error; };
|
|
22
22
|
const agentInput = opts.agent;
|
|
23
23
|
const harnessInput = opts.harness;
|
|
24
|
-
if (agentInput !== undefined && agentInput !== 'claude' && agentInput !== 'codex') invalid('agent_invalid', 'agent must be claude or
|
|
25
|
-
if (harnessInput !== undefined && harnessInput !== 'claude-code' && harnessInput !== 'codex-cli') invalid('harness_invalid', 'harness must be claude-code or
|
|
26
|
-
const harnessAgent = harnessInput === 'codex-cli' ? 'codex' : harnessInput === 'claude-code' ? 'claude' : null;
|
|
24
|
+
if (agentInput !== undefined && agentInput !== 'claude' && agentInput !== 'codex' && agentInput !== 'dsh') invalid('agent_invalid', 'agent must be claude, codex or dsh');
|
|
25
|
+
if (harnessInput !== undefined && harnessInput !== 'claude-code' && harnessInput !== 'codex-cli' && harnessInput !== 'dsh-acp') invalid('harness_invalid', 'harness must be claude-code, codex-cli or dsh-acp');
|
|
26
|
+
const harnessAgent = harnessInput === 'codex-cli' ? 'codex' : harnessInput === 'claude-code' ? 'claude' : harnessInput === 'dsh-acp' ? 'dsh' : null;
|
|
27
27
|
if (agentInput && harnessAgent && agentInput !== harnessAgent) invalid('harness_conflict', 'agent and harness identify different coding CLIs');
|
|
28
28
|
const agent = harnessAgent || agentInput || 'claude';
|
|
29
|
-
const harness = harnessInput || (agent === 'codex' ? 'codex-cli' : 'claude-code');
|
|
29
|
+
const harness = harnessInput || (agent === 'codex' ? 'codex-cli' : agent === 'dsh' ? 'dsh-acp' : 'claude-code');
|
|
30
30
|
const workerProfile = opts.workerProfile === undefined ? 'implementation' : opts.workerProfile;
|
|
31
31
|
if (!WORKER_PROFILES.includes(workerProfile)) invalid('worker_profile_invalid', 'worker_profile must be legacy, implementation or review');
|
|
32
32
|
return { agent, harness, workerProfile };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-3 (docs/session-create-box-restart-and-git-lane-starvation-2026-10-30.html §5 D-4,
|
|
4
|
+
// §6.3, §8, §9 S-9..S-11, S-17): a "create in flight" is invisible to the restart guard.
|
|
5
|
+
// On 2026-10-30 at 02:20:31Z the MBP box's repo-root fleet-apply script restarted CTM 5 s
|
|
6
|
+
// after the operator opened the new-session modal for that box, and the create failed.
|
|
7
|
+
// fleet-apply polls GET /api/instance/update-gate, and the non-force POST /api/restart/ctm
|
|
8
|
+
// refusal both read _restartGuardSnapshot, which summarized LIVE SESSIONS ONLY.
|
|
9
|
+
//
|
|
10
|
+
// This module is the missing signal: a short, in-process lease noted by the LOCAL create
|
|
11
|
+
// handlers (the machine that would restart is the one that notes it -- a machine-routed
|
|
12
|
+
// proxy branch must never note, or a hub would block its own restart for a box's create).
|
|
13
|
+
// It is deliberately tiny: a clock, an expiry, and the last route/hop diagnostic.
|
|
14
|
+
//
|
|
15
|
+
// The lease is advisory only -- the guard turns it into a 409 (or a blocker row), and
|
|
16
|
+
// ?force=true still overrides it exactly as it overrides a live session.
|
|
17
|
+
|
|
18
|
+
const CREATE_INTENT_LEASE_MS = 120000;
|
|
19
|
+
|
|
20
|
+
function createIntentLease({ now = Date.now, leaseMs = CREATE_INTENT_LEASE_MS } = {}) {
|
|
21
|
+
let until = 0;
|
|
22
|
+
let last = null; // { route, forwardedBy, at }
|
|
23
|
+
return {
|
|
24
|
+
note(route, forwardedBy = '') {
|
|
25
|
+
const t = now();
|
|
26
|
+
until = t + leaseMs;
|
|
27
|
+
last = { route: String(route || ''), forwardedBy: String(forwardedBy || ''), at: t };
|
|
28
|
+
},
|
|
29
|
+
active() {
|
|
30
|
+
return now() < until ? { ...last, untilMs: until } : null;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const processLease = createIntentLease();
|
|
36
|
+
|
|
37
|
+
/** Note an in-flight create on THIS machine. `ctxOrReq` may be an HTTP req or a WS ctx. */
|
|
38
|
+
function noteCreateIntent(route, ctxOrReq) {
|
|
39
|
+
let forwardedBy = '';
|
|
40
|
+
try {
|
|
41
|
+
forwardedBy = require('./remote-machine-create').forwardedByOf(ctxOrReq) || '';
|
|
42
|
+
} catch { /* expected: a hop-header read fault only loses the diagnostic field */ }
|
|
43
|
+
processLease.note(route, forwardedBy);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
CREATE_INTENT_LEASE_MS,
|
|
48
|
+
createIntentLease,
|
|
49
|
+
noteCreateIntent,
|
|
50
|
+
activeCreateIntent: () => processLease.active(),
|
|
51
|
+
};
|