create-walle 0.10.0 → 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 +88 -41
- 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 +7 -5
- package/package.json +10 -4
- 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/capture-codex-rollout-records.js +417 -0
- package/template/coding-task-manager/bin/census-codex-lead-history.js +325 -0
- 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/seam-replay-codex.js +301 -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 +25 -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-history-terminal-renderer.js +33 -33
- 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-local-links.js +267 -0
- package/template/coding-task-manager/lib/codex-markdown-lists.js +160 -0
- package/template/coding-task-manager/lib/codex-native-history-prefix.js +4 -0
- package/template/coding-task-manager/lib/codex-paths.js +2 -1
- package/template/coding-task-manager/lib/codex-source-handoff.js +186 -0
- 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-owner-worker-client.js +22 -0
- package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
- package/template/coding-task-manager/lib/feature-manifest.js +1 -3
- package/template/coding-task-manager/lib/fs-watcher.js +3 -2
- package/template/coding-task-manager/lib/harness-history-transition.js +41 -14
- 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 +60 -23
- package/template/coding-task-manager/lib/history-transition-read-op.js +179 -23
- 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/kernel/diag-log.js +12 -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-observer.js +17 -2
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
- package/template/coding-task-manager/lib/lead-model-switch.js +11 -2
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +42 -4
- 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 +18 -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 +56 -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-execution-recipe-metadata.js +16 -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/collaboration-codec.js +94 -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/responses-face.js +24 -2
- 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 +62 -14
- 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-admission-trace.js +69 -0
- 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/raw-history-block.js +3 -1
- package/template/coding-task-manager/lib/read-pool-client.js +36 -24
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/read-pool-telemetry.js +14 -5
- 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 +18 -5
- 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 +43 -11
- package/template/coding-task-manager/lib/root-prompt-flow.js +175 -38
- package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
- package/template/coding-task-manager/lib/server-memory-sampler-runtime.js +10 -0
- package/template/coding-task-manager/lib/server-memory-sampler.js +41 -2
- 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 +38 -39
- 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 +20 -50
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +68 -3
- package/template/coding-task-manager/lib/session-resource-sampler.js +67 -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-status.js +2 -2
- 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 +136 -2
- package/template/coding-task-manager/lib/typing-worker-stages.js +208 -1
- package/template/coding-task-manager/lib/usage-ledger/claude-parse.js +53 -2
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +13 -4
- package/template/coding-task-manager/lib/usage-ledger/read.js +14 -0
- package/template/coding-task-manager/lib/usage-ledger/schema.js +49 -1
- package/template/coding-task-manager/lib/usage-ledger/store.js +337 -6
- package/template/coding-task-manager/lib/usage-ledger/task-read.js +123 -5
- 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/input.js +1 -0
- 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/protocol/message-table.json +0 -10
- package/template/coding-task-manager/protocol/messages.js +0 -10
- package/template/coding-task-manager/protocol/ws-schema.json +0 -20
- package/template/coding-task-manager/protocol/ws-schema.md +0 -2
- 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 -2
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/index.html +297 -240
- 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/client-health-core.js +81 -0
- package/template/coding-task-manager/public/js/client-health-main.js +61 -0
- 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 -4
- package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
- package/template/coding-task-manager/public/js/protocol.js +0 -10
- 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 +18 -3
- 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/session-usage-view.js +1 -0
- 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 -3
- 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 +964 -425
- 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/host-capabilities.js +2 -2
- 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/fly.toml +1 -1
- 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 +12 -5
- 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
- package/template/coding-task-manager/lib/giant-freeze-park.js +0 -31
|
@@ -363,7 +363,7 @@ const OP_META = {
|
|
|
363
363
|
materializeRestoredSessionIndex: { kind: 'write', equality: 'exact', domain: 'core' },
|
|
364
364
|
persistJsonlReconciliationBatch: { kind: 'write', equality: 'exact', domain: 'core' },
|
|
365
365
|
getAllSessionTitles: { kind: 'read', equality: 'exact' },
|
|
366
|
-
setSessionTitleStatusNew: { kind: 'write', equality: 'exact', domain: 'core' }, setSessionTitleMirror: { kind: 'write', equality: 'exact', domain: 'core' }, getSessionTitleMirror: { kind: 'read', equality: 'exact' }, // WP-1
|
|
366
|
+
setSessionTitleStatusNew: { kind: 'write', equality: 'exact', domain: 'core' }, setSessionTitleMirror: { kind: 'write', equality: 'exact', domain: 'core' }, getSessionTitleMirror: { kind: 'read', equality: 'exact' }, applyAgentTitleBackfillRows: { kind: 'write', equality: 'exact', domain: 'core' }, // WP-1 / session-name WP-6
|
|
367
367
|
updateSessionTokens: { kind: 'write', equality: 'exact', domain: 'core' },
|
|
368
368
|
getSessionTokens: { kind: 'read', equality: 'exact' },
|
|
369
369
|
// WP-1 (design doc §5/§9 S-19): last known physical-footprint sample, persisted at
|
|
@@ -426,6 +426,40 @@ const OP_META = {
|
|
|
426
426
|
getHostedSyncSchemaStatus: { kind: 'sqlite-only', equality: 'exact' },
|
|
427
427
|
listHostedWorkspaceBindings: { kind: 'sqlite-only', equality: 'set', idKey: 'logical_id' },
|
|
428
428
|
upsertHostedWorkspaceBinding: { kind: 'write', equality: 'exact', domain: 'core' },
|
|
429
|
+
// WP-2 (docs/remote-machine-hub-sessions-2026-10-22.html §6.1/§8, deferred from WP-0): the hub
|
|
430
|
+
// machine-registry writes. Single-table (`machines`, classified 'core' in
|
|
431
|
+
// coding-task-manager/lib/db-domain-tables.js) — hence the explicit `tables` list Gate 2i
|
|
432
|
+
// checks against the tag, and the domain tag itself, which is what keeps these off the base
|
|
433
|
+
// (firehose) writer behind conversation import once the domain split is on.
|
|
434
|
+
upsertMachineRow: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machines'] },
|
|
435
|
+
recordMachineProbe: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machines'] },
|
|
436
|
+
deleteMachineRow: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machines'] },
|
|
437
|
+
// WP-1 (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §6.1, D-11, §9 S-4): the
|
|
438
|
+
// host-sample pair. `recordHostSample` is one INSERT OR REPLACE plus the 24 h DELETE in a single
|
|
439
|
+
// transaction, single-table (`host_samples`, classified 'core' in
|
|
440
|
+
// coding-task-manager/lib/db-domain-tables.js) — so the explicit `tables` list Gate 2i checks
|
|
441
|
+
// against the tag is exact, and Gate 2g finds the routing declaration the action needs.
|
|
442
|
+
recordHostSample: { kind: 'write', equality: 'exact', domain: 'core', tables: ['host_samples'] },
|
|
443
|
+
// The bounded read beside it (oldest first, `sinceMs`/`limit`). `set` equality, keyed on `at`
|
|
444
|
+
// — the same shape as listSyncOutbox below.
|
|
445
|
+
listHostSamples: { kind: 'read', equality: 'set', idKey: 'at' },
|
|
446
|
+
// WP-2a (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html §6.1, D-4/P-5/P-6, §9 S-4):
|
|
447
|
+
// the machine-owned settings write (single row, single table `machine_self`), the P-5 roster
|
|
448
|
+
// replacement (single table `machines`, one transaction) and the leave() sweep (`machines`).
|
|
449
|
+
// Both tables are classified 'core' in coding-task-manager/lib/db-domain-tables.js.
|
|
450
|
+
setMachineSelf: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machine_self'] },
|
|
451
|
+
replaceRosterMachines: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machines'] },
|
|
452
|
+
deleteAllMachineRows: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machines'] },
|
|
453
|
+
// WP-3 (machine-pool-picker-pairing-dashboard-2026-10-24.html §6.3, D-6/D-9, §9 S-15/S-16): the
|
|
454
|
+
// pairing-offer trio — mint one offer, mark exactly one redeemed (single-use), and the AC-3c burn
|
|
455
|
+
// that flips every live offer at once. Single-table (`machine_pairing_offers`, classified 'core' in
|
|
456
|
+
// coding-task-manager/lib/db-domain-tables.js), so Gate 2i's `tables` list is exact. The bounded
|
|
457
|
+
// read beside them (`listLivePairingOffers`, unspent+unexpired as of `at`) is `set` equality keyed
|
|
458
|
+
// on `id`, the same shape as listHostSamples above.
|
|
459
|
+
insertPairingOffer: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machine_pairing_offers'] },
|
|
460
|
+
markPairingOfferRedeemed: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machine_pairing_offers'] },
|
|
461
|
+
burnLivePairingOffers: { kind: 'write', equality: 'exact', domain: 'core', tables: ['machine_pairing_offers'] },
|
|
462
|
+
listLivePairingOffers: { kind: 'read', equality: 'set', idKey: 'id' },
|
|
429
463
|
seedHostedWorkspaceBindings: { kind: 'sqlite-only', equality: 'exact', domain: 'core', tables: ['workspace_bindings'] },
|
|
430
464
|
updateStartupTaskWorkspaceMapping: { kind: 'write', equality: 'exact', domain: 'core' },
|
|
431
465
|
repointStartupTaskWorkspace: { kind: 'sqlite-only', equality: 'exact', domain: 'core', tables: ['startup_tasks', 'sync_outbox', 'synced_entities'] },
|
|
@@ -784,8 +818,6 @@ const OP_META = {
|
|
|
784
818
|
// the live scrollback_identity table is listed.
|
|
785
819
|
prepareScrollbackForSession: { kind: 'write', equality: 'exact', domain: 'core', tables: ['scrollback_identity'] },
|
|
786
820
|
upsertAgentSessionIdentity: { kind: 'write', equality: 'exact', domain: 'core', tables: ['agent_sessions'] },
|
|
787
|
-
promoteStartupTaskTitleIfUserNamed: { kind: 'write', equality: 'exact', domain: 'core', tables: ['ctm_sessions'] },
|
|
788
|
-
repairSessionTitlesFromStartupTasks: { kind: 'write', equality: 'exact', domain: 'core', tables: ['ctm_sessions'] },
|
|
789
821
|
repairCodexRolloutAgentIdentities: { kind: 'write', equality: 'exact', domain: 'core', tables: ['agent_sessions', 'ctm_sessions'] },
|
|
790
822
|
cleanupOrphanScrollbackIdentities: { kind: 'write', equality: 'exact', domain: 'core', tables: ['scrollback_identity', 'startup_tasks'] },
|
|
791
823
|
// --- writer:'base' pins (deliberately NOT re-routed; behaviour unchanged) ---
|
package/template/wall-e/agent.js
CHANGED
|
@@ -1790,6 +1790,27 @@ async function main() {
|
|
|
1790
1790
|
onError: (err) => console.error('[weekly-eval] Error:', err.message),
|
|
1791
1791
|
});
|
|
1792
1792
|
|
|
1793
|
+
// Lead-cost routing WP-5b §6.8: the daily rules probe. The outcome stream alone cannot move
|
|
1794
|
+
// an off explore cell -- the 7-day probe window needs elapsed time -- so one job per day runs
|
|
1795
|
+
// the evaluator over every explore cell. The write crosses to the brain owner through
|
|
1796
|
+
// runRuntimeJob (the $WALLE_OWNER path), the same shape as the sibling daily brain jobs; there
|
|
1797
|
+
// is no day-of-week gate because the evaluator owns its own timing.
|
|
1798
|
+
scheduler.register({
|
|
1799
|
+
name: 'helper-rules-probe',
|
|
1800
|
+
networkClass: 'local', // local sqlite read + one owner-path write, no provider call
|
|
1801
|
+
run: async () => runRuntimeJob(
|
|
1802
|
+
'helper-rules-probe',
|
|
1803
|
+
() => require('./loops/brain-write').brainWrite('helperRulesDailyTick'),
|
|
1804
|
+
),
|
|
1805
|
+
intervalMs: 24 * 60 * 60 * 1000, // daily
|
|
1806
|
+
pool: 'maintenance',
|
|
1807
|
+
lane: 2,
|
|
1808
|
+
priority: 11,
|
|
1809
|
+
restartCatchupPolicy: 'defer',
|
|
1810
|
+
startDelayMs: 240000, // 4min — well off the boot/readiness path and unique in the maintenance pool
|
|
1811
|
+
onError: (err) => console.error('[helper-rules-probe] Error:', err.message),
|
|
1812
|
+
});
|
|
1813
|
+
|
|
1793
1814
|
// Note: session mining runs inside weekly-eval-loop (step 3), no separate scheduler needed.
|
|
1794
1815
|
|
|
1795
1816
|
const _bootPostRegisterT = _perf.now();
|
|
@@ -12,6 +12,7 @@ const syncApiModule = require('./http/sync-api');
|
|
|
12
12
|
const { handleAdminApi } = require('./http/admin-api');
|
|
13
13
|
const { handleAssistantApi } = require('./http/assistant-api');
|
|
14
14
|
const { handleBackgroundCompletionApi } = require('./http/background-completion-api');
|
|
15
|
+
const { handleHelperRulesApi } = require('./http/helper-rules-api');
|
|
15
16
|
const { handleContextApi } = require('./http/context-api');
|
|
16
17
|
const { handleFeedbackApi } = require('./http/feedback-api');
|
|
17
18
|
const { handleCodingApi } = require('./http/coding-api');
|
|
@@ -2337,6 +2338,10 @@ function routeWalleApi(req, res, url, routeHandlers = {}) {
|
|
|
2337
2338
|
if (!brain || !ensureBrainInit()) return jsonResponse(res, { error: 'Brain module not available' }, 503), true;
|
|
2338
2339
|
return handleBackgroundCompletionApi(req, res, url, { brain });
|
|
2339
2340
|
}
|
|
2341
|
+
// WP-4 (lead-cost-routing-round1-2026-10-21.html §6.4): the stdio MCP proxy's read-only state
|
|
2342
|
+
// read, dispatched here (not inside the frozen handleWalleApi) alongside the block above.
|
|
2343
|
+
// WP-7 extends the same handler with the panel's /cells routes; it answers false for anything else under the prefix.
|
|
2344
|
+
if (url.pathname === '/api/wall-e/helper-rules/guidance' || url.pathname.startsWith('/api/wall-e/helper-rules/cells')) return handleHelperRulesApi(req, res, url, { brain, ensureBrainInit });
|
|
2340
2345
|
if ((url.pathname === '/api/decisions' && req.method === 'POST') || (url.pathname === '/api/decisions/status' && req.method === 'GET')) return require('./http/decisions-api').handleDecisionsApi(req, res, url, routeHandlers.decisions);
|
|
2341
2346
|
// multi-machine WP-5 (§6.6): the brain sync pair. Dispatched here, not inside
|
|
2342
2347
|
// the frozen handleWalleApi, because the doc's spelling is `/api/walle/sync/*`
|
|
@@ -234,11 +234,12 @@ function isConfiguredBrain(dbPath) {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
// Returns '' when the db is not live, otherwise the reason. The write-lock owner check is the one
|
|
237
|
-
// check --force-live does not skip.
|
|
237
|
+
// check --force-live does not skip. The protocol-2 record persists after release (D-3), so a live
|
|
238
|
+
// pid here means "the last write-lock holder is still alive", not "a write is in flight".
|
|
238
239
|
async function liveReason(dbPath, { forceLive, deps }) {
|
|
239
240
|
try {
|
|
240
241
|
const info = JSON.parse(fs.readFileSync(`${dbPath}.write-lock`, 'utf8'));
|
|
241
|
-
if (info && info.pid !== process.pid && pidAlive(info.pid)) return `write-lock
|
|
242
|
+
if (info && info.pid !== process.pid && pidAlive(info.pid)) return `last write-lock holder pid ${info.pid} is alive`;
|
|
242
243
|
} catch {
|
|
243
244
|
/* expected: no lock file, or an unparseable stale one, is "no alive owner" */
|
|
244
245
|
}
|
|
@@ -8,6 +8,7 @@ const { ctmPort: resolveCtmPort } = require('../lib/ctm-endpoint');
|
|
|
8
8
|
const {
|
|
9
9
|
handleProtocolMessage,
|
|
10
10
|
} = require('../mcp-protocol-contract');
|
|
11
|
+
const { fetchExploreCellState, httpJsonGet, leadAgentFromClientInfo } = require('../lib/helper-rules/cell-state');
|
|
11
12
|
const {
|
|
12
13
|
attachDelegateCallerContext,
|
|
13
14
|
resolveCallerParentAgentSessionId,
|
|
@@ -166,10 +167,15 @@ function _localControlPlaneEnabled() {
|
|
|
166
167
|
return !/^(0|false|no|off)$/i.test(String(process.env.WALLE_MCP_LOCAL_CONTROL_PLANE || '').trim());
|
|
167
168
|
}
|
|
168
169
|
|
|
169
|
-
function _localControlResponseOne(message) {
|
|
170
|
-
|
|
170
|
+
async function _localControlResponseOne(message) {
|
|
171
|
+
// WP-4 §6.4: the caller harness's `explore` cell lives in the daemon (this process owns no
|
|
172
|
+
// brain): read-only endpoint, existing breaker machinery, 1500 ms bound, fail-open 'on'.
|
|
173
|
+
const options = message?.method === 'initialize'
|
|
174
|
+
? { leadGuidance: { explore: await fetchExploreCellState({ agent: leadAgentFromClientInfo(message.params?.clientInfo), requestFn: (path) => _executeDaemonRequest(() => httpJsonGet({ host: process.env.WALLE_HOST || '127.0.0.1', port: _wallePort(), path })) }) } }
|
|
175
|
+
: undefined;
|
|
176
|
+
let control = handleProtocolMessage(message, options);
|
|
171
177
|
if (!control.handled) {
|
|
172
|
-
control = require('../mcp-contract').handleControlMessage(message);
|
|
178
|
+
control = require('../mcp-contract').handleControlMessage(message, options);
|
|
173
179
|
}
|
|
174
180
|
return control.handled ? {
|
|
175
181
|
handled: true,
|
|
@@ -178,10 +184,10 @@ function _localControlResponseOne(message) {
|
|
|
178
184
|
} : { handled: false, response: null, protocolVersion: '' };
|
|
179
185
|
}
|
|
180
186
|
|
|
181
|
-
function _localControlResponse(message) {
|
|
187
|
+
async function _localControlResponse(message) {
|
|
182
188
|
if (!_localControlPlaneEnabled()) return { handled: false, response: null };
|
|
183
189
|
if (!Array.isArray(message)) return _localControlResponseOne(message);
|
|
184
|
-
const results = message.map(_localControlResponseOne);
|
|
190
|
+
const results = await Promise.all(message.map((item) => _localControlResponseOne(item)));
|
|
185
191
|
if (!results.every((result) => result.handled)) return { handled: false, response: null };
|
|
186
192
|
const responses = results.map((result) => result.response).filter(Boolean);
|
|
187
193
|
return { handled: true, response: responses.length ? responses : null, protocolVersion: '' };
|
|
@@ -655,7 +661,7 @@ async function handleOne(message) {
|
|
|
655
661
|
protocol,
|
|
656
662
|
});
|
|
657
663
|
}
|
|
658
|
-
const control = _localControlResponse(message);
|
|
664
|
+
const control = await _localControlResponse(message);
|
|
659
665
|
if (control.handled) {
|
|
660
666
|
const selectedProtocol = control.protocolVersion || protocol;
|
|
661
667
|
mcpDiagnostics.recordPhase('local_response_built', {
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Lead-cost routing WP-5a (design §6.6): the helper-rules record — three tables and one
|
|
4
|
+
// seeded kv row. The DDL is a plain string with two callers rather than an exec-in-place,
|
|
5
|
+
// exactly like brain/schema.js's ensureBrainSyncSchema: `MIGRATIONS[100]` runs it on an
|
|
6
|
+
// existing brain walking the ladder forward, and the runner's `ensures` list
|
|
7
|
+
// (brain/schema-ensures.js) runs it on a fresh install, which stamps SCHEMA_VERSION
|
|
8
|
+
// directly and never replays a migration body. Both paths execute the SAME text, which is
|
|
9
|
+
// what tests-integration/migration-baseline-parity.test.js compares.
|
|
10
|
+
//
|
|
11
|
+
// Migration IDs, once written, are never renumbered. Additive and idempotent: a second run
|
|
12
|
+
// changes nothing (IF NOT EXISTS throughout, INSERT OR IGNORE for the seed).
|
|
13
|
+
|
|
14
|
+
const HELPER_RULES_DDL = `
|
|
15
|
+
CREATE TABLE IF NOT EXISTS helper_outcomes (
|
|
16
|
+
id TEXT PRIMARY KEY, -- wait-watch: '<wait_id>:<worker_id>:<n>' ; explore: the delegation invocation id
|
|
17
|
+
cell_key TEXT NOT NULL, -- wait-watch|default|<route_alias> or explore|default|<codex|claude>
|
|
18
|
+
kind TEXT NOT NULL, -- 'wait-watch' | 'explore'
|
|
19
|
+
seq INTEGER NOT NULL, -- per-cell sequence (trailing windows)
|
|
20
|
+
label TEXT, -- wait-watch: useful | empty | late | silent_useful | silent_empty ; explore: NULL
|
|
21
|
+
decision TEXT, -- wait-watch: KEEP_WAITING | WAKE_LEAD ; explore: open | handoff | fallback
|
|
22
|
+
helper_usd REAL, lead_usd REAL,
|
|
23
|
+
seconds_to_report REAL, reread_rate REAL, report_rows INTEGER,
|
|
24
|
+
grade_json TEXT, -- WP-6 fills it; NULL here
|
|
25
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
26
|
+
);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_helper_outcomes_cell ON helper_outcomes(cell_key, seq);
|
|
28
|
+
CREATE TABLE IF NOT EXISTS helper_rule_cells (
|
|
29
|
+
cell_key TEXT PRIMARY KEY, kind TEXT NOT NULL,
|
|
30
|
+
state TEXT NOT NULL DEFAULT 'on', -- on | off | probe (missing row = on)
|
|
31
|
+
user_veto INTEGER NOT NULL DEFAULT 0, -- no probe while set
|
|
32
|
+
metrics_json TEXT,
|
|
33
|
+
state_changed_at TEXT, updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
34
|
+
);
|
|
35
|
+
CREATE TABLE IF NOT EXISTS helper_rule_events (
|
|
36
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT, cell_key TEXT NOT NULL, from_state TEXT, to_state TEXT NOT NULL,
|
|
37
|
+
reason TEXT NOT NULL, evidence_json TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
38
|
+
);
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
// Lead-cost routing round 2 WP-2 (§6.4, S-15): migration 101's additive columns. Round 1 kept
|
|
42
|
+
// only the derived label (`report_rows`), which is precisely what made the mislabelled round-1
|
|
43
|
+
// history impossible to correct — the observed inputs were thrown away. These three columns keep
|
|
44
|
+
// them: `worker_id` is the ctm_session_id the row is addressable by (D-5, `closeOutcomeByWorker`),
|
|
45
|
+
// `facts_json` is the §6.2 facts object the label is re-derivable from (D-1/D-5), and
|
|
46
|
+
// `label_version` says which rule produced the stored decision (NULL facts ⇒ 1, the round-1 rows).
|
|
47
|
+
//
|
|
48
|
+
// SQLite has no `ADD COLUMN IF NOT EXISTS`, so the driver probes `PRAGMA table_info` per column —
|
|
49
|
+
// the same shape brain/recall-hints-migration.js uses. `MIGRATIONS[101]` runs this on an existing
|
|
50
|
+
// brain; the runner's ensures list runs it (right after migration 100's text) on a fresh install,
|
|
51
|
+
// so `baseline + stamp` and the ladder produce byte-identical schemas
|
|
52
|
+
// (tests-integration/migration-baseline-parity.test.js compares sqlite_master, and an ALTER
|
|
53
|
+
// rewrites the stored CREATE TABLE text, so this is load-bearing).
|
|
54
|
+
const HELPER_RULES_V2_COLUMNS = [
|
|
55
|
+
['worker_id', 'TEXT'], // ctm_session_id of the review worker (explore) or watched worker (wait-watch)
|
|
56
|
+
['facts_json', 'TEXT'], // round-2 facts; NULL on round-1 rows
|
|
57
|
+
['label_version', 'INTEGER NOT NULL DEFAULT 1'],
|
|
58
|
+
];
|
|
59
|
+
const HELPER_RULES_V2_INDEX = 'CREATE INDEX IF NOT EXISTS idx_helper_outcomes_worker ON helper_outcomes(worker_id)';
|
|
60
|
+
|
|
61
|
+
// D-6: the `helper_rules.relabelled_to` watermark — the label version the one-time relabel +
|
|
62
|
+
// recovery pass has already run for. Seeded at 1 (the round-1 version) so the FIRST run at
|
|
63
|
+
// LABEL_VERSION 2 does the recovery, and every later call is a no-op.
|
|
64
|
+
const RELABELLED_TO_KEY = 'helper_rules.relabelled_to';
|
|
65
|
+
const RELABELLED_TO_SEED = '1';
|
|
66
|
+
|
|
67
|
+
// WP-0's census measurement (the lead's own cost per burst): the explore rule's
|
|
68
|
+
// "handing off costs more than the lead was already spending" ceiling. Seeded, not
|
|
69
|
+
// hard-coded, so the panel and the evaluator read one number the user can move.
|
|
70
|
+
const LEAD_BURST_USD_KEY = 'helper_rules.lead_burst_usd';
|
|
71
|
+
const LEAD_BURST_USD_SEED = '0.46';
|
|
72
|
+
|
|
73
|
+
// WP-6 (§6.5, D-19): the spot-check grader's pin. Seeded, not hard-coded at the call site, so the
|
|
74
|
+
// user can move it in kv_store and the grader follows — the ONE place a grader model id appears.
|
|
75
|
+
// No fallback is derived from it: an empty value stores the sample as `unavailable`.
|
|
76
|
+
const GRADER_MODEL_KEY = 'helper_rules.grader_model';
|
|
77
|
+
const GRADER_MODEL_SEED = 'claude-opus-5-5';
|
|
78
|
+
|
|
79
|
+
/** Idempotent, additive. Both the ladder (migration 100) and the fresh-install ensures call this. */
|
|
80
|
+
function ensureHelperRulesSchema(d) {
|
|
81
|
+
if (!d || typeof d.exec !== 'function') return;
|
|
82
|
+
d.exec(HELPER_RULES_DDL);
|
|
83
|
+
// Same shape as brain.js's kv writes (INSERT ... ON CONFLICT): a plain INSERT OR IGNORE
|
|
84
|
+
// so a value the user (or a later census) already wrote is never overwritten.
|
|
85
|
+
const seedKv = d.prepare("INSERT OR IGNORE INTO kv_store (key, value, updated_at) VALUES (?, ?, datetime('now'))");
|
|
86
|
+
seedKv.run(LEAD_BURST_USD_KEY, LEAD_BURST_USD_SEED);
|
|
87
|
+
seedKv.run(GRADER_MODEL_KEY, GRADER_MODEL_SEED);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Lead-cost routing round 2 WP-2 (S-15): the migration-101 additions — `worker_id`, `facts_json`,
|
|
92
|
+
* `label_version`, their index, and the `helper_rules.relabelled_to` watermark. Idempotent: each
|
|
93
|
+
* ALTER is skipped once the column exists, the index is `IF NOT EXISTS`, and the seed is
|
|
94
|
+
* `INSERT OR IGNORE`, so the invariant-repair rewind and the fresh-install ensures may re-run it
|
|
95
|
+
* any number of times.
|
|
96
|
+
*/
|
|
97
|
+
function ensureHelperRulesSchemaV2(d) {
|
|
98
|
+
if (!d || typeof d.exec !== 'function') return;
|
|
99
|
+
// Migration 101 sits directly above 100, and the ensures list runs 100's text first, so the
|
|
100
|
+
// table always exists on both paths; a bare handle still gets a complete v2 schema rather than
|
|
101
|
+
// an "no such table" from the first ALTER.
|
|
102
|
+
const readColumns = () => d.prepare('PRAGMA table_info(helper_outcomes)').all().map((row) => row.name);
|
|
103
|
+
let present = new Set(readColumns());
|
|
104
|
+
if (!present.size) {
|
|
105
|
+
ensureHelperRulesSchema(d);
|
|
106
|
+
present = new Set(readColumns());
|
|
107
|
+
}
|
|
108
|
+
for (const [name, type] of HELPER_RULES_V2_COLUMNS) {
|
|
109
|
+
if (present.has(name)) continue;
|
|
110
|
+
d.exec(`ALTER TABLE helper_outcomes ADD COLUMN ${name} ${type}`);
|
|
111
|
+
}
|
|
112
|
+
d.exec(HELPER_RULES_V2_INDEX);
|
|
113
|
+
d.prepare("INSERT OR IGNORE INTO kv_store (key, value, updated_at) VALUES (?, ?, datetime('now'))")
|
|
114
|
+
.run(RELABELLED_TO_KEY, RELABELLED_TO_SEED);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = {
|
|
118
|
+
GRADER_MODEL_KEY,
|
|
119
|
+
GRADER_MODEL_SEED,
|
|
120
|
+
HELPER_RULES_DDL,
|
|
121
|
+
HELPER_RULES_V2_COLUMNS,
|
|
122
|
+
HELPER_RULES_V2_INDEX,
|
|
123
|
+
LEAD_BURST_USD_KEY,
|
|
124
|
+
LEAD_BURST_USD_SEED,
|
|
125
|
+
RELABELLED_TO_KEY,
|
|
126
|
+
RELABELLED_TO_SEED,
|
|
127
|
+
ensureHelperRulesSchema,
|
|
128
|
+
ensureHelperRulesSchemaV2,
|
|
129
|
+
};
|
|
@@ -160,6 +160,32 @@ function ensureSlackInboundJobSeed(d, { now = Date.now } = {}) {
|
|
|
160
160
|
return SLACK_INBOUND_JOB_ID;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
// Migration 57's body (WP-2 fix round 1, db-migration-consolidation), lifted
|
|
164
|
+
// into a named export (clock-free r4 R-4). Heals databases whose
|
|
165
|
+
// conversation_context_snapshots.messages_json was physically dropped by
|
|
166
|
+
// migration 52's now-retired fresh-only branch. That branch used to run right
|
|
167
|
+
// after createTables() on every from-0 install, so any DB created while it was
|
|
168
|
+
// live (almost every live fresh install pre-WP-2) is missing this column —
|
|
169
|
+
// including the column existing but no longer nullable-write-compatible: the
|
|
170
|
+
// write path (_appendRunAttempt, brain/conversation.js) names messages_json
|
|
171
|
+
// unconditionally (with a literal '[]' placeholder — it never carries real
|
|
172
|
+
// content, storage minimization is unaffected), so a DB without the column
|
|
173
|
+
// throws "no such column" on every run-attempt write. Additive + idempotent
|
|
174
|
+
// (column probe). Also run every boot from brain/schema-ensures.js because a
|
|
175
|
+
// later CTM v2 purge can drop it again — clock-free r4 R-4.
|
|
176
|
+
function ensureContextSnapshotMessagesJson(d) {
|
|
177
|
+
const hasTable = d.prepare(
|
|
178
|
+
"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'conversation_context_snapshots' LIMIT 1"
|
|
179
|
+
).get();
|
|
180
|
+
if (!hasTable) return;
|
|
181
|
+
const hasColumn = d.prepare("PRAGMA table_info(conversation_context_snapshots)").all()
|
|
182
|
+
.some((row) => row.name === 'messages_json');
|
|
183
|
+
if (hasColumn) return;
|
|
184
|
+
d.prepare(
|
|
185
|
+
"ALTER TABLE conversation_context_snapshots ADD COLUMN messages_json TEXT NOT NULL DEFAULT '[]'"
|
|
186
|
+
).run();
|
|
187
|
+
}
|
|
188
|
+
|
|
163
189
|
function createMigrationsModule({
|
|
164
190
|
backfillChatMessageParents,
|
|
165
191
|
backfillDefaultBenchmarkProvidersForDb,
|
|
@@ -1821,29 +1847,12 @@ const MIGRATIONS = {
|
|
|
1821
1847
|
// deletion/repair rules. Idempotent: a second run finds nothing to do.
|
|
1822
1848
|
sweepModelRegistryAnomalies(d);
|
|
1823
1849
|
},
|
|
1824
|
-
// Migration 57 (WP-2 fix round 1, db-migration-consolidation):
|
|
1825
|
-
//
|
|
1826
|
-
//
|
|
1827
|
-
//
|
|
1828
|
-
// live (almost every live fresh install pre-WP-2) is missing this column —
|
|
1829
|
-
// including the column existing but no longer nullable-write-compatible: the
|
|
1830
|
-
// write path (_appendRunAttempt) names messages_json unconditionally (with a
|
|
1831
|
-
// literal '[]' placeholder — it never carries real content, storage
|
|
1832
|
-
// minimization is unaffected), so a DB without the column throws "no such
|
|
1833
|
-
// column" on every run-attempt write. Additive + idempotent (column probe) —
|
|
1850
|
+
// Migration 57 (WP-2 fix round 1, db-migration-consolidation): re-adds a dropped
|
|
1851
|
+
// conversation_context_snapshots.messages_json. The body is
|
|
1852
|
+
// ensureContextSnapshotMessagesJson() above (see its comment), which the boot
|
|
1853
|
+
// `ensures` list also runs (clock-free r4 R-4). Additive + idempotent, so
|
|
1834
1854
|
// rerunSafe:true is correct.
|
|
1835
|
-
57: (d) =>
|
|
1836
|
-
const hasTable = d.prepare(
|
|
1837
|
-
"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'conversation_context_snapshots' LIMIT 1"
|
|
1838
|
-
).get();
|
|
1839
|
-
if (!hasTable) return;
|
|
1840
|
-
const hasColumn = d.prepare("PRAGMA table_info(conversation_context_snapshots)").all()
|
|
1841
|
-
.some((row) => row.name === 'messages_json');
|
|
1842
|
-
if (hasColumn) return;
|
|
1843
|
-
d.prepare(
|
|
1844
|
-
"ALTER TABLE conversation_context_snapshots ADD COLUMN messages_json TEXT NOT NULL DEFAULT '[]'"
|
|
1845
|
-
).run();
|
|
1846
|
-
},
|
|
1855
|
+
57: (d) => ensureContextSnapshotMessagesJson(d),
|
|
1847
1856
|
// Migration 58 (WP-3, db-migration-consolidation S-7): the one-time destructive
|
|
1848
1857
|
// RENAME/DROP rebuild of conversation_artifact_provenance's PK (3-col -> 7-col),
|
|
1849
1858
|
// moved here from ensurePromptPurgeSchema (conversation/prompt-purge.js), which now
|
|
@@ -2528,6 +2537,21 @@ const MIGRATIONS = {
|
|
|
2528
2537
|
99: (d) => {
|
|
2529
2538
|
d.exec(DROP_TASK_LEDGER_REMNANTS_SQL);
|
|
2530
2539
|
},
|
|
2540
|
+
// Migration 100 (lead-cost routing WP-5a, §6.6): the helper-rules record — the two rule
|
|
2541
|
+
// cells' outcome/event log, their state rows and the WP-0 `lead_burst_usd` seed. The DDL
|
|
2542
|
+
// lives in brain/helper-rules-schema.js so the fresh-install path (baseline + stamp, zero
|
|
2543
|
+
// migration bodies) creates the identical text through brain/schema-ensures.js — see
|
|
2544
|
+
// tests-integration/migration-baseline-parity.test.js. Additive and idempotent.
|
|
2545
|
+
100: (d) => { require('./helper-rules-schema').ensureHelperRulesSchema(d); },
|
|
2546
|
+
// Migration 101 (lead-cost routing round 2 WP-2, §6.4 D-1/D-5): the ADDITIVE half of the
|
|
2547
|
+
// helper-rules record — `worker_id` (D-5: a row is addressable by worker, so a close survives
|
|
2548
|
+
// a Wall-E restart), `facts_json` (D-1: the observed inputs the label is re-derivable from) and
|
|
2549
|
+
// `label_version` (which rule produced the stored label), plus the worker index and the
|
|
2550
|
+
// `helper_rules.relabelled_to` watermark the one-time relabel/recovery pass reads and sets.
|
|
2551
|
+
// Same two callers as 100 (this ladder entry + the ensures list in brain/schema-ensures.js),
|
|
2552
|
+
// same text, same reason (tests-integration/migration-baseline-parity.test.js). Additive and
|
|
2553
|
+
// idempotent: the ALTERs are `PRAGMA table_info`-guarded, the index is `IF NOT EXISTS`.
|
|
2554
|
+
101: (d) => { require('./helper-rules-schema').ensureHelperRulesSchemaV2(d); },
|
|
2531
2555
|
};
|
|
2532
2556
|
|
|
2533
2557
|
// --- Migration 91 (surface-redesign WP-3) ---------------------------------
|
|
@@ -2937,6 +2961,11 @@ module.exports = createMigrationsModule;
|
|
|
2937
2961
|
// path run — a seed that lived only in MIGRATIONS[94] would exist on an upgraded
|
|
2938
2962
|
// brain and be missing on a brand-new one.
|
|
2939
2963
|
module.exports.ensureSlackInboundJobSeed = ensureSlackInboundJobSeed;
|
|
2964
|
+
// clock-free r4 R-4 (WP-2): migration 57's body, shared with the boot `ensures`
|
|
2965
|
+
// list (brain/schema-ensures.js). A migration body runs once per ladder, so a
|
|
2966
|
+
// column dropped by a LATER CTM v2 purge was never healed; the ensures list runs
|
|
2967
|
+
// on every open.
|
|
2968
|
+
module.exports.ensureContextSnapshotMessagesJson = ensureContextSnapshotMessagesJson;
|
|
2940
2969
|
module.exports.SLACK_INBOUND_JOB_ID = SLACK_INBOUND_JOB_ID;
|
|
2941
2970
|
module.exports.SLACK_INBOUND_JOB_CONFIG = SLACK_INBOUND_JOB_CONFIG;
|
|
2942
2971
|
// WP-14: the exact table set migration 97 drops, so the migration test asserts
|
|
@@ -11,6 +11,11 @@ function _isoStored(value) {
|
|
|
11
11
|
return parsed.toISOString();
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// D-5: an anthropic-messages route relays the Claude CLI's own
|
|
15
|
+
// `output_config.effort` verbatim, so a deployment's levels are the Claude
|
|
16
|
+
// matrix for its own wire model id -- see `perModelLevels` below.
|
|
17
|
+
const ANTHROPIC_MESSAGES_PROTOCOL = 'anthropic-messages';
|
|
18
|
+
|
|
14
19
|
function buildModelDeploymentFacts({ db, providerId, protocol, getFactRow, routePolicy = {}, routeConfigRevision, routeReasoningLevels = [] } = {}) {
|
|
15
20
|
if (!db || typeof db.prepare !== 'function') throw new TypeError('supplied db handle required');
|
|
16
21
|
if (typeof getFactRow !== 'function') throw new TypeError('getFactRow required');
|
|
@@ -23,6 +28,23 @@ function buildModelDeploymentFacts({ db, providerId, protocol, getFactRow, route
|
|
|
23
28
|
|| routeReasoningLevels.some((level) => typeof level !== 'string' || !['low', 'medium', 'xhigh'].includes(level))) {
|
|
24
29
|
throw new TypeError('routeReasoningLevels invalid');
|
|
25
30
|
}
|
|
31
|
+
// D-1/D-2: the per-(route, wire model) producer (llm/worker-route.js
|
|
32
|
+
// routeModelReasoningLevels), called with each registry row's wireModelId.
|
|
33
|
+
// Only an anthropic-messages route has one: `protocol` IS that route's
|
|
34
|
+
// classified upstream API (upstreamApisForRow returns anthropic-messages for
|
|
35
|
+
// exactly one row type), so it is the serializable fact that decides the
|
|
36
|
+
// branch -- a function callback cannot travel here, this module runs inside
|
|
37
|
+
// the brain read worker, whose JSON IPC drops it. The require is lazy for the
|
|
38
|
+
// same reason brain/ never requires llm/ at load time (the seam
|
|
39
|
+
// brain/delegate-model-prefs-store.js already uses). A non-array producer
|
|
40
|
+
// result is a programming error and fails validateModelDeployments below.
|
|
41
|
+
const perModelLevels = protocol === ANTHROPIC_MESSAGES_PROTOCOL
|
|
42
|
+
? (wireModelId) => require('../llm/worker-route').routeModelReasoningLevels({
|
|
43
|
+
type: 'anthropic',
|
|
44
|
+
upstream_apis: [ANTHROPIC_MESSAGES_PROTOCOL],
|
|
45
|
+
model_id: wireModelId,
|
|
46
|
+
})
|
|
47
|
+
: null;
|
|
26
48
|
const routeId = String(providerId || '');
|
|
27
49
|
if (!routeId) throw new TypeError('providerId required');
|
|
28
50
|
const rows = db.prepare(`SELECT r.provider_id, r.model_id, r.max_context_tokens, r.max_output_tokens, r.source AS registry_source, r.last_seen_at,
|
|
@@ -46,6 +68,14 @@ function buildModelDeploymentFacts({ db, providerId, protocol, getFactRow, route
|
|
|
46
68
|
const factRow = limits.factRow;
|
|
47
69
|
const observedAt = _isoStored(factRow?.updated_at || factRow?.fetched_at || row.last_seen_at);
|
|
48
70
|
const sourceKey = factRow ? (factRow.source === 'provider-api' ? 'model-facts-provider-api' : 'model-facts-vendor') : 'unknown';
|
|
71
|
+
// D-2: a per-model routePolicy override still wins (existing precedence);
|
|
72
|
+
// otherwise an anthropic-messages deployment gets the Claude matrix for its
|
|
73
|
+
// own wire model id, and every other route keeps the route-wide list. The
|
|
74
|
+
// caller's array is copied, never aliased.
|
|
75
|
+
let reasoningLevels = routePolicy[wireModelId]?.reasoningLevels;
|
|
76
|
+
if (!Array.isArray(reasoningLevels)) {
|
|
77
|
+
reasoningLevels = perModelLevels ? perModelLevels(wireModelId) : routeReasoningLevels.slice();
|
|
78
|
+
}
|
|
49
79
|
const descriptorBase = {
|
|
50
80
|
version: 1, providerId: routeId, routeId, wireModelId, identityId,
|
|
51
81
|
protocol,
|
|
@@ -54,7 +84,7 @@ function buildModelDeploymentFacts({ db, providerId, protocol, getFactRow, route
|
|
|
54
84
|
sourceKey, observedAt,
|
|
55
85
|
inputModalities: Array.isArray(routePolicy[wireModelId]?.inputModalities) ? routePolicy[wireModelId].inputModalities : ['text'],
|
|
56
86
|
toolCalling: typeof routePolicy[wireModelId]?.toolCalling === 'boolean' ? routePolicy[wireModelId].toolCalling : null,
|
|
57
|
-
reasoningLevels
|
|
87
|
+
reasoningLevels,
|
|
58
88
|
};
|
|
59
89
|
const revisionInput = {
|
|
60
90
|
version: descriptorBase.version,
|
|
@@ -257,6 +257,22 @@ const BRAIN_CALL_WHITELIST = new Set([
|
|
|
257
257
|
// 500 so the live 2,619-question backlog never holds one unbounded write. No
|
|
258
258
|
// provider is reachable from here, so the owner stays credential-free.
|
|
259
259
|
'resolveMemoryConflicts',
|
|
260
|
+
// WP-5a (lead-cost routing §6.6/§6.8): the helper-rules record's four writes. Same
|
|
261
|
+
// CUSTOM_BRAIN_CALLS pattern as commitThinkExtraction above — see
|
|
262
|
+
// wall-e/loops/brain-custom-writes.js and wall-e/lib/helper-rules/store.js (the only
|
|
263
|
+
// writer of the three helper_* tables).
|
|
264
|
+
'helperRulesRecordOutcome',
|
|
265
|
+
'helperRulesCloseOutcome',
|
|
266
|
+
'helperRulesSetCellState',
|
|
267
|
+
'helperRulesDailyTick',
|
|
268
|
+
// Round 2 WP-2 (§6.4 S-16): the close path resolves an open explore row BY worker id (D-5 —
|
|
269
|
+
// a restart cannot orphan it), and the one-time relabel/recovery pass (D-5/D-6) runs through
|
|
270
|
+
// the same owner seam. `helperRulesCloseOutcome` above stays for the id-keyed callers.
|
|
271
|
+
'helperRulesCloseOutcomeByWorker',
|
|
272
|
+
'helperRulesRelabel',
|
|
273
|
+
// WP-6 (§6.5): the spot-check grader's verdict on one explore row — pure DB, written
|
|
274
|
+
// fire-and-forget from the lead-call hook, which runs in the read-only MCP worker.
|
|
275
|
+
'helperRulesSetGrade',
|
|
260
276
|
]);
|
|
261
277
|
|
|
262
278
|
const { OWNER_METHOD_PRIORITY, ownerPriorityFor } = require('../lib/brain-owner-op-priority');
|
|
@@ -20,6 +20,28 @@ function createSchemaEnsuresModule({ conversationProjectionV2, ensureModelFactsS
|
|
|
20
20
|
// MIGRATIONS[95]. Idempotent (INSERT OR IGNORE), so re-running on every boot
|
|
21
21
|
// changes nothing. Required lazily, inside run(), exactly like the two above.
|
|
22
22
|
{ label: 'chat-thread-backfill', run: (d) => require('./chat-thread-store').backfillChatThreads(d) },
|
|
23
|
+
// WP-5a (lead-cost routing §6.6): the helper-rules record + the `helper_rules.lead_burst_usd`
|
|
24
|
+
// seed, which MIGRATIONS[100] owns for an existing brain. Same reasoning as the two above —
|
|
25
|
+
// a brand-new database runs `baseline + stamp` and never replays a migration body, and
|
|
26
|
+
// brain/schema.js's createTables() is frozen (lint/file-size.config.json frozenFunctions), so
|
|
27
|
+
// this list is the one vehicle both paths run for the new tables. Idempotent
|
|
28
|
+
// (IF NOT EXISTS / INSERT OR IGNORE), so re-running on every boot changes nothing.
|
|
29
|
+
{ label: 'helper-rules-schema', run: (d) => require('./helper-rules-schema').ensureHelperRulesSchema(d) },
|
|
30
|
+
// Lead-cost routing round 2 WP-2 (§6.4 S-15): migration 101's additive columns — `worker_id`,
|
|
31
|
+
// `facts_json`, `label_version`, their index and the `helper_rules.relabelled_to` watermark.
|
|
32
|
+
// Runs immediately after the entry above for the same reason (a fresh database is
|
|
33
|
+
// `baseline + stamp` and never replays a migration body), and the ordering is load-bearing:
|
|
34
|
+
// the ALTERs need the table migration 100's text just created. Idempotent.
|
|
35
|
+
{ label: 'helper-rules-schema-v2', run: (d) => require('./helper-rules-schema').ensureHelperRulesSchemaV2(d) },
|
|
36
|
+
// clock-free r4 R-4 (WP-2): migration 57 owns this heal for the ladder, but a
|
|
37
|
+
// migration body runs only once — a CTM v2 purge that drops
|
|
38
|
+
// conversation_context_snapshots.messages_json AFTER 57 already ran was never
|
|
39
|
+
// repaired, and every run-attempt write (_appendRunAttempt) then threw "table
|
|
40
|
+
// conversation_context_snapshots has no column named messages_json". Running
|
|
41
|
+
// the same body on every boot closes that hole. Idempotent (column probe), so
|
|
42
|
+
// re-running on every boot changes nothing. Same lazy-require reasoning as the
|
|
43
|
+
// entries above.
|
|
44
|
+
{ label: 'context-snapshot-messages-json', run: (d) => require('./migrations').ensureContextSnapshotMessagesJson(d) },
|
|
23
45
|
];
|
|
24
46
|
}
|
|
25
47
|
module.exports = { brainSchemaEnsures: createSchemaEnsuresModule };
|
package/template/wall-e/brain.js
CHANGED
|
@@ -1912,7 +1912,7 @@ function initDb(dbPath) {
|
|
|
1912
1912
|
installSqliteWriteLock(newDb, dbPath, {
|
|
1913
1913
|
label: 'wall-e-brain', purpose: 'wall-e-brain-primary', // R3 identity (WP-0)
|
|
1914
1914
|
holdBudgetMs: WRITE_LOCK_HOLD_BUDGET_MS, // WP-7b Item 4: bound the PRIMARY brain lock's holder
|
|
1915
|
-
timeoutMs: _sqliteWriteLockTimeoutMs(),
|
|
1915
|
+
timeoutMs: _sqliteWriteLockTimeoutMs(),
|
|
1916
1916
|
onEvent: _onWriteLockEvent,
|
|
1917
1917
|
onAcquire: () => _assertSchemaUnchanged(newDb, isBrainOwnerWorker), // D-3: mid-life schema-moved guard, owner-role only
|
|
1918
1918
|
incidentLog: { record: (rec) => require('./lib/incident-log').getIncidentLog().record(rec) }, // R3: lazy sink, shared/ never requires this
|
|
@@ -369,7 +369,7 @@ function _execCapture(bin, args, { timeoutMs = 5000 } = {}) { // timeoutMs: prod
|
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
async function _probeBrowserHeadless() {
|
|
372
|
+
async function _probeBrowserHeadless(probeOptions) { // probeOptions.timeoutMs: the seam inspectChromeCapability hands to _autoChromeUsable; its production default (15000) is unchanged and no production caller passes this
|
|
373
373
|
// eslint-disable-next-line global-require
|
|
374
374
|
const { inspectChromeCapability } = require('../tools/local-tools');
|
|
375
375
|
// D-3: inspectChromeCapability() is async (a concurrent work package is
|
|
@@ -379,7 +379,7 @@ async function _probeBrowserHeadless() {
|
|
|
379
379
|
// works" without one — omitting it silently turns `capability` into a
|
|
380
380
|
// Promise, `capability.detected` into undefined, and every host gets
|
|
381
381
|
// misreported as binary_missing. Do not "simplify" this back to a bare call.
|
|
382
|
-
const capability = await inspectChromeCapability();
|
|
382
|
+
const capability = await inspectChromeCapability({ probeOptions });
|
|
383
383
|
const detectedCount = (capability.detected || []).length;
|
|
384
384
|
const evidence = [`chrome candidates on disk: ${detectedCount}`];
|
|
385
385
|
if (capability.executable) {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// One chooser for the coding-journal write path: an explicit dispatcher wins,
|
|
4
|
+
// then the daemon's shared brain-owner client, then the bounded one-shot child
|
|
5
|
+
// this process owns. Choosing a route resolves no brain DB path, starts no
|
|
6
|
+
// child and creates no brain — those stay inside the later persistence
|
|
7
|
+
// callback. The explicit dispatcher option is captured once, so a caller's
|
|
8
|
+
// accessor property is read exactly once.
|
|
9
|
+
function selectJournalDispatcher(options = {}, { createJournalWriteDispatcher, defaultBrainDbPath }) {
|
|
10
|
+
const explicitDispatcher = options.dispatcher;
|
|
11
|
+
if (explicitDispatcher) return Object.freeze({
|
|
12
|
+
dispatcher: explicitDispatcher, defaultAwaitTerminalJournal: true,
|
|
13
|
+
});
|
|
14
|
+
const { getSharedBrainOwnerClient } = require('../lib/brain-owner-worker-client');
|
|
15
|
+
const shared = getSharedBrainOwnerClient();
|
|
16
|
+
if (shared) return Object.freeze({
|
|
17
|
+
dispatcher: createJournalWriteDispatcher({ client: shared }),
|
|
18
|
+
defaultAwaitTerminalJournal: false,
|
|
19
|
+
});
|
|
20
|
+
// Stop hooks and standalone lifecycle processes cannot see the daemon's
|
|
21
|
+
// process-local singleton. The bounded one-shot child owns SQLite and keeps
|
|
22
|
+
// this process free from better-sqlite3 teardown hazards.
|
|
23
|
+
const { writeJournalEntryInChild } = require('../lib/coding-journal-writer-child-client');
|
|
24
|
+
const dispatcher = createJournalWriteDispatcher({
|
|
25
|
+
client: {
|
|
26
|
+
persistCodingJournal(entry) {
|
|
27
|
+
const dbPath = options.dbPath || defaultBrainDbPath(options.env);
|
|
28
|
+
// J-1: no daemon is actually serving a brain (no explicit dbPath, no
|
|
29
|
+
// WALL_E_DATA_DIR, no live-data instance-id.json) — never spawn the
|
|
30
|
+
// one-shot child, which holds an owner grant and would create/migrate
|
|
31
|
+
// the phantom ~/.walle/data brain. Write nothing; skip loudly.
|
|
32
|
+
if (!dbPath) {
|
|
33
|
+
console.error('[wall-e] coding journal write skipped: reason=no_served_brain (no daemon-served brain to write to)');
|
|
34
|
+
return Promise.resolve({ ok: true, skipped: true, reason: 'no_served_brain' });
|
|
35
|
+
}
|
|
36
|
+
return writeJournalEntryInChild(entry, {
|
|
37
|
+
dbPath,
|
|
38
|
+
// S-8: state THIS process's schema generation so the fresh-code child
|
|
39
|
+
// refuses rather than migrating the brain out from under us.
|
|
40
|
+
parentSchemaVersion: require('../brain').SCHEMA_VERSION,
|
|
41
|
+
timeoutMs: options.timeoutMs,
|
|
42
|
+
forkImpl: options.forkImpl,
|
|
43
|
+
env: options.env,
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
return Object.freeze({ dispatcher, defaultAwaitTerminalJournal: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { selectJournalDispatcher };
|