create-walle 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/lib/release-schema.json +2 -2
- package/lib/runtime-closure-policy.json +8 -7
- package/package.json +1 -1
- package/template/coding-task-manager/api-prompts.js +45 -7
- package/template/coding-task-manager/bin/claude-hook.js +55 -1
- package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
- package/template/coding-task-manager/bin/land.js +2069 -0
- package/template/coding-task-manager/bin/memory-census.js +4 -2
- package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
- package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
- package/template/coding-task-manager/db.js +156 -32
- package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
- package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
- package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
- package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
- package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
- package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
- package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
- package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
- package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
- package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
- package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
- package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
- package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
- package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
- package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
- package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
- package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
- package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
- package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
- package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
- package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
- package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
- package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
- package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
- package/template/coding-task-manager/lib/agent-definitions.js +19 -0
- package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
- package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
- package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
- package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
- package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
- package/template/coding-task-manager/lib/agent-presets.js +84 -1
- package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
- package/template/coding-task-manager/lib/agent-version-service.js +74 -11
- package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
- package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
- package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
- package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
- package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
- package/template/coding-task-manager/lib/api/fleet.js +118 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +9 -1
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machines.js +691 -2
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/session-attach.js +623 -0
- package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
- package/template/coding-task-manager/lib/api/sessions.js +77 -51
- package/template/coding-task-manager/lib/api/setup-network.js +544 -16
- package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
- package/template/coding-task-manager/lib/api/setup.js +829 -10
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
- package/template/coding-task-manager/lib/auth-rules.js +292 -21
- package/template/coding-task-manager/lib/background-stop.js +369 -0
- package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
- package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
- package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
- package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
- package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
- package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
- package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
- package/template/coding-task-manager/lib/conversation-sync.js +355 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
- package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
- package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
- package/template/coding-task-manager/lib/db-domains.js +1 -0
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
- package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
- package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +4 -0
- package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
- package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
- package/template/coding-task-manager/lib/fleet-hub.js +762 -0
- package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
- package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
- package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
- package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
- package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
- package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
- package/template/coding-task-manager/lib/fleet-update.js +798 -0
- package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
- package/template/coding-task-manager/lib/fs-watcher.js +58 -42
- package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
- package/template/coding-task-manager/lib/headless-term-service.js +84 -8
- package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
- package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
- package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
- package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
- package/template/coding-task-manager/lib/host-handoff.js +16 -19
- package/template/coding-task-manager/lib/host-stats.js +150 -3
- package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
- package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
- package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
- package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
- package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
- package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
- package/template/coding-task-manager/lib/hub-bridge.js +398 -0
- package/template/coding-task-manager/lib/idle-notify.js +491 -0
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
- package/template/coding-task-manager/lib/instance-manifest.js +5 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
- package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
- package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
- package/template/coding-task-manager/lib/landing/config.js +536 -0
- package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
- package/template/coding-task-manager/lib/landing/gate.js +360 -0
- package/template/coding-task-manager/lib/landing/git.js +344 -0
- package/template/coding-task-manager/lib/landing/lease.js +247 -0
- package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
- package/template/coding-task-manager/lib/landing/proof.js +223 -0
- package/template/coding-task-manager/lib/landing/queue.js +998 -0
- package/template/coding-task-manager/lib/landing/radar.js +489 -0
- package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
- package/template/coding-task-manager/lib/landing/state.js +263 -0
- package/template/coding-task-manager/lib/landing/stop.js +49 -0
- package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
- package/template/coding-task-manager/lib/landing/sync.js +456 -0
- package/template/coding-task-manager/lib/landing/train.js +885 -0
- package/template/coding-task-manager/lib/landing/window.js +57 -0
- package/template/coding-task-manager/lib/launch-environment.js +121 -0
- package/template/coding-task-manager/lib/launch-model-override.js +36 -10
- package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
- package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
- package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
- package/template/coding-task-manager/lib/lead-model-options.js +160 -3
- package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
- package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
- package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
- package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
- package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
- package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
- package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
- package/template/coding-task-manager/lib/machine-registry.js +750 -5
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
- package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
- package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
- package/template/coding-task-manager/lib/memory-join.js +337 -0
- package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
- package/template/coding-task-manager/lib/memory-sync.js +565 -0
- package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
- package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
- package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
- package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
- package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
- package/template/coding-task-manager/lib/model-availability.js +727 -0
- package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
- package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
- package/template/coding-task-manager/lib/model-id-rule.js +19 -0
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
- package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
- package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
- package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
- package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
- package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +6 -4
- package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
- package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
- package/template/coding-task-manager/lib/opencode-cli.js +480 -0
- package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
- package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
- package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
- package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
- package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
- package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
- package/template/coding-task-manager/lib/perf-summary.js +7 -0
- package/template/coding-task-manager/lib/perf-tracker.js +63 -2
- package/template/coding-task-manager/lib/project-config.js +7 -0
- package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/read-pool-client.js +89 -2
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
- package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
- package/template/coding-task-manager/lib/relay-client.js +57 -3
- package/template/coding-task-manager/lib/relink-audit.js +34 -5
- package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
- package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
- package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
- package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
- package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
- package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
- package/template/coding-task-manager/lib/restart-guard.js +18 -6
- package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
- package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
- package/template/coding-task-manager/lib/resume-admission.js +17 -3
- package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
- package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
- package/template/coding-task-manager/lib/runtime-contract.js +3 -1
- package/template/coding-task-manager/lib/schema-indexes.js +1 -0
- package/template/coding-task-manager/lib/session-context-locator.js +742 -0
- package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
- package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
- package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
- package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
- package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
- package/template/coding-task-manager/lib/session-create/response.js +7 -7
- package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
- package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
- package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
- package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
- package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-host-manager.js +60 -0
- package/template/coding-task-manager/lib/session-jobs.js +3 -1
- package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
- package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
- package/template/coding-task-manager/lib/session-park.js +738 -0
- package/template/coding-task-manager/lib/session-path-grant.js +13 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
- package/template/coding-task-manager/lib/session-transport.js +17 -0
- package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
- package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
- package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
- package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
- package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
- package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
- package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
- package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
- package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
- package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
- package/template/coding-task-manager/lib/submission-ack.js +90 -2
- package/template/coding-task-manager/lib/systemd-scope.js +115 -0
- package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
- package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
- package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
- package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
- package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
- package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
- package/template/coding-task-manager/lib/transcript-source.js +36 -4
- package/template/coding-task-manager/lib/transcript-store.js +9 -0
- package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
- package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
- package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
- package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
- package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
- package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
- package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
- package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
- package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
- package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
- package/template/coding-task-manager/lib/walle/turn.js +1 -1
- package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
- package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
- package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
- package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
- package/template/coding-task-manager/lib/walle-row-history.js +495 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
- package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
- package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
- package/template/coding-task-manager/lib/ws/misc.js +1 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
- package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
- package/template/coding-task-manager/oauth-proxy.js +112 -115
- package/template/coding-task-manager/package-lock.json +10 -94
- package/template/coding-task-manager/package.json +4 -3
- package/template/coding-task-manager/protocol/message-table.json +10 -0
- package/template/coding-task-manager/protocol/messages.js +10 -0
- package/template/coding-task-manager/protocol/ws-schema.json +20 -0
- package/template/coding-task-manager/protocol/ws-schema.md +2 -0
- package/template/coding-task-manager/public/css/app.css +170 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +473 -243
- package/template/coding-task-manager/public/js/agent-command.js +86 -0
- package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
- package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
- package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
- package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
- package/template/coding-task-manager/public/js/background-work.js +196 -27
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
- package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
- package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
- package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
- package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
- package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
- package/template/coding-task-manager/public/js/document-review-links.js +9 -1
- package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
- package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
- package/template/coding-task-manager/public/js/message-renderer.js +4 -3
- package/template/coding-task-manager/public/js/model-picker.js +3 -1
- package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
- package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
- package/template/coding-task-manager/public/js/pasted-content.js +236 -0
- package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
- package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
- package/template/coding-task-manager/public/js/prompts.js +11 -10
- package/template/coding-task-manager/public/js/protocol.js +10 -0
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
- package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
- package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
- package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
- package/template/coding-task-manager/public/js/stream-view.js +6 -5
- package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
- package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
- package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
- package/template/coding-task-manager/public/js/walle.js +6 -0
- package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
- package/template/coding-task-manager/public/m/app.css +140 -0
- package/template/coding-task-manager/public/m/app.js +507 -68
- package/template/coding-task-manager/public/m/index.html +17 -0
- package/template/coding-task-manager/public/m/machines.js +838 -4
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
- package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
- package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
- package/template/coding-task-manager/server.js +1950 -11679
- package/template/coding-task-manager/session-integrity.js +64 -4
- package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
- package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
- package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
- package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
- package/template/coding-task-manager/workers/session-host-process.js +5 -5
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +168 -33
- package/template/ctm-relay/lib/protocol.js +14 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/shared/backup-retention.js +82 -0
- package/template/shared/conversation-admission.js +2 -0
- package/template/shared/conversation-provenance.js +3 -7
- package/template/shared/conversation-storage-v2-contract.js +5 -0
- package/template/shared/linked-worktree.js +51 -0
- package/template/shared/macos-fda-target.js +57 -0
- package/template/shared/orphan-parents.js +55 -0
- package/template/shared/release-schema.json +2 -2
- package/template/shared/storage/contract.js +3 -0
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +71 -4
- package/template/wall-e/api-walle.js +21 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
- package/template/wall-e/brain/brain-join.js +859 -0
- package/template/wall-e/brain/brain-sync-membership.js +20 -0
- package/template/wall-e/brain/brain-sync-store.js +131 -77
- package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
- package/template/wall-e/brain/brain-sync-v2.js +578 -0
- package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
- package/template/wall-e/brain/deterministic-id.js +51 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +40 -6
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +23 -7
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +171 -35
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/config/main-loop-exemptions.json +2 -2
- package/template/wall-e/http/admin-api.js +37 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +7 -1
- package/template/wall-e/http/model-admin.js +8 -1
- package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
- package/template/wall-e/http/model-proxy-providers.js +174 -1
- package/template/wall-e/http/model-route-health.js +157 -0
- package/template/wall-e/http/sync-api.js +278 -464
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/ctm-data-dir.js +26 -0
- package/template/wall-e/lib/derivation-home.js +147 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
- package/template/wall-e/lib/helper-rules/grade.js +51 -8
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
- package/template/wall-e/lib/helper-rules/store.js +4 -2
- package/template/wall-e/lib/landing-mcp-tools.js +170 -0
- package/template/wall-e/lib/mcp-client-config.js +133 -14
- package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
- package/template/wall-e/lib/mcp-integration.js +58 -13
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
- package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
- package/template/wall-e/llm/delegate-vendor-default.js +12 -5
- package/template/wall-e/llm/model-roles.js +1 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +66 -17
- package/template/wall-e/loops/brain-custom-writes.js +19 -0
- package/template/wall-e/loops/ingest.js +17 -1
- package/template/wall-e/loops/think.js +19 -4
- package/template/wall-e/mcp-contract.js +222 -6
- package/template/wall-e/mcp-protocol-contract.js +40 -5
- package/template/wall-e/mcp-server.js +128 -29
- package/template/wall-e/mcp-worker-schemas.js +5 -5
- package/template/wall-e/memory/ctm-context-client.js +85 -0
- package/template/wall-e/memory/ctm-session-context.js +9 -3
- package/template/wall-e/memory/hub-bridge-client.js +388 -0
- package/template/wall-e/memory/replica-origin.js +56 -0
- package/template/wall-e/memory/session-pool.js +135 -0
- package/template/wall-e/runtime/live-capabilities.js +8 -3
- package/template/wall-e/server.js +4 -2
- package/template/wall-e/shared/release-schema.json +2 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/storage/contract.js +3 -0
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
- package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
- package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
- package/template/wall-e/tools/chrome-automation.js +6 -0
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +18 -4
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
|
@@ -8,12 +8,64 @@
|
|
|
8
8
|
// legitimately reaches deep into server.js internals (perf tracker, main-DB
|
|
9
9
|
// census, event-loop lag state, etc.) — the handler body stays put, only the
|
|
10
10
|
// route registration/dispatch wiring moves here.
|
|
11
|
+
//
|
|
12
|
+
// Landing-throughput WP-5 shard S4 (design doc §5 D-10 "move-only", §6 "Shard
|
|
13
|
+
// module seam", §8 WP-5, §9 S-21..S-27): two more handlers move out of server.js
|
|
14
|
+
// VERBATIM -- apiDiagnosticsClientHealth (POST /api/diagnostics/client-health)
|
|
15
|
+
// and apiDiagnosticsPerfSummary (GET /api/diagnostics/perf-summary). Each body is
|
|
16
|
+
// identical to server.js's declaration except for the `_deps.` prefix on every
|
|
17
|
+
// identifier that used to resolve to a server.js top-level binding (D-10 rule 1),
|
|
18
|
+
// proven by `node bin/move-only-check.js`. Their route-table entries now call the
|
|
19
|
+
// module-local declarations directly (setup.js's apiSetupTestKey precedent) rather
|
|
20
|
+
// than a configured handler. Injected deps, per function:
|
|
21
|
+
// apiDiagnosticsClientHealth: RESUME_CLIENT_BEACON_METRICS, _clientHealthReports,
|
|
22
|
+
// _ctmDbWorker, _ctmReadPool, _ctmWorktreeWorker, _eventLoopIncidents,
|
|
23
|
+
// _mainloopDiagLogger, _providerIdFromCmd, _recentClientHealthIncidents,
|
|
24
|
+
// _recentClientHealthLifecycleEvents, _resumeClientMetricRollup,
|
|
25
|
+
// _stateSyncClientLedger, _typingInteractionTelemetryEnabled,
|
|
26
|
+
// correlateClientHealthIncident, firstMissingStateSyncBoundary,
|
|
27
|
+
// formatInputPerformanceHeadline, readJsonRequestBody, recordSessionDiagnostic,
|
|
28
|
+
// routeKeyboardIncidentToMainloopDiag, sanitizeClientHealthEnvelope,
|
|
29
|
+
// sanitizeClientHealthLifecycleEnvelope, sanitizeClientHealthMemorySample,
|
|
30
|
+
// sanitizeProcessLanes, sanitizeResumeClientMetric, sendJsonResponse, sessions,
|
|
31
|
+
// summarizePerformanceEvidence, telemetry
|
|
32
|
+
// apiDiagnosticsPerfSummary: CTM_BROWSER_QOS_V2_ENABLED,
|
|
33
|
+
// CTM_STREAM_STATUS_PATCH_V2_ENABLED, _controlSnapshot,
|
|
34
|
+
// _conversationUpdateOutboxBackoff, _ctmDbWorker, _ctmReadPool,
|
|
35
|
+
// _degradedOperations, _desktopIndex, _eventLoopIncidents,
|
|
36
|
+
// _exitedSnapshotBudget, _heartbeatDirtyQueue, _historyBreakerSnapshot,
|
|
37
|
+
// _historyWindowBudget, _loadPressure, _mainDbCensus, _msgResponseCache,
|
|
38
|
+
// _perfTracker, _readPerfCertificationLedger, _recentCatalogBuildInFlight,
|
|
39
|
+
// _recentCatalogGeneration, _recentCatalogMetrics, _recentCatalogPublished,
|
|
40
|
+
// _reclaimRecorder, _runtimeEventBuffer, _sessionResourceSampler,
|
|
41
|
+
// _stateSyncClientLedger, _stateSyncUnknownSubscriptionRejected, _syncIoCensus,
|
|
42
|
+
// _terminalSnapshotBudget, _terminalTailState, _transcriptRoots, _trimCadence,
|
|
43
|
+
// _typingInteractionTelemetryEnabled, _typingInteractionTraces,
|
|
44
|
+
// _visibleRevisionWatchdogEnabled, _walCheckpointMetrics, buildMemoryLedger,
|
|
45
|
+
// buildPerfSummary, dbModule, errorSink, fetchMcpGatewayLedgerStatus,
|
|
46
|
+
// getBackgroundLlmRouteStats, getBroadcastReasonStats, getMainThreadWriteEscapeStats, getWorkerLoopLag,
|
|
47
|
+
// headlessWorker, sessionDiagnostics, sessionHostManager
|
|
48
|
+
// Eight of those are MUTABLE server.js bindings, so server.js injects them as
|
|
49
|
+
// getters (D-10 rule 2), never copied at configure() time: _ctmDbWorker,
|
|
50
|
+
// _ctmReadPool, _ctmWorktreeWorker, _recentCatalogBuildInFlight,
|
|
51
|
+
// _recentCatalogGeneration, _recentCatalogPublished,
|
|
52
|
+
// _stateSyncUnknownSubscriptionRejected, _transcriptRoots. Everything else
|
|
53
|
+
// (functions, const objects never reassigned) is passed by value. `configure`
|
|
54
|
+
// therefore keeps the caller's options object by reference instead of
|
|
55
|
+
// destructuring it -- destructuring would invoke each getter once and freeze a
|
|
56
|
+
// null snapshot of the worker clients (session-messages.js's seam is the
|
|
57
|
+
// precedent).
|
|
11
58
|
|
|
12
59
|
|
|
13
60
|
const { registerApiRoutes } = require('../api-router');
|
|
14
61
|
const { buildRestartReceipts, readRestartLedgerEntries } = require('../restart-ledger');
|
|
15
62
|
const { causalTraceDiagnostics } = require('../../../shared/causal-trace');
|
|
16
63
|
const { readContextBudgetRecord } = require('../context-budget-record');
|
|
64
|
+
// WP-3 (box-idle-sleep-remote-typing-freezes-2026-11-01.html §8 WP-3): the frame-receipt exit
|
|
65
|
+
// counters live in lib/ws/state-sync.js and are read through its own getter -- this route takes a
|
|
66
|
+
// direct module dependency, never a server.js one (the counters are module-level, so the numbers are
|
|
67
|
+
// process-lifetime regardless of which server instance reads them).
|
|
68
|
+
const { getFrameReceiptExitCounts } = require('../ws/state-sync');
|
|
17
69
|
const os = require('os');
|
|
18
70
|
|
|
19
71
|
// WP-0b (attributable restarts, round-2 R1 residual): unlike every other handler in this
|
|
@@ -63,6 +115,27 @@ async function apiContextBudget(req, res, url) {
|
|
|
63
115
|
}
|
|
64
116
|
}
|
|
65
117
|
|
|
118
|
+
// WP-3 (box-idle-sleep-remote-typing-freezes-2026-11-01.html §5 D-7, §6 WP-3, §8 WP-3, §11 A-5):
|
|
119
|
+
// read-only readout of lib/ws/state-sync.js's process-lifetime frame-receipt exit counters. Like
|
|
120
|
+
// apiDiagnosticsRestarts/apiContextBudget above, it owns its FULL body here -- it needs no server.js
|
|
121
|
+
// internals, only the state-sync module's getter, so there is nothing to gain from the usual
|
|
122
|
+
// dispatch-only split. `since` is process start in ms (the counters are module-level and the module
|
|
123
|
+
// loads at boot), so a reader can age the numbers without a second request. Pure observation: this
|
|
124
|
+
// handler neither reads nor touches the per-peer rate limiter or any receipt handling.
|
|
125
|
+
async function apiDiagnosticsReceiptExits(req, res, url) {
|
|
126
|
+
try {
|
|
127
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
128
|
+
res.end(JSON.stringify({
|
|
129
|
+
ok: true,
|
|
130
|
+
counts: getFrameReceiptExitCounts(),
|
|
131
|
+
since: Date.now() - Math.round(process.uptime() * 1000),
|
|
132
|
+
}));
|
|
133
|
+
} catch (e) {
|
|
134
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
135
|
+
res.end(JSON.stringify({ ok: false, error: e.message }));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
66
139
|
function causalTraceDiagnosticPayload(traceIdInput) {
|
|
67
140
|
const traceId = String(traceIdInput || '');
|
|
68
141
|
if (!/^[0-9a-f]{32}$/.test(traceId) || /^0+$/.test(traceId)) {
|
|
@@ -73,72 +146,8 @@ function causalTraceDiagnosticPayload(traceIdInput) {
|
|
|
73
146
|
|
|
74
147
|
let _deps = null;
|
|
75
148
|
|
|
76
|
-
function configure({
|
|
77
|
-
|
|
78
|
-
apiDiagnosticsClientHealthPing,
|
|
79
|
-
apiDiagnosticsLifecycle,
|
|
80
|
-
apiDiagnosticsSessionResources,
|
|
81
|
-
apiDiagnosticsSessionDiagnostics,
|
|
82
|
-
apiDiagnosticsClientHealthRecent,
|
|
83
|
-
apiDiagnosticsResumeMetrics,
|
|
84
|
-
apiDiagnosticsRestartOutcomes,
|
|
85
|
-
apiDiagnosticsTestBlockMain,
|
|
86
|
-
pairableOrigins,
|
|
87
|
-
apiDiagnosticsTestCodexBurst,
|
|
88
|
-
apiDiagnosticsClientHealth,
|
|
89
|
-
apiDiagnosticsWriteLock,
|
|
90
|
-
apiDiagnosticsVersion,
|
|
91
|
-
apiDiagnosticsDbOwner,
|
|
92
|
-
apiDiagnosticsConversationFreshness,
|
|
93
|
-
apiDiagnosticsConversationImport,
|
|
94
|
-
apiDiagnosticsDbCensus,
|
|
95
|
-
apiDiagnosticsMainDbTop,
|
|
96
|
-
apiDiagnosticsUploads,
|
|
97
|
-
apiDiagnosticsTestDbOwnerWedge,
|
|
98
|
-
apiDiagnosticsPerfSummary,
|
|
99
|
-
apiDiagnosticsMainDbBudget,
|
|
100
|
-
apiDiagnosticsFsCensus,
|
|
101
|
-
apiDiagnosticsEventLoop,
|
|
102
|
-
apiDiagnosticsRestoreAdmission,
|
|
103
|
-
apiDiagnosticsMainWatchdog,
|
|
104
|
-
apiDiagnosticsWatcher,
|
|
105
|
-
apiDiagnosticsRenderChurn,
|
|
106
|
-
apiDiagnosticsSessionViewers,
|
|
107
|
-
apiDiagnosticsSubmissions,
|
|
108
|
-
} = {}) {
|
|
109
|
-
_deps = {
|
|
110
|
-
apiDiagnosticsClientFreeze,
|
|
111
|
-
apiDiagnosticsClientHealthPing,
|
|
112
|
-
apiDiagnosticsLifecycle,
|
|
113
|
-
apiDiagnosticsSessionResources,
|
|
114
|
-
apiDiagnosticsSessionDiagnostics,
|
|
115
|
-
apiDiagnosticsClientHealthRecent,
|
|
116
|
-
apiDiagnosticsResumeMetrics,
|
|
117
|
-
apiDiagnosticsRestartOutcomes,
|
|
118
|
-
apiDiagnosticsTestBlockMain,
|
|
119
|
-
pairableOrigins,
|
|
120
|
-
apiDiagnosticsTestCodexBurst,
|
|
121
|
-
apiDiagnosticsClientHealth,
|
|
122
|
-
apiDiagnosticsWriteLock,
|
|
123
|
-
apiDiagnosticsVersion,
|
|
124
|
-
apiDiagnosticsDbOwner,
|
|
125
|
-
apiDiagnosticsConversationFreshness,
|
|
126
|
-
apiDiagnosticsConversationImport,
|
|
127
|
-
apiDiagnosticsDbCensus,
|
|
128
|
-
apiDiagnosticsMainDbTop,
|
|
129
|
-
apiDiagnosticsUploads,
|
|
130
|
-
apiDiagnosticsTestDbOwnerWedge,
|
|
131
|
-
apiDiagnosticsPerfSummary,
|
|
132
|
-
apiDiagnosticsMainDbBudget,
|
|
133
|
-
apiDiagnosticsFsCensus,
|
|
134
|
-
apiDiagnosticsEventLoop,
|
|
135
|
-
apiDiagnosticsRestoreAdmission,
|
|
136
|
-
apiDiagnosticsMainWatchdog,
|
|
137
|
-
apiDiagnosticsWatcher,
|
|
138
|
-
apiDiagnosticsRenderChurn,
|
|
139
|
-
apiDiagnosticsSessionViewers,
|
|
140
|
-
apiDiagnosticsSubmissions,
|
|
141
|
-
};
|
|
149
|
+
function configure(deps = {}) {
|
|
150
|
+
_deps = deps;
|
|
142
151
|
}
|
|
143
152
|
|
|
144
153
|
// RL-WP-4 (render-lane design D-6): a test harness DECLARES the origins a hermetic server may
|
|
@@ -202,7 +211,7 @@ function register() {
|
|
|
202
211
|
{ method: 'POST', path: '/api/diagnostics/test/pairable-origins', handler: (req, res, url) => apiDiagnosticsTestPairableOriginsSet(req, res, url) },
|
|
203
212
|
{ method: 'DELETE', path: '/api/diagnostics/test/pairable-origins', handler: (req, res, url) => apiDiagnosticsTestPairableOriginsClear(req, res, url) },
|
|
204
213
|
{ method: 'POST', path: '/api/diagnostics/test/codex-burst', handler: (req, res, url) => _deps.apiDiagnosticsTestCodexBurst(req, res, url) },
|
|
205
|
-
{ method: 'POST', path: '/api/diagnostics/client-health', handler: (req, res, url) =>
|
|
214
|
+
{ method: 'POST', path: '/api/diagnostics/client-health', handler: (req, res, url) => apiDiagnosticsClientHealth(req, res, url) },
|
|
206
215
|
{ method: 'GET', path: '/api/diagnostics/write-lock', handler: (req, res, url) => _deps.apiDiagnosticsWriteLock(req, res, url) },
|
|
207
216
|
{ method: 'GET', path: '/api/diagnostics/version', handler: (req, res, url) => _deps.apiDiagnosticsVersion(req, res, url) },
|
|
208
217
|
{ method: 'GET', path: '/api/diagnostics/db-owner', handler: (req, res, url) => _deps.apiDiagnosticsDbOwner(req, res, url) },
|
|
@@ -212,7 +221,7 @@ function register() {
|
|
|
212
221
|
{ method: 'GET', path: '/api/diagnostics/main-db-top', handler: (req, res, url) => _deps.apiDiagnosticsMainDbTop(req, res, url) },
|
|
213
222
|
{ method: 'GET', path: '/api/diagnostics/uploads', handler: (req, res, url) => _deps.apiDiagnosticsUploads(req, res, url) },
|
|
214
223
|
{ method: 'POST', path: '/api/diagnostics/test/db-owner-wedge', handler: (req, res, url) => _deps.apiDiagnosticsTestDbOwnerWedge(req, res, url) },
|
|
215
|
-
{ method: 'GET', path: '/api/diagnostics/perf-summary', handler: (req, res, url) =>
|
|
224
|
+
{ method: 'GET', path: '/api/diagnostics/perf-summary', handler: (req, res, url) => apiDiagnosticsPerfSummary(req, res, url) },
|
|
216
225
|
{ method: 'GET', path: '/api/diagnostics/main-db-budget', handler: (req, res, url) => _deps.apiDiagnosticsMainDbBudget(req, res, url) },
|
|
217
226
|
{ method: 'GET', path: '/api/diagnostics/fs-census', handler: (req, res, url) => _deps.apiDiagnosticsFsCensus(req, res, url) },
|
|
218
227
|
{ method: 'GET', path: '/api/diagnostics/event-loop', handler: (req, res, url) => _deps.apiDiagnosticsEventLoop(req, res, url) },
|
|
@@ -223,8 +232,479 @@ function register() {
|
|
|
223
232
|
{ method: 'GET', path: '/api/diagnostics/session-viewers', handler: (req, res, url) => _deps.apiDiagnosticsSessionViewers(req, res, url) },
|
|
224
233
|
{ method: 'GET', path: '/api/diagnostics/submissions', handler: (req, res, url) => _deps.apiDiagnosticsSubmissions(req, res, url) },
|
|
225
234
|
{ method: 'GET', path: '/api/diagnostics/restarts', handler: (req, res, url) => apiDiagnosticsRestarts(req, res, url) },
|
|
235
|
+
// WP-3 (box-idle-sleep-remote-typing-freezes-2026-11-01.html §8 WP-3): process-lifetime
|
|
236
|
+
// frame-receipt exit counters (read-only; the next live measurement names where a hub-typed
|
|
237
|
+
// keystroke's `painted` receipt dies on the box).
|
|
238
|
+
{ method: 'GET', path: '/api/diagnostics/receipt-exits', handler: (req, res, url) => apiDiagnosticsReceiptExits(req, res, url) },
|
|
226
239
|
{ method: 'GET', path: '/api/context-budget', handler: (req, res, url) => apiContextBudget(req, res, url) },
|
|
227
240
|
]);
|
|
228
241
|
}
|
|
229
242
|
|
|
230
|
-
|
|
243
|
+
async function apiDiagnosticsClientHealth(req, res, url) {
|
|
244
|
+
try {
|
|
245
|
+
// Fresh-load LoAF evidence can contain up to 20 frames x 8 bounded script
|
|
246
|
+
// descriptors. Admit that bounded pre-sanitization shape, then let
|
|
247
|
+
// sanitizeClientHealthEnvelope enforce the retained field and string caps.
|
|
248
|
+
const raw = await _deps.readJsonRequestBody(req, { limitBytes: 128 * 1024 });
|
|
249
|
+
// Layered-resume and switch beacons use a compact metric shape on the existing endpoint.
|
|
250
|
+
if (raw && typeof raw === 'object' && _deps.RESUME_CLIENT_BEACON_METRICS.has(raw.metric)) {
|
|
251
|
+
const metric = _deps.sanitizeResumeClientMetric(raw);
|
|
252
|
+
if (!metric) {
|
|
253
|
+
return _deps.sendJsonResponse(res, 400, { ok: false, error: 'sessionId and ms are required' });
|
|
254
|
+
}
|
|
255
|
+
const { sessionId, ms } = metric;
|
|
256
|
+
const rateKey = `resume-metric:${sessionId}`;
|
|
257
|
+
const now = Date.now();
|
|
258
|
+
const prior = _deps._clientHealthReports.get(rateKey) || { windowStartedAt: now, count: 0, events: new Set() };
|
|
259
|
+
if (now - prior.windowStartedAt >= 60_000) {
|
|
260
|
+
prior.windowStartedAt = now;
|
|
261
|
+
prior.count = 0;
|
|
262
|
+
prior.events.clear();
|
|
263
|
+
}
|
|
264
|
+
if (prior.count >= 240) return _deps.sendJsonResponse(res, 429, { ok: false, error: 'client-health rate limit exceeded' });
|
|
265
|
+
prior.count += 1;
|
|
266
|
+
_deps._clientHealthReports.set(rateKey, prior);
|
|
267
|
+
if (_deps._clientHealthReports.size > 500) _deps._clientHealthReports.delete(_deps._clientHealthReports.keys().next().value);
|
|
268
|
+
_deps._resumeClientMetricRollup.add(metric, now);
|
|
269
|
+
_deps.recordSessionDiagnostic(sessionId, 'resume-client-metric', metric);
|
|
270
|
+
try {
|
|
271
|
+
_deps.telemetry.track(metric.metric, {
|
|
272
|
+
duration_ms: ms,
|
|
273
|
+
l0_outcome: metric.l0Outcome,
|
|
274
|
+
switch_path: metric.switchPath,
|
|
275
|
+
hot_reject_reason: metric.hotRejectReason,
|
|
276
|
+
kind: metric.kind,
|
|
277
|
+
frozen_frame_path: metric.path,
|
|
278
|
+
frozen_frame_font_faithful: metric.fontFaithful,
|
|
279
|
+
frozen_frame_cover_ms: metric.coverMs,
|
|
280
|
+
frozen_frame_max_age_hit: metric.maxAgeHit,
|
|
281
|
+
frozen_frame_activation_epoch: metric.activationEpoch,
|
|
282
|
+
});
|
|
283
|
+
} catch {}
|
|
284
|
+
return _deps.sendJsonResponse(res, 200, { ok: true });
|
|
285
|
+
}
|
|
286
|
+
// WP-1 (design/ctm-memory-footprint-round2-2026-08-14 §6): Poisson-sampled renderer
|
|
287
|
+
// memory beacon riding this same channel. Unprotected 'client-memory' event — the
|
|
288
|
+
// default 120/session ring + DB caps are fine for a trend metric (no db.js change).
|
|
289
|
+
// Kept ahead of the lifecycle branch below (own recordType tag, own rate key) so
|
|
290
|
+
// neither route's dedupe/count bookkeeping observes the other's traffic.
|
|
291
|
+
if (raw?.recordType === 'client-memory') {
|
|
292
|
+
const memorySample = _deps.sanitizeClientHealthMemorySample(raw);
|
|
293
|
+
if (!memorySample) {
|
|
294
|
+
return _deps.sendJsonResponse(res, 400, { ok: false, error: 'invalid client-memory sample' });
|
|
295
|
+
}
|
|
296
|
+
const rateKey = `client-memory:${memorySample.sessionId}`;
|
|
297
|
+
const now = Date.now();
|
|
298
|
+
const prior = _deps._clientHealthReports.get(rateKey) || { windowStartedAt: now, count: 0, events: new Set() };
|
|
299
|
+
if (now - prior.windowStartedAt >= 60_000) {
|
|
300
|
+
prior.windowStartedAt = now;
|
|
301
|
+
prior.count = 0;
|
|
302
|
+
prior.events.clear();
|
|
303
|
+
}
|
|
304
|
+
if (prior.count >= 20) return _deps.sendJsonResponse(res, 429, { ok: false, error: 'client-health rate limit exceeded' });
|
|
305
|
+
prior.count += 1;
|
|
306
|
+
_deps._clientHealthReports.set(rateKey, prior);
|
|
307
|
+
if (_deps._clientHealthReports.size > 500) _deps._clientHealthReports.delete(_deps._clientHealthReports.keys().next().value);
|
|
308
|
+
_deps.recordSessionDiagnostic(memorySample.sessionId, 'client-memory', memorySample.sample);
|
|
309
|
+
return _deps.sendJsonResponse(res, 200, { ok: true, recordType: 'client-memory' });
|
|
310
|
+
}
|
|
311
|
+
if (raw?.recordType === 'lifecycle') {
|
|
312
|
+
const lifecycle = _deps.sanitizeClientHealthLifecycleEnvelope(raw);
|
|
313
|
+
if (!lifecycle) {
|
|
314
|
+
return _deps.sendJsonResponse(res, 400, { ok: false, error: 'invalid lifecycle envelope' });
|
|
315
|
+
}
|
|
316
|
+
const rateKey = `lifecycle:${lifecycle.tabIdHash}:${lifecycle.runIdHash}`;
|
|
317
|
+
const now = Date.now();
|
|
318
|
+
const prior = _deps._clientHealthReports.get(rateKey) || { windowStartedAt: now, count: 0, events: new Set() };
|
|
319
|
+
if (now - prior.windowStartedAt >= 60_000) {
|
|
320
|
+
prior.windowStartedAt = now;
|
|
321
|
+
prior.count = 0;
|
|
322
|
+
prior.events.clear();
|
|
323
|
+
}
|
|
324
|
+
const duplicate = prior.events.has(lifecycle.eventId)
|
|
325
|
+
|| _deps._recentClientHealthLifecycleEvents.has(lifecycle.eventId);
|
|
326
|
+
if (!duplicate && prior.count >= 20) {
|
|
327
|
+
return _deps.sendJsonResponse(res, 429, { ok: false, error: 'client-health rate limit exceeded' });
|
|
328
|
+
}
|
|
329
|
+
if (!duplicate) prior.count += 1;
|
|
330
|
+
prior.events.add(lifecycle.eventId);
|
|
331
|
+
_deps._clientHealthReports.set(rateKey, prior);
|
|
332
|
+
if (_deps._clientHealthReports.size > 500) _deps._clientHealthReports.delete(_deps._clientHealthReports.keys().next().value);
|
|
333
|
+
_deps._recentClientHealthLifecycleEvents.upsert(lifecycle);
|
|
334
|
+
return _deps.sendJsonResponse(res, 200, { ok: true, duplicate, recordType: 'lifecycle' });
|
|
335
|
+
}
|
|
336
|
+
const envelope = _deps.sanitizeClientHealthEnvelope(raw);
|
|
337
|
+
if (!envelope.tabId || !envelope.runId || !envelope.incidentId) {
|
|
338
|
+
return _deps.sendJsonResponse(res, 400, { ok: false, error: 'tabId, runId, and incidentId are required' });
|
|
339
|
+
}
|
|
340
|
+
const rateKey = `${envelope.tabId}:${envelope.runId}`;
|
|
341
|
+
const now = Date.now();
|
|
342
|
+
const prior = _deps._clientHealthReports.get(rateKey) || { windowStartedAt: now, count: 0, events: new Set() };
|
|
343
|
+
if (now - prior.windowStartedAt >= 60_000) {
|
|
344
|
+
prior.windowStartedAt = now;
|
|
345
|
+
prior.count = 0;
|
|
346
|
+
prior.events.clear();
|
|
347
|
+
}
|
|
348
|
+
const eventKey = `${envelope.incidentId}:${envelope.phase}`;
|
|
349
|
+
if (prior.events.has(eventKey)) return _deps.sendJsonResponse(res, 200, { ok: true, duplicate: true });
|
|
350
|
+
if (prior.count >= 20) return _deps.sendJsonResponse(res, 429, { ok: false, error: 'client-health rate limit exceeded' });
|
|
351
|
+
prior.count += 1;
|
|
352
|
+
prior.events.add(eventKey);
|
|
353
|
+
_deps._clientHealthReports.set(rateKey, prior);
|
|
354
|
+
if (_deps._clientHealthReports.size > 500) _deps._clientHealthReports.delete(_deps._clientHealthReports.keys().next().value);
|
|
355
|
+
|
|
356
|
+
for (const row of envelope.stateSync) _deps._stateSyncClientLedger.mergeClientSnapshot(row);
|
|
357
|
+
const correlated = _deps.correlateClientHealthIncident(envelope.incident, _deps._eventLoopIncidents, envelope.clock);
|
|
358
|
+
// S-30: `latestForSession` now throws on an empty clientId -- an untrusted client-health
|
|
359
|
+
// payload can omit both `row.clientId` and `websocket.clientId`; treat that as "no row"
|
|
360
|
+
// rather than let a malformed beat 500 this endpoint.
|
|
361
|
+
const mergedRows = envelope.stateSync
|
|
362
|
+
.map((row) => {
|
|
363
|
+
const beatClientId = String(row.clientId || envelope.websocket.clientId || '');
|
|
364
|
+
return beatClientId ? _deps._stateSyncClientLedger.latestForSession(row.sessionId, beatClientId) : null;
|
|
365
|
+
})
|
|
366
|
+
.filter(Boolean);
|
|
367
|
+
const firstMissingBoundary = mergedRows.map(row => ({
|
|
368
|
+
sessionId: row.sessionId,
|
|
369
|
+
clientId: row.clientId,
|
|
370
|
+
socketGeneration: row.socketGeneration,
|
|
371
|
+
boundary: row.firstMissingBoundary || _deps.firstMissingStateSyncBoundary(row),
|
|
372
|
+
})).find(row => row.boundary) || null;
|
|
373
|
+
const processLanes = _deps.sanitizeProcessLanes({
|
|
374
|
+
readPool: _deps._ctmReadPool?.getStatus?.() || null,
|
|
375
|
+
worktreeWorker: _deps._ctmWorktreeWorker?.getStatus?.() || null,
|
|
376
|
+
dbOwner: _deps._ctmDbWorker?.getStatus?.() || null,
|
|
377
|
+
});
|
|
378
|
+
const performanceSummary = _deps.summarizePerformanceEvidence(envelope.performance);
|
|
379
|
+
if (envelope.incident.kind === 'interaction_stall' && envelope.phase === 'detected') {
|
|
380
|
+
const diagnosticSessionId = envelope.activeSessionId
|
|
381
|
+
|| envelope.deliveryGap?.sessionId
|
|
382
|
+
|| envelope.stateSync[0]?.sessionId
|
|
383
|
+
|| '';
|
|
384
|
+
const diagnosticSession = diagnosticSessionId ? _deps.sessions.get(diagnosticSessionId) : null;
|
|
385
|
+
const interactionStallMs = Math.max(
|
|
386
|
+
Number(envelope.incident.mainGapMs || 0),
|
|
387
|
+
Number(performanceSummary.inputDelayMs || 0),
|
|
388
|
+
);
|
|
389
|
+
if (diagnosticSessionId) _deps.recordSessionDiagnostic(diagnosticSessionId, 'interaction-stall', {
|
|
390
|
+
durationMs: interactionStallMs,
|
|
391
|
+
provider: diagnosticSession?._providerId || _deps._providerIdFromCmd(diagnosticSession?.cmd || ''),
|
|
392
|
+
activeTab: diagnosticSessionId === envelope.activeSessionId,
|
|
393
|
+
kind: envelope.incident.kind,
|
|
394
|
+
});
|
|
395
|
+
// WP-3 (docs/mainloop-composer-freeze-2026-08-20.html §5 D-6, §6, §8 WP-3): the client
|
|
396
|
+
// floor dropped 500ms -> 200ms (public/js/client-health-core.js); a keyboard incident
|
|
397
|
+
// that clears the NEW 200ms bar but not the old 500ms one is exactly the class this WP
|
|
398
|
+
// exists to make visible, so it gets its own [mainloop-diag] line independent of the
|
|
399
|
+
// per-session recordSessionDiagnostic row above.
|
|
400
|
+
_deps.routeKeyboardIncidentToMainloopDiag(_deps._mainloopDiagLogger, {
|
|
401
|
+
kind: envelope.incident.kind,
|
|
402
|
+
ms: interactionStallMs,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
const inputPerformanceHeadline = _deps.formatInputPerformanceHeadline(performanceSummary, {
|
|
406
|
+
enabled: _deps._typingInteractionTelemetryEnabled,
|
|
407
|
+
});
|
|
408
|
+
// S-6: renderCount/sincePaint above only count terminal render spans — indistinguishable
|
|
409
|
+
// from "just painted" when a tab never rendered a span at all. paint.count is the true
|
|
410
|
+
// rAF-presented counter the paint-drought classifier itself uses (client-health-core.js).
|
|
411
|
+
const paintSnapshot = envelope.paint || { count: 0, lastPresentedAtMs: 0 };
|
|
412
|
+
const paintSincePresentedMs = paintSnapshot.lastPresentedAtMs > 0
|
|
413
|
+
? Math.max(0, Math.round(now - paintSnapshot.lastPresentedAtMs))
|
|
414
|
+
: 0;
|
|
415
|
+
console.warn(
|
|
416
|
+
`[client-health] incident=${envelope.incidentId} phase=${envelope.phase} domain=${correlated.domain} kind=${correlated.kind} `
|
|
417
|
+
+ `serverIncident=${correlated.serverIncidentId || 'none'} tab=${envelope.tabId.slice(0, 16)} `
|
|
418
|
+
+ `run=${envelope.runId.slice(0, 16)} boundary=${firstMissingBoundary?.boundary || 'none'} `
|
|
419
|
+
+ `clientBoundary=${envelope.deliveryGap?.boundary || 'none'} `
|
|
420
|
+
+ `wsBuffered=${envelope.websocket.bufferedAmount} worktreeQueued=${processLanes.worktreeWorker?.queued || 0} `
|
|
421
|
+
+ `clientBuild=${String(envelope.clientBuild?.loadedAsset || envelope.clientBuild?.assetEpoch || 'unknown').slice(0, 16)} `
|
|
422
|
+
+ `renderer=${envelope.renderer.webglContexts}webgl/${envelope.renderer.activeTerminals}active/`
|
|
423
|
+
+ `${envelope.renderer.hiddenTerminals}hidden/${envelope.renderer.sessions}sess `
|
|
424
|
+
+ inputPerformanceHeadline
|
|
425
|
+
+ `loaf=${performanceSummary.loafMs}/${performanceSummary.blockingMs}/${performanceSummary.pauseMs}ms `
|
|
426
|
+
+ `loafScript=${performanceSummary.scriptSource || 'none'}:${performanceSummary.scriptFunction || 'anonymous'}`
|
|
427
|
+
+ `@${performanceSummary.scriptCharPos}(offset-advisory)/${performanceSummary.scriptMs}ms `
|
|
428
|
+
+ `renderSpan=${performanceSummary.renderSpan || 'none'}/${performanceSummary.renderSpanMs}ms `
|
|
429
|
+
+ `renderCount=${envelope.performance.renderSpanCount} sincePaint=${Math.round(envelope.performance.msSinceLastPaint)}ms `
|
|
430
|
+
+ `paint=${paintSnapshot.count}/${paintSincePresentedMs}ms `
|
|
431
|
+
+ `wake=${Number(envelope.incident.wake || 0)}`,
|
|
432
|
+
);
|
|
433
|
+
_deps._recentClientHealthIncidents.push(Object.freeze({
|
|
434
|
+
receivedAt: now,
|
|
435
|
+
incidentId: envelope.incidentId,
|
|
436
|
+
tabId: envelope.tabId,
|
|
437
|
+
runId: envelope.runId,
|
|
438
|
+
phase: envelope.phase,
|
|
439
|
+
classification: correlated.kind,
|
|
440
|
+
incidentDomain: correlated.domain,
|
|
441
|
+
serverIncidentId: correlated.serverIncidentId || '',
|
|
442
|
+
firstMissingBoundary,
|
|
443
|
+
clientDeliveryGap: envelope.deliveryGap,
|
|
444
|
+
mainGapMs: envelope.incident.mainGapMs,
|
|
445
|
+
workerTickDeltaMs: envelope.incident.workerTickDeltaMs,
|
|
446
|
+
lifecycle: envelope.lifecycle,
|
|
447
|
+
wake: envelope.wake,
|
|
448
|
+
websocket: envelope.websocket,
|
|
449
|
+
clientBuild: envelope.clientBuild,
|
|
450
|
+
collector: envelope.performance.collector,
|
|
451
|
+
performance: envelope.performance,
|
|
452
|
+
renderer: envelope.renderer,
|
|
453
|
+
stateSync: mergedRows,
|
|
454
|
+
processLanes,
|
|
455
|
+
}));
|
|
456
|
+
if (_deps._recentClientHealthIncidents.length > 100) {
|
|
457
|
+
_deps._recentClientHealthIncidents.splice(0, _deps._recentClientHealthIncidents.length - 100);
|
|
458
|
+
}
|
|
459
|
+
return _deps.sendJsonResponse(res, 200, {
|
|
460
|
+
ok: true,
|
|
461
|
+
schemaVersion: 1,
|
|
462
|
+
classification: correlated.kind,
|
|
463
|
+
incidentDomain: correlated.domain,
|
|
464
|
+
serverIncidentId: correlated.serverIncidentId || '',
|
|
465
|
+
firstMissingBoundary,
|
|
466
|
+
clientDeliveryGap: envelope.deliveryGap,
|
|
467
|
+
});
|
|
468
|
+
} catch (error) {
|
|
469
|
+
return _deps.sendJsonResponse(res, 400, { ok: false, error: error.message });
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
async function apiDiagnosticsPerfSummary(req, res, url) {
|
|
474
|
+
try {
|
|
475
|
+
const censusLimit = Math.max(1, Math.min(256, Number(url?.searchParams?.get('censusLimit')) || 10));
|
|
476
|
+
const eventLoop = _deps._perfTracker.getEventLoopStats();
|
|
477
|
+
const pressure = _deps._loadPressure.getStatus();
|
|
478
|
+
const readPool = _deps._ctmReadPool?.getStatus?.() || null;
|
|
479
|
+
const dbOwner = _deps._ctmDbWorker?.getStatus?.() || null;
|
|
480
|
+
const providerIndex = _deps._desktopIndex.status();
|
|
481
|
+
const processTreeRssBytes = Math.round(
|
|
482
|
+
(Number(_deps._sessionResourceSampler.snapshot?.processTree?.rssMB) || 0) * 1024 * 1024,
|
|
483
|
+
);
|
|
484
|
+
// (a) physical footprint + (b) mirror visibility (design doc §6a/§6b). Both are
|
|
485
|
+
// async and spawned off the main thread (footprint via child_process; the mirrors
|
|
486
|
+
// report via IPC round-trip to the pooled host process) — AC-0d never blocks the
|
|
487
|
+
// main thread synchronously for these. Both resolve to an empty/null value on
|
|
488
|
+
// any failure so perf-summary never 500s because a diagnostic sample was slow.
|
|
489
|
+
//
|
|
490
|
+
// D-1 (§8 WP-0): prefer the 60s sweep's own main-process footprint sample
|
|
491
|
+
// (_sampleLifecycleResources -> _sessionResourceSampler.snapshot.platform.main) --
|
|
492
|
+
// it is already fresh (sampled at most one sweep interval ago) whenever the sweep has
|
|
493
|
+
// run at least once recently, so most perf-summary polls no longer need a second
|
|
494
|
+
// on-demand footprint round trip for the same pid. Falls back to sampling on demand only
|
|
495
|
+
// when the cached sample is missing or older than 2 sweep intervals (sweep stalled,
|
|
496
|
+
// or this is the very first request before any sweep has run).
|
|
497
|
+
let physFootprintBytes = null;
|
|
498
|
+
const sweepSnapshot = _deps._sessionResourceSampler.snapshot;
|
|
499
|
+
const sweepIntervalMs = Math.max(1, Number(_deps._sessionResourceSampler.intervalMs) || 60_000);
|
|
500
|
+
const sweepAgeMs = Date.now() - (Number(sweepSnapshot?.sampledAt) || 0);
|
|
501
|
+
const sweepFootprintMB = sweepSnapshot?.platform?.main?.footprintMB;
|
|
502
|
+
if (sweepFootprintMB != null && sweepAgeMs <= sweepIntervalMs * 2) {
|
|
503
|
+
physFootprintBytes = Math.round(sweepFootprintMB * 1024 * 1024);
|
|
504
|
+
} else {
|
|
505
|
+
try {
|
|
506
|
+
const footprintMB = await _deps._sessionResourceSampler.sampleFootprintMB(process.pid);
|
|
507
|
+
physFootprintBytes = footprintMB == null ? null : Math.round(footprintMB * 1024 * 1024);
|
|
508
|
+
} catch (error) {
|
|
509
|
+
_deps.errorSink.report('diagnostics:physical-footprint-sample', error);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
let mirrors = [];
|
|
513
|
+
try {
|
|
514
|
+
mirrors = await _deps.sessionHostManager.requestPoolMirrorsReport();
|
|
515
|
+
} catch (error) {
|
|
516
|
+
console.warn(`[diagnostics] mirrors report failed: ${error.message}`);
|
|
517
|
+
}
|
|
518
|
+
// WP-3/S5: pool gauges the pooled-host process alone can answer (frame-emitter
|
|
519
|
+
// session count, archive-store pending backlog) -- same IPC round trip shape as the
|
|
520
|
+
// mirrors report above, same zeroed-not-thrown failure posture.
|
|
521
|
+
// No try/catch: requestPoolPoolsReport rides _poolRequest, which RESOLVES to its
|
|
522
|
+
// zeroed emptyResult on timeout / no pool / send failure (lib/session-host-manager.js
|
|
523
|
+
// "never rejects" contract) -- a catch here would be a new bare-console tail for a
|
|
524
|
+
// path that cannot reject (G-2 count-ceiling, tests/db-owner-log-discipline.test.js).
|
|
525
|
+
const poolsFromHost = await _deps.sessionHostManager.requestPoolPoolsReport();
|
|
526
|
+
// WP-6 (§7 "Ledger visibility", §8 WP-6/AC-6a): the gateway's own
|
|
527
|
+
// /_status, normalized for the ledger by fetchMcpGatewayLedgerStatus()
|
|
528
|
+
// above. Same shape whether the gateway is up or down (zeroed, never
|
|
529
|
+
// thrown) -- there is nothing to catch here, matching the
|
|
530
|
+
// poolsFromHost "never rejects" contract just above.
|
|
531
|
+
const mcpGatewayStatus = await _deps.fetchMcpGatewayLedgerStatus();
|
|
532
|
+
// D-1 (§8 WP-0): sum of every footprint the sweep actually sampled this pass (main,
|
|
533
|
+
// pooled session-host, desktop index, and every live session) -- `null`, not 0, when
|
|
534
|
+
// the sweep has not sampled anything yet (first request before any sweep, or
|
|
535
|
+
// FOOTPRINT_TRUTH disabled) so the ledger cannot mistake "unsampled" for "0 bytes".
|
|
536
|
+
// There is no true tree-wide footprint measurement (`treeFootprintBytes`) to compare it
|
|
537
|
+
// against, so that field is left for a caller with that data; the RSS-based
|
|
538
|
+
// unattributedTreeRssBytes estimate keeps its current meaning until one exists.
|
|
539
|
+
let knownFootprintMB = 0;
|
|
540
|
+
let knownFootprintSamples = 0;
|
|
541
|
+
for (const entry of Object.values(sweepSnapshot?.platform || {})) {
|
|
542
|
+
if (entry?.footprintMB != null) { knownFootprintMB += Number(entry.footprintMB); knownFootprintSamples += 1; }
|
|
543
|
+
}
|
|
544
|
+
for (const session of sweepSnapshot?.sessions || []) {
|
|
545
|
+
if (session?.footprintMB != null) { knownFootprintMB += Number(session.footprintMB); knownFootprintSamples += 1; }
|
|
546
|
+
}
|
|
547
|
+
const knownFootprintBytes = knownFootprintSamples > 0 ? Math.round(knownFootprintMB * 1024 * 1024) : null;
|
|
548
|
+
// WP-4 (§8 WP-4): the same sweep-sampled pool-host footprint D-1 already folds into
|
|
549
|
+
// knownFootprintBytes above, handed to the ledger a second time so it can compute
|
|
550
|
+
// poolHostBaseMB (footprint minus every mirror's attributed bytes) -- null, not 0,
|
|
551
|
+
// when the sweep has not sampled the pool host this pass.
|
|
552
|
+
const poolHostFootprintMB = sweepSnapshot?.platform?.['session-host-pool']?.footprintMB ?? null;
|
|
553
|
+
const memory = _deps.buildMemoryLedger({
|
|
554
|
+
processMemory: process.memoryUsage(),
|
|
555
|
+
processTreeRssBytes,
|
|
556
|
+
physFootprintBytes,
|
|
557
|
+
footprints: { knownFootprintBytes, treeFootprintBytes: null },
|
|
558
|
+
mirrors,
|
|
559
|
+
poolHostFootprintMB,
|
|
560
|
+
caches: {
|
|
561
|
+
messageResponses: _deps._msgResponseCache.status(),
|
|
562
|
+
terminalSnapshots: _deps._terminalSnapshotBudget.status(),
|
|
563
|
+
exitedTerminalSnapshots: _deps._exitedSnapshotBudget.status(),
|
|
564
|
+
// WP-3/S5: same budget primitive as the two above, previously absent from the
|
|
565
|
+
// ledger entirely (§1d: "8 MB, same primitive as the ledgered budgets").
|
|
566
|
+
historyWindow: _deps._historyWindowBudget.status(),
|
|
567
|
+
},
|
|
568
|
+
// WP-3/S5: pools the ledger previously could not see at all. archivePending* comes
|
|
569
|
+
// from the pooled host process (main process holds no archive-store instance of its
|
|
570
|
+
// own -- the store lives in lib/headless-term-service.js, WP-1B). frameEmitterSessions
|
|
571
|
+
// rides the same round trip. sessionDiagnosticsSessions/terminalTailSessions are
|
|
572
|
+
// in-heap and read directly.
|
|
573
|
+
pools: {
|
|
574
|
+
archivePending: {
|
|
575
|
+
rows: poolsFromHost.archivePendingRows,
|
|
576
|
+
bytes: poolsFromHost.archivePendingBytes,
|
|
577
|
+
dropped: poolsFromHost.archiveDroppedRows,
|
|
578
|
+
},
|
|
579
|
+
frameEmitterSessions: poolsFromHost.frameEmitterSessions,
|
|
580
|
+
sessionDiagnosticsSessions: _deps.sessionDiagnostics.size(),
|
|
581
|
+
terminalTailSessions: _deps._terminalTailState.size,
|
|
582
|
+
// WP-6/AC-6a: {reachable, servers: {<name>: {state, pid, rssBytes,
|
|
583
|
+
// toolCalls, sessions, adopted}}, totalRssBytes, warmChildren} --
|
|
584
|
+
// zeroed (never thrown) when the gateway is unreachable.
|
|
585
|
+
mcpGateway: mcpGatewayStatus,
|
|
586
|
+
},
|
|
587
|
+
workers: {
|
|
588
|
+
readPool: (readPool?.workers || []).map((worker) => ({
|
|
589
|
+
kind: 'thread',
|
|
590
|
+
...(worker.memory || {}),
|
|
591
|
+
openConnections: worker.openConnections,
|
|
592
|
+
})),
|
|
593
|
+
dbOwner: dbOwner?.memory ? {
|
|
594
|
+
kind: 'thread',
|
|
595
|
+
...dbOwner.memory,
|
|
596
|
+
heapStatistics: dbOwner.heapStatistics || null,
|
|
597
|
+
openConnections: Number(dbOwner.openConnections) || 0,
|
|
598
|
+
} : null,
|
|
599
|
+
providerIndex: providerIndex.memory ? {
|
|
600
|
+
...providerIndex.memory,
|
|
601
|
+
openConnections: 0,
|
|
602
|
+
} : null,
|
|
603
|
+
bulkService: readPool?.bulkService?.memory ? {
|
|
604
|
+
...readPool.bulkService.memory,
|
|
605
|
+
openConnections: Number(readPool.bulkService.worker?.openConnections) || 0,
|
|
606
|
+
} : null,
|
|
607
|
+
},
|
|
608
|
+
});
|
|
609
|
+
const payload = _deps.buildPerfSummary({
|
|
610
|
+
eventLoop,
|
|
611
|
+
pressure,
|
|
612
|
+
headlessWorker: _deps.getWorkerLoopLag(), // WP-0 D-4
|
|
613
|
+
perfCertificationLedger: _deps._readPerfCertificationLedger(),
|
|
614
|
+
backgroundLlmRouteStats: _deps.getBackgroundLlmRouteStats(),
|
|
615
|
+
// `?censusLimit=N` widens both tripwire tables. The default of 10 is right for the
|
|
616
|
+
// dashboard, but it hid the real volume offender during the 2026-09-12 main-loop
|
|
617
|
+
// investigation: the fs-watcher scan's existence-check entry (tens of thousands of
|
|
618
|
+
// calls, but few ms) ranks by sumMs and fell off the list between two reads, so the
|
|
619
|
+
// biggest call-COUNT source on the main thread was invisible. Capped at 256,
|
|
620
|
+
// matching the tripwire's own TRIPWIRE_MAX_KEYS.
|
|
621
|
+
mainDb: _deps._mainDbCensus.getTripwireTop({ limit: censusLimit }),
|
|
622
|
+
syncIo: _deps._syncIoCensus.getTripwireTop({ limit: censusLimit }),
|
|
623
|
+
transcriptRoots: _deps._transcriptRoots,
|
|
624
|
+
wal: {
|
|
625
|
+
..._deps._walCheckpointMetrics,
|
|
626
|
+
truncateSuccessRatio: _deps._walCheckpointMetrics.truncateAttempts > 0
|
|
627
|
+
? _deps._walCheckpointMetrics.truncateSuccesses / _deps._walCheckpointMetrics.truncateAttempts
|
|
628
|
+
: null,
|
|
629
|
+
},
|
|
630
|
+
dbOwner,
|
|
631
|
+
readPool, mainTimers: { cpuByTimer: _deps._perfTracker.getTimerCpuStats?.() || {} }, broadcast: { byReason: _deps.getBroadcastReasonStats?.()?.byReason || {} }, // WP-0 M-1 (hub-local-cpu-memory-burn §7) + WP-0 M-2 (§3.2/§7): folded onto this line, not a new one, so the moved-body line budget is unchanged
|
|
632
|
+
writeLock: _deps.dbModule.getWriteLockStats?.() || null,
|
|
633
|
+
mainWriteEscapes: _deps.getMainThreadWriteEscapeStats(),
|
|
634
|
+
degraded: _deps._degradedOperations.getStatus(),
|
|
635
|
+
memory: { ...memory, retireNoReclaim: _deps._reclaimRecorder.getRetireNoReclaim(), reclaimRing: _deps._reclaimRecorder.getReclaimRing(), trimCadence: _deps._trimCadence.getStatus() }, // WP-6 D-9/AC-6a + WP-3 §6.3: folded onto this line -- handleApi is a frozen-length function (lint/file-size.config.json)
|
|
636
|
+
providerIndex: _deps._desktopIndex.status(),
|
|
637
|
+
typingInteractions: _deps._typingInteractionTelemetryEnabled
|
|
638
|
+
? _deps._typingInteractionTraces.snapshot()
|
|
639
|
+
: { interactions: [], providers: {} },
|
|
640
|
+
codexInputTraces: _deps._typingInteractionTelemetryEnabled
|
|
641
|
+
? _deps._typingInteractionTraces.publicSnapshot({
|
|
642
|
+
contextFor: ({ startedAt, endedAt }) => ({
|
|
643
|
+
eventLoopMaxMs: Number(_deps._eventLoopIncidents.correlate({ startedAt, endedAt })?.blockedMs || 0),
|
|
644
|
+
}),
|
|
645
|
+
})
|
|
646
|
+
: { interactions: [], providers: { codex: { count: 0 } } },
|
|
647
|
+
typingLatencyFlags: {
|
|
648
|
+
typingE2eTelemetry: _deps._typingInteractionTelemetryEnabled,
|
|
649
|
+
codexInputTrace: _deps._typingInteractionTelemetryEnabled,
|
|
650
|
+
streamStatusPatchV2: _deps.CTM_STREAM_STATUS_PATCH_V2_ENABLED,
|
|
651
|
+
stateSyncClientLedgerV2: true,
|
|
652
|
+
stateSyncInteractiveSupersede: true,
|
|
653
|
+
browserQosV2: _deps.CTM_BROWSER_QOS_V2_ENABLED,
|
|
654
|
+
stateSyncAtomicHandoffLease: true,
|
|
655
|
+
visibleRevisionWatchdog: _deps._visibleRevisionWatchdogEnabled,
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
659
|
+
res.end(JSON.stringify({
|
|
660
|
+
ok: true,
|
|
661
|
+
...payload,
|
|
662
|
+
recentCatalog: {
|
|
663
|
+
..._deps._recentCatalogMetrics,
|
|
664
|
+
generation: _deps._recentCatalogGeneration,
|
|
665
|
+
publishedGeneration: _deps._recentCatalogPublished.generation,
|
|
666
|
+
publishedBytes: _deps._recentCatalogPublished.bytes,
|
|
667
|
+
variants: _deps._recentCatalogPublished.variants.size,
|
|
668
|
+
buildInFlight: _deps._recentCatalogBuildInFlight,
|
|
669
|
+
},
|
|
670
|
+
heartbeatProjection: _deps._heartbeatDirtyQueue.status(),
|
|
671
|
+
mainDbRequestGuard: _deps._mainDbCensus.getRequestGuard(),
|
|
672
|
+
controlSnapshot: _deps._controlSnapshot.status(),
|
|
673
|
+
runtimeEvents: _deps._runtimeEventBuffer.getStatus(),
|
|
674
|
+
conversationPublication: _deps._conversationUpdateOutboxBackoff.getStatus(),
|
|
675
|
+
historyBreakers: _deps._historyBreakerSnapshot(),
|
|
676
|
+
stateSyncLifecycle: {
|
|
677
|
+
unknownSessionSubscriptionRejections: _deps._stateSyncUnknownSubscriptionRejected,
|
|
678
|
+
ledgerCausalityRepairs: Number(_deps._stateSyncClientLedger.stats?.().causalityRepairs || 0),
|
|
679
|
+
pendingClients: (() => {
|
|
680
|
+
const stats = _deps.headlessWorker.getStatus?.().legacy || {};
|
|
681
|
+
return {
|
|
682
|
+
sessions: Number(stats.pendingStateSyncSessions || 0),
|
|
683
|
+
clients: Number(stats.pendingStateSyncClients || 0),
|
|
684
|
+
oldestAgeMs: Number(stats.pendingStateSyncOldestAgeMs || 0),
|
|
685
|
+
counters: {
|
|
686
|
+
...(stats.pendingStateSyncCounters || {}),
|
|
687
|
+
unknownServerRejected: _deps._stateSyncUnknownSubscriptionRejected,
|
|
688
|
+
},
|
|
689
|
+
};
|
|
690
|
+
})(),
|
|
691
|
+
stallWarnings: (() => {
|
|
692
|
+
const stats = _deps.headlessWorker.getStatus?.().legacy || {};
|
|
693
|
+
return {
|
|
694
|
+
identities: Number(stats.stalledWarningIdentities || 0),
|
|
695
|
+
counters: stats.stalledWarningCounters || {},
|
|
696
|
+
};
|
|
697
|
+
})(),
|
|
698
|
+
},
|
|
699
|
+
}));
|
|
700
|
+
} catch (e) {
|
|
701
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
702
|
+
res.end(JSON.stringify({ error: e.message }));
|
|
703
|
+
}
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// WP-5 shard S4: the two verbatim bodies below are appended here by
|
|
708
|
+
// bin/move-only-check.js's proof (identical to server.js's declarations up to
|
|
709
|
+
// the `_deps.` prefix).
|
|
710
|
+
module.exports = { apiDiagnosticsTestPairableOriginsSet, apiDiagnosticsTestPairableOriginsClear, causalTraceDiagnosticPayload, apiContextBudget, apiDiagnosticsClientHealth, apiDiagnosticsPerfSummary, configure, register };
|