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
|
@@ -25,6 +25,18 @@ function mergePendingInteractionIds(existing, incoming, limit = PENDING_IDS_LIMI
|
|
|
25
25
|
return merged.slice(-limit);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
// WP-4 (R-7, clock-free-tests-followups-r3-2026-10-24.html §5 R-7, §6 WP-4): keep the per-id
|
|
29
|
+
// inputSeq map to exactly the ids `pending` still carries, oldest dropped first, capped at
|
|
30
|
+
// `limit` -- the same "keep the most recent N" policy mergePendingInteractionIds applies to the
|
|
31
|
+
// id list itself, so the two can never drift apart.
|
|
32
|
+
function prunePendingInputSeqs(byId, pending, limit = PENDING_IDS_LIMIT) {
|
|
33
|
+
for (const id of Array.from(byId.keys())) {
|
|
34
|
+
if (!pending.includes(id)) byId.delete(id);
|
|
35
|
+
}
|
|
36
|
+
while (byId.size > limit) byId.delete(byId.keys().next().value);
|
|
37
|
+
return byId;
|
|
38
|
+
}
|
|
39
|
+
|
|
28
40
|
// Post ONE 'typing-stage' message covering every id currently pending for this session -- the
|
|
29
41
|
// STAGES store's note() (lib/typing-interaction-trace.js) fans it out per-interactionId and is
|
|
30
42
|
// idempotent per (interactionId, stage), so calling this more than once for the same boundary is
|
|
@@ -38,4 +50,199 @@ function noteWorkerTypingStage(postTransport, sessionId, interactionIds, stage,
|
|
|
38
50
|
});
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
|
|
53
|
+
// --- WP-3 shadow echo matchers -----------------------------------------------------------
|
|
54
|
+
// Design doc: composer-freeze-followups-load-sigstop-attribution-2026-10-20.html §5 D-C2
|
|
55
|
+
// (two per-key matchers, shadow-only, OPTIONAL stages) and §1.3 (most existing stages are
|
|
56
|
+
// "first X after the key", not that key's echo -- e.g. pty-output lands 0-3 ms after
|
|
57
|
+
// pty-written in 14 of 18 retained slow rows, which no agent CLI can do).
|
|
58
|
+
//
|
|
59
|
+
// Prior art, both rules copied as-is:
|
|
60
|
+
// - echo-bytes = VS Code terminal typeahead's rule: the predicted char is "eaten" out of
|
|
61
|
+
// the incoming BYTE STREAM once SGR/escape sequences are skipped
|
|
62
|
+
// (terminalTypeAheadAddon.ts, `input.eatChar(this._char)`).
|
|
63
|
+
// - echo-cell = mosh's rule: a prediction is confirmed only when "a letter we hypothesized
|
|
64
|
+
// to appear in a particular cell did appear there" (mosh paper, USENIX ATC'12).
|
|
65
|
+
//
|
|
66
|
+
// Both stamps are per-key (ONE interactionId), shadow-only: nothing reads them as truth and
|
|
67
|
+
// no existing stage changes meaning (that decision is WP-5, on WP-4's numbers, per D-C4).
|
|
68
|
+
const ECHO_PREDICTION_CAP = 24;
|
|
69
|
+
// D-C2: a prediction that neither matcher confirmed within this window is dropped -- the CLI
|
|
70
|
+
// may echo arbitrarily late, but a stale prediction can only ever produce a false positive
|
|
71
|
+
// against a later, unrelated redraw.
|
|
72
|
+
const ECHO_PREDICTION_TTL_MS = 10_000;
|
|
73
|
+
|
|
74
|
+
// One grapheme, at most 4 UTF-8 bytes, no C0 control / ESC / DEL -- the D-C2 input class that
|
|
75
|
+
// can be predicted at all. This is also what server.js uses to decide whether a keystroke
|
|
76
|
+
// carries an `echo` payload; it lives here so server.js stays at its file-size ratchet.
|
|
77
|
+
const _echoSegmenter = new Intl.Segmenter();
|
|
78
|
+
function isSingleGraphemeEcho(data) {
|
|
79
|
+
if (typeof data !== 'string' || !data) return false;
|
|
80
|
+
if (Buffer.byteLength(data, 'utf8') > 4) return false;
|
|
81
|
+
if (/[\x00-\x1f\x7f]/.test(data)) return false;
|
|
82
|
+
let count = 0;
|
|
83
|
+
for (const _segment of _echoSegmenter.segment(data)) {
|
|
84
|
+
count += 1;
|
|
85
|
+
if (count > 1) return false;
|
|
86
|
+
}
|
|
87
|
+
return count === 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// D-C2: the byte matcher must look at what the CLI actually printed, not at the escape
|
|
91
|
+
// sequences around it. Strip CSI (`ESC [ ... final`), OSC (`ESC ] ... BEL | ESC \`) and any
|
|
92
|
+
// other two-byte `ESC x`, leaving only the printable text.
|
|
93
|
+
function stripEscapeSequences(text) {
|
|
94
|
+
const source = String(text ?? '');
|
|
95
|
+
let out = '';
|
|
96
|
+
let index = 0;
|
|
97
|
+
while (index < source.length) {
|
|
98
|
+
if (source[index] !== '\x1b') {
|
|
99
|
+
out += source[index];
|
|
100
|
+
index += 1;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const next = source[index + 1];
|
|
104
|
+
if (next === '[') {
|
|
105
|
+
let end = index + 2;
|
|
106
|
+
// ECMA-48 CSI: parameter/intermediate bytes are 0x20-0x3f, the final byte is 0x40-0x7e.
|
|
107
|
+
while (end < source.length) {
|
|
108
|
+
const code = source.charCodeAt(end);
|
|
109
|
+
if (code >= 0x40 && code <= 0x7e) break;
|
|
110
|
+
end += 1;
|
|
111
|
+
}
|
|
112
|
+
index = end + 1;
|
|
113
|
+
} else if (next === ']') {
|
|
114
|
+
let end = index + 2;
|
|
115
|
+
while (end < source.length && source[end] !== '\x07'
|
|
116
|
+
&& !(source[end] === '\x1b' && source[end + 1] === '\\')) {
|
|
117
|
+
end += 1;
|
|
118
|
+
}
|
|
119
|
+
if (end >= source.length) index = source.length;
|
|
120
|
+
else index = source[end] === '\x07' ? end + 1 : end + 2;
|
|
121
|
+
} else if (next === undefined) {
|
|
122
|
+
index = source.length;
|
|
123
|
+
} else {
|
|
124
|
+
index += 2;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// D-C2, called from the 'note-input' handler (headless-term-service.js). Merges the incoming
|
|
131
|
+
// interactionIds exactly like the inline block it replaces, then -- when the keystroke carries
|
|
132
|
+
// a single-grapheme `echo` -- records where the CLI's echo SHOULD land from here: the cursor
|
|
133
|
+
// cell of the mirror at this instant, in the buffer that is active at this instant.
|
|
134
|
+
function armEchoPrediction(entry, msg) {
|
|
135
|
+
if (!entry || !entry.state || !msg) return;
|
|
136
|
+
if (Array.isArray(msg.interactionIds) && msg.interactionIds.length) {
|
|
137
|
+
entry.state.pendingTypingInteractionIds = mergePendingInteractionIds(
|
|
138
|
+
entry.state.pendingTypingInteractionIds, msg.interactionIds,
|
|
139
|
+
);
|
|
140
|
+
entry.state.typingIdsAwaitingFeed = true;
|
|
141
|
+
// WP-4 (R-7): remember each pending id's OWN inputSeq here, so emitSettled can tell "the
|
|
142
|
+
// offered frame did not yet contain this key's echo" apart from "worker->main delivery or
|
|
143
|
+
// main-thread queueing" (the (i)/(ii) split design r3 §1.4 says today's stamps cannot make).
|
|
144
|
+
// Earliest seq wins for an id seen twice; the Math.max(0, ...) normalization is the same one
|
|
145
|
+
// headless-term-service.js's 'note-input' handler applies to msg.inputSeq.
|
|
146
|
+
const inputSeq = Math.max(0, Number(msg.inputSeq) || 0);
|
|
147
|
+
const seqById = entry.state.pendingTypingInputSeqById instanceof Map
|
|
148
|
+
? entry.state.pendingTypingInputSeqById
|
|
149
|
+
: new Map();
|
|
150
|
+
for (const rawId of msg.interactionIds) {
|
|
151
|
+
const id = String(rawId);
|
|
152
|
+
if (!seqById.has(id) || inputSeq < seqById.get(id)) seqById.set(id, inputSeq);
|
|
153
|
+
}
|
|
154
|
+
entry.state.pendingTypingInputSeqById = prunePendingInputSeqs(
|
|
155
|
+
seqById, entry.state.pendingTypingInteractionIds,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
const echo = msg.echo;
|
|
159
|
+
if (!echo || !echo.interactionId || typeof echo.char !== 'string' || !echo.char) return;
|
|
160
|
+
const buf = entry.term?.buffer?.active;
|
|
161
|
+
if (!buf) return;
|
|
162
|
+
if (!Array.isArray(entry.state.echoPredictions)) entry.state.echoPredictions = [];
|
|
163
|
+
const predictions = entry.state.echoPredictions;
|
|
164
|
+
predictions.push({
|
|
165
|
+
interactionId: String(echo.interactionId),
|
|
166
|
+
char: echo.char,
|
|
167
|
+
row: buf.baseY + buf.cursorY,
|
|
168
|
+
col: buf.cursorX,
|
|
169
|
+
bufferType: buf.type,
|
|
170
|
+
armedAt: Date.now(),
|
|
171
|
+
bytes: false,
|
|
172
|
+
cell: false,
|
|
173
|
+
});
|
|
174
|
+
// D-C2 bound: never more than 24 pending, oldest dropped first.
|
|
175
|
+
while (predictions.length > ECHO_PREDICTION_CAP) predictions.shift();
|
|
176
|
+
return predictions;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// D-C2, called once per applied NON-seed feed (headless-term-service.js's feed onApplied).
|
|
180
|
+
// Each matcher stamps AT MOST ONCE per prediction, for that prediction's single id only --
|
|
181
|
+
// never the session's whole pending set (that is the R1/R2 misattribution this shadows).
|
|
182
|
+
function matchEchoPredictions(postTransport, sessionId, entry, data, now = Date.now()) {
|
|
183
|
+
const predictions = entry?.state?.echoPredictions;
|
|
184
|
+
if (!Array.isArray(predictions) || !predictions.length) return;
|
|
185
|
+
const text = stripEscapeSequences(data);
|
|
186
|
+
const buf = entry.term?.buffer?.active;
|
|
187
|
+
const kept = [];
|
|
188
|
+
for (const prediction of predictions) {
|
|
189
|
+
if (!prediction.bytes && prediction.char && text.includes(prediction.char)) {
|
|
190
|
+
prediction.bytes = true;
|
|
191
|
+
noteWorkerTypingStage(postTransport, sessionId, [prediction.interactionId], 'echo-bytes');
|
|
192
|
+
}
|
|
193
|
+
if (!prediction.cell && buf && buf.type === prediction.bufferType) {
|
|
194
|
+
const line = buf.getLine(prediction.row);
|
|
195
|
+
if (line?.getCell(prediction.col)?.getChars() === prediction.char) {
|
|
196
|
+
prediction.cell = true;
|
|
197
|
+
noteWorkerTypingStage(postTransport, sessionId, [prediction.interactionId], 'echo-cell');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// D-C2: drop when both matchers hit, or past the 10 s window.
|
|
201
|
+
if (prediction.bytes && prediction.cell) continue;
|
|
202
|
+
if (now - prediction.armedAt > ECHO_PREDICTION_TTL_MS) continue;
|
|
203
|
+
kept.push(prediction);
|
|
204
|
+
}
|
|
205
|
+
entry.state.echoPredictions = kept;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// WP-4 (R-7), called from headless-term-service.js's emitSettled ONLY after
|
|
209
|
+
// _stateSyncEmitter.onMirrorUpdated returned `sent` -- the frame that just shipped is the first
|
|
210
|
+
// one that could carry these keys' echoes, so stamp `frame-posted` for exactly the pending ids
|
|
211
|
+
// the frame's `echoedThroughSeq` already covers (recorded inputSeq >= 1 AND <= offeredEchoSeq).
|
|
212
|
+
// An id with NO recorded seq is treated as echoed, which preserves the pre-WP-4 blanket clear.
|
|
213
|
+
// Returns the ids that remain un-echoed (recorded seq > offeredEchoSeq) so the caller can keep
|
|
214
|
+
// only those pending -- that is what makes `emit-offered -> frame-posted` readable as "the
|
|
215
|
+
// offered frame DID contain this key's echo" versus "the frame lacked it" instead of collapsing
|
|
216
|
+
// both into one delivery gap.
|
|
217
|
+
function noteFramePostedForEchoed(postTransport, sessionId, entry, offeredEchoSeq) {
|
|
218
|
+
const pending = Array.isArray(entry?.state?.pendingTypingInteractionIds)
|
|
219
|
+
? entry.state.pendingTypingInteractionIds
|
|
220
|
+
: [];
|
|
221
|
+
const seqById = entry?.state?.pendingTypingInputSeqById;
|
|
222
|
+
const covering = Math.max(0, Number(offeredEchoSeq) || 0);
|
|
223
|
+
const echoedIds = [];
|
|
224
|
+
const remaining = [];
|
|
225
|
+
for (const rawId of pending) {
|
|
226
|
+
const id = String(rawId);
|
|
227
|
+
const seq = seqById instanceof Map && seqById.has(id) ? Number(seqById.get(id)) : 0;
|
|
228
|
+
if (seq > covering) remaining.push(id);
|
|
229
|
+
else echoedIds.push(id);
|
|
230
|
+
}
|
|
231
|
+
noteWorkerTypingStage(postTransport, sessionId, echoedIds, 'frame-posted', { offeredEchoSeq: covering });
|
|
232
|
+
// The echoed ids are delivered; only the un-echoed ones stay pending (and keep their seq).
|
|
233
|
+
if (seqById instanceof Map) {
|
|
234
|
+
for (const id of echoedIds) seqById.delete(id);
|
|
235
|
+
}
|
|
236
|
+
return remaining;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
module.exports = {
|
|
240
|
+
mergePendingInteractionIds,
|
|
241
|
+
noteWorkerTypingStage,
|
|
242
|
+
noteFramePostedForEchoed,
|
|
243
|
+
PENDING_IDS_LIMIT,
|
|
244
|
+
isSingleGraphemeEcho,
|
|
245
|
+
armEchoPrediction,
|
|
246
|
+
matchEchoPredictions,
|
|
247
|
+
ECHO_PREDICTION_CAP,
|
|
248
|
+
};
|
|
@@ -267,6 +267,37 @@ function createClaudeFileParser({ sessionId, agentId = '', state = null } = {})
|
|
|
267
267
|
// it just emitted (the store's primary key dedups across passes as well).
|
|
268
268
|
const seenAliases = new Set();
|
|
269
269
|
|
|
270
|
+
// The vendor ids of the rows THIS slice saw (WP-3, design §5 D-8). A re-read from 0 no
|
|
271
|
+
// longer deletes the file's prior facts up front (D-7); instead the store sweeps, at EOF,
|
|
272
|
+
// only the prior facts whose vendor id the new reading OBSERVED and no longer re-emits.
|
|
273
|
+
// So this is the evidence half of that rule: every id that proves a source row is still
|
|
274
|
+
// in the file, whether or not this reading turned it into a fact.
|
|
275
|
+
//
|
|
276
|
+
// * responses -- the provider message id of every assistant record (with or without
|
|
277
|
+
// usage: a record the reading no longer admits is exactly one whose call must go);
|
|
278
|
+
// * prompts -- the id of every row the parser ACCEPTS as a prompt row, and only
|
|
279
|
+
// those rows. Later rows of the same turn (a tool_result `user` row, for instance)
|
|
280
|
+
// carry the same promptId, so collecting the id off every record would "observe" a
|
|
281
|
+
// prompt whose OWN row the vendor cut -- and the sweep would then delete the prompt
|
|
282
|
+
// fact and its aliases. Observation happens in the prompt-recording path alone;
|
|
283
|
+
// * toolUses -- every tool_use block id, which is the vendor id of a spawn, an edge
|
|
284
|
+
// and an attempt alike.
|
|
285
|
+
//
|
|
286
|
+
// De-duplicated within the slice (a Set), and NOT persisted in the checkpoint: it
|
|
287
|
+
// describes one slice's reading, never a resume position.
|
|
288
|
+
const observedResponses = new Set();
|
|
289
|
+
const observedPrompts = new Set();
|
|
290
|
+
const observedToolUses = new Set();
|
|
291
|
+
|
|
292
|
+
function observeToolUses(content) {
|
|
293
|
+
if (!Array.isArray(content)) return;
|
|
294
|
+
for (const block of content) {
|
|
295
|
+
if (!block || block.type !== 'tool_use') continue;
|
|
296
|
+
if (typeof block.id !== 'string' || block.id === '') continue;
|
|
297
|
+
observedToolUses.add(block.id);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
270
301
|
function recordCall(row) {
|
|
271
302
|
const existing = indexByKey.get(row.call_key);
|
|
272
303
|
if (existing === undefined) {
|
|
@@ -315,11 +346,14 @@ function createClaudeFileParser({ sessionId, agentId = '', state = null } = {})
|
|
|
315
346
|
if (record.type === 'assistant') {
|
|
316
347
|
const message = record.message;
|
|
317
348
|
const usage = message && message.usage;
|
|
349
|
+
const responseId = responseIdOf(message);
|
|
350
|
+
if (responseId !== '') observedResponses.add(responseId);
|
|
351
|
+
observeToolUses(message && message.content);
|
|
318
352
|
// Admission: a usage object and a nonempty response id. A requestId is NOT required (it
|
|
319
353
|
// is absent in every one of the six historical glm-5-3 transcripts, which is what the
|
|
320
354
|
// old rule discarded), and no prefix is required on the id.
|
|
321
355
|
if (usage && typeof usage === 'object'
|
|
322
|
-
&&
|
|
356
|
+
&& responseId !== ''
|
|
323
357
|
&& nonEmptyText(message.model) !== '<synthetic>') {
|
|
324
358
|
const promptId = agentId === '' ? persisted.current_prompt_id : null;
|
|
325
359
|
recordCall(callRowFor(record, offset, { sessionId, agentId, promptId }));
|
|
@@ -440,6 +474,10 @@ function createClaudeFileParser({ sessionId, agentId = '', state = null } = {})
|
|
|
440
474
|
// other silently.
|
|
441
475
|
const promptId = nonEmptyText(entry.promptId) || nonEmptyText(entry.uuid);
|
|
442
476
|
if (!promptId) return;
|
|
477
|
+
// The row is accepted as a prompt, so its id proves THIS record's own row is present
|
|
478
|
+
// (WP-3 D-8). Recorded here, and nowhere else: an id carried by a later row of the same
|
|
479
|
+
// turn would observe a prompt whose own row the vendor removed.
|
|
480
|
+
observedPrompts.add(promptId);
|
|
443
481
|
const digest = providerMessageDigestFor(nonEmptyText(entry.uuid)) || null;
|
|
444
482
|
// Every persisted prompt row is where attribution goes next -- a human task, or the
|
|
445
483
|
// `/clear` / `/compact` boundary that broke the previous turn. A boundary therefore gets
|
|
@@ -478,7 +516,17 @@ function createClaudeFileParser({ sessionId, agentId = '', state = null } = {})
|
|
|
478
516
|
}
|
|
479
517
|
|
|
480
518
|
function drain() {
|
|
481
|
-
const out = {
|
|
519
|
+
const out = {
|
|
520
|
+
calls, prompts, aliases, spawns, delegations, attempts, reported,
|
|
521
|
+
// The ids this slice observed (WP-3 D-8). Never persisted: they describe one slice's
|
|
522
|
+
// reading, and the store clears its own copy of them at EOF.
|
|
523
|
+
observed: {
|
|
524
|
+
responses: [...observedResponses],
|
|
525
|
+
prompts: [...observedPrompts],
|
|
526
|
+
toolUses: [...observedToolUses],
|
|
527
|
+
},
|
|
528
|
+
state: persisted,
|
|
529
|
+
};
|
|
482
530
|
calls = [];
|
|
483
531
|
prompts = [];
|
|
484
532
|
aliases = [];
|
|
@@ -489,6 +537,9 @@ function createClaudeFileParser({ sessionId, agentId = '', state = null } = {})
|
|
|
489
537
|
indexByKey.clear();
|
|
490
538
|
seenAliases.clear();
|
|
491
539
|
seenPrompts.clear();
|
|
540
|
+
observedResponses.clear();
|
|
541
|
+
observedPrompts.clear();
|
|
542
|
+
observedToolUses.clear();
|
|
492
543
|
return out;
|
|
493
544
|
}
|
|
494
545
|
|
|
@@ -205,10 +205,13 @@ function createUsageIngestor({ store, sliceBytes = DEFAULT_SLICE_BYTES, pricer =
|
|
|
205
205
|
let firstBatch = true;
|
|
206
206
|
let done = false;
|
|
207
207
|
let remaining = maxBytes;
|
|
208
|
-
// WP-8b: when a file RESETS to offset 0 (its checkpoint was discarded by a
|
|
209
|
-
// parser_version or head change) the store must
|
|
210
|
-
//
|
|
211
|
-
//
|
|
208
|
+
// WP-8b/WP-3: when a file RESETS to offset 0 (its checkpoint was discarded by a
|
|
209
|
+
// parser_version or head change) the store must reconcile the facts this file wrote
|
|
210
|
+
// under the old reading. For a CODEX file that stays today's eager delete (WP-8b). For
|
|
211
|
+
// a CLAUDE file it is a SNAPSHOT instead (WP-3 D-7): the vendor rewrites a compacted
|
|
212
|
+
// transcript, so the new reading sees fewer rows than the reading that wrote those
|
|
213
|
+
// facts, and deleting them would destroy usage nothing can re-create. The flag rides
|
|
214
|
+
// the first slice only: a brand-new file (no row) never resets, and the re-read's later
|
|
212
215
|
// slices append to the facts the first slice just re-created.
|
|
213
216
|
const resetOnFirstBatch = !!row && offset === 0;
|
|
214
217
|
|
|
@@ -257,6 +260,12 @@ function createUsageIngestor({ store, sliceBytes = DEFAULT_SLICE_BYTES, pricer =
|
|
|
257
260
|
reported: out.reported,
|
|
258
261
|
checkpoint,
|
|
259
262
|
reset: firstBatch && resetOnFirstBatch,
|
|
263
|
+
// The ids this slice OBSERVED (WP-3 D-8) and whether this slice reached EOF. The
|
|
264
|
+
// store uses them only for a Claude file: a prior fact whose vendor id was seen
|
|
265
|
+
// but which the new reading no longer emits is swept at EOF, while one whose row
|
|
266
|
+
// the vendor deleted is kept. Both are ignored for Codex (D-10).
|
|
267
|
+
observed: out.observed || null,
|
|
268
|
+
final: checkpoint.status === 'current',
|
|
260
269
|
price,
|
|
261
270
|
});
|
|
262
271
|
calls += upserted.callsWritten;
|
|
@@ -506,6 +506,11 @@ function resolveScope(coreDb, ctmSessionId) {
|
|
|
506
506
|
delegatedCtmSessions.push(childId);
|
|
507
507
|
workers.push({
|
|
508
508
|
ctm_session_id: childId,
|
|
509
|
+
// WP-2: the CTM session whose OWN turn launched this worker -- the BFS node whose children are
|
|
510
|
+
// being read. The launch-time fallback (task-read.js) may only charge a worker to the scope
|
|
511
|
+
// ROOT's canonical turns, so a worker launched by another worker (a nested delegation) is
|
|
512
|
+
// excluded by comparing this field against the scope's own CTM session id.
|
|
513
|
+
parent_ctm_session_id: String(current.ctmId),
|
|
509
514
|
generation: Number.isInteger(child.generation) && child.generation >= 1 ? child.generation : null,
|
|
510
515
|
generation_ends_ms: generationEndsMs(child.generation, child.runtime_json),
|
|
511
516
|
launches: workerLaunches(child, childId),
|
|
@@ -708,6 +713,10 @@ function availabilityOf(ledgerDb) {
|
|
|
708
713
|
// v5: the native local turn of a prompt, beside its event-derived identity. A ledger
|
|
709
714
|
// written before the column reads it as an explicit UNAVAILABLE fact, never a throw.
|
|
710
715
|
prompt_native_turn_id: prompts.has('native_turn_id'),
|
|
716
|
+
// D-3 (WP-1): whether a prompt row still carries its SOURCE file. A prompt written before the
|
|
717
|
+
// column existed reads as an explicit `source_less` fact on the page; the raw file id itself is
|
|
718
|
+
// internal plumbing and never crosses this boundary.
|
|
719
|
+
prompt_source_file: prompts.has('source_file_id'),
|
|
711
720
|
prompt_aliases: hasAll(aliases, ['prompt_id', 'provider_message_digest']),
|
|
712
721
|
revision: tableColumns(ledgerDb, 'usage_ledger_meta').has('value'),
|
|
713
722
|
};
|
|
@@ -986,6 +995,7 @@ function readLedgerSession(ledgerDb, scope, options = {}) {
|
|
|
986
995
|
if (available.source_event_digest) promptColumns.push('source_event_digest');
|
|
987
996
|
if (available.prompt_content_fingerprint) promptColumns.push('content_fingerprint');
|
|
988
997
|
if (available.prompt_native_turn_id) promptColumns.push('native_turn_id');
|
|
998
|
+
if (available.prompt_source_file) promptColumns.push('source_file_id');
|
|
989
999
|
const promptSizeColumns = available.prompt_metadata
|
|
990
1000
|
? ", CASE WHEN text IS NULL THEN 0 ELSE length(CAST(text AS BLOB)) END AS text_bytes, CASE WHEN text IS NULL THEN 0 ELSE length(text) END AS text_chars"
|
|
991
1001
|
: ', 0 AS text_bytes, 0 AS text_chars';
|
|
@@ -1106,6 +1116,10 @@ function readLedgerSession(ledgerDb, scope, options = {}) {
|
|
|
1106
1116
|
source_event_digest: available.source_event_digest ? row.source_event_digest ?? null : null,
|
|
1107
1117
|
content_fingerprint: available.prompt_content_fingerprint ? row.content_fingerprint ?? null : null,
|
|
1108
1118
|
native_turn_id: available.prompt_native_turn_id ? row.native_turn_id ?? null : null,
|
|
1119
|
+
// D-3: `true` only when the column EXISTS and the row's value is NULL. Without the column
|
|
1120
|
+
// the read cannot prove the prompt is sourceless, so it reports `false` ("cannot prove") and
|
|
1121
|
+
// the prompt is never matched by time.
|
|
1122
|
+
source_less: available.prompt_source_file ? row.source_file_id == null : false,
|
|
1109
1123
|
kind: available.prompt_metadata ? (row.kind ?? null) : null,
|
|
1110
1124
|
text: fetched ? overviewTextFor.get(key) : null,
|
|
1111
1125
|
text_truncated: available.prompt_metadata ? row.text_truncated === 1 || row.text_truncated === true : null,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
const { createMigrationRunner, pragmaVersionStore } = require('../../../shared/db-migration-runner');
|
|
17
17
|
|
|
18
|
-
const USAGE_LEDGER_SCHEMA_VERSION =
|
|
18
|
+
const USAGE_LEDGER_SCHEMA_VERSION = 8;
|
|
19
19
|
|
|
20
20
|
// The complete v1 schema, in one place. Each statement is idempotent
|
|
21
21
|
// (IF NOT EXISTS) so a re-run of the baseline against a partially-created file
|
|
@@ -302,6 +302,52 @@ function createV7(db) {
|
|
|
302
302
|
`);
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
+
// v8 (usage-vendor-rewrite WP-3, design §5 D-7/D-8): the non-destructive re-read scratch
|
|
306
|
+
// state for CLAUDE files. Claude Code rewrites a large transcript after compaction -- it
|
|
307
|
+
// removes every row before the last compact boundary and renames a new file over the old
|
|
308
|
+
// path -- so a re-read from 0 sees FEWER rows than the reading that wrote the ledger's
|
|
309
|
+
// facts. Until this version the reset deleted the file's facts up front, which destroyed
|
|
310
|
+
// real, already-recorded usage (the measured incident: 4.5 days of one lead session's calls
|
|
311
|
+
// and every launch receipt). The two tables here make the re-read a snapshot refresh
|
|
312
|
+
// instead of a retraction (D-7) while keeping today's safety for a fact whose row IS still
|
|
313
|
+
// present but which the new reading no longer emits (D-8):
|
|
314
|
+
//
|
|
315
|
+
// * usage_reread_prior -- the keys of the file's prior facts, snapshotted on the first
|
|
316
|
+
// slice of a re-read instead of deleting them. `fact_key` is the JSON array of the
|
|
317
|
+
// fact's primary-key values in PK column order, so it is comparable as text and
|
|
318
|
+
// rebuildable in SQL (json_array) and in JS (JSON.stringify) identically. `vendor_id`
|
|
319
|
+
// is the provider id a fact can be matched against what the new reading OBSERVED;
|
|
320
|
+
// NULL means the identity is an older form nothing can match (swept at EOF, which is
|
|
321
|
+
// exactly today's behaviour for a stale key).
|
|
322
|
+
// * usage_reread_seen -- the vendor ids the re-read actually SAW, in three kinds:
|
|
323
|
+
// 'response' (an assistant message.id), 'prompt' (the id of a row the parser accepted as a
|
|
324
|
+
// prompt row -- never a later row of the same turn, which carries the same promptId) and
|
|
325
|
+
// 'tool_use' (a tool_use block id).
|
|
326
|
+
//
|
|
327
|
+
// Both are per-file scratch: they are cleared for the file in the same transaction as the
|
|
328
|
+
// slice that reaches EOF. They are bounded by that file's own fact count. Codex files never
|
|
329
|
+
// write here -- they keep the eager reset delete (D-10).
|
|
330
|
+
//
|
|
331
|
+
// It is a pure CREATE TABLE step (no data rewrite), so the migration is inherently re-run
|
|
332
|
+
// safe and idempotent.
|
|
333
|
+
function createV8(db) {
|
|
334
|
+
db.exec(`
|
|
335
|
+
CREATE TABLE IF NOT EXISTS usage_reread_prior (
|
|
336
|
+
file_id INTEGER NOT NULL,
|
|
337
|
+
kind TEXT NOT NULL CHECK(kind IN ('call','prompt','alias','spawn','delegation','attempt')),
|
|
338
|
+
fact_key TEXT NOT NULL, -- JSON array of the fact's primary-key values, in PK column order
|
|
339
|
+
vendor_id TEXT, -- NULL = not derivable (older identity form) -> swept at EOF
|
|
340
|
+
PRIMARY KEY(file_id, kind, fact_key)
|
|
341
|
+
) WITHOUT ROWID;
|
|
342
|
+
CREATE TABLE IF NOT EXISTS usage_reread_seen (
|
|
343
|
+
file_id INTEGER NOT NULL,
|
|
344
|
+
kind TEXT NOT NULL CHECK(kind IN ('response','prompt','tool_use')),
|
|
345
|
+
vendor_id TEXT NOT NULL,
|
|
346
|
+
PRIMARY KEY(file_id, kind, vendor_id)
|
|
347
|
+
) WITHOUT ROWID;
|
|
348
|
+
`);
|
|
349
|
+
}
|
|
350
|
+
|
|
305
351
|
// Built lazily on first use so merely requiring this module has no side effects
|
|
306
352
|
// (no module-level runner construction, no DDL, no env reads).
|
|
307
353
|
let _runner = null;
|
|
@@ -323,6 +369,7 @@ function runner() {
|
|
|
323
369
|
5: { up: createV5, label: 'v5 prompt native turn id' },
|
|
324
370
|
6: { up: createV6, label: 'v6 delegation edges' },
|
|
325
371
|
7: { up: createV7, label: 'v7 delegation launch attempts' },
|
|
372
|
+
8: { up: createV8, label: 'v8 claude re-read snapshot' },
|
|
326
373
|
},
|
|
327
374
|
baseline: (db) => {
|
|
328
375
|
createV1(db);
|
|
@@ -332,6 +379,7 @@ function runner() {
|
|
|
332
379
|
createV5(db);
|
|
333
380
|
createV6(db);
|
|
334
381
|
createV7(db);
|
|
382
|
+
createV8(db);
|
|
335
383
|
},
|
|
336
384
|
versionStore: pragmaVersionStore(),
|
|
337
385
|
});
|