create-walle 0.10.1 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/lib/owner-write-safety.js +135 -0
- package/lib/public-runtime.js +13 -5
- package/lib/release-schema.json +3 -2
- package/lib/runtime-closure-policy.json +6 -4
- package/package.json +1 -1
- package/template/bin/deps-doctor.js +1 -1
- package/template/bin/node-bin.sh +11 -0
- package/template/coding-task-manager/api-prompts.js +10 -22
- package/template/coding-task-manager/bin/claude-hook.js +7 -3
- package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
- package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
- package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
- package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
- package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
- package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
- package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
- package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
- package/template/coding-task-manager/db.js +705 -286
- package/template/coding-task-manager/git-utils.js +44 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
- package/template/coding-task-manager/lib/agent-presets.js +15 -0
- package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
- package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
- package/template/coding-task-manager/lib/api/host-stats.js +98 -0
- package/template/coding-task-manager/lib/api/ingress.js +35 -12
- package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
- package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
- package/template/coding-task-manager/lib/api/machines.js +461 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
- package/template/coding-task-manager/lib/api/providers.js +53 -6
- package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
- package/template/coding-task-manager/lib/api/sessions.js +160 -8
- package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
- package/template/coding-task-manager/lib/api/worktrees.js +38 -37
- package/template/coding-task-manager/lib/approval-drift.js +16 -1
- package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
- package/template/coding-task-manager/lib/approval-scope.js +68 -4
- package/template/coding-task-manager/lib/auth-context.js +32 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
- package/template/coding-task-manager/lib/auth-rules.js +186 -45
- package/template/coding-task-manager/lib/broadcast-serialize.js +2 -1
- package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
- package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
- package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
- package/template/coding-task-manager/lib/claude-session-title.js +6 -30
- package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
- package/template/coding-task-manager/lib/client-diag-handler.js +5 -0
- package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
- package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
- package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
- package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
- package/template/coding-task-manager/lib/codex-paths.js +2 -1
- package/template/coding-task-manager/lib/coding-agent-models.js +21 -30
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
- package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
- package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
- package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
- package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
- package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
- package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
- package/template/coding-task-manager/lib/db-domains.js +21 -2
- package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
- package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
- package/template/coding-task-manager/lib/feature-manifest.js +1 -1
- package/template/coding-task-manager/lib/fs-watcher.js +3 -2
- package/template/coding-task-manager/lib/harness-history-transition.js +3 -3
- package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
- package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
- package/template/coding-task-manager/lib/headless-term-service.js +55 -17
- package/template/coding-task-manager/lib/host-control-dial.js +167 -0
- package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
- package/template/coding-task-manager/lib/host-handoff.js +51 -13
- package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
- package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
- package/template/coding-task-manager/lib/host-stats.js +328 -0
- package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
- package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
- package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
- package/template/coding-task-manager/lib/hosted-sync-worker.js +113 -5
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
- package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
- package/template/coding-task-manager/lib/instance-manifest.js +13 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
- package/template/coding-task-manager/lib/launch-model-override.js +160 -1
- package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
- package/template/coding-task-manager/lib/lead-model-switch.js +3 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
- package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
- package/template/coding-task-manager/lib/login-tripwire.js +1 -0
- package/template/coding-task-manager/lib/machine-pairing.js +238 -0
- package/template/coding-task-manager/lib/machine-pool.js +409 -0
- package/template/coding-task-manager/lib/machine-registry.js +749 -0
- package/template/coding-task-manager/lib/machine-self.js +66 -0
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +52 -4
- package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
- package/template/coding-task-manager/lib/media-journal.js +84 -27
- package/template/coding-task-manager/lib/media-store-options.js +43 -15
- package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
- package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
- package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
- package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
- package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
- package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
- package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
- package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-history-control.js +2 -2
- package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
- package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
- package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
- package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
- package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
- package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
- package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
- package/template/coding-task-manager/lib/read-pool-client.js +5 -2
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
- package/template/coding-task-manager/lib/remote-command-context.js +12 -0
- package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
- package/template/coding-task-manager/lib/remote-machine-catalog.js +1062 -0
- package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
- package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
- package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
- package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
- package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
- package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
- package/template/coding-task-manager/lib/restart-preflight.js +9 -2
- package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
- package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
- package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
- package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
- package/template/coding-task-manager/lib/resume-cwd.js +13 -0
- package/template/coding-task-manager/lib/resume-from-store.js +12 -1
- package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
- package/template/coding-task-manager/lib/resume-preflight.js +21 -16
- package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
- package/template/coding-task-manager/lib/review-repo-registry.js +17 -0
- package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
- package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
- package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +167 -33
- package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
- package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
- package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
- package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +95 -6
- package/template/coding-task-manager/lib/session-create/identity.js +20 -1
- package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
- package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
- package/template/coding-task-manager/lib/session-create/provider-process.js +34 -37
- package/template/coding-task-manager/lib/session-create/response.js +30 -12
- package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
- package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
- package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
- package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
- package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
- package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
- package/template/coding-task-manager/lib/session-host-manager.js +152 -206
- package/template/coding-task-manager/lib/session-jobs.js +17 -9
- package/template/coding-task-manager/lib/session-lifecycle.js +18 -0
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +9 -0
- package/template/coding-task-manager/lib/session-resource-sampler.js +19 -9
- package/template/coding-task-manager/lib/session-standup.js +67 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +42 -3
- package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
- package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
- package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
- package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
- package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +21 -22
- package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
- package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
- package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
- package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
- package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
- package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
- package/template/coding-task-manager/lib/transcript-link.js +77 -0
- package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
- package/template/coding-task-manager/lib/transcript-source.js +8 -3
- package/template/coding-task-manager/lib/transcript-store.js +40 -0
- package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
- package/template/coding-task-manager/lib/typing-interaction-trace.js +92 -0
- package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
- package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
- package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
- package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
- package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -1
- package/template/coding-task-manager/lib/ws-router.js +68 -1
- package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
- package/template/coding-task-manager/oauth-proxy.js +99 -55
- package/template/coding-task-manager/package-lock.json +24 -0
- package/template/coding-task-manager/package.json +3 -0
- package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
- package/template/coding-task-manager/providers/codex-mcp.js +14 -5
- package/template/coding-task-manager/public/css/app.css +279 -1
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/index.html +294 -223
- package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
- package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
- package/template/coding-task-manager/public/js/background-work.js +13 -7
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
- package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
- package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
- package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
- package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
- package/template/coding-task-manager/public/js/history-scroller.js +187 -9
- package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
- package/template/coding-task-manager/public/js/machine-pool-shared.js +436 -0
- package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
- package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
- package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
- package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
- package/template/coding-task-manager/public/js/reviews.js +7 -3
- package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
- package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
- package/template/coding-task-manager/public/js/row-join.js +4 -2
- package/template/coding-task-manager/public/js/session-model-picker.js +1 -1
- package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
- package/template/coding-task-manager/public/js/state-sync-client.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
- package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
- package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +52 -2
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -12
- package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
- package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +210 -73
- package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
- package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
- package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
- package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
- package/template/coding-task-manager/public/js/walle-session.js +30 -7
- package/template/coding-task-manager/public/m/app.css +226 -8
- package/template/coding-task-manager/public/m/app.js +502 -9
- package/template/coding-task-manager/public/m/index.html +38 -1
- package/template/coding-task-manager/public/m/machines.js +1313 -0
- package/template/coding-task-manager/public/m/pool-failover.js +391 -0
- package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
- package/template/coding-task-manager/public/m/sw.js +5 -0
- package/template/coding-task-manager/queue-engine.js +13 -0
- package/template/coding-task-manager/server/approvals.js +5 -6
- package/template/coding-task-manager/server/boot.js +136 -17
- package/template/coding-task-manager/server.js +902 -239
- package/template/coding-task-manager/session-integrity.js +7 -9
- package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
- package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
- package/template/coding-task-manager/workers/session-host-process.js +14 -3
- package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
- package/template/coding-task-manager/workers/worktree-worker.js +34 -0
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/scripts/conversation-storage-v2-migration.js +78 -11
- package/template/shared/conversation-storage-v2-contract.js +42 -6
- package/template/shared/fixtures/worker-status-payloads.json +392 -0
- package/template/shared/git-remote-key.js +83 -0
- package/template/shared/host-identity.js +98 -2
- package/template/shared/owner-write-safety.js +135 -0
- package/template/shared/public-runtime.js +13 -5
- package/template/shared/release-schema.json +3 -2
- package/template/shared/report-citations.js +14 -0
- package/template/shared/sqlite-write-lock.js +361 -223
- package/template/shared/storage/contract.js +35 -3
- package/template/wall-e/agent.js +21 -0
- package/template/wall-e/api-walle.js +5 -0
- package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
- package/template/wall-e/brain/helper-rules-schema.js +129 -0
- package/template/wall-e/brain/migrations.js +51 -22
- package/template/wall-e/brain/model-deployment-facts.js +31 -1
- package/template/wall-e/brain/owner-call-whitelist.js +16 -0
- package/template/wall-e/brain/schema-ensures.js +22 -0
- package/template/wall-e/brain.js +1 -1
- package/template/wall-e/coding/journal-dispatcher.js +51 -0
- package/template/wall-e/coding/session-journal.js +28 -40
- package/template/wall-e/coding-orchestrator.js +23 -26
- package/template/wall-e/http/auth.js +18 -1
- package/template/wall-e/http/blog-views-api.js +318 -0
- package/template/wall-e/http/helper-rules-api.js +321 -0
- package/template/wall-e/http/model-proxy-providers.js +3 -1
- package/template/wall-e/http/telemetry-api.js +12 -0
- package/template/wall-e/lib/blog-view-policy.js +88 -0
- package/template/wall-e/lib/blog-view-store.js +169 -0
- package/template/wall-e/lib/client-config-lock.js +2 -1
- package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
- package/template/wall-e/lib/error-kinds.js +10 -1
- package/template/wall-e/lib/feature-manifest.js +1 -1
- package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +357 -0
- package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
- package/template/wall-e/lib/helper-rules/grade.js +277 -0
- package/template/wall-e/lib/helper-rules/label.js +247 -0
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
- package/template/wall-e/lib/helper-rules/store.js +667 -0
- package/template/wall-e/lib/mcp-integration.js +5 -6
- package/template/wall-e/lib/runtime-worker-pool.js +1 -0
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
- package/template/wall-e/lib/telemetry-db-schema.js +37 -0
- package/template/wall-e/lib/telemetry-process-client.js +76 -1
- package/template/wall-e/llm/default-fallback.js +4 -0
- package/template/wall-e/llm/model-catalog.js +13 -4
- package/template/wall-e/llm/model-roles.js +6 -0
- package/template/wall-e/llm/portkey-http.js +150 -0
- package/template/wall-e/llm/portkey-sync.js +15 -145
- package/template/wall-e/llm/worker-mcp-routing.js +61 -0
- package/template/wall-e/llm/worker-route.js +43 -1
- package/template/wall-e/loops/brain-custom-writes.js +45 -0
- package/template/wall-e/mcp-protocol-contract.js +41 -1
- package/template/wall-e/mcp-server.js +13 -2
- package/template/wall-e/mcp-worker-schemas.js +20 -2
- package/template/wall-e/memory/ctm-context-client.js +25 -5
- package/template/wall-e/shared/release-schema.json +3 -2
- package/template/wall-e/shared/sqlite-write-lock.js +361 -223
- package/template/wall-e/shared/storage/contract.js +35 -3
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
- package/template/wall-e/tools/local-tools.js +6 -4
- package/template/wall-e/workers/brain-owner-worker.js +9 -0
- package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
- package/template/wall-e/workers/telemetry-worker.js +8 -0
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
7
|
var TERMINAL = new Set(['sent', 'needs_attention', 'blocked', 'failed']);
|
|
8
|
+
// WP-1 (C1, design §6 / R3/R6): the closed vocabulary the server publishes next to a
|
|
9
|
+
// terminal status. `retry` repeats the SAME admitted request, `resend` is an explicit
|
|
10
|
+
// new attempt, `review` restores the preserved prompt and needs a confirmation, and
|
|
11
|
+
// `none` means the user has nothing to do here.
|
|
12
|
+
var RECOVERY_ACTIONS = new Set(['retry', 'resend', 'review', 'none']);
|
|
8
13
|
var DEFAULT_INACTIVITY_MS = 20000;
|
|
9
14
|
var LEGACY_DEADLINE_MS = 12000;
|
|
10
15
|
var DEFAULT_ATTENTION_MS = 600000;
|
|
@@ -18,6 +23,18 @@
|
|
|
18
23
|
return String(candidate.type || candidate.agentType || candidate.sessionType || '').toLowerCase();
|
|
19
24
|
}
|
|
20
25
|
|
|
26
|
+
// Never invent an action from prose, and never let an unrecognized value grant a
|
|
27
|
+
// resend. A frame the current server produced always carries one of the four; a frame
|
|
28
|
+
// with no usable verdict is a legacy frame, so the historical `retryable: true`
|
|
29
|
+
// verdict keeps its old same-ID meaning and anything else is conservative: review
|
|
30
|
+
// restores the preserved prompt and requires an explicit confirmation before a
|
|
31
|
+
// possible duplicate, and can never mint a fresh id on its own.
|
|
32
|
+
function normalizeRecoveryAction(value, retryable) {
|
|
33
|
+
var clean = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
34
|
+
if (RECOVERY_ACTIONS.has(clean)) return clean;
|
|
35
|
+
return retryable === true ? 'retry' : 'review';
|
|
36
|
+
}
|
|
37
|
+
|
|
21
38
|
function createManager(options) {
|
|
22
39
|
options = options || {};
|
|
23
40
|
var records = new Map();
|
|
@@ -30,6 +47,18 @@
|
|
|
30
47
|
var createId = options.createId || function() {
|
|
31
48
|
return typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : fallbackId();
|
|
32
49
|
};
|
|
50
|
+
// One replacement per original: the gesture is idempotent, so a double click (or a
|
|
51
|
+
// second UI affordance reaching the same original) returns the successor it already
|
|
52
|
+
// started instead of minting a second id. Never published: publicRecord must not
|
|
53
|
+
// expose a live record object.
|
|
54
|
+
var successors = new Map();
|
|
55
|
+
// AC-1b (WP-1): the reentrancy fence. The entry is acquired BEFORE any caller-supplied
|
|
56
|
+
// callback can run (createId, publish/onChange, getSessionType, transport), so a callback
|
|
57
|
+
// that re-enters resend() for the SAME original while the first call is still executing --
|
|
58
|
+
// a synchronous double gesture, or a publish-driven UI re-render -- joins the operation
|
|
59
|
+
// already in flight instead of minting a second identity. It is released on every exit
|
|
60
|
+
// that did not register a successor.
|
|
61
|
+
var operations = new Map();
|
|
33
62
|
|
|
34
63
|
function isCurrent() {
|
|
35
64
|
if (disposed) return false;
|
|
@@ -58,6 +87,13 @@
|
|
|
58
87
|
function eraseRecord(record) {
|
|
59
88
|
clearRecordTimers(record);
|
|
60
89
|
records.delete(record.clientMessageId);
|
|
90
|
+
successors.delete(record.clientMessageId);
|
|
91
|
+
operations.delete(record.clientMessageId);
|
|
92
|
+
// A retired record must not stay reachable through another record's supersession link:
|
|
93
|
+
// the successor map is a live-object map, never a graveyard of erased records.
|
|
94
|
+
successors.forEach(function(candidate, originalId) {
|
|
95
|
+
if (candidate === record) successors.delete(originalId);
|
|
96
|
+
});
|
|
61
97
|
record.clientMessageId = '';
|
|
62
98
|
record.sessionId = '';
|
|
63
99
|
record.text = '';
|
|
@@ -67,6 +103,8 @@
|
|
|
67
103
|
record.message = '';
|
|
68
104
|
record.signal = '';
|
|
69
105
|
record.status = '';
|
|
106
|
+
record.recoveryAction = 'none';
|
|
107
|
+
record.supersedesClientMessageId = '';
|
|
70
108
|
record.alarmed = false;
|
|
71
109
|
record.retryable = false;
|
|
72
110
|
record.lateConfirmationReported = false;
|
|
@@ -129,6 +167,13 @@
|
|
|
129
167
|
if (!record || record.settled) return record;
|
|
130
168
|
Object.assign(record, patch || {});
|
|
131
169
|
if (record.status !== 'sent') record.alarmed = true;
|
|
170
|
+
// A record that settles into a terminal failure owns its recovery policy, even when
|
|
171
|
+
// the settling path (a transport failure or an inactivity deadline) has no server
|
|
172
|
+
// frame to copy it from.
|
|
173
|
+
if (record.status === 'sent') record.recoveryAction = 'none';
|
|
174
|
+
else if (TERMINAL.has(record.status)) {
|
|
175
|
+
record.recoveryAction = usableRecoveryAction(patch && patch.recoveryAction, record.retryable === true);
|
|
176
|
+
}
|
|
132
177
|
record.settled = true;
|
|
133
178
|
clearRecordTimers(record);
|
|
134
179
|
if (!publish(record)) return record;
|
|
@@ -136,6 +181,11 @@
|
|
|
136
181
|
return record;
|
|
137
182
|
}
|
|
138
183
|
|
|
184
|
+
function usableRecoveryAction(value, retryable) {
|
|
185
|
+
var clean = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
186
|
+
return RECOVERY_ACTIONS.has(clean) ? clean : normalizeRecoveryAction('', retryable);
|
|
187
|
+
}
|
|
188
|
+
|
|
139
189
|
function ackTruthEnabled() {
|
|
140
190
|
if (typeof options.isAckTruthEnabled !== 'function') return true;
|
|
141
191
|
var result = guardedCallback(options.isAckTruthEnabled, null, [], null);
|
|
@@ -226,7 +276,13 @@
|
|
|
226
276
|
reason: '',
|
|
227
277
|
message: 'Sending...',
|
|
228
278
|
signal: '',
|
|
279
|
+
recoveryAction: 'none',
|
|
229
280
|
};
|
|
281
|
+
// Local supersession link (C1/R6): what this new attempt replaces. It is a client
|
|
282
|
+
// bookkeeping field for the queue/UI lanes, never part of the transport frame.
|
|
283
|
+
if (submitOptions.supersedesClientMessageId) {
|
|
284
|
+
record.supersedesClientMessageId = String(submitOptions.supersedesClientMessageId);
|
|
285
|
+
}
|
|
230
286
|
record.promise = new Promise(function(resolve) { record.resolve = resolve; });
|
|
231
287
|
var submissionPromise = record.promise;
|
|
232
288
|
records.set(clientMessageId, record);
|
|
@@ -308,18 +364,35 @@
|
|
|
308
364
|
if (record.settled && !TERMINAL.has(status)) return true;
|
|
309
365
|
if (!record.settled && ackTruthEnabled()) armSubmissionDeadline(record);
|
|
310
366
|
if (!guardRecord(record)) return false;
|
|
367
|
+
var has = function(name) { return Boolean(message) && Object.prototype.hasOwnProperty.call(message, name); };
|
|
368
|
+
var incomingReason = String((message && (message.reason || message.code)) || '');
|
|
369
|
+
var incomingMessage = String((message && message.message) || '');
|
|
370
|
+
var failure = TERMINAL.has(status) && status !== 'sent';
|
|
371
|
+
// A later duplicate frame for the SAME terminal failure often carries only the
|
|
372
|
+
// status (the direct reply and the broadcast race). It must not erase the rich
|
|
373
|
+
// message/reason/recovery verdict the first frame already published.
|
|
374
|
+
var sameFailure = failure && record.settled === true && String(record.status || '') === status;
|
|
375
|
+
var retryable = has('retryable') ? message.retryable === true : (sameFailure && record.retryable === true);
|
|
376
|
+
var recoveryAction = !failure ? 'none'
|
|
377
|
+
: has('recoveryAction') ? normalizeRecoveryAction(message.recoveryAction, retryable)
|
|
378
|
+
: sameFailure ? normalizeRecoveryAction(record.recoveryAction, retryable)
|
|
379
|
+
: normalizeRecoveryAction('', retryable);
|
|
311
380
|
var patch = {
|
|
312
381
|
status: status === 'accepted' ? 'pending' : status,
|
|
313
|
-
reason: String(
|
|
382
|
+
reason: sameFailure && !incomingReason ? String(record.reason || '') : incomingReason,
|
|
314
383
|
// Server verdict on whether re-sending the SAME prompt can succeed once
|
|
315
384
|
// the condition clears. Callers use it instead of matching code strings.
|
|
316
|
-
retryable:
|
|
317
|
-
// A
|
|
318
|
-
//
|
|
319
|
-
message: String(
|
|
320
|
-
:
|
|
321
|
-
|
|
385
|
+
retryable: retryable,
|
|
386
|
+
// A terminal reply without prose must not look in flight or claim a known no-effect
|
|
387
|
+
// outcome when its typed recovery policy requires uncertainty review.
|
|
388
|
+
message: sameFailure && !incomingMessage ? String(record.message || '')
|
|
389
|
+
: incomingMessage || (status === 'sent' ? 'Sent'
|
|
390
|
+
: TERMINAL.has(status) ? (recoveryAction === 'review' ? 'Delivery unconfirmed: ' : 'Prompt not sent: ') + String(message.reason || message.code || status).replace(/_/g, ' ')
|
|
391
|
+
: 'Sending...'),
|
|
322
392
|
signal: String(message.signal || ''),
|
|
393
|
+
// WP-1 (AC-1a/AC-1e): the typed recovery verdict. Exact enum; an unrecognized
|
|
394
|
+
// value never grants a fresh resend.
|
|
395
|
+
recoveryAction: recoveryAction,
|
|
323
396
|
};
|
|
324
397
|
if (TERMINAL.has(status)) reconcileTerminal(record, patch);
|
|
325
398
|
else {
|
|
@@ -351,6 +424,9 @@
|
|
|
351
424
|
return true;
|
|
352
425
|
}
|
|
353
426
|
|
|
427
|
+
// AC-1a: a same-ID retry is only ever correct for the server's `retry` verdict --
|
|
428
|
+
// the admitted request is still executable. Every other policy (resend/review/none)
|
|
429
|
+
// must go through resend(), which mints exactly one fresh id on an explicit gesture.
|
|
354
430
|
function retry(clientMessageId) {
|
|
355
431
|
if (!isCurrent()) return Promise.resolve(neutralResult());
|
|
356
432
|
var record = records.get(String(clientMessageId || ''));
|
|
@@ -358,6 +434,12 @@
|
|
|
358
434
|
if (!TERMINAL.has(record.status) || record.status === 'sent') {
|
|
359
435
|
return Promise.resolve({ ok: false, status: record.status, reason: 'submission_in_flight' });
|
|
360
436
|
}
|
|
437
|
+
var action = normalizeRecoveryAction(record.recoveryAction, record.retryable === true);
|
|
438
|
+
if (action !== 'retry') {
|
|
439
|
+
return Promise.resolve({
|
|
440
|
+
ok: false, status: record.status, reason: 'recovery_action_not_retry', recoveryAction: action,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
361
443
|
return submit(record.sessionId, record.text, {
|
|
362
444
|
attachments: record.attachments,
|
|
363
445
|
source: record.source,
|
|
@@ -365,6 +447,79 @@
|
|
|
365
447
|
});
|
|
366
448
|
}
|
|
367
449
|
|
|
450
|
+
// AC-1b/AC-1c: the ONE explicit fresh-attempt path. Only a user gesture may call it
|
|
451
|
+
// (nothing here is scheduled, drained or timer-driven), it requires a settled UNSENT
|
|
452
|
+
// original whose server verdict permits a new attempt, and a `review` verdict also
|
|
453
|
+
// requires the caller's explicit confirmation. The id is minted once; text,
|
|
454
|
+
// attachments, source and session are carried over unchanged.
|
|
455
|
+
function resend(clientMessageId, resendOptions) {
|
|
456
|
+
resendOptions = resendOptions || {};
|
|
457
|
+
var confirmUncertain = resendOptions.confirmUncertain === true;
|
|
458
|
+
if (!isCurrent()) return Promise.resolve(neutralResult());
|
|
459
|
+
var originalId = String(clientMessageId || '');
|
|
460
|
+
var record = records.get(originalId);
|
|
461
|
+
if (!record || !guardRecord(record)) {
|
|
462
|
+
return Promise.resolve(!isCurrent() ? neutralResult() : { ok: false, status: 'failed', reason: 'submission_not_found' });
|
|
463
|
+
}
|
|
464
|
+
var started = successors.get(originalId);
|
|
465
|
+
if (started && records.get(started.clientMessageId) === started) return started.promise;
|
|
466
|
+
var inFlight = operations.get(originalId);
|
|
467
|
+
if (inFlight) return inFlight.promise;
|
|
468
|
+
if (!record.settled || record.status === 'sent') {
|
|
469
|
+
return Promise.resolve({ ok: false, status: record.status, reason: 'submission_in_flight' });
|
|
470
|
+
}
|
|
471
|
+
var action = normalizeRecoveryAction(record.recoveryAction, record.retryable === true);
|
|
472
|
+
if (action !== 'resend' && !(action === 'review' && confirmUncertain)) {
|
|
473
|
+
return Promise.resolve({
|
|
474
|
+
ok: false, status: record.status, reason: 'recovery_not_permitted', recoveryAction: action,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
var operation = { released: false, promise: null, resolve: null };
|
|
478
|
+
operation.promise = new Promise(function(resolve) { operation.resolve = resolve; });
|
|
479
|
+
operations.set(originalId, operation);
|
|
480
|
+
function release(result) {
|
|
481
|
+
if (!operation.released) {
|
|
482
|
+
operation.released = true;
|
|
483
|
+
if (operations.get(originalId) === operation) operations.delete(originalId);
|
|
484
|
+
operation.resolve(result);
|
|
485
|
+
}
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
try {
|
|
489
|
+
var idResult = guardedCallback(createId, null, [], record);
|
|
490
|
+
if (!idResult.current || !idResult.value) return release(neutralResult());
|
|
491
|
+
if (!guardRecord(record)) return release(neutralResult());
|
|
492
|
+
var candidateId = String(idResult.value);
|
|
493
|
+
// The successor must be a NEW identity: the original's own id, or any id already
|
|
494
|
+
// tracked, would overwrite a live record (and silently re-drive a different prompt).
|
|
495
|
+
if (candidateId === originalId || records.has(candidateId)) {
|
|
496
|
+
return release({ ok: false, status: record.status, reason: 'duplicate_client_message_id' });
|
|
497
|
+
}
|
|
498
|
+
var successorPromise = submit(record.sessionId, record.text, {
|
|
499
|
+
attachments: record.attachments,
|
|
500
|
+
source: record.source,
|
|
501
|
+
clientMessageId: candidateId,
|
|
502
|
+
supersedesClientMessageId: originalId,
|
|
503
|
+
});
|
|
504
|
+
// submit() registers and publishes the successor before it returns, so the link is
|
|
505
|
+
// only recorded once the replacement really exists; a denied preflight leaves the
|
|
506
|
+
// original (text, attachments, ids) exactly as it was and frees the fence.
|
|
507
|
+
if (!guardRecord(record)) return release(successorPromise);
|
|
508
|
+
var successor = records.get(candidateId);
|
|
509
|
+
if (!successor || String(successor.supersedesClientMessageId || '') !== originalId) {
|
|
510
|
+
return release(successorPromise);
|
|
511
|
+
}
|
|
512
|
+
successors.set(originalId, successor);
|
|
513
|
+
// One replacement, one promise: the re-entrant gesture and this call resolve to the
|
|
514
|
+
// same successor, and a later gesture gets that successor's own promise back.
|
|
515
|
+
release(successorPromise);
|
|
516
|
+
return successor.promise;
|
|
517
|
+
} catch (error) {
|
|
518
|
+
release({ ok: false, status: 'failed', reason: 'resend_failed' });
|
|
519
|
+
throw error;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
368
523
|
function dismiss(clientMessageId) {
|
|
369
524
|
if (!isCurrent()) return false;
|
|
370
525
|
var record = records.get(String(clientMessageId || ''));
|
|
@@ -381,6 +536,7 @@
|
|
|
381
536
|
if (!dismissed.current) return false;
|
|
382
537
|
}
|
|
383
538
|
records.delete(record.clientMessageId);
|
|
539
|
+
successors.delete(record.clientMessageId);
|
|
384
540
|
clearRecordTimers(record);
|
|
385
541
|
record.clientMessageId = '';
|
|
386
542
|
record.sessionId = '';
|
|
@@ -397,10 +553,17 @@
|
|
|
397
553
|
disposed = true;
|
|
398
554
|
records.forEach(function(record) { denyRecord(record); });
|
|
399
555
|
records.clear();
|
|
556
|
+
operations.forEach(function(operation) {
|
|
557
|
+
if (operation.released) return;
|
|
558
|
+
operation.released = true;
|
|
559
|
+
operation.resolve(neutralResult());
|
|
560
|
+
});
|
|
561
|
+
operations.clear();
|
|
562
|
+
successors.clear();
|
|
400
563
|
}
|
|
401
564
|
|
|
402
565
|
var manager = { submit: submit, handleStatus: handleStatus, handleWalleUser: handleWalleUser,
|
|
403
|
-
handleInputDropped: handleInputDropped, retry: retry, dismiss: dismiss, dispose: dispose };
|
|
566
|
+
handleInputDropped: handleInputDropped, retry: retry, resend: resend, dismiss: dismiss, dispose: dispose };
|
|
404
567
|
Object.defineProperty(manager, 'records', { enumerable: true, get: function() {
|
|
405
568
|
if (!isCurrent()) records.forEach(function(record) { denyRecord(record); });
|
|
406
569
|
return records;
|
|
@@ -411,6 +574,8 @@
|
|
|
411
574
|
return {
|
|
412
575
|
classifySessionType: classifySessionType,
|
|
413
576
|
createManager: createManager,
|
|
577
|
+
normalizeRecoveryAction: normalizeRecoveryAction,
|
|
578
|
+
RECOVERY_ACTIONS: Array.from(RECOVERY_ACTIONS),
|
|
414
579
|
DEFAULT_INACTIVITY_MS: DEFAULT_INACTIVITY_MS,
|
|
415
580
|
LEGACY_DEADLINE_MS: LEGACY_DEADLINE_MS,
|
|
416
581
|
DEFAULT_ATTENTION_MS: DEFAULT_ATTENTION_MS,
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
(function(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) module.exports = factory();
|
|
3
|
+
else root.PromptSubmissionTray = factory();
|
|
4
|
+
})(typeof globalThis !== 'undefined' ? globalThis : this, function() {
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
// WP-1 (C2, design §6 / R6, docs/queue-delivery-recovery-evidence-2026-10-23.html): the
|
|
8
|
+
// per-record submission tray row, extracted from index.html (which sits at its file-size
|
|
9
|
+
// ceiling). Every dependency that can only exist in the page -- the tray element, its
|
|
10
|
+
// composer clearance, the live manager, and the owner-fenced recovery route -- is passed in
|
|
11
|
+
// explicitly, so this module owns no globals and no queue state of its own.
|
|
12
|
+
var QUIET_REVEAL_MS = 5000;
|
|
13
|
+
var SENT_FLASH_MS = 2200;
|
|
14
|
+
var FAILURE_STATUSES = ['needs_attention', 'blocked', 'failed'];
|
|
15
|
+
var ROW_CSS = 'display:flex;align-items:center;gap:8px;padding:9px 10px;border:1px solid var(--border);border-radius:6px;background:var(--bg-secondary, var(--bg-lighter));box-shadow:0 6px 20px rgba(0,0,0,.28);font-size:12px;color:var(--text-primary, var(--text))';
|
|
16
|
+
|
|
17
|
+
function normalizeRecoveryAction(value) {
|
|
18
|
+
var clean = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
19
|
+
return clean === 'retry' || clean === 'resend' || clean === 'review' ? clean : 'none';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function rowId(clientMessageId) {
|
|
23
|
+
return 'prompt-submission-' + String(clientMessageId || '');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function trayButton(doc, label, onClick) {
|
|
27
|
+
var el = doc.createElement('button');
|
|
28
|
+
el.className = 'btn small';
|
|
29
|
+
el.textContent = label;
|
|
30
|
+
el.onclick = onClick;
|
|
31
|
+
return el;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// AC-1a/AC-1e (WP-1 fix): a row's callbacks and timers are bound to the manager and the record
|
|
35
|
+
// the row was rendered for. The manager identity is captured once, at render time, and re-checked
|
|
36
|
+
// before every DOM/recovery/dismiss effect -- a later getManager() that answers with a NEW manager
|
|
37
|
+
// (a logout, or a fresh lease) can never authorize an old row's timer or handler. A caller may add
|
|
38
|
+
// its own predicate for a record the manager does not track (a queue-owned review record that
|
|
39
|
+
// survived a reload): the clientMessageId is never authority on its own.
|
|
40
|
+
function createLifetime(dependencies) {
|
|
41
|
+
var tracksOwner = typeof dependencies.getManager === 'function';
|
|
42
|
+
var owner = tracksOwner ? dependencies.getManager() : null;
|
|
43
|
+
function ownerCurrent() {
|
|
44
|
+
if (!tracksOwner) return true;
|
|
45
|
+
return !!owner && dependencies.getManager() === owner;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
owner: owner,
|
|
49
|
+
ownerCurrent: ownerCurrent,
|
|
50
|
+
current: function current(record) {
|
|
51
|
+
if (!ownerCurrent()) return false;
|
|
52
|
+
if (typeof dependencies.isCurrent !== 'function') return true;
|
|
53
|
+
try { return dependencies.isCurrent(record) === true; }
|
|
54
|
+
catch (_) { return false; }
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// AC-1f (WP-1 fix): a recovery gesture is one-shot WHILE it runs -- a double click cannot start
|
|
60
|
+
// two replacements -- but a refusal, a throw or a rejected callback must hand the button back. An
|
|
61
|
+
// inert Resend/confirm button is a dead end for the user; the row stays locked only when the
|
|
62
|
+
// gesture really committed (its owner retires the row at that point).
|
|
63
|
+
function runGesture(row, flag, record, lifetime, gesture, onCommit) {
|
|
64
|
+
if (row.dataset[flag] === '1') return;
|
|
65
|
+
row.dataset[flag] = '1';
|
|
66
|
+
function release(committed) {
|
|
67
|
+
if (committed === true) return;
|
|
68
|
+
if (!lifetime.current(record)) return;
|
|
69
|
+
row.dataset[flag] = '';
|
|
70
|
+
}
|
|
71
|
+
var result;
|
|
72
|
+
try { result = gesture(); }
|
|
73
|
+
catch (error) { release(false); throw error; }
|
|
74
|
+
Promise.resolve(result).then(function(committed) {
|
|
75
|
+
release(committed === true);
|
|
76
|
+
// A committed successor has nothing left to say here: the surface that was only raised for
|
|
77
|
+
// the uncertain attempt retires itself. The check is the page identity the row was rendered
|
|
78
|
+
// against -- never the record predicate, which the commit itself is allowed to invalidate.
|
|
79
|
+
if (committed === true && typeof onCommit === 'function') onCommit();
|
|
80
|
+
}, function() { release(false); });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// R6: an uncertain outcome is never resolved by re-sending on the user's behalf. The Review
|
|
84
|
+
// gesture only opens the preserved prompt (the server's own message is the uncertainty
|
|
85
|
+
// warning); the SEND is a second, explicit click, and it is reported as a confirmed resend.
|
|
86
|
+
function appendReviewPanel(doc, row, record, dependencies, lifetime) {
|
|
87
|
+
var panel = doc.createElement('div');
|
|
88
|
+
panel.dataset.ctmReviewPanel = '1';
|
|
89
|
+
panel.style.cssText = 'flex-basis:100%;display:grid;gap:6px;padding-top:6px;border-top:1px dashed var(--border)';
|
|
90
|
+
var warning = doc.createElement('div');
|
|
91
|
+
warning.dataset.ctmReviewWarning = '1';
|
|
92
|
+
warning.style.cssText = 'color:var(--yellow);font-size:11px';
|
|
93
|
+
warning.textContent = String(record.message || 'CTM could not confirm what happened to this prompt.');
|
|
94
|
+
panel.appendChild(warning);
|
|
95
|
+
var preserved = doc.createElement('pre');
|
|
96
|
+
preserved.dataset.ctmReviewText = '1';
|
|
97
|
+
preserved.style.cssText = 'white-space:pre-wrap;margin:0;max-height:140px;overflow:auto;font:inherit';
|
|
98
|
+
// Exactly the text the user typed, byte for byte -- never re-typed, never re-worded.
|
|
99
|
+
preserved.textContent = String(record.text || '');
|
|
100
|
+
panel.appendChild(preserved);
|
|
101
|
+
var actions = doc.createElement('div');
|
|
102
|
+
actions.dataset.ctmReviewActions = '1';
|
|
103
|
+
actions.style.cssText = 'display:flex;gap:6px';
|
|
104
|
+
actions.appendChild(trayButton(doc, 'Send as new attempt', function() {
|
|
105
|
+
// The explicit confirmation R6 requires, and a one-shot gesture: a double click must not
|
|
106
|
+
// start two replacements. A refused answer re-arms it -- nothing was sent.
|
|
107
|
+
runGesture(row, 'ctmReviewDispatched', record, lifetime, function() {
|
|
108
|
+
row.dataset.ctmReviewOpen = '';
|
|
109
|
+
return dependencies.onRecovery('resend', record, { confirmUncertain: true });
|
|
110
|
+
}, function committedSuccessor() {
|
|
111
|
+
if (!lifetime.ownerCurrent()) return;
|
|
112
|
+
// Only a row this surface created is retired here; a row the manager still renders belongs
|
|
113
|
+
// to the manager's own dismiss path.
|
|
114
|
+
if (row.dataset.ctmReviewRow === '1') row.remove();
|
|
115
|
+
});
|
|
116
|
+
}));
|
|
117
|
+
// Closing the review never touches the prompt: the queue item keeps its text, images and
|
|
118
|
+
// pending state, and Send Next can open the review again.
|
|
119
|
+
actions.appendChild(trayButton(doc, 'Cancel', function() {
|
|
120
|
+
if (!lifetime.current(record)) return;
|
|
121
|
+
row.dataset.ctmReviewOpen = '';
|
|
122
|
+
row.dataset.ctmReviewDispatched = '';
|
|
123
|
+
row.style.flexWrap = '';
|
|
124
|
+
panel.remove();
|
|
125
|
+
if (row.dataset.ctmReviewRow === '1') row.remove();
|
|
126
|
+
}));
|
|
127
|
+
panel.appendChild(actions);
|
|
128
|
+
row.appendChild(panel);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function renderStatus(record, dependencies) {
|
|
132
|
+
if (!record || !dependencies || !dependencies.document) return null;
|
|
133
|
+
var doc = dependencies.document;
|
|
134
|
+
var lifetime = createLifetime(dependencies);
|
|
135
|
+
var manager = lifetime.owner;
|
|
136
|
+
if (!lifetime.ownerCurrent()) return null;
|
|
137
|
+
var now = function() { return dependencies.now ? Number(dependencies.now()) : Date.now(); };
|
|
138
|
+
var setTimer = function(callback, delayMs) {
|
|
139
|
+
return dependencies.setTimer ? dependencies.setTimer(callback, delayMs) : setTimeout(callback, delayMs);
|
|
140
|
+
};
|
|
141
|
+
var tray = dependencies.ensureTray();
|
|
142
|
+
dependencies.positionTray(tray);
|
|
143
|
+
var id = rowId(record.clientMessageId);
|
|
144
|
+
var row = doc.getElementById(id);
|
|
145
|
+
if (!row) {
|
|
146
|
+
row = doc.createElement('div');
|
|
147
|
+
row.id = id;
|
|
148
|
+
row.style.cssText = ROW_CSS;
|
|
149
|
+
tray.appendChild(row);
|
|
150
|
+
}
|
|
151
|
+
// Quiet happy path (user feedback 2026-08-20: stacked "Sending prompt..." rows sat over the
|
|
152
|
+
// composer for a whole 21-min turn saying nothing). The tray's real job is the FAILURE lane --
|
|
153
|
+
// Retry/Restore when a prompt would otherwise be silently lost -- so pending/queued rows stay
|
|
154
|
+
// hidden unless a prompt is still unacknowledged after 5s, a 'sent' that was never shown
|
|
155
|
+
// dismisses without the "Prompt sent" flash, and a user-hidden quiet row stays hidden until
|
|
156
|
+
// its status escalates to a failure (loss protection always wins over the quieting).
|
|
157
|
+
var quietStatus = record.status === 'pending' || record.status === 'queued';
|
|
158
|
+
if (!quietStatus && row.dataset.hiddenByUser === '1') delete row.dataset.hiddenByUser;
|
|
159
|
+
if (quietStatus) {
|
|
160
|
+
if (!row.dataset.quietRevealAt) {
|
|
161
|
+
row.dataset.quietRevealAt = String(now() + QUIET_REVEAL_MS);
|
|
162
|
+
row.style.display = 'none';
|
|
163
|
+
setTimer(function() {
|
|
164
|
+
if (!lifetime.current(record)) return;
|
|
165
|
+
var live = doc.getElementById(rowId(record.clientMessageId));
|
|
166
|
+
if (live && live.dataset.quietRevealAt && live.dataset.hiddenByUser !== '1') live.style.display = 'flex';
|
|
167
|
+
}, QUIET_REVEAL_MS);
|
|
168
|
+
} else if (row.dataset.hiddenByUser === '1' || now() < Number(row.dataset.quietRevealAt)) {
|
|
169
|
+
row.style.display = 'none';
|
|
170
|
+
} else {
|
|
171
|
+
row.style.display = 'flex';
|
|
172
|
+
}
|
|
173
|
+
} else if (record.status === 'sent' && row.style.display === 'none') {
|
|
174
|
+
row.remove();
|
|
175
|
+
setTimer(function() {
|
|
176
|
+
if (lifetime.current(record) && manager) manager.dismiss(record.clientMessageId);
|
|
177
|
+
}, 0);
|
|
178
|
+
return null;
|
|
179
|
+
} else {
|
|
180
|
+
delete row.dataset.quietRevealAt;
|
|
181
|
+
row.style.display = 'flex';
|
|
182
|
+
}
|
|
183
|
+
row.textContent = '';
|
|
184
|
+
var label = doc.createElement('span');
|
|
185
|
+
label.style.flex = '1';
|
|
186
|
+
label.textContent = record.status === 'pending' ? 'Sending prompt...'
|
|
187
|
+
: record.status === 'sent' ? 'Prompt sent' : (record.message || 'Prompt needs attention');
|
|
188
|
+
row.appendChild(label);
|
|
189
|
+
var failure = FAILURE_STATUSES.indexOf(record.status) >= 0;
|
|
190
|
+
var action = failure ? normalizeRecoveryAction(record.recoveryAction) : 'none';
|
|
191
|
+
if (action === 'retry') {
|
|
192
|
+
// Same admitted request: the server said this ID is still executable.
|
|
193
|
+
row.appendChild(trayButton(doc, 'Retry', function() {
|
|
194
|
+
if (lifetime.current(record) && manager) manager.retry(record.clientMessageId);
|
|
195
|
+
}));
|
|
196
|
+
} else if (action === 'resend') {
|
|
197
|
+
// Explicit new attempt only -- nothing here is scheduled or automatic.
|
|
198
|
+
row.appendChild(trayButton(doc, 'Resend', function() {
|
|
199
|
+
runGesture(row, 'ctmResendDispatched', record, lifetime, function() {
|
|
200
|
+
return dependencies.onRecovery('resend', record, { confirmUncertain: false });
|
|
201
|
+
});
|
|
202
|
+
}));
|
|
203
|
+
} else if (action === 'review') {
|
|
204
|
+
row.appendChild(trayButton(doc, 'Review', function() {
|
|
205
|
+
if (!lifetime.current(record)) return;
|
|
206
|
+
row.dataset.ctmReviewOpen = '1';
|
|
207
|
+
renderStatus(record, dependencies);
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
210
|
+
if (action === 'review' && row.dataset.ctmReviewOpen === '1') {
|
|
211
|
+
row.style.flexWrap = 'wrap';
|
|
212
|
+
appendReviewPanel(doc, row, record, dependencies, lifetime);
|
|
213
|
+
} else {
|
|
214
|
+
row.style.flexWrap = '';
|
|
215
|
+
}
|
|
216
|
+
if (record.status !== 'pending' && record.status !== 'queued') {
|
|
217
|
+
row.appendChild(trayButton(doc, 'Dismiss', function() {
|
|
218
|
+
if (lifetime.current(record) && manager) manager.dismiss(record.clientMessageId);
|
|
219
|
+
}));
|
|
220
|
+
if (record.status === 'sent') {
|
|
221
|
+
setTimer(function() {
|
|
222
|
+
if (lifetime.current(record) && manager) manager.dismiss(record.clientMessageId);
|
|
223
|
+
}, SENT_FLASH_MS);
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
// Quiet rows get a HIDE-ONLY dismiss -- never CTMPromptOutbox.dismiss here, that would drop
|
|
227
|
+
// the durable retry record while the prompt is still in flight. The row (and its tracking)
|
|
228
|
+
// stays; only the pixels go, and a failure escalation clears hiddenByUser above.
|
|
229
|
+
row.appendChild(trayButton(doc, 'Dismiss', function() {
|
|
230
|
+
if (!lifetime.current(record)) return;
|
|
231
|
+
row.dataset.hiddenByUser = '1';
|
|
232
|
+
row.style.display = 'none';
|
|
233
|
+
}));
|
|
234
|
+
}
|
|
235
|
+
return row;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// AC-1e (WP-1 fix): the review surface for a QUEUE-owned item. The queue owns the item, and the
|
|
239
|
+
// manager may hold no record for it at all (a preserved item after a reload), so the caller passes
|
|
240
|
+
// a read-only snapshot plus its own lifetime predicate. This renderer never mints, sends or
|
|
241
|
+
// persists anything of its own.
|
|
242
|
+
function renderItemReview(record, dependencies) {
|
|
243
|
+
if (!record || !dependencies || !dependencies.document) return null;
|
|
244
|
+
var doc = dependencies.document;
|
|
245
|
+
var lifetime = createLifetime(dependencies);
|
|
246
|
+
if (!lifetime.current(record)) return null;
|
|
247
|
+
var tray = dependencies.ensureTray();
|
|
248
|
+
dependencies.positionTray(tray);
|
|
249
|
+
var row = doc.getElementById(rowId(record.clientMessageId));
|
|
250
|
+
var ownsRow = false;
|
|
251
|
+
if (!row) {
|
|
252
|
+
row = doc.createElement('div');
|
|
253
|
+
row.id = rowId(record.clientMessageId);
|
|
254
|
+
row.style.cssText = ROW_CSS;
|
|
255
|
+
tray.appendChild(row);
|
|
256
|
+
ownsRow = true;
|
|
257
|
+
}
|
|
258
|
+
// Cancel removes a row this surface created itself; a row the manager already renders stays,
|
|
259
|
+
// with its own Review gesture, and is closed back to its normal state instead.
|
|
260
|
+
row.dataset.ctmReviewRow = ownsRow ? '1' : '';
|
|
261
|
+
row.dataset.ctmReviewOpen = '1';
|
|
262
|
+
row.dataset.ctmReviewDispatched = '';
|
|
263
|
+
row.style.display = 'flex';
|
|
264
|
+
row.style.flexWrap = 'wrap';
|
|
265
|
+
row.textContent = '';
|
|
266
|
+
var label = doc.createElement('span');
|
|
267
|
+
label.style.flex = '1';
|
|
268
|
+
label.textContent = 'Uncertain delivery — review this prompt before sending it again';
|
|
269
|
+
row.appendChild(label);
|
|
270
|
+
appendReviewPanel(doc, row, record, dependencies, lifetime);
|
|
271
|
+
return row;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
renderStatus: renderStatus,
|
|
276
|
+
renderItemReview: renderItemReview,
|
|
277
|
+
normalizeRecoveryAction: normalizeRecoveryAction,
|
|
278
|
+
QUIET_REVEAL_MS: QUIET_REVEAL_MS,
|
|
279
|
+
SENT_FLASH_MS: SENT_FLASH_MS,
|
|
280
|
+
};
|
|
281
|
+
});
|