create-walle 0.10.1 → 0.10.2
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 +4 -0
- package/lib/owner-write-safety.js +135 -0
- package/lib/public-runtime.js +13 -5
- package/lib/release-schema.json +3 -2
- package/lib/runtime-closure-policy.json +6 -4
- package/package.json +1 -1
- package/template/bin/deps-doctor.js +1 -1
- package/template/bin/node-bin.sh +11 -0
- package/template/coding-task-manager/api-prompts.js +10 -22
- package/template/coding-task-manager/bin/claude-hook.js +7 -3
- package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
- package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
- package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
- package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
- package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
- package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
- package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
- package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
- package/template/coding-task-manager/db.js +705 -286
- package/template/coding-task-manager/git-utils.js +44 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
- package/template/coding-task-manager/lib/agent-presets.js +15 -0
- package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
- package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
- package/template/coding-task-manager/lib/api/host-stats.js +98 -0
- package/template/coding-task-manager/lib/api/ingress.js +35 -12
- package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
- package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
- package/template/coding-task-manager/lib/api/machines.js +461 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
- package/template/coding-task-manager/lib/api/providers.js +53 -6
- package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
- package/template/coding-task-manager/lib/api/sessions.js +160 -8
- package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
- package/template/coding-task-manager/lib/api/worktrees.js +38 -37
- package/template/coding-task-manager/lib/approval-drift.js +16 -1
- package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
- package/template/coding-task-manager/lib/approval-scope.js +68 -4
- package/template/coding-task-manager/lib/auth-context.js +32 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
- package/template/coding-task-manager/lib/auth-rules.js +186 -45
- package/template/coding-task-manager/lib/broadcast-serialize.js +2 -1
- package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
- package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
- package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
- package/template/coding-task-manager/lib/claude-session-title.js +6 -30
- package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
- package/template/coding-task-manager/lib/client-diag-handler.js +5 -0
- package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
- package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
- package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
- package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
- package/template/coding-task-manager/lib/codex-paths.js +2 -1
- package/template/coding-task-manager/lib/coding-agent-models.js +21 -30
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
- package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
- package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
- package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
- package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
- package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
- package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
- package/template/coding-task-manager/lib/db-domains.js +21 -2
- package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
- package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
- package/template/coding-task-manager/lib/feature-manifest.js +1 -1
- package/template/coding-task-manager/lib/fs-watcher.js +3 -2
- package/template/coding-task-manager/lib/harness-history-transition.js +3 -3
- package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
- package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
- package/template/coding-task-manager/lib/headless-term-service.js +55 -17
- package/template/coding-task-manager/lib/host-control-dial.js +167 -0
- package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
- package/template/coding-task-manager/lib/host-handoff.js +51 -13
- package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
- package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
- package/template/coding-task-manager/lib/host-stats.js +328 -0
- package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
- package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
- package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
- package/template/coding-task-manager/lib/hosted-sync-worker.js +113 -5
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
- package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
- package/template/coding-task-manager/lib/instance-manifest.js +13 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
- package/template/coding-task-manager/lib/launch-model-override.js +160 -1
- package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
- package/template/coding-task-manager/lib/lead-model-switch.js +3 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
- package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
- package/template/coding-task-manager/lib/login-tripwire.js +1 -0
- package/template/coding-task-manager/lib/machine-pairing.js +238 -0
- package/template/coding-task-manager/lib/machine-pool.js +409 -0
- package/template/coding-task-manager/lib/machine-registry.js +749 -0
- package/template/coding-task-manager/lib/machine-self.js +66 -0
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +52 -4
- package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
- package/template/coding-task-manager/lib/media-journal.js +84 -27
- package/template/coding-task-manager/lib/media-store-options.js +43 -15
- package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
- package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
- package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
- package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
- package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
- package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
- package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
- package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-history-control.js +2 -2
- package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
- package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
- package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
- package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
- package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
- package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
- package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
- package/template/coding-task-manager/lib/read-pool-client.js +5 -2
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
- package/template/coding-task-manager/lib/remote-command-context.js +12 -0
- package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
- package/template/coding-task-manager/lib/remote-machine-catalog.js +1062 -0
- package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
- package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
- package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
- package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
- package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
- package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
- package/template/coding-task-manager/lib/restart-preflight.js +9 -2
- package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
- package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
- package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
- package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
- package/template/coding-task-manager/lib/resume-cwd.js +13 -0
- package/template/coding-task-manager/lib/resume-from-store.js +12 -1
- package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
- package/template/coding-task-manager/lib/resume-preflight.js +21 -16
- package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
- package/template/coding-task-manager/lib/review-repo-registry.js +17 -0
- package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
- package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
- package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +167 -33
- package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
- package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
- package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
- package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +95 -6
- package/template/coding-task-manager/lib/session-create/identity.js +20 -1
- package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
- package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
- package/template/coding-task-manager/lib/session-create/provider-process.js +34 -37
- package/template/coding-task-manager/lib/session-create/response.js +30 -12
- package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
- package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
- package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
- package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
- package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
- package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
- package/template/coding-task-manager/lib/session-host-manager.js +152 -206
- package/template/coding-task-manager/lib/session-jobs.js +17 -9
- package/template/coding-task-manager/lib/session-lifecycle.js +18 -0
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +9 -0
- package/template/coding-task-manager/lib/session-resource-sampler.js +19 -9
- package/template/coding-task-manager/lib/session-standup.js +67 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +42 -3
- package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
- package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
- package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
- package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
- package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +21 -22
- package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
- package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
- package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
- package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
- package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
- package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
- package/template/coding-task-manager/lib/transcript-link.js +77 -0
- package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
- package/template/coding-task-manager/lib/transcript-source.js +8 -3
- package/template/coding-task-manager/lib/transcript-store.js +40 -0
- package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
- package/template/coding-task-manager/lib/typing-interaction-trace.js +92 -0
- package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
- package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
- package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
- package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
- package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -1
- package/template/coding-task-manager/lib/ws-router.js +68 -1
- package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
- package/template/coding-task-manager/oauth-proxy.js +99 -55
- package/template/coding-task-manager/package-lock.json +24 -0
- package/template/coding-task-manager/package.json +3 -0
- package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
- package/template/coding-task-manager/providers/codex-mcp.js +14 -5
- package/template/coding-task-manager/public/css/app.css +279 -1
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/index.html +294 -223
- package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
- package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
- package/template/coding-task-manager/public/js/background-work.js +13 -7
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
- package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
- package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
- package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
- package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
- package/template/coding-task-manager/public/js/history-scroller.js +187 -9
- package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
- package/template/coding-task-manager/public/js/machine-pool-shared.js +436 -0
- package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
- package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
- package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
- package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
- package/template/coding-task-manager/public/js/reviews.js +7 -3
- package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
- package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
- package/template/coding-task-manager/public/js/row-join.js +4 -2
- package/template/coding-task-manager/public/js/session-model-picker.js +1 -1
- package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
- package/template/coding-task-manager/public/js/state-sync-client.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
- package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
- package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +52 -2
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -12
- package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
- package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +210 -73
- package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
- package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
- package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
- package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
- package/template/coding-task-manager/public/js/walle-session.js +30 -7
- package/template/coding-task-manager/public/m/app.css +226 -8
- package/template/coding-task-manager/public/m/app.js +502 -9
- package/template/coding-task-manager/public/m/index.html +38 -1
- package/template/coding-task-manager/public/m/machines.js +1313 -0
- package/template/coding-task-manager/public/m/pool-failover.js +391 -0
- package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
- package/template/coding-task-manager/public/m/sw.js +5 -0
- package/template/coding-task-manager/queue-engine.js +13 -0
- package/template/coding-task-manager/server/approvals.js +5 -6
- package/template/coding-task-manager/server/boot.js +136 -17
- package/template/coding-task-manager/server.js +902 -239
- package/template/coding-task-manager/session-integrity.js +7 -9
- package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
- package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
- package/template/coding-task-manager/workers/session-host-process.js +14 -3
- package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
- package/template/coding-task-manager/workers/worktree-worker.js +34 -0
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/scripts/conversation-storage-v2-migration.js +78 -11
- package/template/shared/conversation-storage-v2-contract.js +42 -6
- package/template/shared/fixtures/worker-status-payloads.json +392 -0
- package/template/shared/git-remote-key.js +83 -0
- package/template/shared/host-identity.js +98 -2
- package/template/shared/owner-write-safety.js +135 -0
- package/template/shared/public-runtime.js +13 -5
- package/template/shared/release-schema.json +3 -2
- package/template/shared/report-citations.js +14 -0
- package/template/shared/sqlite-write-lock.js +361 -223
- package/template/shared/storage/contract.js +35 -3
- package/template/wall-e/agent.js +21 -0
- package/template/wall-e/api-walle.js +5 -0
- package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
- package/template/wall-e/brain/helper-rules-schema.js +129 -0
- package/template/wall-e/brain/migrations.js +51 -22
- package/template/wall-e/brain/model-deployment-facts.js +31 -1
- package/template/wall-e/brain/owner-call-whitelist.js +16 -0
- package/template/wall-e/brain/schema-ensures.js +22 -0
- package/template/wall-e/brain.js +1 -1
- package/template/wall-e/coding/journal-dispatcher.js +51 -0
- package/template/wall-e/coding/session-journal.js +28 -40
- package/template/wall-e/coding-orchestrator.js +23 -26
- package/template/wall-e/http/auth.js +18 -1
- package/template/wall-e/http/blog-views-api.js +318 -0
- package/template/wall-e/http/helper-rules-api.js +321 -0
- package/template/wall-e/http/model-proxy-providers.js +3 -1
- package/template/wall-e/http/telemetry-api.js +12 -0
- package/template/wall-e/lib/blog-view-policy.js +88 -0
- package/template/wall-e/lib/blog-view-store.js +169 -0
- package/template/wall-e/lib/client-config-lock.js +2 -1
- package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
- package/template/wall-e/lib/error-kinds.js +10 -1
- package/template/wall-e/lib/feature-manifest.js +1 -1
- package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +357 -0
- package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
- package/template/wall-e/lib/helper-rules/grade.js +277 -0
- package/template/wall-e/lib/helper-rules/label.js +247 -0
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
- package/template/wall-e/lib/helper-rules/store.js +667 -0
- package/template/wall-e/lib/mcp-integration.js +5 -6
- package/template/wall-e/lib/runtime-worker-pool.js +1 -0
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
- package/template/wall-e/lib/telemetry-db-schema.js +37 -0
- package/template/wall-e/lib/telemetry-process-client.js +76 -1
- package/template/wall-e/llm/default-fallback.js +4 -0
- package/template/wall-e/llm/model-catalog.js +13 -4
- package/template/wall-e/llm/model-roles.js +6 -0
- package/template/wall-e/llm/portkey-http.js +150 -0
- package/template/wall-e/llm/portkey-sync.js +15 -145
- package/template/wall-e/llm/worker-mcp-routing.js +61 -0
- package/template/wall-e/llm/worker-route.js +43 -1
- package/template/wall-e/loops/brain-custom-writes.js +45 -0
- package/template/wall-e/mcp-protocol-contract.js +41 -1
- package/template/wall-e/mcp-server.js +13 -2
- package/template/wall-e/mcp-worker-schemas.js +20 -2
- package/template/wall-e/memory/ctm-context-client.js +25 -5
- package/template/wall-e/shared/release-schema.json +3 -2
- package/template/wall-e/shared/sqlite-write-lock.js +361 -223
- package/template/wall-e/shared/storage/contract.js +35 -3
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
- package/template/wall-e/tools/local-tools.js +6 -4
- package/template/wall-e/workers/brain-owner-worker.js +9 -0
- package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
- package/template/wall-e/workers/telemetry-worker.js +8 -0
|
@@ -26,6 +26,13 @@ const PROJECT_TRUST_ENV = 'CTM_CODEX_PROJECT_TRUST';
|
|
|
26
26
|
const HTTP_TRANSPORT_ENV = 'CTM_CODEX_HTTP_TRANSPORT';
|
|
27
27
|
const HTTP_TRANSPORT_PROVIDER_ID = 'ctm-openai-https';
|
|
28
28
|
|
|
29
|
+
// WP-2 (lead-cost-routing-round1-2026-10-21.html §5 D-6): a Codex LEAD calls Wall-E's MCP tools
|
|
30
|
+
// as direct function calls instead of invoking them from inside a code-mode `exec` script, so a
|
|
31
|
+
// long `walle_worker_wait` is a real client-side MCP call the client can hold. The key lives
|
|
32
|
+
// under `[features.code_mode]` (`features.code_mode.direct_only_tool_namespaces`, verified on
|
|
33
|
+
// codex-cli 0.162.1). Codex WORKERS never carry it -- they are denied walle_worker_wait anyway.
|
|
34
|
+
const CODEX_LEAD_DIRECT_TOOL_ARGS = Object.freeze(['-c', 'features.code_mode.direct_only_tool_namespaces=["mcp__wall_e"]']);
|
|
35
|
+
|
|
29
36
|
function isCodexCommand(cmd) {
|
|
30
37
|
return path.basename(String(cmd || '')).toLowerCase() === 'codex';
|
|
31
38
|
}
|
|
@@ -527,6 +534,20 @@ function applyCodexHttpTransportOverride(args, options = {}) {
|
|
|
527
534
|
};
|
|
528
535
|
}
|
|
529
536
|
|
|
537
|
+
// WP-2 (D-6): the lead-only direct-tool namespace, its own prepareCodexLaunch step so it does not
|
|
538
|
+
// depend on the HTTP-transport flag (off by default). A LEAD is the launch that reaches
|
|
539
|
+
// prepareCodexLaunch with no model_provider override: every Codex worker already carries one
|
|
540
|
+
// (codexWorkerProviderArgs, resolve-launch-params.js), while a routed lead gets its override later
|
|
541
|
+
// in provider-process.js's argsTransform. Idempotent: a pair already present is never doubled.
|
|
542
|
+
function applyCodexLeadDirectToolArgs(args) {
|
|
543
|
+
const originalArgs = Array.isArray(args) ? args.slice() : [];
|
|
544
|
+
if (argsContainCodexModelProviderOverride(originalArgs)) return { args: originalArgs, added: false, skipped: 'worker_provider_override' };
|
|
545
|
+
if (originalArgs.some((value) => String(value).startsWith('features.code_mode.direct_only_tool_namespaces='))) {
|
|
546
|
+
return { args: originalArgs, added: false, skipped: 'already_configured' };
|
|
547
|
+
}
|
|
548
|
+
return { args: [...CODEX_LEAD_DIRECT_TOOL_ARGS, ...originalArgs], added: true };
|
|
549
|
+
}
|
|
550
|
+
|
|
530
551
|
function argsContainProjectTrustOverride(args, projectPath) {
|
|
531
552
|
const resolved = path.resolve(String(projectPath || '').trim());
|
|
532
553
|
const quoted = JSON.stringify(resolved);
|
|
@@ -842,7 +863,10 @@ function prepareCodexLaunch(options = {}) {
|
|
|
842
863
|
// in this branch.
|
|
843
864
|
const _cfgStartedAt = Date.now();
|
|
844
865
|
const projectTrustReport = applyProjectTrustOverride(args, options);
|
|
845
|
-
|
|
866
|
+
// WP-2 (D-6): the lead step runs BEFORE the transport step -- the transport override is itself a
|
|
867
|
+
// model_provider block, and only a WORKER's override (present before the launch plan) means skip.
|
|
868
|
+
const leadDirectReport = applyCodexLeadDirectToolArgs(projectTrustReport.args);
|
|
869
|
+
const transportReport = applyCodexHttpTransportOverride(leadDirectReport.args, options);
|
|
846
870
|
const missingEnvReport = applyMissingMcpEnvOverrides(transportReport.args, options);
|
|
847
871
|
const learnedMcpReport = applyLearnedMcpFailureOverrides(missingEnvReport.args, options);
|
|
848
872
|
const cfgMs = Date.now() - _cfgStartedAt;
|
|
@@ -856,7 +880,7 @@ function prepareCodexLaunch(options = {}) {
|
|
|
856
880
|
learned: learnedMcpReport,
|
|
857
881
|
};
|
|
858
882
|
return {
|
|
859
|
-
args: mcpReport.args, skillReport, mcpReport, projectTrustReport, transportReport,
|
|
883
|
+
args: mcpReport.args, skillReport, mcpReport, projectTrustReport, transportReport, leadDirectReport,
|
|
860
884
|
timings: { skillWalkMs, cfgMs },
|
|
861
885
|
};
|
|
862
886
|
}
|
|
@@ -962,6 +986,8 @@ module.exports = {
|
|
|
962
986
|
MCP_FAILURE_TTL_MS,
|
|
963
987
|
QUARANTINE_TTL_STARTUP_MS,
|
|
964
988
|
MCP_READINESS_PROBE_TIMEOUT_MS,
|
|
989
|
+
CODEX_LEAD_DIRECT_TOOL_ARGS,
|
|
990
|
+
applyCodexLeadDirectToolArgs,
|
|
965
991
|
applyLearnedMcpFailureOverrides,
|
|
966
992
|
applyMissingMcpEnvOverrides,
|
|
967
993
|
applyCodexHttpTransportOverride,
|
|
@@ -980,6 +1006,7 @@ module.exports = {
|
|
|
980
1006
|
argsContainCodexModelProviderOverride,
|
|
981
1007
|
applyCodexHttpTransportOverride,
|
|
982
1008
|
applyMissingMcpEnvOverrides,
|
|
1009
|
+
CODEX_LEAD_DIRECT_TOOL_ARGS,
|
|
983
1010
|
applyProjectTrustOverride,
|
|
984
1011
|
argsContainProjectTrustOverride,
|
|
985
1012
|
codexHttpTransportConfigArgs,
|
|
@@ -97,15 +97,16 @@ async function prepareCodexLink(payload, db, assertLive = () => {}) {
|
|
|
97
97
|
assertLive();
|
|
98
98
|
const resumeId = thread?.id || payload.threadId;
|
|
99
99
|
if (!resumeId) return { status, thread, known, resolved: null, modelTruth: null };
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
// The verified native state path already has precedence in findCodexSessionFiles. It does not
|
|
101
|
+
// depend on a global index refresh. Missing/mismatched native state still needs the async index
|
|
102
|
+
// recovery: an index-only miss must not leave a discoverable rollout linked as identity-only.
|
|
103
|
+
let rolloutPath = history.findCodexStateRolloutPath(resumeId, payload.homeDir);
|
|
104
|
+
if (!rolloutPath || !history.codexRolloutFileMatchesThread(rolloutPath, resumeId)) {
|
|
105
|
+
await history.ensureCodexRolloutIndex(payload.homeDir);
|
|
106
|
+
assertLive();
|
|
107
|
+
rolloutPath = history.findCodexSessionFiles(resumeId, null, payload.homeDir, { indexOnly: true })[0] || '';
|
|
108
|
+
}
|
|
107
109
|
assertLive();
|
|
108
|
-
const rolloutPath = history.findCodexSessionFiles(resumeId, null, payload.homeDir, { indexOnly: true })[0] || '';
|
|
109
110
|
const observation = await observeCodexRollout(rolloutPath, db, assertLive);
|
|
110
111
|
assertLive();
|
|
111
112
|
const agentSessionId = history.codexRolloutIdFromPath(rolloutPath) || resumeId;
|
|
@@ -26,6 +26,7 @@ const fs = require('fs');
|
|
|
26
26
|
const path = require('path');
|
|
27
27
|
const os = require('os');
|
|
28
28
|
const crypto = require('crypto');
|
|
29
|
+
const { isWritableOnlyByOwner } = require('../../shared/owner-write-safety');
|
|
29
30
|
|
|
30
31
|
function homeBase(homeDir) {
|
|
31
32
|
return homeDir || process.env.HOME || process.env.USERPROFILE || os.homedir() || '';
|
|
@@ -77,7 +78,7 @@ function resolveCodexSessionsRoot(options = {}) {
|
|
|
77
78
|
out.refusalCode = 'wrong-owner';
|
|
78
79
|
return out;
|
|
79
80
|
}
|
|
80
|
-
if ((
|
|
81
|
+
if (!isWritableOnlyByOwner(stat)) {
|
|
81
82
|
out.validationStatus = 'refused';
|
|
82
83
|
out.refusalCode = 'unsafe-permissions';
|
|
83
84
|
return out;
|
|
@@ -288,18 +288,6 @@ function isGenericCodingSessionLabel(label, agentType = 'codex') {
|
|
|
288
288
|
|| lower === 'session';
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
function shouldApplyCodexAutoTitle({ session, existingTitle } = {}) {
|
|
292
|
-
if (existingTitle && existingTitle.userRenamed) return false;
|
|
293
|
-
for (const candidate of [session?.label, existingTitle?.title]) {
|
|
294
|
-
const text = normalizeTitleText(candidate);
|
|
295
|
-
if (text && !/^Codex:\s*/i.test(text) && !isGenericCodingSessionLabel(text, 'codex')) return false;
|
|
296
|
-
}
|
|
297
|
-
const title = normalizeTitleText(existingTitle?.title || session?.label || '');
|
|
298
|
-
if (!title) return true;
|
|
299
|
-
if (/^Codex:\s*/i.test(title) && !isGenericCodingSessionLabel(title, 'codex')) return true;
|
|
300
|
-
return isGenericCodingSessionLabel(title, 'codex');
|
|
301
|
-
}
|
|
302
|
-
|
|
303
291
|
function resolveModelToRegistry(modelName) {
|
|
304
292
|
if (!modelName) return null;
|
|
305
293
|
let provider = null;
|
|
@@ -561,11 +549,23 @@ function createCodingAgentModelSync({
|
|
|
561
549
|
if (!modelStateRuntime) _persistSessionModel(session, model);
|
|
562
550
|
changed = true;
|
|
563
551
|
}
|
|
564
|
-
if (agentType === 'codex'
|
|
552
|
+
if (agentType === 'codex') {
|
|
565
553
|
const existingTitle = titlesById.get(session.id) || null;
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
554
|
+
// WP-4/D-10: the thread's OWN name (threads.name) is read on EVERY tick — there is no
|
|
555
|
+
// one-shot `_codexTitleSynced` latch any more, and no title-vs-label precedence test that
|
|
556
|
+
// could let a CTM title block the name (S-22). applyProviderTitle owns the tier rules: it
|
|
557
|
+
// re-asserts a drifted tier-1 (user-renamed) row outward, skips a row already carrying this
|
|
558
|
+
// exact name, and writes the agent name over an older tier-2/tier-3 title.
|
|
559
|
+
const agentName = session._claudeSessionId ? getCodexThreadAgentName(session._claudeSessionId) : '';
|
|
560
|
+
if (agentName) {
|
|
561
|
+
const outcome = applyProviderTitle({ db: dbModule, sessionId: session.id, provider: 'codex', agentName }); // not a dbModule method — no dispatchOwnerMutation
|
|
562
|
+
if (outcome.applied === 'agent') {
|
|
563
|
+
session.label = `Codex: ${agentName}`;
|
|
564
|
+
changed = true;
|
|
565
|
+
}
|
|
566
|
+
} else {
|
|
567
|
+
// No thread name at all: the CTM live label is the only signal left, so it repairs a
|
|
568
|
+
// stale auto-title. Never a tier-2 (`provider_title`) row, never the user's own name.
|
|
569
569
|
const liveLabel = normalizeTitleText(session.label);
|
|
570
570
|
if (liveLabel
|
|
571
571
|
&& !isGenericCodingSessionLabel(liveLabel, 'codex')
|
|
@@ -573,16 +573,6 @@ function createCodingAgentModelSync({
|
|
|
573
573
|
dispatchOwnerMutation(dbModule, 'setSessionTitleNew', [session.id, liveLabel, false], 'coding-agent title');
|
|
574
574
|
changed = true;
|
|
575
575
|
}
|
|
576
|
-
session._codexTitleSynced = true;
|
|
577
|
-
} else {
|
|
578
|
-
// Requires the exact Codex thread id — cwd/spawn-time matching is unsafe for periodic refresh.
|
|
579
|
-
const agentName = session._claudeSessionId ? getCodexThreadAgentName(session._claudeSessionId) : '';
|
|
580
|
-
if (agentName) {
|
|
581
|
-
session.label = `Codex: ${agentName}`;
|
|
582
|
-
session._codexTitleSynced = true;
|
|
583
|
-
applyProviderTitle({ db: dbModule, sessionId: session.id, provider: 'codex', agentName }); // not a dbModule method — no dispatchOwnerMutation
|
|
584
|
-
changed = true;
|
|
585
|
-
}
|
|
586
576
|
}
|
|
587
577
|
}
|
|
588
578
|
}
|
|
@@ -688,7 +678,7 @@ function createCodingAgentModelSync({
|
|
|
688
678
|
if (agentType === 'gemini' && !modelStateRuntime) {
|
|
689
679
|
context.result = { id: session.id, modelName: _modelArgValue(session.args) };
|
|
690
680
|
} else {
|
|
691
|
-
const item = { id: session.id, agentType, directory: session.cwd || (session.meta && session.meta.cwd) || '', knownSourceRevision: agentType === 'opencode' ? modelSyncState.knownSourceRevision(session.id) : '', claudeJsonlPath, codexThreadId: agentType === 'codex' ? (session._providerResumeId || session._claudeSessionId || '') : (session._claudeSessionId || session._providerResumeId || null), wantCodexTitle: agentType === 'codex' &&
|
|
681
|
+
const item = { id: session.id, agentType, directory: session.cwd || (session.meta && session.meta.cwd) || '', knownSourceRevision: agentType === 'opencode' ? modelSyncState.knownSourceRevision(session.id) : '', claudeJsonlPath, codexThreadId: agentType === 'codex' ? (session._providerResumeId || session._claudeSessionId || '') : (session._claudeSessionId || session._providerResumeId || null), wantCodexTitle: agentType === 'codex' && !!(session._providerResumeId || session._claudeSessionId) }; // WP-4/D-10: no one-shot latch gates the name read
|
|
692
682
|
if (modelStateRuntime) {
|
|
693
683
|
Object.assign(item, { owner: context.ownerSnapshot, providerSessionId: context.ownerSnapshot.providerSessionId, processGeneration: context.ownerSnapshot.processGeneration, providerEnv: modelProviderEnv(session), geminiTranscriptPath: session._geminiTranscriptPath || '' });
|
|
694
684
|
// The pre-await half of the source binding, and the prior checkpoint this request may carry.
|
|
@@ -758,7 +748,7 @@ function createCodingAgentModelSync({
|
|
|
758
748
|
&& (session.model_id !== model.model_id || session.model_provider !== model.model_provider);
|
|
759
749
|
if (agentType === 'claude' && model) claudeResolved += 1; if (modelChanged && session.model_id && String(session.model_source || '') === 'db:restore') repairedStamps += 1; // I-6: ONLY a stamp still carrying the pre-apply db:restore provenance is a repair; a mid-session /model switch on a live-sourced row is a normal change
|
|
760
750
|
const truthChanged = _claudeTruthNeedsApply(session, truth);
|
|
761
|
-
const needsTitleDecision = agentType === 'codex'
|
|
751
|
+
const needsTitleDecision = agentType === 'codex'; // WP-4/D-10: a title decision is taken on every probe, never once
|
|
762
752
|
// Codex: the effort of the rollout's latest turn_context (observed, never requested).
|
|
763
753
|
const codexEffortChanged = agentType === 'codex' && result.modelEffort !== undefined
|
|
764
754
|
&& String(session.model_effort || '') !== String(result.modelEffort || '');
|
|
@@ -853,7 +843,9 @@ function createCodingAgentModelSync({
|
|
|
853
843
|
changed = true;
|
|
854
844
|
}
|
|
855
845
|
}
|
|
856
|
-
|
|
846
|
+
// entry.titleSynced is the batch's "the title decision ran" receipt (the completion cache
|
|
847
|
+
// below and the durable applier's latch both consume it); the session no longer carries a
|
|
848
|
+
// one-shot `_codexTitleSynced` gate of its own.
|
|
857
849
|
const complete = (!context.intent.modelId || entry.modelPersisted)
|
|
858
850
|
&& (agentType !== 'codex' || entry.titleSynced);
|
|
859
851
|
if (complete) modelSyncState.cacheCompletedContext(context);
|
|
@@ -942,5 +934,4 @@ module.exports = {
|
|
|
942
934
|
opencodeDataDbPath,
|
|
943
935
|
isGenericCodingSessionLabel,
|
|
944
936
|
resolveModelToRegistry,
|
|
945
|
-
shouldApplyCodexAutoTitle,
|
|
946
937
|
};
|
|
@@ -3,9 +3,28 @@
|
|
|
3
3
|
// Pure decoders for native provider evidence. These functions deliberately do no discovery or I/O.
|
|
4
4
|
const SYNTHETIC = '<synthetic>';
|
|
5
5
|
const { CLAUDE_ALIASES } = require('./claude-model-selection-vocabulary');
|
|
6
|
+
const { WORKER_MODEL_ALIAS } = require('./model-proxy/lead-worker-picks');
|
|
6
7
|
const ALIASES = new Set([...CLAUDE_ALIASES, 'default']);
|
|
7
8
|
const GEMINI_ALIASES = new Set(['auto', 'default', 'pro', 'flash', 'flash-lite']);
|
|
8
9
|
|
|
10
|
+
/*
|
|
11
|
+
* The ONE reserved delegate alias (WORKER_MODEL_ALIAS in lib/model-proxy/lead-worker-picks.js). It names
|
|
12
|
+
* what a lead's SUBAGENTS ask the proxy for -- never a model a session's own CLI runs -- so it is
|
|
13
|
+
* refused by VALUE (trimmed, case-insensitive) before any producer can hand it to the ledger as a
|
|
14
|
+
* lead fact. Normal CLI aliases and policies keep their existing behavior.
|
|
15
|
+
*
|
|
16
|
+
* The value is normalised through the SAME one marker rule `modelClass` applies below:
|
|
17
|
+
* The reserved alias with `[1m]` is wearing the session's context marker, not a different
|
|
18
|
+
* model, so it can never be a lead fact either. Exactly one marker, and no blacklist of lookalikes
|
|
19
|
+
* (lookalikes, `claude-opus-5-5[1m]` and every real id keep their existing behavior).
|
|
20
|
+
*/
|
|
21
|
+
function isReservedWorkerModel(value) {
|
|
22
|
+
if (typeof value !== 'string') return false;
|
|
23
|
+
const folded = value.trim().toLowerCase();
|
|
24
|
+
const base = folded.endsWith('[1m]') ? folded.slice(0, -4) : folded;
|
|
25
|
+
return base === WORKER_MODEL_ALIAS;
|
|
26
|
+
}
|
|
27
|
+
|
|
9
28
|
function bounded(value, required = false) {
|
|
10
29
|
if (typeof value !== 'string') return null;
|
|
11
30
|
const valueTrimmed = value.trim();
|
|
@@ -46,6 +65,7 @@ function emit(out, args) { const item = observation(...args); if (item) out.push
|
|
|
46
65
|
function modelClass(raw) {
|
|
47
66
|
const name = bounded(raw, true);
|
|
48
67
|
if (!name) return null;
|
|
68
|
+
if (isReservedWorkerModel(name)) return null;
|
|
49
69
|
const suffix = name.toLowerCase().endsWith('[1m]') ? '[1m]' : '';
|
|
50
70
|
const base = suffix ? name.slice(0, -4) : name;
|
|
51
71
|
const folded = base.toLowerCase();
|
|
@@ -165,7 +185,9 @@ function codexSettingsCandidate(owner, rec, index, resumeId) {
|
|
|
165
185
|
if (rec.type !== 'event_msg' || p.type !== 'thread_settings_applied' || !p.thread_id ||
|
|
166
186
|
(p.thread_id !== owner.providerSessionId && p.thread_id !== resumeId) || !p.thread_settings) return null;
|
|
167
187
|
const model = bounded(p.thread_settings.model, true);
|
|
168
|
-
|
|
188
|
+
// Codex carries the same reserved alias in its thread settings and turn contexts when a lead's
|
|
189
|
+
// subagents are routed through the proxy; neither can be the lead's own model (AC-0d).
|
|
190
|
+
if (!model || isReservedWorkerModel(model)) return null;
|
|
169
191
|
const ordinal = Number.isSafeInteger(rec.ordinal) && rec.ordinal >= 0 ? String(rec.ordinal) : null;
|
|
170
192
|
return { at: time(rec.timestamp), index, value: model, effort: p.thread_settings.reasoning_effort ?? null,
|
|
171
193
|
sourceRevision: ordinal, source: 'codex:thread-settings' };
|
|
@@ -186,6 +208,7 @@ function codexTurnContextCandidate(owner, rec, index, resumeId) {
|
|
|
186
208
|
if (!(rec.type === 'turn_context' || (rec.type === 'event_msg' && p.type === 'turn_context'))) return null;
|
|
187
209
|
const model = bounded(p.model ?? p.model_id, true);
|
|
188
210
|
const turnId = p.turn_id == null ? null : String(p.turn_id);
|
|
211
|
+
if (isReservedWorkerModel(model)) return null;
|
|
189
212
|
return { at: time(rec.timestamp), index, payload: p, model, turnId };
|
|
190
213
|
}
|
|
191
214
|
|
|
@@ -297,4 +320,6 @@ module.exports = { claudeModelObservations, claudeHookModelObservations, codexMo
|
|
|
297
320
|
laterRank: later, isCodexRelatedRecord, codexThreadMatches,
|
|
298
321
|
claudeIdentityCandidate, claudeTurnCandidate, claudeIdentityObservations, claudeTurnObservations,
|
|
299
322
|
codexSettingsCandidate, codexSettingsObservations, codexTurnContextCandidate, codexTerminalCandidate,
|
|
300
|
-
codexTurnObservations
|
|
323
|
+
codexTurnObservations,
|
|
324
|
+
// WP-0: the one shared "is this the reserved delegate alias?" predicate (see the doc comment above).
|
|
325
|
+
isReservedWorkerModel };
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isReservedWorkerModel } = require('./coding-session-model-adapters');
|
|
4
|
+
|
|
3
5
|
const PRIORITY = Object.freeze({ resolved: 3, lastCompletedTurn: 2, selection: 1 });
|
|
4
6
|
const MODEL_RESULT_PAGE_SIZE = 8;
|
|
5
7
|
const MAX_MODEL_RESULT_BYTES = 1024 * 1024;
|
|
6
8
|
|
|
7
9
|
function concrete(fact, allowNullKind) {
|
|
8
10
|
return !!fact && typeof fact.value === 'string' && fact.value.trim() !== '' && Buffer.byteLength(fact.value.trim(), 'utf8') <= 256 && !fact.value.includes('<synthetic>') && Number.isFinite(fact.observedAtMs) && fact.observedAtMs >= 0 &&
|
|
11
|
+
// WP-0 (AC-0c): a historical row may still HOLD the reserved alias (it is kept for audit), but it
|
|
12
|
+
// is never a compatibility model -- the real selection/turn wins by the existing precedence below.
|
|
13
|
+
!isReservedWorkerModel(fact.value) &&
|
|
9
14
|
(fact.selectionKind === 'concrete' || (allowNullKind && fact.selectionKind === null));
|
|
10
15
|
}
|
|
11
16
|
|
|
@@ -1470,7 +1470,7 @@ function createDurableModelResultApplier({ modelStateRuntime, isCurrent, isOwner
|
|
|
1470
1470
|
context.capturedSignature = refreshSignature(context.session, context.agentType);
|
|
1471
1471
|
if (context.agentType === 'opencode' && context.result.sourceRevision) context.nextSourceRevision = String(context.result.sourceRevision);
|
|
1472
1472
|
cacheCompleted(context);
|
|
1473
|
-
if (context.agentType === 'codex'
|
|
1473
|
+
if (context.agentType === 'codex') { // WP-4/D-10: the thread name is decided on every completed probe, never once
|
|
1474
1474
|
context.needsTitleDecision = true;
|
|
1475
1475
|
intents.push({ id: context.session.id, agentType: 'codex', generation, capturedSignature: context.capturedSignature,
|
|
1476
1476
|
agentSessionId: context.ownerSnapshot.providerSessionId, liveLabel: normalizeTitle(context.session.label),
|
|
@@ -1488,7 +1488,6 @@ function createDurableModelResultApplier({ modelStateRuntime, isCurrent, isOwner
|
|
|
1488
1488
|
const entry = byId.get(String(context.session.id));
|
|
1489
1489
|
if (!entry || Number(entry.generation) !== generation || entry.capturedSignature !== context.capturedSignature) continue;
|
|
1490
1490
|
if (entry.titleApplied && entry.title && entry.titleKind !== 'live') { const label = `Codex: ${entry.title}`; if (context.session.label !== label) { context.session.label = label; titleChanged = true; } }
|
|
1491
|
-
if (entry.titleSynced) context.session._codexTitleSynced = true;
|
|
1492
1491
|
if (entry.titleSynced) cacheCompleted(context);
|
|
1493
1492
|
}
|
|
1494
1493
|
if (titleChanged && typeof broadcastSessionList === 'function') broadcastSessionList();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isReservedWorkerModel } = require('./coding-session-model-adapters');
|
|
4
|
+
|
|
3
5
|
const SOURCE_GROUPS = {
|
|
4
6
|
claude: {
|
|
5
7
|
selection: ['hook:PostModelSwitch', 'hook:SessionStart', 'transcript:identity', 'db:restore'],
|
|
@@ -54,6 +56,14 @@ function validateObservation(input) {
|
|
|
54
56
|
if (fields.outcome !== 'completed' || fields.value === null || fields.selectionKind !== 'concrete') return null;
|
|
55
57
|
}
|
|
56
58
|
if (fields.kind === 'selection' && ['alias', 'policy'].includes(fields.selectionKind) && fields.value === null) return null;
|
|
59
|
+
/*
|
|
60
|
+
* WP-0 (AC-0b): the reserved delegate alias is refused by VALUE for every kind, whatever
|
|
61
|
+
* selectionKind a caller claims for it -- a lead session's own model can never be what its
|
|
62
|
+
* subagents ask the proxy for. `validFact`/`validPrior` deliberately stay permissive, so a row
|
|
63
|
+
* already persisted with the alias still loads (the projection skips the fact; history is never
|
|
64
|
+
* rewritten or dropped).
|
|
65
|
+
*/
|
|
66
|
+
if (isReservedWorkerModel(fields.value)) return null;
|
|
57
67
|
return { ...fields, processGeneration: input.processGeneration, observedAtMs: input.observedAtMs };
|
|
58
68
|
}
|
|
59
69
|
|
|
@@ -127,7 +127,6 @@ function createCodingSessionModelSyncState({
|
|
|
127
127
|
String(session?.model_source || ''),
|
|
128
128
|
Number(session?.model_observed_at || 0),
|
|
129
129
|
String(session?.label || ''),
|
|
130
|
-
session?._codexTitleSynced === true,
|
|
131
130
|
String(session?._claudeSessionId || session?.agentSessionId || ''),
|
|
132
131
|
/*
|
|
133
132
|
* Corrective finding 10: the PURE provider-source inputs a checkpoint's offsets are relative to.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const path = require('path');
|
|
3
4
|
const { ANCHOR_PREFIX, cursorAnchorGuard } = require('./source-checkpoint');
|
|
4
5
|
|
|
5
6
|
// WP-1 (design D-3/D-4): the conversation cursor is an anchor guard and nothing else.
|
|
@@ -77,13 +78,22 @@ function commitConversationBatchAndTranscriptCursor(db, options) {
|
|
|
77
78
|
OR transcript_files.status IS NOT 'ok'
|
|
78
79
|
OR transcript_files.last_error IS NOT ''
|
|
79
80
|
`);
|
|
81
|
+
// A row's `ctm_session_id` changing under this upsert used to be silent -- one committed import
|
|
82
|
+
// re-keys the file to a different owner (a re-import of the same rollout under another session)
|
|
83
|
+
// with nothing in the log to say so. Read the prior owner inside the transaction, before the write.
|
|
84
|
+
const readPriorOwner = db.prepare('SELECT ctm_session_id FROM transcript_files WHERE jsonl_path = ?');
|
|
80
85
|
return db.transaction(() => {
|
|
86
|
+
const priorOwner = readPriorOwner.get(options.filePath);
|
|
81
87
|
const committed = options.commitBatch(db, options.batch);
|
|
82
88
|
// WP-1 (S-3b): the guard is stored as-is; the manifest receipt binding is deleted with
|
|
83
89
|
// the whole-prefix proof it fenced.
|
|
84
90
|
upsert.run(options.filePath, options.agentSessionId, options.ctmSessionId, options.provider,
|
|
85
91
|
String(options.stat.dev ?? ''), String(options.stat.ino ?? ''), Number(options.stat.size || 0),
|
|
86
92
|
Number(options.stat.mtimeMs || 0), options.offset, options.parserVersion, options.guard);
|
|
93
|
+
// One line, ids only (truncated). The basename, never the full path, and never any content.
|
|
94
|
+
const prior = priorOwner ? String(priorOwner.ctm_session_id || '') : '';
|
|
95
|
+
const next = String(options.ctmSessionId || '');
|
|
96
|
+
if (priorOwner && prior !== next) console.log(`[transcript-owner] cursor commit changed owner ${path.basename(String(options.filePath || ''))}: ${prior.slice(0, 8)} -> ${next.slice(0, 8)}`);
|
|
87
97
|
return committed;
|
|
88
98
|
})();
|
|
89
99
|
}
|
|
@@ -456,7 +456,14 @@ function resolveCreateLaunchParams(ctx) {
|
|
|
456
456
|
// alias because startup_tasks still stores that legacy column.
|
|
457
457
|
const requestedTitle = String(msg.title || msg.label || '').replace(/^Resume:\s*/i, '').trim().slice(0, 120);
|
|
458
458
|
const walleResumeRequest = msg.resumeWalle === true && !msg._isRestore;
|
|
459
|
-
|
|
459
|
+
// D-1: every resume sender echoes the row's own DISPLAYED title back (`label`/`title`), and
|
|
460
|
+
// an echoed label is not user intent — so a resume never yields a tier-1 (user) name.
|
|
461
|
+
// D-13/WP-5: a CTM-composed label (`Shell:`, `Folder:`, `Code Review:`, a review session, a
|
|
462
|
+
// best-of attempt, the Claude Desktop fork) declares itself with `titleIntent:'default'`, so it is
|
|
463
|
+
// written at tier 3 like any other echo. An absent titleIntent keeps today's semantics (an old
|
|
464
|
+
// client causes no regression), and the New Session modal's typed label still lands tier 1.
|
|
465
|
+
const hasExplicitClientTitle = !msg._isRestore && !walleResumeRequest && !isResumeLaunch
|
|
466
|
+
&& msg.titleIntent !== 'default' && !!requestedTitle;
|
|
460
467
|
let title = requestedTitle;
|
|
461
468
|
if (!title) {
|
|
462
469
|
const agentName = cmd.includes('claude') ? 'Claude Code'
|
|
@@ -91,8 +91,9 @@ function ctmLifecycleJournalPath({ env = process.env, configDir = null, instance
|
|
|
91
91
|
return path.join(resolveEffectiveDataDir({ env, configDir }), 'logs', fileName);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
function appendCtmBootLine({ pid = process.pid, env = process.env, configDir = null, instanceTag = null, port = null } = {}) {
|
|
94
|
+
function appendCtmBootLine({ pid = process.pid, env = process.env, configDir = null, instanceTag = null, port = null, enteredAtServer = false } = {}) {
|
|
95
95
|
_reportLaunchdProcessTypeOnBoot(env);
|
|
96
|
+
_reportBootEntryOnBoot(env, { enteredAtServer });
|
|
96
97
|
return appendLifecycleLine(ctmLifecycleJournalPath({ env, configDir, instanceTag, port }), {
|
|
97
98
|
ts: new Date().toISOString(),
|
|
98
99
|
event: 'ctm-boot',
|
|
@@ -127,10 +128,25 @@ function _reportLaunchdProcessTypeOnBoot(env = process.env) {
|
|
|
127
128
|
} catch { /* expected: a boot-time advisory must never block boot; the plist may be unreadable on a hardened install */ }
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
// WP-2 (clock-free r6 OQ-6): report-only boot check for the OTHER install drift — a launchd-managed
|
|
132
|
+
// CTM whose plist still points at server.js directly, so bin/ctm-service-entry.js's conversation-storage
|
|
133
|
+
// boot gate never ran. Rather than diff the plist (a second source of truth, and one that can't tell a
|
|
134
|
+
// wrapper that execs the entry from a real bypass — D-2), the caller reports the RUNTIME fact
|
|
135
|
+
// `require.main === module`. Warns once per boot so the drift can't stay silent for a month; never blocks
|
|
136
|
+
// boot, never invokes launchctl, never reads or writes the plist. Only the real launchd-managed primary
|
|
137
|
+
// is checked — a /ctm-dev instance (CTM_MANAGED_BY_LAUNCHD unset/'0') or non-darwin host has no plist.
|
|
138
|
+
function _reportBootEntryOnBoot(env = process.env, { enteredAtServer = false, platform = process.platform, warn = console.warn } = {}) {
|
|
139
|
+
if (!enteredAtServer || env.CTM_MANAGED_BY_LAUNCHD !== '1' || platform !== 'darwin') return;
|
|
140
|
+
try {
|
|
141
|
+
warn('[launchd] CTM was started at server.js, so the conversation-storage boot gate did not run; re-run bin/install-service.sh or npx create-walle to enter through bin/ctm-service-entry.js');
|
|
142
|
+
} catch { /* expected: a boot-time advisory must never block boot */ }
|
|
143
|
+
}
|
|
144
|
+
|
|
130
145
|
module.exports = {
|
|
131
146
|
resolvePrimaryDataDir,
|
|
132
147
|
resolveEffectiveDataDir,
|
|
133
148
|
isPrimaryInstance,
|
|
134
149
|
ctmLifecycleJournalPath,
|
|
135
150
|
appendCtmBootLine,
|
|
151
|
+
_reportBootEntryOnBoot,
|
|
136
152
|
};
|
|
@@ -93,6 +93,13 @@ const TABLE_DOMAINS = Object.freeze({
|
|
|
93
93
|
// WP-3 (§6.4 S-12): where a shipped transcript landed on THIS instance. Same domain as
|
|
94
94
|
// agent_sessions (the identity row it is written alongside) so one handle serves the consumer.
|
|
95
95
|
sync_transcript_replicas: 'core',
|
|
96
|
+
// WP-0 (remote-machine-hub-sessions-2026-10-22.html §6.1): the hub machine registry.
|
|
97
|
+
machines: 'core',
|
|
98
|
+
// WP-1 (machine-pool-picker-pairing-dashboard-2026-10-24.html §6.1, D-4/D-6/D-11): the machine
|
|
99
|
+
// pool's own tables, same domain as `machines` — one 'core' handle serves the whole feature.
|
|
100
|
+
host_samples: 'core',
|
|
101
|
+
machine_self: 'core',
|
|
102
|
+
machine_pairing_offers: 'core',
|
|
96
103
|
// Legacy pre-v1 predecessors of ctm_sessions/agent_sessions/session_index.
|
|
97
104
|
// Superseded but their CREATE TABLE IF NOT EXISTS guards remain for
|
|
98
105
|
// fresh-v0 / mid-migration databases. Same domain as their successors
|
|
@@ -193,6 +193,26 @@ const CTM_WRITE_OPS = Object.freeze([
|
|
|
193
193
|
'deleteChain', 'deleteCtmSession', 'deleteFolder', 'deleteHook', 'deleteImage',
|
|
194
194
|
'deletePermissionRule', 'deletePrompt', 'deleteReview', 'deleteReviewComment',
|
|
195
195
|
'deleteSessionAnalysis', 'deleteStaleAnalyses', 'deleteTemplate',
|
|
196
|
+
// WP-2 (docs/remote-machine-hub-sessions-2026-10-22.html §6.1/§8, deferred from WP-0): the hub
|
|
197
|
+
// machine-registry writes. `machines` is domain 'core' (lib/db-domain-tables.js), and each op's
|
|
198
|
+
// OP_META row in shared/storage/contract.js carries the same tag — Gate 2c (CTM_WRITE_OPS →
|
|
199
|
+
// OP_META kind:'write' + domain) and Gate 2c-inventory (a domain-tagged write op outside this
|
|
200
|
+
// list) are exactly the two assertions that require the pair to land together.
|
|
201
|
+
'upsertMachineRow', 'recordMachineProbe', 'deleteMachineRow',
|
|
202
|
+
// WP-1 (machine-pool-picker-pairing-dashboard-2026-10-24.html §6.1, D-11): the 60 s host-sample
|
|
203
|
+
// write, on the same `core` handle as the machines rows above; its OP_META row in
|
|
204
|
+
// shared/storage/contract.js carries the matching kind:'write' + domain + tables:['host_samples'].
|
|
205
|
+
'recordHostSample',
|
|
206
|
+
// WP-2a (machine-pool-picker-pairing-dashboard-2026-10-24.html §6.1, D-4/P-5/P-6): the
|
|
207
|
+
// machine-owned settings write, the P-5 roster replacement (one transaction: upsert listed,
|
|
208
|
+
// delete unlisted, never self) and the leave() sweep. Each OP_META row in shared/storage/contract.js
|
|
209
|
+
// carries the matching kind:'write' + domain:'core'.
|
|
210
|
+
'setMachineSelf', 'replaceRosterMachines', 'deleteAllMachineRows',
|
|
211
|
+
// WP-3 (machine-pool-picker-pairing-dashboard-2026-10-24.html §6.3, D-6/D-9): the pairing-offer
|
|
212
|
+
// writes — mint, single-use redeem, and the 5-wrong-redeem burn. `machine_pairing_offers` is
|
|
213
|
+
// classified 'core' in lib/db-domain-tables.js and each op's OP_META row in
|
|
214
|
+
// shared/storage/contract.js carries the matching kind:'write' + domain + tables.
|
|
215
|
+
'insertPairingOffer', 'markPairingOfferRedeemed', 'burnLivePairingOffers',
|
|
196
216
|
'deleteWorkspace', 'detachPromotedProviderChildSessions', 'duplicatePrompt',
|
|
197
217
|
'enqueueSyncOutbox', 'flushSessionDiagnostics', 'flushSessionMetadataUpdates', 'heartbeatStartupTasks', 'incrementApprovalRuleMatch',
|
|
198
218
|
'markStartupTaskExited', 'markStartupTaskUserPromptInput', 'markSyncOutboxDeliveredThrough', 'recordSyncOutboxServed',
|
|
@@ -205,7 +225,7 @@ const CTM_WRITE_OPS = Object.freeze([
|
|
|
205
225
|
'supersedeHeldApprovalDecision', 'expireStaleHeldApprovalDecision', 'resolveApprovalDecision', 'claimWallePermissionResolution', 'commitWallePermissionResolution', 'expireOpenWallePermissions', 'restorePromptVersion', 'reviveStartupTask',
|
|
206
226
|
'saveApprovalAiRefinementRule', 'saveApprovalRescuePattern', 'saveImage',
|
|
207
227
|
'setAlwaysAsk', 'setPermRuleExceptions', 'setPromptParent',
|
|
208
|
-
'setScrollbackIdentity', 'setSessionStar', 'setSessionTitleMirror', 'setSessionTitleStatusNew',
|
|
228
|
+
'setScrollbackIdentity', 'setSessionStar', 'setSessionTitleMirror', 'setSessionTitleStatusNew', 'applyAgentTitleBackfillRows',
|
|
209
229
|
'setSetting', 'startAnalysisRun', 'toggleApprovalRule', 'toggleAutoApproval',
|
|
210
230
|
'toggleHook', 'trackPromptUsage', 'transferSessionOwnership', 'updateChain',
|
|
211
231
|
'updateCodingSessionModel', 'updateFolder', 'updateHarvestState',
|
|
@@ -256,7 +276,6 @@ const CTM_WRITE_OPS = Object.freeze([
|
|
|
256
276
|
'recordSyncPeerConflict', 'updateStartupTaskTitle', 'updateStartupTaskClaudeSession',
|
|
257
277
|
'updateStartupTaskAttentionDismissal', 'updateStartupTaskLifecycle',
|
|
258
278
|
'markStartupTaskParked', 'prepareScrollbackForSession', 'upsertAgentSessionIdentity',
|
|
259
|
-
'promoteStartupTaskTitleIfUserNamed', 'repairSessionTitlesFromStartupTasks',
|
|
260
279
|
'repairCodexRolloutAgentIdentities', 'cleanupOrphanScrollbackIdentities',
|
|
261
280
|
].concat(require('../../shared/storage/ctm-domain-operation-contract').WORKSPACE_ACTIVITY_OWNER_WRITE_OPS));
|
|
262
281
|
|
|
@@ -124,6 +124,13 @@ const RAW_DB_OWNER_OPS = {
|
|
|
124
124
|
updatePromptEffectiveness: { expectedMs: 5000, resumable: false },
|
|
125
125
|
applySafeRelinkRepairs: { expectedMs: 1000, resumable: false },
|
|
126
126
|
recoverSessionIntegrity: { expectedMs: 1000, resumable: false },
|
|
127
|
+
// WP-3 (worker-transcript-link-derived-not-discovered-2026-10-25.html §5 D-5): one bounded,
|
|
128
|
+
// idempotent boot pass that fills agent_sessions.jsonl_path for Claude rows whose transcript is
|
|
129
|
+
// already at the derived path. `expectedMs` is a budget HINT, not a deadline: the dispatch
|
|
130
|
+
// deadline is max(interactive floor 60s, expectedMs*8) (lib/db-owner-op-deadline.js), and the op
|
|
131
|
+
// is additionally bounded by payload.limit (<=500 rows). Not resumable: the caller is a
|
|
132
|
+
// fire-and-forget boot hook with no redrive, and a redrive could only re-run a no-op.
|
|
133
|
+
linkDerivedClaudeTranscripts: { expectedMs: 2000, resumable: false },
|
|
127
134
|
backfillSessionMessagesAsync: { expectedMs: 500, resumable: false },
|
|
128
135
|
runContentRowsBackfillSweep: { expectedMs: 500, resumable: false },
|
|
129
136
|
deleteStaleSessionAnalysesFromArtifact: {
|
|
@@ -39,6 +39,7 @@ const SCHEMA_SOURCE_FILES = Object.freeze([
|
|
|
39
39
|
'lib/migrations/v52-coding-session-launch-generations.js',
|
|
40
40
|
'lib/migrations/v53-session-model-intent.js',
|
|
41
41
|
'lib/migrations/v54-session-lead-model.js',
|
|
42
|
+
'lib/migrations/v56-host-samples-and-machine-pool.js',
|
|
42
43
|
'lib/migrations/v29-usage-accounting.js', 'lib/migrations/v30-usage-reporting.js', 'lib/migrations/v36-conversation-projection-deletes.js',
|
|
43
44
|
'../shared/usage-store.js', '../shared/usage-reporting-schema.js',
|
|
44
45
|
'lib/delete-ctm-session-saga.js',
|
|
@@ -1557,7 +1557,7 @@ const FEATURES = [
|
|
|
1557
1557
|
// no polarity/tunable/config pattern matched; 1 site(s); first: db.js:4416
|
|
1558
1558
|
{ id: "ctm_ctm_sqlite_synchronous", env: "CTM_SQLITE_SYNCHRONOUS", owner: "ctm-core-team", stage: "ops", defaultOn: true, since: "2026-08-24", expires: null, note: "unclassified raw read; needs manual triage" },
|
|
1559
1559
|
// numeric-tunable suffix/read shape; 1 site(s); first: db.js:4373
|
|
1560
|
-
{ id: "ctm_ctm_sqlite_write_lock_stale_ms", env: "CTM_SQLITE_WRITE_LOCK_STALE_MS", owner: "ctm-core-team", stage: "
|
|
1560
|
+
{ id: "ctm_ctm_sqlite_write_lock_stale_ms", env: "CTM_SQLITE_WRITE_LOCK_STALE_MS", owner: "ctm-core-team", stage: "removed", defaultOn: false, since: "2026-08-24", expires: null, note: "retired 2026-10-23 (fsevents-churn WP-1, docs/fsevents-churn-kernel-write-lock-2026-10-23.html D-4): the SQLite write lock is a kernel lock on a .mutex lock DB released by the OS when its holder dies, so stale-claim recovery and its age knob were deleted; no read of this name survives." },
|
|
1561
1561
|
// !== '0' comparison found; 1 site(s); first: server.js:448
|
|
1562
1562
|
{ id: "ctm_ctm_stale_grid_embargo", env: "CTM_STALE_GRID_EMBARGO", owner: "ctm-core-team", stage: "stable", defaultOn: true, since: "2026-08-24", expires: null },
|
|
1563
1563
|
// !== '0' comparison found; 1 site(s); first: server.js:19764
|
|
@@ -4,6 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const EventEmitter = require('events');
|
|
5
5
|
const { namedInterval, runSync, wrap } = require('./perf-tracker');
|
|
6
6
|
const envFlags = require('./env-flags');
|
|
7
|
+
const { isWritableOnlyByOwner } = require('../../shared/owner-write-safety');
|
|
7
8
|
|
|
8
9
|
// Design doc mainloop-composer-freeze-2026-08-20.html §5 D-1, §6, §9 S-1/S-4. The 60s
|
|
9
10
|
// scan tick and the attach/reattach directory walk ran completely unwrapped, so the
|
|
@@ -103,7 +104,7 @@ function resolveRoot(root) {
|
|
|
103
104
|
result.refusalCode = 'wrong-owner';
|
|
104
105
|
return result;
|
|
105
106
|
}
|
|
106
|
-
if ((
|
|
107
|
+
if (!isWritableOnlyByOwner(targetStat)) {
|
|
107
108
|
result.validationStatus = 'refused';
|
|
108
109
|
result.refusalCode = 'unsafe-permissions';
|
|
109
110
|
return result;
|
|
@@ -159,7 +160,7 @@ async function resolveRootAsync(root) {
|
|
|
159
160
|
result.refusalCode = 'wrong-owner';
|
|
160
161
|
return result;
|
|
161
162
|
}
|
|
162
|
-
if ((
|
|
163
|
+
if (!isWritableOnlyByOwner(targetStat)) {
|
|
163
164
|
result.validationStatus = 'refused';
|
|
164
165
|
result.refusalCode = 'unsafe-permissions';
|
|
165
166
|
return result;
|
|
@@ -4,7 +4,7 @@ const NATIVE_ORIGINS = new Set(['native-codex', 'native-claude', 'native-opencod
|
|
|
4
4
|
const KNOWN_ORIGINS = new Set([...NATIVE_ORIGINS, 'routed-proxy', 'portable-transcript']);
|
|
5
5
|
// S-3: the adapter/schema ids and the version membership test come from the one qualified table.
|
|
6
6
|
const { CODEX_CONTROL_ADAPTER, CODEX_COMPACTION_SCHEMA_RECEIPT, CODEX_PRE_TURN_COMPACTION_SCHEMA,
|
|
7
|
-
isQualifiedCodexVersion } = require('./codex-harness-qualification');
|
|
7
|
+
isQualifiedCodexVersion, isNonElevatedCyberAccessProgram } = require('./codex-harness-qualification');
|
|
8
8
|
// S-4: the ONE portable-kind set. `native-media` is a message whose only non-text content parts are
|
|
9
9
|
// input_image parts (D-2); it is portable only to a Codex target, which is the planner's job below.
|
|
10
10
|
const PORTABLE_HISTORY_KINDS = new Set(['text', 'tool-pair', 'native-world-state', 'native-lifecycle', 'native-media']);
|
|
@@ -48,8 +48,8 @@ function inspectTransition({ sourceRecipe, targetRecipe, snapshot, signal } = {}
|
|
|
48
48
|
if (!sourceCheckpoint) return refuse('source_checkpoint_unknown');
|
|
49
49
|
if (codexHistorySource && sourceProviderId !== targetProviderId
|
|
50
50
|
&& (!qualifiedCodexHistorySource
|
|
51
|
-
|| sourceRecipe.cyberAccessProgram
|
|
52
|
-
|| snapshot.previousSettings?.cyberAccessProgram
|
|
51
|
+
|| !isNonElevatedCyberAccessProgram(sourceRecipe.cyberAccessProgram)
|
|
52
|
+
|| !isNonElevatedCyberAccessProgram(snapshot.previousSettings?.cyberAccessProgram)
|
|
53
53
|
|| targetRecipe.harness !== 'codex-cli' || !isQualifiedCodexVersion(targetRecipe.harnessVersion))) {
|
|
54
54
|
return refuse('native_fork_adapter_unqualified', { sourceCheckpoint });
|
|
55
55
|
}
|