elanous 0.2.19 → 0.2.20
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{J5H7BvqgSI8DUjtRRcA_S → Bam1YziK2iH9bN4K0utGk}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 1268.0840ff91e083fcbd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-77fad80cf54477c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1612-f60c0c93ec773f81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1844-9ec4b1d12f6e80eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1948.15f356b15a625597.js +5 -0
- package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2977-e38442e86289f1d3.js → 211-9c9090c59e2c5907.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2116-6429c188eb846ab8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/224-e7be8f762fe74986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2549-89c518a4c8ed4d00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5755-ea7ed88eb956f47b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-94ed6f78e9814b2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4847.56f5bc454fbcc827.js → 6110.1297d4093fdfbb0d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6158.af2e93b7adff709b.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1470.98a6ab61ccb4131c.js → 726.83532d69452ee24b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 7327-2d69fb321ba73389.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{8870-9614a213b990b10b.js → 7748-6e51bfe927019f5c.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9247-c1753a059e7bac08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7647.2fcd30d894d5ee30.js → 935.4ddaa99fc1d1126c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{ae787e4c-e5b1ef00b2dbceca.js → a9f2b54d-33c0689b70ed8cf3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-c855c24de7db74fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-85b316bb4235980b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-9b2b26a33cb2cd42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-c9955fde67b1bcb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7a852956c74015a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c5a5c621be0e04ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-4ba4abe096b6c2a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-575d4a8b4f7becb2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f5d56ff5f45ad164.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-2260e9eef0357421.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-7c058069c5e7fa63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-dc5da0b8a2edb8a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-466bf0ee16ad1432.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-a23bc71713bcc08f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/{page-5b29d9b06ceadade.js → page-ed4a6f799f005d09.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-9cd565005b93aca6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-55f0f40c6db95f15.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-474cb5888ea0e8f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-35bfec2e631d3eae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ca21f9ad3208a61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f9ccb1b1adbea14d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-ec102c9b8b691e37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-a9c2cfa8dda922a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6da35144878feb6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-f6055495e9ed7ea8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-25204694fa9984a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-a60e035f151d84d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-189c587f36874538.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-c56634bde705a65d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-db03ae3589a81c9e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4a6463b97f0ad94f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-75bffecc9aa1004e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a8d2fe0c669e0de4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-31d5b875760bb62d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c26fa10aac6c21c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-68793c6e10331d66.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-46d5201d2207a511.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d81c07a7b4f618ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-be1c4e8697f22360.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-cf0a4b4abead71ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-a4717e2c4bf7a28f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-0fd895fab9b62c1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8b6c1454a8e8f306.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c6e4364d9de8f717.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-0acc8e198f7b0dfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-34882c84f84021c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-0506a1e0e4bdb2f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → f6231284-45726550aba08fca.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2ea96958.e8c7e112de50b067.js → f6b7c9ba.64a895b8b2fedbdc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-c260571513bf43c2.js +1 -0
- package/apps/pwa/out/_next/static/css/c23d959d3ee15e57.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/demo/editor-recipes.yaml +22 -0
- package/graphs/retro/daily.yaml +25 -0
- package/graphs/retro/recipes.yaml +24 -0
- package/package.json +1 -1
- package/scripts/ask-marker-check.ts +3 -1
- package/scripts/land-global-checks.ts +89 -0
- package/scripts/lib/pch-regress-map.ts +2 -1
- package/scripts/release-loop/gate-node.ts +296 -25
- package/scripts/release-loop/gate-timing.ts +116 -7
- package/scripts/release-loop/preflight.ts +6 -4
- package/scripts/release-loop/publish-window.ts +141 -0
- package/scripts/release-loop/release-docs.ts +1 -4
- package/scripts/release-loop/release-universe.ts +38 -0
- package/scripts/release-loop/resume-release.ts +4 -1
- package/scripts/release-loop/unattended-release.ts +10 -2
- package/scripts/release-story/draft.ts +5 -1
- package/scripts/retro/shadow-compare.ts +71 -0
- package/scripts/rhythm/daily.ts +6 -1
- package/src/agent-mission/driver.ts +34 -6
- package/src/autopilot/build/llm-conflict-merge.ts +132 -7
- package/src/autopilot/build/merge-intent.ts +135 -7
- package/src/away/release-watch.ts +20 -3
- package/src/cli/config-drift.ts +513 -0
- package/src/cli/log-event-names.ts +4 -0
- package/src/cli/pr-cli.ts +20 -0
- package/src/cli/release-cli.ts +20 -5
- package/src/cli/retro-cli.ts +78 -0
- package/src/cli/tasks-cli.ts +94 -8
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -4
- package/src/dashboard/slash-runtime/help-from-registry.ts +57 -31
- package/src/domains/outbound-log-probe.ts +6 -1
- package/src/graph-runner/graph-run-api.ts +205 -0
- package/src/graph-runner/runner.ts +11 -1
- package/src/harness/harness-cli-command.ts +419 -52
- package/src/harness/harness-queue.ts +315 -25
- package/src/harness/harness-salvage-cli.ts +62 -0
- package/src/hq/fence-outcomes.ts +63 -0
- package/src/hq/fence-wrapper.ts +33 -0
- package/src/hq/hq.ts +11 -1
- package/src/index.ts +69 -6
- package/src/maturity/feature-maturity.ts +2 -2
- package/src/nexus/api/graph-kinds.ts +10 -4
- package/src/nexus/api/graphs-api.ts +178 -6
- package/src/nexus/api/http-server.ts +38 -3
- package/src/nexus/api/loop-edges.ts +4 -2
- package/src/nexus/api/ops-api.ts +22 -7
- package/src/nexus/api/ops-board-route.ts +48 -0
- package/src/onboarding/entry-hints.ts +5 -0
- package/src/onboarding.ts +24 -6
- package/src/release-loop/feature-store.ts +14 -11
- package/src/release-loop/gate-shards.ts +158 -0
- package/src/release-loop/release-schedule.ts +6 -2
- package/src/retro/daily.ts +372 -0
- package/src/seat-loop/op-decide.ts +173 -0
- package/src/seat-loop/seat-loop.ts +60 -3
- package/src/seat-loop/seat-report.ts +58 -3
- package/src/self-dev/ask-launch-flow.ts +5 -4
- package/src/self-dev/ask-launch-io.ts +49 -1
- package/src/self-dev/ask-path-candidates.ts +40 -2
- package/src/self-dev/draft-sweep.ts +371 -16
- package/src/self-dev/draft-triage-rules.ts +19 -4
- package/src/self-dev/pr-preview.ts +84 -16
- package/src/self-implement/blocked-draft-policy.ts +101 -0
- package/src/self-implement/execution-clarification.ts +11 -0
- package/src/self-implement/gate-env-retry.ts +83 -0
- package/src/self-implement/orchestrator.ts +218 -5
- package/src/self-implement/run-stop.ts +123 -0
- package/src/self-implement/run-ttl.ts +258 -0
- package/src/self-implement/salvage-retention.ts +123 -0
- package/src/self-implement/seams.ts +4 -0
- package/src/self-implement/self-implement-cli.ts +2 -0
- package/src/self-implement/sibling-resync.ts +223 -0
- package/src/self-implement/stop-autoheal.ts +204 -0
- package/src/task-agent/board.ts +1 -1
- package/src/task-agent/card-evidence.ts +99 -10
- package/src/task-agent/judge.ts +7 -0
- package/src/task-agent/live-moves.ts +120 -20
- package/src/task-agent/mission.ts +1 -1
- package/src/task-agent/shadow.ts +10 -1
- package/src/task-agent/task-hand.ts +7 -2
- package/src/task-orchestrator/surfaces/pod-command-job.ts +19 -5
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +89 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +93 -10
- package/src/task-orchestrator/surfaces/pod-pool.ts +147 -34
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +19 -3
- package/src/telegram-commands.ts +41 -0
- package/src/testing/real-cli-spawn.ts +106 -0
- package/src/user-config.ts +56 -3
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1157-cba0e8553d35a980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/171-23a877ed11720de9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2336-e830c777eb6bce04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-e061bb24cd2b5cde.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3094.67339318c7f72a3a.js +0 -2
- package/apps/pwa/out/_next/static/chunks/338-ceb956612dcfaa86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3395-835e4ceaa6335ba4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3441-be82e3595aef3a20.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3689-89905039bf3e7257.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3822-6f268bc26c6a84ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4457-d7df81c90f9d0268.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4551-77dadae76f6cbace.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4978.6fd93b974441e87f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-f746f6549b869f91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-5bfed1e23790b745.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-9bc8561fde416e07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/649-ca96d1c5d09e02b8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6726-85a7db59b288c53f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6735-33267c4630d0d963.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7633-141682015873beb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-143791231c99bd02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8430-a10cfba8ef282d4e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-12c2f30dea62291c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/976-4a9b4ebdca7c739a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-15cdf568bafa9fc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-deef5ee191830f14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-b193da485f9a14b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b6e1a79df0e214f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-e84df4d907f703c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a5fb9a5db89ae4ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-1499f481d7fc52d6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c7cf753aeb648790.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4118469e514e10fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-e968f7630654332a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-505915052f947022.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c2f962fb4a3b06c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7b5ed0bd8a589ec4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-cf8193250dd42dd4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-cf3f5dfa35dea8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a15e7fcc283e9ca7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-d2915e7b70ff3d0e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-b70cd005d9169e25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2595f0eba29f57e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-c776322454156e36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-77bbd17f4435aa10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-049689e611ecc936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-85954a4fb09c44eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e773e552e1068ee6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5633c4bfa7684b4a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d829b92bd01b4994.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-061c317fc771becf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a45ece8865ed4b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-0be990618c0d56bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-bfea4865dc244b73.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d6ba8e337741484.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-76a88b55d816482e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-bba1542df59f61ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4185c95689bb372e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b699e1a8d5d34b8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c225e338c31bf274.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-449353f70507ca1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-90b889714102476d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f1ee7fbeb7f96ddc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-d59a95e1434dfaa0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-71491a23414d1a47.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-de7112bdb65fa4fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-feb4d0d88079660d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f17d887b40dd6b1d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-8da77be2192bcd5d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-72c3b9a5e9582b29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3afe4c8d0c48c39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-b9308f2d8a931531.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-6f35f9d892fa630b.js +0 -1
- package/apps/pwa/out/_next/static/css/85f53c6f35d11382.css +0 -1
- /package/apps/pwa/out/_next/static/{J5H7BvqgSI8DUjtRRcA_S → Bam1YziK2iH9bN4K0utGk}/_ssgManifest.js +0 -0
|
@@ -8,6 +8,8 @@ export interface PreviewOptions {
|
|
|
8
8
|
scenario?: string;
|
|
9
9
|
/** Main-based combined preview: only existing config paths may be enabled. */
|
|
10
10
|
flags?: readonly string[];
|
|
11
|
+
/** PR heads to preview together on main when no feature flags exist. */
|
|
12
|
+
bundlePrs?: readonly number[];
|
|
11
13
|
commentPr?: number;
|
|
12
14
|
}
|
|
13
15
|
export interface PreviewResult {
|
|
@@ -35,14 +37,50 @@ export interface PreviewDeps {
|
|
|
35
37
|
probePwa?: (url: string) => Promise<boolean>;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
const SCENARIOS: Record<string, string> = {
|
|
39
|
-
|
|
40
|
+
const SCENARIOS: Record<string, { input: string; expected: string; matches: (snapshot: string) => boolean }> = {
|
|
41
|
+
// GOODHART (#24844 review): a group head (`▸ 시작`) or the echoed `/help` is not the list. The /help modal
|
|
42
|
+
// (help-from-registry.ts) prints one `/name description` row per command; the «시작» group alone has six.
|
|
43
|
+
// Pass only when at least three other start-group commands are listed as rows.
|
|
44
|
+
S2: { input: '/help', expected: 'help command list (/status, /model, /clear ... rows)', matches: (s) =>
|
|
45
|
+
['status', 'model', 'clear', 'new', 'resume'].filter((name) => new RegExp(`(?:^|\\s)/${name}(?: \\([^)]*\\))?\\s{2,}\\S`, 'mu').test(s)).length >= 3 },
|
|
46
|
+
S3: { input: '/status', expected: 'model and connection', matches: (s) => /모델|model/iu.test(s) && /연결|connection/iu.test(s) },
|
|
47
|
+
S6: { input: '/now', expected: 'current runs or schedules', matches: (s) => /지금|도는 런|스케줄|running|schedule/iu.test(s) },
|
|
48
|
+
S7: { input: '/term list', expected: 'terminal/PTY list', matches: (s) => /terminal|pty|터미널/iu.test(s) },
|
|
49
|
+
S8: { input: '/model', expected: 'model choices', matches: (s) => /빠름|보통|깊음|terra|sol|luna|선택/iu.test(s) },
|
|
50
|
+
S9: { input: '/harness', expected: 'harness usage or stages', matches: (s) => /usage:.*harness|저작|구현|리뷰|착지/iu.test(s) },
|
|
40
51
|
};
|
|
41
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Lines of `after` that were not already on `before`'s screen (multiset by line, trailing spaces ignored).
|
|
55
|
+
* A prefix check is not enough: the PTY re-renders and scrolls, so the previous scenario's answer can
|
|
56
|
+
* reappear anywhere on the next screen (#24844 review). A repeated line is conservatively treated as old.
|
|
57
|
+
*/
|
|
58
|
+
export function previewFreshLines(before: string, after: string): string {
|
|
59
|
+
const seen = new Map<string, number>();
|
|
60
|
+
for (const line of before.split('\n')) {
|
|
61
|
+
const key = line.trimEnd();
|
|
62
|
+
if (key) seen.set(key, (seen.get(key) ?? 0) + 1);
|
|
63
|
+
}
|
|
64
|
+
return after.split('\n').filter((line) => {
|
|
65
|
+
const key = line.trimEnd();
|
|
66
|
+
if (!key) return false;
|
|
67
|
+
const left = seen.get(key) ?? 0;
|
|
68
|
+
if (left > 0) { seen.set(key, left - 1); return false; }
|
|
69
|
+
return true;
|
|
70
|
+
}).join('\n');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Whether a fresh screen region shows the scenario's expected answer (exported for the preview tests). */
|
|
74
|
+
export function previewScenarioMatches(scenario: string, fresh: string): boolean {
|
|
75
|
+
const entry = Object.hasOwn(SCENARIOS, scenario) ? SCENARIOS[scenario] : undefined;
|
|
76
|
+
if (!entry) throw new Error(`TUI-COMFORT §4: unsupported scenario ${scenario}`);
|
|
77
|
+
return entry.matches(fresh);
|
|
78
|
+
}
|
|
79
|
+
|
|
42
80
|
export function previewScenarioInput(scenario: string): string {
|
|
43
81
|
const text = Object.hasOwn(SCENARIOS, scenario) ? SCENARIOS[scenario] : undefined;
|
|
44
82
|
if (!text) throw new Error(`TUI-COMFORT §4: unsupported scenario ${scenario}; available: ${Object.keys(SCENARIOS).join(', ')}`);
|
|
45
|
-
return text;
|
|
83
|
+
return text.input;
|
|
46
84
|
}
|
|
47
85
|
|
|
48
86
|
const defaultRun: NonNullable<PreviewDeps['run']> = (command, args, cwd, timeoutMs = 120_000) => {
|
|
@@ -60,13 +98,18 @@ export async function runPrPreview(options: PreviewOptions, deps: PreviewDeps =
|
|
|
60
98
|
if (isPr && !Number.isSafeInteger(Number(target))) throw new Error('preview: invalid PR number');
|
|
61
99
|
if (/^\d+$/u.test(target) && !isPr) throw new Error('preview: invalid PR number');
|
|
62
100
|
if (options.commentPr !== undefined && (!Number.isSafeInteger(options.commentPr) || options.commentPr <= 0)) throw new Error('preview: invalid --comment-pr');
|
|
101
|
+
const bundlePrs = options.bundlePrs ?? [];
|
|
102
|
+
if (bundlePrs.length && (target !== 'main' || (options.flags?.length ?? 0) > 0)) throw new Error('preview: --bundle-pr requires main without feature flags');
|
|
103
|
+
if (bundlePrs.length && (new Set(bundlePrs).size !== bundlePrs.length || bundlePrs.some((pr) => !Number.isSafeInteger(pr) || pr <= 0))) throw new Error('preview: invalid or duplicate --bundle-pr');
|
|
63
104
|
if (target === 'main' && options.commentPr === undefined) throw new Error('preview: main ⊕ flags requires --comment-pr <PR number> to publish the result');
|
|
64
105
|
if (isPr && options.commentPr !== undefined && options.commentPr !== Number(target)) throw new Error('preview: --comment-pr must match the target PR');
|
|
65
106
|
const flags = options.flags ?? [];
|
|
66
107
|
if (flags.length && target !== 'main') throw new Error('preview: --flag requires main (main ⊕ feature flags)');
|
|
67
108
|
if (flags.some((flag) => !/^[a-zA-Z][\w-]*(?:\.[a-zA-Z][\w-]*)+$/u.test(flag))) throw new Error('preview: --flag expects an existing dotted config path');
|
|
68
|
-
const
|
|
69
|
-
|
|
109
|
+
const scenarios = (options.scenario ?? 'S2').split(',').map((id) => id.trim());
|
|
110
|
+
if (scenarios.length === 0 || new Set(scenarios).size !== scenarios.length) throw new Error('preview: duplicate or empty scenario');
|
|
111
|
+
for (const id of scenarios) previewScenarioInput(id);
|
|
112
|
+
const scenario = scenarios.join(',');
|
|
70
113
|
const check = (command: string, args: readonly string[], cwd: string, timeout?: number): string => {
|
|
71
114
|
const r = run(command, args, cwd, timeout);
|
|
72
115
|
if (r.status !== 0) throw new Error(`preview: ${command} ${args.join(' ')} failed: ${(r.stdout + '\n' + r.stderr).slice(-600)}`);
|
|
@@ -99,6 +142,16 @@ export async function runPrPreview(options: PreviewOptions, deps: PreviewDeps =
|
|
|
99
142
|
const pr = JSON.parse(check('gh', ['pr', 'view', String(prNumber), '--json', 'headRefOid,headRefName'], root)) as { headRefOid?: string; headRefName?: string };
|
|
100
143
|
if (pr.headRefName !== target || pr.headRefOid !== head || (branchPrHead !== undefined && branchPrHead !== head)) throw new Error('preview: branch does not match the target PR head; use the PR number');
|
|
101
144
|
}
|
|
145
|
+
const bundleHeads = bundlePrs.map((number) => {
|
|
146
|
+
const pr = JSON.parse(check('gh', ['pr', 'view', String(number), '--json', 'number,headRefOid'], root)) as { number?: number; headRefOid?: string };
|
|
147
|
+
if (pr.number !== number || !/^[0-9a-f]{40}$/iu.test(pr.headRefOid ?? '')) throw new Error(`preview: PR #${number} head is unavailable`);
|
|
148
|
+
const oid = pr.headRefOid!;
|
|
149
|
+
if (run('git', ['cat-file', '-e', `${oid}^{commit}`], root).status !== 0) {
|
|
150
|
+
check('git', ['fetch', '--no-tags', 'origin', `pull/${number}/head`], root, 120_000);
|
|
151
|
+
if (check('git', ['rev-parse', '--verify', 'FETCH_HEAD^{commit}'], root) !== oid) throw new Error(`preview: PR #${number} head changed while fetching; retry`);
|
|
152
|
+
}
|
|
153
|
+
return { number, oid };
|
|
154
|
+
});
|
|
102
155
|
const directory = (deps.makeDir ?? (() => {
|
|
103
156
|
const previews = join(root, '.elanous-test', 'previews');
|
|
104
157
|
mkdirSync(previews, { recursive: true });
|
|
@@ -112,6 +165,11 @@ export async function runPrPreview(options: PreviewOptions, deps: PreviewDeps =
|
|
|
112
165
|
try {
|
|
113
166
|
check('git', ['worktree', 'add', '--detach', worktree, head], root);
|
|
114
167
|
added = true;
|
|
168
|
+
for (const { number, oid } of bundleHeads) {
|
|
169
|
+
const current = JSON.parse(check('gh', ['pr', 'view', String(number), '--json', 'number,headRefOid'], root)) as { number?: number; headRefOid?: string };
|
|
170
|
+
if (current.number !== number || current.headRefOid !== oid) throw new Error(`preview: PR #${number} head changed while preparing bundle; retry`);
|
|
171
|
+
check('git', ['-c', 'user.name=elanous-preview', '-c', 'user.email=preview@localhost', 'merge', '--no-ff', '--no-edit', oid], worktree, 120_000);
|
|
172
|
+
}
|
|
115
173
|
check('bun', ['install', '--frozen-lockfile'], worktree, 300_000);
|
|
116
174
|
check('bun', ['install', '--frozen-lockfile'], join(worktree, 'apps/pwa'), 300_000);
|
|
117
175
|
for (const flag of flags) {
|
|
@@ -145,17 +203,27 @@ export async function runPrPreview(options: PreviewOptions, deps: PreviewDeps =
|
|
|
145
203
|
if (pty.held !== true || !/^pty_[\w-]+$/u.test(pty.ptyId ?? '')) throw new Error('preview: B-1 held TUI did not return a PTY reference');
|
|
146
204
|
heldPty = pty.ptyId;
|
|
147
205
|
const snapshotArgs = ['bin/elanous.mjs', '--test', 'pty', 'snapshot', pty.ptyId!] as const;
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
206
|
+
const rows: string[] = [];
|
|
207
|
+
const snapshots: string[] = [];
|
|
208
|
+
for (const id of scenarios) {
|
|
209
|
+
const { input, expected, matches } = SCENARIOS[id]!;
|
|
210
|
+
const before = check('bun', snapshotArgs, worktree);
|
|
211
|
+
check('bun', ['bin/elanous.mjs', '--test', 'pty', 'text', pty.ptyId!, input, '--enter'], worktree);
|
|
212
|
+
// A constant sleep misses slow frames under load — poll until this scenario's expected response (≤ 20s).
|
|
213
|
+
let snapshot = '';
|
|
214
|
+
let matched = false;
|
|
215
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
216
|
+
await wait(1000);
|
|
217
|
+
snapshot = check('bun', snapshotArgs, worktree);
|
|
218
|
+
const fresh = previewFreshLines(before, snapshot);
|
|
219
|
+
matched = snapshot !== 'ok' && snapshot !== before && matches(fresh);
|
|
220
|
+
if (matched) break;
|
|
221
|
+
}
|
|
222
|
+
const observed = snapshot && snapshot !== 'ok' && snapshot !== before;
|
|
223
|
+
rows.push(`| TUI-COMFORT §4 ${id} | \`${input}\` → ${matched ? `expected ${expected} matched` : `friction: expected ${expected} not found${observed ? '' : ' (no response within 20s)'}`} |`);
|
|
224
|
+
snapshots.push(`<details><summary>Inner PTY snapshot ${id}</summary>\n\n\`\`\`text\n${snapshot.slice(-3000).replaceAll('```', "'''")}\n\`\`\`\n</details>`);
|
|
156
225
|
}
|
|
157
|
-
|
|
158
|
-
report = `| Check | Observation |\n|---|---|\n| head | \`${head}\` |\n| B-1 version | ${version.slice(0, 120)} |\n| P-1 PWA | \`${endpoint}/app/\` served the built PWA |\n| TUI-COMFORT §4 ${scenario} | \`${input}\` → snapshot captured |\n\n<details><summary>Inner PTY snapshot</summary>\n\n\`\`\`text\n${snapshot.slice(-3000).replaceAll('```', "'''")}\n\`\`\`\n</details>`;
|
|
226
|
+
report = `| Check | Observation |\n|---|---|\n| head | \`${head}\` |${bundleHeads.length ? `\n| bundled PR heads | ${bundleHeads.map(({ number, oid }) => `#${number} \`${oid}\``).join(' ⊕ ')} |` : ''}\n| B-1 version | ${version.slice(0, 120)} |\n| P-1 PWA | \`${endpoint}/app/\` served the built PWA |\n${rows.join('\n')}\n\n${snapshots.join('\n\n')}`;
|
|
159
227
|
} catch (error) {
|
|
160
228
|
report = `| Check | Friction |\n|---|---|\n| head | \`${head}\` |\n| TUI-COMFORT §4 ${scenario} | ${String(error).replaceAll('|', '\\|').slice(0, 700)} |`;
|
|
161
229
|
} finally {
|
|
@@ -167,7 +235,7 @@ export async function runPrPreview(options: PreviewOptions, deps: PreviewDeps =
|
|
|
167
235
|
}
|
|
168
236
|
(deps.dispose ?? ((dir) => rmSync(dir, { recursive: true, force: true })))(directory);
|
|
169
237
|
}
|
|
170
|
-
const status = report.includes('| Friction |') ? 'friction' : 'passed';
|
|
238
|
+
const status = report.includes('| Friction |') || report.includes('→ friction:') ? 'friction' : 'passed';
|
|
171
239
|
const body = `## PR preview — ${target} (${status})\n\n${report}`;
|
|
172
240
|
if (prNumber === undefined) throw new Error('preview: cannot comment without a PR number');
|
|
173
241
|
check('gh', ['pr', 'comment', String(prNumber), '--body', body], root);
|
|
@@ -1,6 +1,107 @@
|
|
|
1
|
+
import type { AbandonedClassification } from './abandoned-classification.js';
|
|
2
|
+
|
|
1
3
|
/** Environment interruptions have a resumable branch, not a human draft decision. */
|
|
2
4
|
export function blockedDraftDisposition(classification: string | undefined): 'open-draft' | 'preserve-branch' {
|
|
3
5
|
return classification === 'provider-error' || classification === 'quota-exhausted' || classification === 'credential-failure'
|
|
4
6
|
? 'preserve-branch'
|
|
5
7
|
: 'open-draft';
|
|
6
8
|
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* DRAFT-NOT-ARCHIVE (RFC-draft-pr-accumulation-root-fix R1 · 첫 조각)
|
|
12
|
+
*
|
|
13
|
+
* S: 멈춘 런은 산출을 draft PR 로 남겼다 — PR 이 «실패 보관소»가 되어 열린 PR 이 200 을 넘고 겹침 검사가 눈이 멀었다.
|
|
14
|
+
* C: 닫힌 147건 중 사람이 실제로 봐야 했던 것은 «주인 자리» 47건뿐이었다.
|
|
15
|
+
* Q: 어느 멈춤이 PR 을 열 자격이 있나?
|
|
16
|
+
* A: 사람 판단이 필요한 멈춤(needs-owner)만. 나머지(harvestable)는 수확 가지 `salvage/<run>/<leaf>` ⊕ 런 원장의 «사유 · 다음 수»로 남긴다.
|
|
17
|
+
* `tools.selfImplement.draftOnStop` = 'always'(기본 · 종전) | 'needs-owner-only'.
|
|
18
|
+
*/
|
|
19
|
+
export type DraftOnStopMode = 'needs-owner-only' | 'always';
|
|
20
|
+
export const DRAFT_ON_STOP_MODES = ['needs-owner-only', 'always'] as const satisfies readonly DraftOnStopMode[];
|
|
21
|
+
export const DEFAULT_DRAFT_ON_STOP: DraftOnStopMode = 'always';
|
|
22
|
+
|
|
23
|
+
/** landable = 승인된 산출(merge-approved-abandoned) — 다음 수가 `pr land` 이므로 수확 가지로 숨기지 않고 PR 로 남긴다(⛔ needs-owner 라벨은 안 단다). */
|
|
24
|
+
export type StopClass = 'needs-owner' | 'harvestable' | 'landable';
|
|
25
|
+
|
|
26
|
+
const LANDABLE: ReadonlySet<string> = new Set<AbandonedClassification>(['merge-approved-abandoned']);
|
|
27
|
+
|
|
28
|
+
/** 사람(주인 자리)이 골·계약·처분을 정해야 풀리는 멈춤. 모르는 분류는 «needs-owner» 쪽으로 기운다(⛔ 산출을 PR 밖으로 숨기지 않는다). */
|
|
29
|
+
const NEEDS_OWNER: ReadonlySet<string> = new Set<AbandonedClassification>([
|
|
30
|
+
'contract-conflict',
|
|
31
|
+
'goal-unconvergeable-candidate',
|
|
32
|
+
'pr-declined',
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const HARVESTABLE: ReadonlySet<string> = new Set<AbandonedClassification>([
|
|
36
|
+
'implementation-deficit',
|
|
37
|
+
'report-deficit',
|
|
38
|
+
'artifact-deficit',
|
|
39
|
+
'run-deadline-exceeded',
|
|
40
|
+
'already-satisfied',
|
|
41
|
+
'quota-exhausted',
|
|
42
|
+
'provider-error',
|
|
43
|
+
'credential-failure',
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
export function stopClassFor(classification: string | undefined): StopClass {
|
|
47
|
+
if (classification && NEEDS_OWNER.has(classification)) return 'needs-owner';
|
|
48
|
+
if (classification && LANDABLE.has(classification)) return 'landable';
|
|
49
|
+
if (classification && HARVESTABLE.has(classification)) return 'harvestable';
|
|
50
|
+
return 'needs-owner';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const NEXT_MOVE: Record<string, string> = {
|
|
54
|
+
'implementation-deficit': '수확 가지에서 같은 골을 이어 돌린다(resume 1회) — 그래도 멈추면 needs-owner',
|
|
55
|
+
'report-deficit': '수확 가지에서 완료 증거·보고를 보강해 다시 게이트에 올린다',
|
|
56
|
+
'artifact-deficit': '수확 가지에서 요구 산출물을 채워 다시 돌린다',
|
|
57
|
+
'run-deadline-exceeded': '수확 가지에서 이어 돌리거나, 산출이 작으면 골을 쪼개 재발사한다',
|
|
58
|
+
'merge-approved-abandoned': '승인된 산출이다 — 이 PR 을 착지 경로(pr land)로 올린다',
|
|
59
|
+
'already-satisfied': '고칠 것이 없다 — 재발사하지 말고 카드를 닫는다',
|
|
60
|
+
'quota-exhausted': '용량 회복 뒤 수확 가지에서 이어 돌린다',
|
|
61
|
+
'provider-error': 'provider 복구 뒤 수확 가지에서 이어 돌린다',
|
|
62
|
+
'credential-failure': '인증 복구 뒤 수확 가지에서 이어 돌린다',
|
|
63
|
+
'contract-conflict': '주인 자리가 골의 상충 기준을 정정한다',
|
|
64
|
+
'goal-unconvergeable-candidate': '주인 자리가 되풀이된 must-fix 와 골 계약을 대조해 골을 다시 쓰거나 쪼갠다',
|
|
65
|
+
'pr-declined': '주인 자리가 거절 사유를 반영할지 골을 다시 정할지 정한다',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export function nextMoveFor(classification: string | undefined): string {
|
|
69
|
+
return (classification && NEXT_MOVE[classification]) ?? '주인 자리가 중단 사유를 읽고 처분을 정한다(분류 못 함)';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type DraftOnStopDecision =
|
|
73
|
+
| { action: 'open-draft'; stopClass: StopClass; mode: DraftOnStopMode; ownerLabel?: string }
|
|
74
|
+
| { action: 'salvage-branch'; stopClass: 'harvestable'; mode: 'needs-owner-only' };
|
|
75
|
+
|
|
76
|
+
/** 'always' 는 종전 그대로(라벨도 그대로). 'needs-owner-only' 는 harvestable → 수확 가지 · needs-owner·landable → draft ⊕ 주인 자리 라벨.
|
|
77
|
+
* ⛔ 자리를 모르면 자리 라벨을 «안 단다»(OP 로 추측해 달면 «안다»고 말하는 셈이다) — `elanous:needs-owner` 만 남는다. */
|
|
78
|
+
export function decideDraftOnStop(input: { mode: DraftOnStopMode; classification: string | undefined; seat?: string }): DraftOnStopDecision {
|
|
79
|
+
const stopClass = stopClassFor(input.classification);
|
|
80
|
+
if (input.mode !== 'needs-owner-only') return { action: 'open-draft', stopClass, mode: 'always' };
|
|
81
|
+
if (stopClass === 'harvestable') return { action: 'salvage-branch', stopClass, mode: 'needs-owner-only' };
|
|
82
|
+
const ownerLabel = ownerSeatLabel(input.seat);
|
|
83
|
+
return { action: 'open-draft', stopClass, mode: 'needs-owner-only', ...(ownerLabel ? { ownerLabel } : {}) };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const SEATS = ['OP', 'TC', 'MK', 'UX'] as const;
|
|
87
|
+
|
|
88
|
+
/** 주인 자리 라벨 — `helper-repair` 가 읽는 `elanous:seat-<자리>` 꼴. 아는 자리일 때만 낸다(모르면 undefined). */
|
|
89
|
+
export function ownerSeatLabel(seat: string | undefined): string | undefined {
|
|
90
|
+
const trimmed = seat?.trim().toUpperCase();
|
|
91
|
+
return trimmed && (SEATS as readonly string[]).includes(trimmed) ? `elanous:seat-${trimmed}` : undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** 런 하나의 수확 가지 — `salvage/run-<6hex>/<가지 잎>`. 잎이 `-r<6hex>` 로 끝나면 `selectRunSalvageRefs` 가 그대로 찾는다. */
|
|
95
|
+
export function salvageBranchForRun(runId: string, branch: string): string {
|
|
96
|
+
// `salvage-branches.ts` `runSuffixKey` 와 같은 규칙 — 그 모듈은 실행 러너를 끌고 와 user-config 가 부를 수 없다.
|
|
97
|
+
const key = /^(?:run-)?([0-9a-f]{6})/i.exec(runId.trim())?.[1]?.toLowerCase();
|
|
98
|
+
const runShort = key ? `run-${key}` : (runId.replace(/[^A-Za-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 24) || 'run-unknown');
|
|
99
|
+
const leaf = branch.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^[-.]+|[-.]+$/g, '').replace(/\.\.+/g, '.').replace(/\.lock$/i, '-lock') || 'branch';
|
|
100
|
+
return `salvage/${runShort}/${leaf}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function parseDraftOnStopMode(raw: unknown): { mode: DraftOnStopMode; invalid: boolean } {
|
|
104
|
+
if (raw === undefined) return { mode: DEFAULT_DRAFT_ON_STOP, invalid: false };
|
|
105
|
+
if (typeof raw === 'string' && (DRAFT_ON_STOP_MODES as readonly string[]).includes(raw)) return { mode: raw as DraftOnStopMode, invalid: false };
|
|
106
|
+
return { mode: DEFAULT_DRAFT_ON_STOP, invalid: true };
|
|
107
|
+
}
|
|
@@ -15,6 +15,10 @@ import { appendRunLedgerEntry, type RunLedgerWriter } from './run-ledger.js';
|
|
|
15
15
|
|
|
16
16
|
export interface ExecutionClarificationContext {
|
|
17
17
|
runId: string;
|
|
18
|
+
outsideFiles?: readonly string[];
|
|
19
|
+
/** Full outside count — when larger than `outsideFiles`, the card says how many names it does not show. */
|
|
20
|
+
outsideCount?: number;
|
|
21
|
+
declaredPaths?: readonly string[];
|
|
18
22
|
budget?: ClarificationContext['budget'];
|
|
19
23
|
pendingQuestionCount?: number;
|
|
20
24
|
config?: { hitl?: { executionDeadlineMinutes?: number } };
|
|
@@ -71,6 +75,13 @@ export async function askAtExecution(
|
|
|
71
75
|
|
|
72
76
|
const request = toAskUserQuestionRequest(decision);
|
|
73
77
|
if (!request) throw new Error('Execution clarification policy approved a question without a valid wire request.');
|
|
78
|
+
if (candidate.id === 'execution_scope' && ctx.outsideFiles) {
|
|
79
|
+
const sibling = (file: string) => ctx.declaredPaths === undefined ? 'unknown'
|
|
80
|
+
: file.endsWith('.test.ts') && ctx.declaredPaths.includes(file.replace(/\.test\.ts$/, '.ts')) ? 'yes' : 'no';
|
|
81
|
+
const hidden = Math.max(0, (ctx.outsideCount ?? ctx.outsideFiles.length) - ctx.outsideFiles.length);
|
|
82
|
+
const details = `Run ID: ${ctx.runId}\nOutside files:\n${ctx.outsideFiles.map(file => `- ${file} (declared-path sibling test: ${sibling(file)})`).join('\n')}${hidden > 0 ? `\n- … ${hidden} more outside file(s) not shown — inspect the worktree diff before expanding scope` : ''}`;
|
|
83
|
+
for (const question of request.questions) question.question += `\n\n${details}`;
|
|
84
|
+
}
|
|
74
85
|
const configured = ctx.config === undefined
|
|
75
86
|
? getUserConfig().hitl?.executionDeadlineMinutes
|
|
76
87
|
: ctx.config.hitl?.executionDeadlineMinutes;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// ── GATE-ENV-RETRY (0.2.20 P1) — 환경 결손 gate 실패는 «게이트만» 다시 돈다 ─────────────
|
|
2
|
+
//
|
|
3
|
+
// S: 하니스 후반 gate 가 «환경 결손»(시험 결과 미수신 · git index.lock 경합 · tsc 힙 OOM ·
|
|
4
|
+
// 「측정 불가」 · 네트워크/레지스트리 타임아웃)을 자식 실패와 같은 칸으로 받아,
|
|
5
|
+
// 재작업 없이 `abandoned` 로 런을 끝냈다.
|
|
6
|
+
// C: 📏 10-06 — TASK-AGENT 런 PR #24438 «test-result-unavailable · escalating without rework» ·
|
|
7
|
+
// NESTEDGUARD3 baseline index.lock 경합 · tsc 힙 OOM «could not measure».
|
|
8
|
+
// 구현은 멀쩡한데 «잰 쪽»이 넘어졌고, 그 구현이 버려진 칸으로 셌다.
|
|
9
|
+
// Q: 구현을 버리지 않고 잴 수 있나?
|
|
10
|
+
// A: ⓐ 이 판정자가 «환경 결손»이라 말하면 짧게 쉬고 gate «만» 다시 돈다(기본 2회).
|
|
11
|
+
// ⓑ 그래도 결손이면 브랜치·PR 을 남기고 `harvestable` 로 끝낸다(「버림」이 아니라 「수확 대기」).
|
|
12
|
+
//
|
|
13
|
+
// ⛔ 틀리는 방향이 비대칭이다(`self-dev/execution-transient.ts` 와 같은 계산):
|
|
14
|
+
// 도입 실패를 「환경」으로 부르면 → 자식 결손이 재작업 없이 수확 칸으로 빠진다.
|
|
15
|
+
// ⇒ `introduced > 0` 또는 자식 책임이 «있음»이면 무조건 거짓. 어휘는 좁게 둔다.
|
|
16
|
+
// ⛔ `budget-exceeded`·`module-load-error` 는 넣지 않는다 — 다시 재도 같은 값이 나온다.
|
|
17
|
+
|
|
18
|
+
/** 환경 결손의 종류 — 관측(로그)과 PR 문면에 그대로 실린다. */
|
|
19
|
+
export type GateEnvDeficitKind =
|
|
20
|
+
| 'test-result-unavailable'
|
|
21
|
+
| 'infrastructure-failure'
|
|
22
|
+
| 'git-lock'
|
|
23
|
+
| 'out-of-memory'
|
|
24
|
+
| 'unmeasured'
|
|
25
|
+
| 'network-timeout';
|
|
26
|
+
|
|
27
|
+
export type GateEnvDeficitVerdict =
|
|
28
|
+
| { readonly envDeficit: true; readonly kind: GateEnvDeficitKind }
|
|
29
|
+
| { readonly envDeficit: false; readonly reason: 'passed' | 'introduced' | 'child-responsible' | 'non-retryable-reason' | 'no-env-signal' };
|
|
30
|
+
|
|
31
|
+
export interface GateEnvDeficitInput {
|
|
32
|
+
readonly passed: boolean;
|
|
33
|
+
readonly log?: string;
|
|
34
|
+
readonly reflectGateFacts?: {
|
|
35
|
+
readonly introduced?: number;
|
|
36
|
+
readonly unknownReason?: string;
|
|
37
|
+
readonly childResponsibility?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** unknownReason 중 «다시 재면 풀릴 수 있는» 것만. */
|
|
42
|
+
const RETRYABLE_UNKNOWN_REASONS: ReadonlySet<string> = new Set(['test-result-unavailable', 'infrastructure-failure']);
|
|
43
|
+
|
|
44
|
+
/** unknownReason 중 «다시 재도 같은 값이 나오는» 것 — 로그에 환경 어휘가 섞여 있어도 이 사유가 이긴다. */
|
|
45
|
+
const NON_RETRYABLE_UNKNOWN_REASONS: ReadonlySet<string> = new Set(['budget-exceeded', 'module-load-error']);
|
|
46
|
+
|
|
47
|
+
/** 로그 어휘 — ⛔ 좁게(위 비대칭). 순서가 곧 우선순위. */
|
|
48
|
+
const LOG_PATTERNS: ReadonlyArray<readonly [GateEnvDeficitKind, RegExp]> = [
|
|
49
|
+
['git-lock', /index\.lock|another git process seems to be running|cannot lock ref/i],
|
|
50
|
+
['out-of-memory', /javascript heap out of memory|heap out of memory|oomkilled|fatal error: .*allocation failed/i],
|
|
51
|
+
['unmeasured', /could not measure|측정 불가/i],
|
|
52
|
+
['network-timeout', /\b(?:ETIMEDOUT|ECONNRESET|EAI_AGAIN|ENOTFOUND)\b|registry\.npmjs\.org.*(?:timeout|timed out)|network timeout|socket hang up/i],
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 순수: 실패한 gate 결과가 «환경 결손»인가를 판정한다.
|
|
57
|
+
* ⛔ 도입 실패(`introduced > 0`)·자식 책임 있음은 언제나 거짓 — 그 동작은 바꾸지 않는다.
|
|
58
|
+
*/
|
|
59
|
+
export function classifyGateEnvDeficit(gate: GateEnvDeficitInput): GateEnvDeficitVerdict {
|
|
60
|
+
if (gate.passed) return { envDeficit: false, reason: 'passed' };
|
|
61
|
+
const facts = gate.reflectGateFacts;
|
|
62
|
+
if ((facts?.introduced ?? 0) > 0) return { envDeficit: false, reason: 'introduced' };
|
|
63
|
+
if (facts?.childResponsibility !== undefined && facts.childResponsibility !== 'none') {
|
|
64
|
+
return { envDeficit: false, reason: 'child-responsible' };
|
|
65
|
+
}
|
|
66
|
+
if (facts?.unknownReason !== undefined && NON_RETRYABLE_UNKNOWN_REASONS.has(facts.unknownReason)) {
|
|
67
|
+
return { envDeficit: false, reason: 'non-retryable-reason' };
|
|
68
|
+
}
|
|
69
|
+
if (facts?.unknownReason !== undefined && RETRYABLE_UNKNOWN_REASONS.has(facts.unknownReason)) {
|
|
70
|
+
return { envDeficit: true, kind: facts.unknownReason as GateEnvDeficitKind };
|
|
71
|
+
}
|
|
72
|
+
const log = gate.log ?? '';
|
|
73
|
+
for (const [kind, pattern] of LOG_PATTERNS) {
|
|
74
|
+
if (pattern.test(log)) return { envDeficit: true, kind };
|
|
75
|
+
}
|
|
76
|
+
return { envDeficit: false, reason: 'no-env-signal' };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 기본 재시도 정책 — 짧게 쉬고 gate 만 최대 2회. */
|
|
80
|
+
export const DEFAULT_GATE_ENV_RETRY = { attempts: 2, delayMs: 20_000 } as const;
|
|
81
|
+
|
|
82
|
+
/** 수확 대기로 남길 때 PR·종료 사유에 싣는 표지. */
|
|
83
|
+
export const GATE_ENV_DEFICIT_HARVESTABLE_MARK = 'env-deficit, harvestable';
|