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
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// S-1 (D-4): the command-to-agent rule lives in ONE place — the UMD module shared with the client.
|
|
4
|
+
const { detectAgentType } = require('../public/js/agent-command');
|
|
5
|
+
|
|
3
6
|
const CONV_CLI_SURFACES = Object.freeze({
|
|
4
7
|
conv: Object.freeze({ available: true, live: true, source: 'canonical-rows' }),
|
|
5
8
|
cli: Object.freeze({ available: true, source: 'pty' }),
|
|
@@ -13,9 +16,26 @@ const CLI_ONLY_SURFACES = Object.freeze({
|
|
|
13
16
|
conv: Object.freeze({ available: false, live: false, source: 'canonical-rows' }),
|
|
14
17
|
cli: Object.freeze({ available: true, source: 'pty' }),
|
|
15
18
|
});
|
|
19
|
+
// D-4 (deepseek-harness-acp-agent-2026-10-28.html §5): an ACP agent driven over pipes has no
|
|
20
|
+
// terminal UI, so its only surface is the Conversation view backed by canonical rows — the client
|
|
21
|
+
// creates no xterm for it (public/js/stream-view.js gates on surfaces.cli.available).
|
|
22
|
+
const CONV_ONLY_SURFACES = Object.freeze({
|
|
23
|
+
conv: Object.freeze({ available: true, live: true, source: 'canonical-rows' }),
|
|
24
|
+
cli: Object.freeze({ available: false, source: 'pty' }),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// WP-15 (§15.4 R-15.1): how an agent takes its INITIAL prompt. 'positional' = the CLI's own
|
|
28
|
+
// initial-prompt operand (`claude [prompt]`, `codex [PROMPT]`, `gemini query`, `cursor-agent
|
|
29
|
+
// [prompt...]`, C-15), which is the vendor-supported way to start a session already working.
|
|
30
|
+
// 'queue' = the prompt must go through the session's own transport (walle: a real structured turn,
|
|
31
|
+
// C-5). null = neither is measured to submit, so a server-started session must refuse instead of
|
|
32
|
+
// silently never starting (C-8 dsh; OQ-15.1 opencode).
|
|
33
|
+
const LAUNCH_PROMPT_POSITIONAL = 'positional';
|
|
34
|
+
const LAUNCH_PROMPT_QUEUE = 'queue';
|
|
16
35
|
|
|
17
36
|
const AGENT_CAPABILITIES = Object.freeze({
|
|
18
37
|
claude: Object.freeze({
|
|
38
|
+
launchPrompt: LAUNCH_PROMPT_POSITIONAL,
|
|
19
39
|
agentType: 'claude',
|
|
20
40
|
providerId: 'claude-code',
|
|
21
41
|
label: 'Claude Code',
|
|
@@ -36,12 +56,20 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
36
56
|
steer: 'queue-interrupt', rewind: false, branch: false,
|
|
37
57
|
modelControl: false, branching: false, export: true,
|
|
38
58
|
promptNavigation: 'transcript',
|
|
59
|
+
// WP-1 (wheel-reader-only-where-history-exists-2026-10-28 §5 D-3/D-4): the continuous reader can
|
|
60
|
+
// only serve a provider whose history CTM owns as a transcript -- the exact set server.js's
|
|
61
|
+
// _transcriptHistoryProvider (:39540) can answer (claude, codex). Every other provider has no
|
|
62
|
+
// reader source, so its wheel-up must forward to the app instead of opening a reader that exits
|
|
63
|
+
// at once (opencode incident 2026-10-28). Flips to 'transcript' only in the same commit that
|
|
64
|
+
// teaches _transcriptHistoryProvider to return that provider.
|
|
65
|
+
historyReader: 'transcript',
|
|
39
66
|
review: true,
|
|
40
67
|
resume: true,
|
|
41
68
|
resumeSpec: (id) => ({ cmd: 'claude', args: ['--resume', id] }),
|
|
42
69
|
titleSpec: { kind: 'agentSdk', readsUserName: true, readsAiTitle: true, launchArgs: (name) => ['-n', name] },
|
|
43
70
|
}),
|
|
44
71
|
codex: Object.freeze({
|
|
72
|
+
launchPrompt: LAUNCH_PROMPT_POSITIONAL,
|
|
45
73
|
agentType: 'codex',
|
|
46
74
|
providerId: 'codex',
|
|
47
75
|
label: 'Codex',
|
|
@@ -62,12 +90,15 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
62
90
|
steer: 'queue-interrupt', rewind: false, branch: false,
|
|
63
91
|
modelControl: false, branching: false, export: true,
|
|
64
92
|
promptNavigation: 'transcript',
|
|
93
|
+
// Codex rollout lanes are a real reader source (_transcriptHistoryProvider, server.js:39540).
|
|
94
|
+
historyReader: 'transcript',
|
|
65
95
|
review: true,
|
|
66
96
|
resume: true,
|
|
67
97
|
resumeSpec: (id) => ({ cmd: 'codex', args: ['resume', id] }),
|
|
68
98
|
titleSpec: { kind: 'appServerJsonRpc', readsUserName: true, readsAiTitle: false },
|
|
69
99
|
}),
|
|
70
100
|
gemini: Object.freeze({
|
|
101
|
+
launchPrompt: LAUNCH_PROMPT_POSITIONAL,
|
|
71
102
|
agentType: 'gemini',
|
|
72
103
|
providerId: 'gemini',
|
|
73
104
|
label: 'Gemini',
|
|
@@ -80,6 +111,8 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
80
111
|
semanticApprovals: false,
|
|
81
112
|
steer: false, rewind: false, branch: false, modelControl: false,
|
|
82
113
|
promptNavigation: 'terminal',
|
|
114
|
+
// No CTM transcript / rollout rows for gemini -- the continuous reader has no source here.
|
|
115
|
+
historyReader: 'none',
|
|
83
116
|
review: false,
|
|
84
117
|
resume: true,
|
|
85
118
|
// Resumes by provider session id, not a CTM-owned JSONL transcript, so restart-restore must
|
|
@@ -88,7 +121,49 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
88
121
|
resumeSpec: (id) => ({ cmd: 'gemini', args: ['--session', id] }),
|
|
89
122
|
titleSpec: null,
|
|
90
123
|
}),
|
|
124
|
+
// WP-2 (D-3/D-4, §9 S-2): DeepSeek Harness is driven over the Agent Client Protocol on pipes
|
|
125
|
+
// (lib/acp/*, a later WP), never through node-pty, so it declares conv-only surfaces and ACP
|
|
126
|
+
// input/control fidelity. dsh resumes through ACP `session/resume` on attach using the stored ACP
|
|
127
|
+
// session id, and CTM's own transcript IS required (resumesWithoutTranscript:false — the session
|
|
128
|
+
// cannot be restored from the provider alone). resumeSpec is null because there is no CLI argv
|
|
129
|
+
// resume form. WP-2 only registers the id; no session can be created yet.
|
|
130
|
+
dsh: Object.freeze({
|
|
131
|
+
// WP-15 (§15.4 R-15.3, C-8): an ACP session has no ptyProcess, so no launch operand exists and
|
|
132
|
+
// the queue lane's sendFn answers `session_not_live` forever -- a server-started dsh session
|
|
133
|
+
// would never start. Declared null so callers refuse instead.
|
|
134
|
+
launchPrompt: null,
|
|
135
|
+
agentType: 'dsh',
|
|
136
|
+
providerId: 'dsh',
|
|
137
|
+
label: 'DeepSeek Harness',
|
|
138
|
+
liveStatus: true,
|
|
139
|
+
stateDetector: false,
|
|
140
|
+
structuredTranscript: true,
|
|
141
|
+
surfaces: CONV_ONLY_SURFACES,
|
|
142
|
+
semanticInput: true,
|
|
143
|
+
semanticQueue: false,
|
|
144
|
+
semanticApprovals: true,
|
|
145
|
+
inputFidelity: 'acp', controlFidelity: 'acp',
|
|
146
|
+
messages: Object.freeze({ stream: true, durable: true, branching: false }),
|
|
147
|
+
input: Object.freeze({ send: true, queue: false, interrupt: true, attachments: false }),
|
|
148
|
+
approvals: Object.freeze({ authoritative: true, resolve: true }),
|
|
149
|
+
work: Object.freeze({ phase: true, tasks: false, subagents: false }),
|
|
150
|
+
controls: Object.freeze({ model: false, cwd: false, sandbox: false }),
|
|
151
|
+
artifacts: Object.freeze({ files: true, diffs: false, tests: false }),
|
|
152
|
+
steer: 'queue-interrupt', rewind: false, branch: false,
|
|
153
|
+
modelControl: false, branching: false, export: true,
|
|
154
|
+
promptNavigation: 'transcript',
|
|
155
|
+
historyReader: 'none',
|
|
156
|
+
review: false,
|
|
157
|
+
resume: true,
|
|
158
|
+
resumeSpec: () => null,
|
|
159
|
+
resumesWithoutTranscript: false,
|
|
160
|
+
titleSpec: null,
|
|
161
|
+
}),
|
|
91
162
|
opencode: Object.freeze({
|
|
163
|
+
// WP-15 (§15.4 R-15.3, OQ-15.1): `opencode --prompt` exists, but whether the TUI submits it is
|
|
164
|
+
// UNMEASURED, so it is not claimed here. Flips to `{ flag: '--prompt' }` only with a recorded
|
|
165
|
+
// PTY transcript.
|
|
166
|
+
launchPrompt: null,
|
|
92
167
|
agentType: 'opencode',
|
|
93
168
|
providerId: 'opencode',
|
|
94
169
|
label: 'OpenCode',
|
|
@@ -111,6 +186,9 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
111
186
|
steer: 'queue-interrupt', rewind: false, branch: false,
|
|
112
187
|
modelControl: false, branching: false, export: true,
|
|
113
188
|
promptNavigation: 'transcript',
|
|
189
|
+
// OpenCode rows land in session_message_rows (commitProviderSnapshot), never in the
|
|
190
|
+
// transcript_files/transcript_events the reader reads -- no reader source, so wheel-up forwards.
|
|
191
|
+
historyReader: 'none',
|
|
114
192
|
review: true,
|
|
115
193
|
resume: true,
|
|
116
194
|
// OpenCode keeps history in its own SQLite db (no CTM JSONL transcript, file_size 0), and its
|
|
@@ -126,6 +204,8 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
126
204
|
titleSpec: null,
|
|
127
205
|
}),
|
|
128
206
|
walle: Object.freeze({
|
|
207
|
+
// C-5: the queue lane delivers a real structured turn for a walle session, so it does submit.
|
|
208
|
+
launchPrompt: LAUNCH_PROMPT_QUEUE,
|
|
129
209
|
agentType: 'walle',
|
|
130
210
|
providerId: 'walle',
|
|
131
211
|
label: 'Wall-E',
|
|
@@ -146,12 +226,16 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
146
226
|
steer: true, rewind: true, branch: true,
|
|
147
227
|
modelControl: true, branching: true, export: true,
|
|
148
228
|
promptNavigation: 'chat',
|
|
229
|
+
// The reader serves terminal providers; Wall-E's native surface is not one.
|
|
230
|
+
historyReader: 'none',
|
|
149
231
|
review: true,
|
|
150
232
|
resume: false,
|
|
151
233
|
resumeSpec: () => null,
|
|
152
234
|
titleSpec: null,
|
|
153
235
|
}),
|
|
154
236
|
cursor: Object.freeze({
|
|
237
|
+
// C-15: `cursor-agent [options] [command] [prompt...]`.
|
|
238
|
+
launchPrompt: LAUNCH_PROMPT_POSITIONAL,
|
|
155
239
|
agentType: 'cursor',
|
|
156
240
|
providerId: 'cursor',
|
|
157
241
|
label: 'Cursor',
|
|
@@ -164,6 +248,8 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
164
248
|
semanticApprovals: false,
|
|
165
249
|
steer: false, rewind: false, branch: false, modelControl: false,
|
|
166
250
|
promptNavigation: 'terminal',
|
|
251
|
+
// Cursor chats are cloud-backed with no local transcript -- no reader source.
|
|
252
|
+
historyReader: 'none',
|
|
167
253
|
review: false,
|
|
168
254
|
resume: true,
|
|
169
255
|
// Cursor chats are cloud-backed: there's no local transcript (JSONL/SQLite)
|
|
@@ -175,6 +261,8 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
175
261
|
titleSpec: null,
|
|
176
262
|
}),
|
|
177
263
|
shell: Object.freeze({
|
|
264
|
+
// A plain shell has no agent to hand a prompt to.
|
|
265
|
+
launchPrompt: null,
|
|
178
266
|
agentType: 'shell',
|
|
179
267
|
providerId: 'shell',
|
|
180
268
|
label: 'Shell',
|
|
@@ -187,6 +275,8 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
187
275
|
semanticApprovals: false,
|
|
188
276
|
steer: false, rewind: false, branch: false, modelControl: false,
|
|
189
277
|
promptNavigation: 'terminal',
|
|
278
|
+
// A plain shell has no CTM transcript -- the reader has no source, so its wheel-up forwards.
|
|
279
|
+
historyReader: 'none',
|
|
190
280
|
review: false,
|
|
191
281
|
resume: false,
|
|
192
282
|
resumeSpec: () => null,
|
|
@@ -194,24 +284,14 @@ const AGENT_CAPABILITIES = Object.freeze({
|
|
|
194
284
|
}),
|
|
195
285
|
});
|
|
196
286
|
|
|
197
|
-
function detectAgentType(cmd) {
|
|
198
|
-
if (!cmd) return null;
|
|
199
|
-
const s = String(cmd).toLowerCase();
|
|
200
|
-
if (s.includes('claude')) return 'claude';
|
|
201
|
-
if (s.includes('codex')) return 'codex';
|
|
202
|
-
if (s.includes('gemini')) return 'gemini';
|
|
203
|
-
if (s.includes('opencode') || s.includes('open-code')) return 'opencode';
|
|
204
|
-
if (s.includes('cursor')) return 'cursor';
|
|
205
|
-
if (s === 'walle' || s.includes('wall-e') || s.includes('walle')) return 'walle';
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
287
|
function normalizeAgentType(value) {
|
|
210
288
|
if (!value) return null;
|
|
211
289
|
const s = String(value).toLowerCase().replace(/_/g, '-');
|
|
212
290
|
if (AGENT_CAPABILITIES[s]) return s;
|
|
213
291
|
if (s === 'claude-code') return 'claude';
|
|
214
292
|
if (s === 'gemini-cli') return 'gemini';
|
|
293
|
+
// D-3/S-4: the `_`→`-` rewrite above already turns 'deepseek_harness' into this form.
|
|
294
|
+
if (s === 'deepseek-harness') return 'dsh';
|
|
215
295
|
if (s === 'opencode-cli' || s === 'open-code') return 'opencode';
|
|
216
296
|
if (s === 'cursor-agent' || s === 'cursor-cli') return 'cursor';
|
|
217
297
|
return detectAgentType(s);
|
|
@@ -222,6 +302,19 @@ function getAgentCapabilities(value) {
|
|
|
222
302
|
return AGENT_CAPABILITIES[type] || AGENT_CAPABILITIES.shell;
|
|
223
303
|
}
|
|
224
304
|
|
|
305
|
+
// WP-11 (D-20, docs/deepseek-harness-acp-agent-2026-10-28.html): the PER-SESSION form of the
|
|
306
|
+
// capability record. The static `dsh` row above stays `input.attachments: false` — what a dsh session
|
|
307
|
+
// can actually accept is the LIVE child's own `initialize` answer
|
|
308
|
+
// (`agentCapabilities.promptCapabilities.image`, lib/acp/dsh-session-runtime.js), which is false for a
|
|
309
|
+
// bridge that does not advertise image prompts. `imageInput:true` is therefore the ONLY way a dsh
|
|
310
|
+
// session advertises attachments, and every other agent type is returned unchanged.
|
|
311
|
+
function getSessionAgentCapabilities(value, { imageInput = false } = {}) {
|
|
312
|
+
const type = normalizeAgentType(value) || 'shell';
|
|
313
|
+
const caps = AGENT_CAPABILITIES[type] || AGENT_CAPABILITIES.shell;
|
|
314
|
+
if (type !== 'dsh') return caps;
|
|
315
|
+
return { ...caps, input: Object.freeze({ ...(caps.input || {}), attachments: imageInput === true }) };
|
|
316
|
+
}
|
|
317
|
+
|
|
225
318
|
function getAgentSurfaceIds(value) {
|
|
226
319
|
const surfaces = getAgentCapabilities(value).surfaces || CLI_ONLY_SURFACES;
|
|
227
320
|
return ['cli', 'web', 'conv'].filter((surface) => surfaces[surface]?.available === true);
|
|
@@ -251,14 +344,51 @@ function getTitleSpec(agentType) {
|
|
|
251
344
|
return caps.titleSpec || null;
|
|
252
345
|
}
|
|
253
346
|
|
|
347
|
+
// WP-15 (§15.4 R-15.1, §15.5 API): the ONE place that knows how to turn (agentType, prompt) into
|
|
348
|
+
// launch argv. `launchPromptMode` is the read-only query; `launchPromptArgv` is the argv builder for
|
|
349
|
+
// the only mode that has an argv form.
|
|
350
|
+
function launchPromptMode(agentType) {
|
|
351
|
+
const mode = getAgentCapabilities(agentType).launchPrompt;
|
|
352
|
+
return mode === LAUNCH_PROMPT_POSITIONAL || mode === LAUNCH_PROMPT_QUEUE ? mode : null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function typedError(code, message) {
|
|
356
|
+
const error = new Error(message);
|
|
357
|
+
error.code = code;
|
|
358
|
+
return error;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// R-15.4: a prompt is only safe as a positional operand when it cannot be read as a flag or as a
|
|
362
|
+
// subcommand. Never insert `--`: lib/create/resolve-launch-params.js:327 declines its approval-hook
|
|
363
|
+
// injection for an argv whose terminator is not last, so a `--` here would silently drop the hook.
|
|
364
|
+
function launchPromptArgv(agentType, prompt) {
|
|
365
|
+
const type = normalizeAgentType(agentType) || String(agentType == null ? '' : agentType).toLowerCase() || 'unknown';
|
|
366
|
+
if (launchPromptMode(agentType) !== LAUNCH_PROMPT_POSITIONAL) {
|
|
367
|
+
throw typedError('launch_prompt_unsupported', `${type} does not take its prompt as a launch argument`);
|
|
368
|
+
}
|
|
369
|
+
if (typeof prompt !== 'string' || prompt.trim() === '') {
|
|
370
|
+
throw typedError('prompt_not_argv_safe', 'a launch prompt must be a non-empty string');
|
|
371
|
+
}
|
|
372
|
+
if (prompt[0] === '-') {
|
|
373
|
+
throw typedError('prompt_not_argv_safe', 'a launch prompt must not start with "-" (it would parse as an option)');
|
|
374
|
+
}
|
|
375
|
+
if (!/\s/.test(prompt.trim())) {
|
|
376
|
+
throw typedError('prompt_not_argv_safe', 'a launch prompt must be more than one bare word (it could match a subcommand)');
|
|
377
|
+
}
|
|
378
|
+
return [prompt];
|
|
379
|
+
}
|
|
380
|
+
|
|
254
381
|
module.exports = {
|
|
255
382
|
AGENT_CAPABILITIES,
|
|
256
383
|
detectAgentType,
|
|
257
384
|
normalizeAgentType,
|
|
258
385
|
getAgentCapabilities,
|
|
386
|
+
getSessionAgentCapabilities,
|
|
259
387
|
getAgentSurfaceIds,
|
|
260
388
|
canResumeAgent,
|
|
261
389
|
resumesWithoutTranscript,
|
|
262
390
|
getResumeSpec,
|
|
263
391
|
getTitleSpec,
|
|
392
|
+
launchPromptMode,
|
|
393
|
+
launchPromptArgv,
|
|
264
394
|
};
|
|
@@ -8,7 +8,9 @@ const { definitionForCli } = require('./agent-definitions');
|
|
|
8
8
|
const { canAutoUpgrade } = require('./agent-upgrade-planner');
|
|
9
9
|
|
|
10
10
|
const CACHE_VERSION = 2;
|
|
11
|
-
|
|
11
|
+
// WP-2 (S-5): the DeepSeek Harness CLI (`dsh`) joins discovery so an install is found on PATH;
|
|
12
|
+
// _cliBinForAgentType maps agentType 'dsh' to the same binary name through its default fallback.
|
|
13
|
+
const DEFAULT_AGENTS = Object.freeze(['claude', 'codex', 'gemini', 'opencode', 'cursor-agent', 'dsh']);
|
|
12
14
|
|
|
13
15
|
function _pathHash(envPath) {
|
|
14
16
|
return crypto.createHash('sha256').update(String(envPath || '')).digest('hex');
|
|
@@ -212,6 +214,29 @@ function _publicEntry(entry, envPath) {
|
|
|
212
214
|
};
|
|
213
215
|
}
|
|
214
216
|
|
|
217
|
+
/**
|
|
218
|
+
* WP-13b: the definition's `installIdentity` (agent-definitions.js, the `dsh` entry) is the same
|
|
219
|
+
* rule lib/agent-version-service.js applies at version-check time (_installIdentityHolds), and it
|
|
220
|
+
* exists because the NAME is not unique on this host: homebrew ships the unrelated "Dancer's shell"
|
|
221
|
+
* as `dsh`, so a bare PATH hit would report the DeepSeek Harness as installed when it is not.
|
|
222
|
+
*
|
|
223
|
+
* An agent whose definition carries no `installIdentity` is untouched (claude/codex/opencode/gemini/
|
|
224
|
+
* cursor read exactly as before). An entry that is not `available` at all is also untouched — there
|
|
225
|
+
* is no path to judge, and "not found" stays "not found".
|
|
226
|
+
*/
|
|
227
|
+
function _installIdentityHolds(def, entry) {
|
|
228
|
+
if (!def || !def.installIdentity || !entry || !entry.available) return true;
|
|
229
|
+
// The realpath decides when discovery resolved one: a symlink's own path proves nothing.
|
|
230
|
+
return def.installIdentity.test(String(entry.realpath || entry.path || ''));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** `_publicEntry`, plus the install-identity gate: a wrong-named binary is surfaced as unavailable. */
|
|
234
|
+
function _publicEntryForAgent(agent, entry, envPath) {
|
|
235
|
+
const pub = _publicEntry(entry, envPath);
|
|
236
|
+
if (_installIdentityHolds(definitionForCli(agent), entry)) return pub;
|
|
237
|
+
return { ...pub, available: false };
|
|
238
|
+
}
|
|
239
|
+
|
|
215
240
|
function discoverAgent(agent, { env = process.env, now = Date.now(), extraBinDirs, preferCandidate } = {}) {
|
|
216
241
|
const envPath = env.PATH || process.env.PATH || '';
|
|
217
242
|
return _entryFromFingerprint(agent, _findOnPath(agent, envPath, extraBinDirs, preferCandidate), envPath, now, 'path-scan');
|
|
@@ -244,8 +269,8 @@ function getAvailableAgents({
|
|
|
244
269
|
cache.agents[agent] = entry;
|
|
245
270
|
changed = true;
|
|
246
271
|
}
|
|
247
|
-
result.agents[agent] =
|
|
248
|
-
result[agent] = !!
|
|
272
|
+
result.agents[agent] = _publicEntryForAgent(agent, entry, envPath);
|
|
273
|
+
result[agent] = !!result.agents[agent].available;
|
|
249
274
|
}
|
|
250
275
|
|
|
251
276
|
if (changed || !cache.generatedAt) {
|
|
@@ -266,8 +291,8 @@ function getCachedAvailableAgents({
|
|
|
266
291
|
const result = { ok: true, cacheFile, generatedAt: cache.generatedAt || 0, agents: {} };
|
|
267
292
|
for (const agent of agents) {
|
|
268
293
|
const entry = cache.agents[agent];
|
|
269
|
-
result.agents[agent] =
|
|
270
|
-
result[agent] = !!
|
|
294
|
+
result.agents[agent] = _publicEntryForAgent(agent, entry, envPath);
|
|
295
|
+
result[agent] = !!result.agents[agent].available && !result.agents[agent].stale;
|
|
271
296
|
}
|
|
272
297
|
return result;
|
|
273
298
|
}
|
|
@@ -55,6 +55,25 @@ const AGENT_DEFINITIONS = Object.freeze({
|
|
|
55
55
|
// --method skips opencode's install-method detection and its interactive "Install anyways?" prompt.
|
|
56
56
|
selfUpdate: { args: ['upgrade', '--method', 'curl'], label: 'opencode upgrade --method curl' },
|
|
57
57
|
}),
|
|
58
|
+
// WP-12 (AC-12a): the DeepSeek Harness (`dsh`, package @deepseek-ai/dsh). No brew channel: homebrew
|
|
59
|
+
// and homebrew-cask have no formula/cask for it (brew's `dsh` is the unrelated "Dancer's shell"),
|
|
60
|
+
// which tests/agent-version-service.test.js records in its noSourceByDesign table.
|
|
61
|
+
//
|
|
62
|
+
// installIdentity is the same rule lib/hermetic-agent-launch-guard.js applies to the dsh entrypoint,
|
|
63
|
+
// and it exists for the same reason: the name `dsh` is NOT unique on this host. Path discovery finds
|
|
64
|
+
// homebrew's "Dancer's shell", so an install counts only when its realpath is inside the
|
|
65
|
+
// @deepseek-ai/dsh package; anything else reports as not installed instead of probing the wrong
|
|
66
|
+
// binary's `--version`. Enforced by lib/agent-version-service.js (_installIdentityHolds).
|
|
67
|
+
dsh: Object.freeze({
|
|
68
|
+
id: 'dsh',
|
|
69
|
+
cli: 'dsh',
|
|
70
|
+
name: 'DeepSeek Harness',
|
|
71
|
+
versionArgs: ['--version'],
|
|
72
|
+
latest: {
|
|
73
|
+
'npm-global': { kind: 'npm', package: '@deepseek-ai/dsh' },
|
|
74
|
+
},
|
|
75
|
+
installIdentity: /(?:^|\/)@deepseek-ai\/dsh\//,
|
|
76
|
+
}),
|
|
58
77
|
cursor: Object.freeze({
|
|
59
78
|
id: 'cursor',
|
|
60
79
|
cli: 'cursor-agent',
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
// table header, and a copy stranded under a table is migrated by migrateCodexNotify().
|
|
11
11
|
|
|
12
12
|
const fs = require('fs');
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const HOOK_BIN_DIR = path.join(path.resolve(__dirname, '..'), 'bin');
|
|
13
|
+
const { hookShimPath } = require('./agent-hooks-shim');
|
|
16
14
|
|
|
17
15
|
function parseTomlDottedKeySegments(value) {
|
|
18
16
|
const src = String(value || '');
|
|
@@ -233,7 +231,17 @@ function stripCtmMarkerLines(text) {
|
|
|
233
231
|
.join('\n');
|
|
234
232
|
}
|
|
235
233
|
|
|
236
|
-
|
|
234
|
+
// The notify marker CTM owns, and the one predicate every ownership site uses. It matches BOTH
|
|
235
|
+
// forms CTM has ever written: the legacy `…/codex-notify.js` script path in the array, and the
|
|
236
|
+
// stable-shim form's quoted array element `"codex-notify"`. A quoted-element match is deliberately
|
|
237
|
+
// exact, so a user notify like `["say", "codex-notify-done"]` is NOT treated as ours.
|
|
238
|
+
const OWNS_NOTIFY = 'codex-notify';
|
|
239
|
+
|
|
240
|
+
/** Does this TOML text (a line, or a whole file) name CTM's Codex notify? */
|
|
241
|
+
function isCtmNotifyText(text) {
|
|
242
|
+
const t = String(text || '');
|
|
243
|
+
return t.includes(`${OWNS_NOTIFY}.js`) || t.includes(`"${OWNS_NOTIFY}"`);
|
|
244
|
+
}
|
|
237
245
|
|
|
238
246
|
/** Index of the line where a top-level key may be inserted: the first real table header, hoisted
|
|
239
247
|
* above any comment block attached directly to it. Returns lines.length when there is no table. */
|
|
@@ -257,8 +265,10 @@ function insertTopLevelKey(text, keyLine) {
|
|
|
257
265
|
return out.join('\n');
|
|
258
266
|
}
|
|
259
267
|
|
|
260
|
-
|
|
261
|
-
|
|
268
|
+
/** The top-level `notify` line CTM writes. It names the per-port stable shim (`~/.walle/bin/ctm-hook-<port>`),
|
|
269
|
+
* never a repo path, so a CTM checkout move cannot change a byte Codex hashes for hook trust. */
|
|
270
|
+
function codexNotifyLine(port, { shimPath = hookShimPath(port) } = {}) {
|
|
271
|
+
return `notify = [${JSON.stringify(shimPath)}, "codex-notify", "${port}", "stop"]`;
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
/** Codex's otlp-http exporter posts to the endpoint verbatim, so it must carry the OTLP logs path. */
|
|
@@ -284,7 +294,7 @@ function stripLegacyNotifyTable(text) {
|
|
|
284
294
|
scan.statements.forEach((s, idx) => {
|
|
285
295
|
if (!isPlainTable(s, 'notify')) return;
|
|
286
296
|
const body = tableBodyStatements(scan.statements, idx);
|
|
287
|
-
if (body.some((b) => stmtText(scan.lines, b)
|
|
297
|
+
if (body.some((b) => isCtmNotifyText(stmtText(scan.lines, b)))) doomed.push(...body);
|
|
288
298
|
});
|
|
289
299
|
return doomed.length ? tidyTail(linesWithout(scan.lines, doomed)) : text;
|
|
290
300
|
}
|
|
@@ -308,7 +318,7 @@ function codexPatchRefusal(scan) {
|
|
|
308
318
|
for (const s of scan.statements) {
|
|
309
319
|
if (s.kind === 'key' && s.table === null && s.key === 'notify') {
|
|
310
320
|
if (s.end > s.start) return 'notify-multiline';
|
|
311
|
-
if (!stmtText(scan.lines, s)
|
|
321
|
+
if (!isCtmNotifyText(stmtText(scan.lines, s))) return 'notify-user-value';
|
|
312
322
|
}
|
|
313
323
|
if (s.kind === 'header' && s.header.segments[0] === 'otel' && s.header.segments[1] === 'exporter') return 'otel-exporter-subtable';
|
|
314
324
|
}
|
|
@@ -322,18 +332,18 @@ function codexPatchRefusal(scan) {
|
|
|
322
332
|
*/
|
|
323
333
|
const workspaceHooks = require('./agent-hooks-codex-workspace')({ scanTomlStatements, tableBodyStatements, stmtText, linesWithout });
|
|
324
334
|
|
|
325
|
-
function patchCodexConfig(text, port) {
|
|
335
|
+
function patchCodexConfig(text, port, { shimPath = hookShimPath(port) } = {}) {
|
|
326
336
|
const input = String(text || '');
|
|
327
337
|
let scan = scanTomlStatements(input);
|
|
328
338
|
const refused = codexPatchRefusal(scan) || workspaceHooks.refusal(scan);
|
|
329
339
|
if (refused) return { text: input, changed: false, refused };
|
|
330
340
|
|
|
331
|
-
const notifyLine = codexNotifyLine(port);
|
|
341
|
+
const notifyLine = codexNotifyLine(port, { shimPath });
|
|
332
342
|
let cur = stripLegacyNotifyTable(input);
|
|
333
343
|
scan = scanTomlStatements(cur);
|
|
334
344
|
// A CTM-written notify stranded under [otel] is scoped otel.notify and never fires.
|
|
335
345
|
const stranded = scan.statements.filter((s) => s.kind === 'key' && s.key === 'notify' && s.table === 'otel'
|
|
336
|
-
&& stmtText(scan.lines, s)
|
|
346
|
+
&& isCtmNotifyText(stmtText(scan.lines, s)));
|
|
337
347
|
if (stranded.length) cur = dropStatements(scan.lines, stranded).join('\n');
|
|
338
348
|
cur = stripCtmMarkerLines(cur);
|
|
339
349
|
|
|
@@ -355,7 +365,8 @@ function patchCodexConfig(text, port) {
|
|
|
355
365
|
lines.splice(header.end + 1, 0, exporterLine);
|
|
356
366
|
cur = lines.join('\n');
|
|
357
367
|
}
|
|
358
|
-
|
|
368
|
+
// The command names the stable per-port shim, so Codex's trusted-hook hash survives a checkout move.
|
|
369
|
+
const hookCommand = `${JSON.stringify(shimPath)} codex-workspace-hook ${port} PostToolUse`;
|
|
359
370
|
cur = workspaceHooks.patch(cur, port, hookCommand);
|
|
360
371
|
return { text: cur, changed: cur !== input };
|
|
361
372
|
}
|
|
@@ -369,7 +380,7 @@ function unpatchCodexConfig(text, port) {
|
|
|
369
380
|
let scan = scanTomlStatements(cur);
|
|
370
381
|
if (!scan.balanced) return input;
|
|
371
382
|
const doomed = scan.statements.filter((s) => s.kind === 'key' && s.key === 'notify' && (s.table === null || s.table === 'otel')
|
|
372
|
-
&& stmtText(scan.lines, s)
|
|
383
|
+
&& isCtmNotifyText(stmtText(scan.lines, s)));
|
|
373
384
|
doomed.push(...scan.statements.filter((s) => s.table === 'otel' && isExporterKey(s) && stmtText(scan.lines, s).includes(`localhost:${port}`)));
|
|
374
385
|
if (doomed.length) cur = dropStatements(scan.lines, doomed).join('\n');
|
|
375
386
|
scan = scanTomlStatements(cur);
|
|
@@ -387,7 +398,8 @@ function unpatchCodexConfig(text, port) {
|
|
|
387
398
|
}
|
|
388
399
|
|
|
389
400
|
/**
|
|
390
|
-
* Boot-prune migration: move a CTM `notify = [... codex-notify.js
|
|
401
|
+
* Boot-prune migration: move a CTM `notify = [...]` line (legacy `codex-notify.js` path or the shim
|
|
402
|
+
* form's `"codex-notify"` array element) stranded under a table
|
|
391
403
|
* (the live [otel] shape) to the top level. If a top-level notify already exists the stranded
|
|
392
404
|
* copy is just dropped. Single-line values only (what the installer writes). Pure.
|
|
393
405
|
* Returns { text, moved, removed } — `removed` lists the dropped lines for logging.
|
|
@@ -398,7 +410,7 @@ function migrateCodexNotify(text) {
|
|
|
398
410
|
if (!scan.balanced || otelShapeRefusal(scan)) return { text: input, moved: false, removed: [] };
|
|
399
411
|
const topLevelNotify = scan.statements.some((s) => s.kind === 'key' && s.table === null && s.key === 'notify');
|
|
400
412
|
const doomed = scan.statements.filter((s) => s.kind === 'key' && s.key === 'notify' && s.table !== null
|
|
401
|
-
&& s.end === s.start && scan.lines[s.start]
|
|
413
|
+
&& s.end === s.start && isCtmNotifyText(scan.lines[s.start]));
|
|
402
414
|
if (!doomed.length) return { text: input, moved: false, removed: [] };
|
|
403
415
|
const removed = doomed.map((s) => ({ table: s.table, line: scan.lines[s.start].trim() }));
|
|
404
416
|
const cleaned = dropStatements(scan.lines, doomed).join('\n');
|
|
@@ -418,7 +430,7 @@ function backupCodexConfig(filePath) {
|
|
|
418
430
|
}
|
|
419
431
|
|
|
420
432
|
module.exports = {
|
|
421
|
-
codexExporterForm,
|
|
433
|
+
codexExporterForm, codexNotifyLine, isCtmNotifyText,
|
|
422
434
|
parseTomlTableHeader, stripTomlSection, stripCtmMarkerLines,
|
|
423
435
|
patchCodexConfig, unpatchCodexConfig, migrateCodexNotify, backupCodexConfig,
|
|
424
436
|
scanTomlStatements,
|
|
@@ -18,6 +18,14 @@ module.exports = function createCodexWorkspaceHooks({ scanTomlStatements, tableB
|
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// CTM-owned PostToolUse hook command for <port>, in either form CTM has ever written:
|
|
22
|
+
// legacy — node "<any checkout>/bin/codex-workspace-hook.js" <port> PostToolUse
|
|
23
|
+
// shim — "<home>/.walle/bin/ctm-hook-<port>" codex-workspace-hook <port> PostToolUse
|
|
24
|
+
// Ownership is the command shape (port-matched), never a filename anywhere in the text: a comment
|
|
25
|
+
// that merely names codex-workspace-hook.js is not an entry. Matching both forms is what makes the
|
|
26
|
+
// 2026-11-01 migration REPLACE the legacy group instead of duplicating it (design doc §5 D-6).
|
|
27
|
+
const OWNED_COMMAND = /^(?:node\s+(?:"[^"\n]*codex-workspace-hook\.js"|[^\s]*codex-workspace-hook\.js)|"[^"\n]*\/ctm-hook-\d+")\s+(?:codex-workspace-hook\s+)?(\d+)\s+PostToolUse$/;
|
|
28
|
+
|
|
21
29
|
function remove(text, port) {
|
|
22
30
|
const scan = scanTomlStatements(text);
|
|
23
31
|
if (!scan.balanced) return text;
|
|
@@ -38,7 +46,7 @@ module.exports = function createCodexWorkspaceHooks({ scanTomlStatements, tableB
|
|
|
38
46
|
const command = body.find(entry => entry.kind === 'key' && entry.key === 'command');
|
|
39
47
|
const type = body.find(entry => entry.kind === 'key' && entry.key === 'type');
|
|
40
48
|
const value = command && stringValue(scan.lines, command);
|
|
41
|
-
const match = typeof value === 'string' && value.match(
|
|
49
|
+
const match = typeof value === 'string' && value.match(OWNED_COMMAND);
|
|
42
50
|
if (match && Number(match[1]) === Number(port) && type && stringValue(scan.lines, type) === 'command') {
|
|
43
51
|
group.owned += 1;
|
|
44
52
|
doomed.push(...body);
|
|
@@ -25,7 +25,8 @@ const fs = require('fs');
|
|
|
25
25
|
const path = require('path');
|
|
26
26
|
const os = require('os');
|
|
27
27
|
const { getPreset, PRESETS } = require('./agent-presets');
|
|
28
|
-
const { codexExporterForm, patchCodexConfig, unpatchCodexConfig, stripTomlSection, backupCodexConfig } = require('./agent-hooks-codex-toml');
|
|
28
|
+
const { codexExporterForm, isCtmNotifyText, patchCodexConfig, unpatchCodexConfig, stripTomlSection, backupCodexConfig } = require('./agent-hooks-codex-toml');
|
|
29
|
+
const { hookShimPath, ensureHookShim, hookShimState, removeHookShim } = require('./agent-hooks-shim');
|
|
29
30
|
const { PLUGIN_SOURCE, MANAGED_LINE } = require('./agent-hooks-opencode-plugin');
|
|
30
31
|
|
|
31
32
|
const CTM_ROOT = path.resolve(__dirname, '..');
|
|
@@ -375,7 +376,8 @@ function planInstall(agent, port) {
|
|
|
375
376
|
...(patched.refused ? { refused: patched.refused } : {}),
|
|
376
377
|
changes: [
|
|
377
378
|
{ description: `[otel] block → http://localhost:${port}/v1/logs (OTLP/HTTP JSON)` },
|
|
378
|
-
{ description: `notify array (top-level, above the first [table]) →
|
|
379
|
+
{ description: `notify array (top-level, above the first [table]) → ${hookShimPath(port)} codex-notify ${port} stop` },
|
|
380
|
+
{ description: `[[hooks.PostToolUse]] command → ${hookShimPath(port)} codex-workspace-hook ${port} PostToolUse` },
|
|
379
381
|
],
|
|
380
382
|
};
|
|
381
383
|
}
|
|
@@ -442,9 +444,18 @@ function applyPlan(plan) {
|
|
|
442
444
|
return { written: true, filePath: plan.filePath, bytes: plan.nextText.length };
|
|
443
445
|
}
|
|
444
446
|
|
|
445
|
-
/** Convenience for tests / CLI: install = plan + apply.
|
|
446
|
-
|
|
447
|
-
function
|
|
447
|
+
/** Convenience for tests / CLI: install = plan + apply. Codex writes its per-port shim first (a config must
|
|
448
|
+
* never name a shim CTM could not create; a refused plan writes nothing); uninstall drops the shim. */
|
|
449
|
+
function install(agent, port) {
|
|
450
|
+
const plan = planInstall(agent, port);
|
|
451
|
+
if (agent === 'codex' && !plan.refused) ensureHookShim({ port });
|
|
452
|
+
return applyPlan(plan);
|
|
453
|
+
}
|
|
454
|
+
function uninstall(agent, port) {
|
|
455
|
+
const result = applyPlan(planUninstall(agent, port));
|
|
456
|
+
if (agent === 'codex') removeHookShim({ port });
|
|
457
|
+
return result;
|
|
458
|
+
}
|
|
448
459
|
|
|
449
460
|
// ─── hookStatus: structural, never a marker ───────────────────────────────
|
|
450
461
|
|
|
@@ -483,9 +494,13 @@ function hookStatus(agent, port) {
|
|
|
483
494
|
try {
|
|
484
495
|
if (agent === 'codex') {
|
|
485
496
|
const { text } = readCodexConfig();
|
|
486
|
-
//
|
|
487
|
-
|
|
488
|
-
|
|
497
|
+
// Plan-equality, not a shape probe (design codex-hook-stable-shim-trust-safe-self-repair-2026-11-01 D-2):
|
|
498
|
+
// `outdated` whenever the idempotent patcher would change a byte or the shim body drifted; a
|
|
499
|
+
// refusal carries `error`, which refreshOutdatedHooks never writes.
|
|
500
|
+
if (!isCtmNotifyText(text) || !codexExporterForm(text, port)) return { state: 'missing', ...base };
|
|
501
|
+
const plan = planInstall('codex', port);
|
|
502
|
+
const drift = plan.willWrite || hookShimState({ port }) !== 'current';
|
|
503
|
+
return { state: drift ? 'outdated' : 'installed', ...base, ...(plan.refused ? { error: `refused:${plan.refused}` } : {}) };
|
|
489
504
|
}
|
|
490
505
|
if (preset.configFormat === 'plugin') {
|
|
491
506
|
const { text, managed } = readOpencodePlugin(preset);
|