elanous 0.2.14 → 0.2.16
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/chunks/{1307-6e7e0377c1db0bdc.js → 1307-b46d45b705e8c9ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +1 -0
- package/apps/pwa/out/_next/static/chunks/899-46946fe8363e1262.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9103-7a3ae7f60af3b99f.js → 9103-60fbef33e66f0a46.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-79c3ed84baaedd03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-7b2b4f378354869a.js → page-3cb52e5ea8fc2fa5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-a424ef80885d1743.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-c1e20d7d338713f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-1512d91c7491ed62.js → page-482c5dbde699947c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-1e962b31d1f11081.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-a627db94ec6904a0.js → page-8c2d9526164f5d09.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-ffff6d819fbc6e0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/{page-e6b84ab07d3567d5.js → page-a0e2a6d1bfb52fc5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c53598cfce6156f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/{page-fed69f9759d248d0.js → page-13a63953f53c6a23.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-15374909d8f1aebd.js → page-5d3c8429d04f3831.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-012a742f81218b01.js → page-3193bdc0bbab047a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-76270efaee638f17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-99effd9d893a43dc.js → page-6107ca8ddd5e3bdd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{layout-938de57ae0315e46.js → layout-dce686e582c23937.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d3d53b146416e422.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-160089123a40dd91.js → page-1a61c7ca1ceb3ae7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/{page-629e1ede482ec6eb.js → page-51f811fa119308b6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-dacff46049e1557e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-27e99b4e54a849d4.js → page-4167348049166852.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-de52e8fdf9095f7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-36a7d994f4ca0299.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/{page-32cde713be47cddb.js → page-ca3952cd78a83ca2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-e7e10cd3386222e5.js → page-5b042736aa113756.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-acb749f1e432bcf3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-cd78862707999911.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-54b9ef8afe6278fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-e64caff084f7ce21.js → page-1ebfe049c640e171.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-db07eaffba0df7e3.js → page-57924393e3e4e539.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9e0ce6c8129fa641.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-31fa1ce4c4aff9ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-86f91034bd5cabe5.js → page-0f5cd57ca928f42b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-abe8e3b74bea1ffc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-4364ef9f4e7c7f0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-ce4d8a1215ce53a3.js → page-d28573d6792b4275.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/{page-58043db78ba519ae.js → page-59f03fda76c03d22.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/{page-357750dfb91bf960.js → page-d751de5f8062ff5e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/term/{page-274703bc41b71333.js → page-fe1759f94003b32b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-d64c984e855c8c68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-86914b0dee8ab7f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/{page-3b7e821dc492bdfd.js → page-9afdee66b820c76e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d4aef67abf264874.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-f8da5dc6f3752276.js → page-1ea64acadd704ace.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-2f810b18d89ecba6.js → page-3544f154c87b43ee.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-30c2073bfc21c004.js +1 -0
- package/apps/pwa/out/_next/static/css/001d5fbaee388a25.css +1 -0
- package/apps/pwa/out/_next/static/css/{04dabcbcc4bfa6db.css → 085673d826b98b62.css} +1 -1
- package/apps/pwa/out/_next/static/rv9cierV0jSOvDBm1g0XB/_buildManifest.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +15 -15
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +15 -15
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +15 -15
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +15 -15
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +15 -15
- package/apps/pwa/out/ceo/index.html +1 -0
- package/apps/pwa/out/ceo/index.txt +33 -0
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +15 -15
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +15 -15
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +15 -15
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +15 -15
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +15 -15
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +15 -15
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +15 -15
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +15 -15
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +15 -15
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +15 -15
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +15 -15
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +15 -15
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +15 -15
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +15 -15
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +15 -15
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +15 -15
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +15 -15
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +15 -15
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +15 -15
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +15 -15
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +16 -16
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +15 -15
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +15 -15
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +15 -15
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +15 -15
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +15 -15
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +15 -15
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +15 -15
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +15 -15
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +15 -15
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +15 -15
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +15 -15
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +15 -15
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +15 -15
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +15 -15
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +15 -15
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +15 -15
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +15 -15
- package/graphs/doc-gen/doc-gen.yaml +24 -0
- package/graphs/doc-gen/recipes.yaml +3 -0
- package/graphs/heal/heal-loop.yaml +1 -1
- package/graphs/implement-loop.yaml +1 -1
- package/graphs/orchestrator/orchestrator.yaml +7 -0
- package/graphs/orchestrator/recipes.yaml +3 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -2
- package/graphs/steward/recipes.yaml +2 -1
- package/package.json +1 -1
- package/scripts/brand/check.ts +7 -5
- package/scripts/ci-public-export-import-gate.ts +154 -0
- package/scripts/ci-test-interference-gate.ts +5 -1
- package/scripts/ci-typecheck-changed.ts +82 -31
- package/scripts/docs/doc-rot.ts +164 -0
- package/scripts/docs/generate-graph-anatomy.ts +437 -0
- package/scripts/docs-cli-check.ts +4 -4
- package/scripts/expose-rubric-suggest.ts +18 -12
- package/scripts/goals/goal-census.ts +343 -0
- package/scripts/lecture-note/node.ts +31 -11
- package/scripts/lessons/handbook-page.ts +30 -3
- package/scripts/marketing/generate-ax-brief.ts +140 -0
- package/scripts/marketing/generate-feature-map.ts +118 -0
- package/scripts/measure/author-section-contribution.ts +84 -0
- package/scripts/release-loop/checklist-gate-node.ts +53 -14
- package/scripts/release-loop/cut-branch.ts +43 -13
- package/scripts/release-loop/gate-node.ts +82 -14
- package/scripts/release-loop/vault-note-node.ts +257 -8
- package/scripts/release-story/draft.ts +57 -9
- package/scripts/rhythm/daily.ts +263 -76
- package/scripts/rhythm/monthly.ts +97 -0
- package/scripts/rhythm/weekly.ts +30 -9
- package/scripts/smart-merge/resync-shadow.ts +147 -0
- package/src/acp/client.ts +17 -2
- package/src/agent-env/profile.ts +161 -0
- package/src/agent-mission/driver.ts +51 -1
- package/src/agent-mission/supervisor-metrics-cli.ts +40 -0
- package/src/agent-mission/supervisor-metrics.ts +218 -0
- package/src/agent-substrate/pr-reviewer.ts +2 -0
- package/src/ask-user-question/pending-questions.ts +5 -0
- package/src/auth/github-app-token.ts +112 -13
- package/src/autopilot/build/llm-conflict-merge.ts +32 -6
- package/src/autopilot/track-agent-shadow.ts +2 -1
- package/src/briefing/brief-items.ts +276 -0
- package/src/budget/usage-outcomes.ts +204 -0
- package/src/claims/claims-render.ts +14 -5
- package/src/cli/agent-env-cli.ts +21 -0
- package/src/cli/brief-cli.ts +73 -0
- package/src/cli/decisions-cli.ts +9 -0
- package/src/cli/doctor-cli.ts +23 -1
- package/src/cli/doctor-node-modules.ts +147 -0
- package/src/cli/intake-cli.ts +46 -17
- package/src/cli/know-cli.ts +20 -0
- package/src/cli/logs-cli.ts +43 -1
- package/src/cli/pod-cli.ts +2 -0
- package/src/cli/pr-cli.ts +80 -12
- package/src/cli/release-cli.ts +66 -29
- package/src/cli/seat-requests-cli.ts +52 -0
- package/src/cli/self-update.ts +200 -1
- package/src/cli/usage-cli.ts +26 -0
- package/src/context-bus/context-now-public.ts +16 -6
- package/src/context-bus/context-now.ts +3 -1
- package/src/context-bus/coord-events.ts +6 -4
- package/src/decisions/decision-cards.ts +33 -7
- package/src/decisions/proact-meter.ts +286 -0
- package/src/decisions/proact1-lite.ts +86 -0
- package/src/decisions/web-push-decision-cards.ts +1 -1
- package/src/discord-self-message.ts +9 -0
- package/src/domains/alert-audit.ts +271 -0
- package/src/domains/core-tools.ts +4 -3
- package/src/domains/ops-facts-tool.ts +31 -1
- package/src/flow-loop/split.ts +24 -0
- package/src/harness/harness-cli-command.ts +147 -17
- package/src/harness/harness-incidents.ts +2 -0
- package/src/harness/harness-pod-dispatch.ts +67 -8
- package/src/harness/harness-queue.ts +380 -50
- package/src/harness/harness-seams.ts +13 -3
- package/src/harness/helper-repair.ts +218 -0
- package/src/harness/helper-scan.ts +27 -4
- package/src/harness/launch-stamp.ts +236 -0
- package/src/harness/ledger-write-guard-child.fixture.ts +12 -0
- package/src/harness/ledger-write-guard.ts +35 -0
- package/src/harness/nested-elanous-policy.ts +114 -0
- package/src/harness/pod-memory-policy.ts +15 -0
- package/src/harness/repository-name.ts +55 -0
- package/src/hq/fence-audit.ts +90 -0
- package/src/hq/hq.ts +70 -6
- package/src/hq/lease.ts +9 -7
- package/src/hq/move-plan.ts +126 -0
- package/src/hq/promote.ts +31 -0
- package/src/hq/transfer.ts +185 -0
- package/src/index.ts +189 -13
- package/src/intake-plane/check.ts +63 -0
- package/src/intake-plane/digest.ts +65 -21
- package/src/intake-plane/front-classifier.ts +6 -0
- package/src/intake-plane/items.ts +3 -2
- package/src/intake-plane/lens.ts +177 -0
- package/src/intake-plane/route.ts +145 -1
- package/src/knowledge/know-find.ts +105 -0
- package/src/llm.ts +75 -19
- package/src/loops/budget.ts +36 -5
- package/src/loops/checker.ts +2 -2
- package/src/loops/orchestrator/author-depth.ts +65 -9
- package/src/loops/orchestrator/author-input-check.ts +8 -3
- package/src/loops/orchestrator/author-ledger.ts +3 -1
- package/src/loops/orchestrator/finish-rate.ts +14 -3
- package/src/loops/orchestrator/seat-share.ts +56 -0
- package/src/loops/orchestrator/tick.ts +107 -29
- package/src/loops/orchestrator/traffic.ts +117 -11
- package/src/loops/registry.ts +142 -61
- package/src/maturity/bot-slash-catalog.ts +11 -2
- package/src/maturity/feature-maturity.ts +4 -3
- package/src/maturity/tui-slash-availability.ts +40 -0
- package/src/mss/logging/log-store.ts +35 -4
- package/src/nexus/api/http-server.ts +28 -14
- package/src/nexus/api/loop-edges.ts +173 -0
- package/src/nexus/api/schedules-read.ts +13 -0
- package/src/nexus/api/seat-requests.ts +79 -56
- package/src/oauth/overload-failover-launch.ts +75 -0
- package/src/oauth/overload-failover.ts +137 -0
- package/src/prompt-enhance/enhance.ts +6 -1
- package/src/release-loop/auto-start.ts +6 -3
- package/src/release-loop/checklist.ts +19 -5
- package/src/release-loop/feature-store.ts +59 -31
- package/src/release-loop/merged-pr-checklist.ts +125 -0
- package/src/release-loop/placement.ts +98 -29
- package/src/seat-dispatch/seat-ask.ts +33 -6
- package/src/seat-dispatch/seat-request-eligibility.ts +19 -0
- package/src/seat-dispatch/seat-request-ledger.ts +133 -0
- package/src/seat-loop/seat-loop.ts +215 -12
- package/src/self-dev/ask-launch-flow.ts +22 -1
- package/src/self-dev/authored-goal-trace.ts +64 -0
- package/src/self-dev/dev-cli.ts +19 -1
- package/src/self-dev/dev-pipeline.ts +14 -9
- package/src/self-dev/draft-sweep.ts +90 -10
- package/src/self-dev/draft-triage-rules.ts +25 -8
- package/src/self-dev/entrance-registry.ts +10 -6
- package/src/self-dev/old-door.ts +73 -0
- package/src/self-dev/orchestrate.ts +15 -1
- package/src/self-dev/review-provider-fallback.ts +6 -1
- package/src/self-dev/run-supervisor.ts +49 -2
- package/src/self-implement/app-api-budget.ts +166 -0
- package/src/self-implement/budget-gate.ts +7 -5
- package/src/self-implement/follow-up-goals.ts +289 -0
- package/src/self-implement/frozen-merges.ts +3 -2
- package/src/self-implement/goal-author.ts +50 -6
- package/src/self-implement/goal-clarification-escalation.ts +5 -0
- package/src/self-implement/heal-intake.ts +120 -2
- package/src/self-implement/heal-triage.ts +44 -0
- package/src/self-implement/host-regate.ts +9 -2
- package/src/self-implement/l8-merge-queue.ts +132 -0
- package/src/self-implement/orchestrator.ts +325 -47
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/revert-guard.ts +42 -7
- package/src/self-implement/run-ledger.ts +6 -0
- package/src/self-implement/run-status-mapping.ts +2 -0
- package/src/self-implement/seams.ts +45 -16
- package/src/self-implement/self-implement-cli.ts +1 -0
- package/src/self-implement/speed-claims.ts +338 -0
- package/src/session-runtime/index.ts +2 -0
- package/src/session-runtime/retry-api.ts +87 -0
- package/src/session-runtime/retry-policy.ts +107 -6
- package/src/steward/triage.ts +74 -3
- package/src/steward/working-backwards.ts +20 -2
- package/src/task-cards/card-cli.ts +25 -0
- package/src/task-cards/card-store.ts +5 -3
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +63 -48
- package/src/task-orchestrator/surfaces/pod-command-job.ts +84 -9
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +4 -3
- package/src/task-orchestrator/surfaces/pod-ledger-prod-sink.ts +75 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +70 -9
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +37 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +166 -46
- package/src/task-orchestrator/surfaces/self-implement.ts +7 -1
- package/src/telegram-commands.ts +5 -0
- package/src/telegram.ts +72 -4
- package/src/user-config.ts +64 -7
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/nodes/bash.ts +9 -1
- package/apps/pwa/out/_next/static/chunks/4562-071d8bac44a01069.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-2df489622a52a33a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-74383f890f075511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-c496bb16da85385f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-1abfe3aec3be6bdc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-fb260b9283dbf646.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-61ec1d2e92bdd50a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-fd7e200d4d83fbd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d47266766766d227.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2ce5471926761fdd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-e995d30f6800b6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-39f89c53038a51d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-5a753bb4ec0cc511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-04250f0e2c0d03df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-341480ed8e3c1ea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8ac8d71c2adf9c8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e1e47d8d940aba3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-94dc383d3d54db1a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-b3759cc14da80908.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-194dce4a83143fce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-35bdeae2e2c17147.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-16bef3da05a900c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-134c1bc762aee62c.js +0 -1
- package/apps/pwa/out/_next/static/css/2e33713c444d5b39.css +0 -1
- package/apps/pwa/out/_next/static/x6mjI6vqOkVVu0jFuDkz1/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{x6mjI6vqOkVVu0jFuDkz1 → rv9cierV0jSOvDBm1g0XB}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CLAIM_IDLE_HOURS, PR_LABELS, STALLED_DRAFT_HOURS } from '../github/pr-labels.js';
|
|
2
2
|
import { debug } from '../debug/log.js';
|
|
3
|
-
import { decideDraft, type DraftTriagePr } from './draft-triage-rules.js';
|
|
3
|
+
import { decideDraft, sameGoalPr, type DraftTriagePr } from './draft-triage-rules.js';
|
|
4
4
|
|
|
5
5
|
export interface SweepDraft extends DraftTriagePr {
|
|
6
6
|
readonly title: string;
|
|
@@ -33,6 +33,18 @@ export interface DraftSweepAdapters {
|
|
|
33
33
|
getLatestFileChanges?(draft: SweepDraft, repository: string): Promise<Readonly<Record<string, string>> | undefined>;
|
|
34
34
|
/** Optional merge-time file inventory for the existing all-files-landed decision. */
|
|
35
35
|
getPrFiles?(repository: string, number: number): Promise<readonly string[] | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* Review and gate posture for the daily count. Omitted means unknown — not harvestable and not blocked.
|
|
38
|
+
* `review: 'pass'` is a review PASS; `mustFix` means must-fix remains; `gate: 'pass'` is a green gate.
|
|
39
|
+
*/
|
|
40
|
+
getReviewGate?(draft: SweepDraft, repository: string): Promise<SweepReviewGate | undefined>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Review PASS and gate posture used only by the daily old-draft count. */
|
|
44
|
+
export interface SweepReviewGate {
|
|
45
|
+
readonly review?: 'pass' | 'fail';
|
|
46
|
+
readonly mustFix?: boolean;
|
|
47
|
+
readonly gate?: 'pass' | 'fail';
|
|
36
48
|
}
|
|
37
49
|
|
|
38
50
|
export interface DraftSweepOptions {
|
|
@@ -67,9 +79,23 @@ export interface DraftSweepResult {
|
|
|
67
79
|
claimed?: number;
|
|
68
80
|
/** Running claims older than the idle window, including those kept by liveness. */
|
|
69
81
|
claimExpired?: number;
|
|
82
|
+
/**
|
|
83
|
+
* One line per sweep: harness drafts older than 24h, split into closable (a same-goal landing exists),
|
|
84
|
+
* harvestable (review PASS and gate pass), and blocked (must-fix remains).
|
|
85
|
+
*/
|
|
86
|
+
daily?: DraftSweepDaily;
|
|
70
87
|
error?: string;
|
|
71
88
|
}
|
|
72
89
|
|
|
90
|
+
/** Daily old-draft census. `date` is the sweep clock's UTC calendar day. */
|
|
91
|
+
export interface DraftSweepDaily {
|
|
92
|
+
readonly date: string;
|
|
93
|
+
readonly over24h: number;
|
|
94
|
+
readonly closable: number;
|
|
95
|
+
readonly harvestable: number;
|
|
96
|
+
readonly blocked: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
73
99
|
const stateLabels = PR_LABELS.filter((label) => label.axis === 'state');
|
|
74
100
|
const label = (action: 'mark-stalled' | 'close', name?: string): string => {
|
|
75
101
|
const match = PR_LABELS.find((entry) => entry.axis === 'state' && entry.sweep.action === action && (name === undefined || entry.name.endsWith(name)));
|
|
@@ -115,7 +141,7 @@ export async function supersedeDraftsOnMerge(input: {
|
|
|
115
141
|
const mergedFiles = await adapters.getPrFiles?.(repository, merged.number);
|
|
116
142
|
const landed = { ...merged, changedFiles: mergedFiles };
|
|
117
143
|
for (const draft of drafts) {
|
|
118
|
-
if (draft.number !== merged.number && !liveBranches.has(draft.branch)
|
|
144
|
+
if (draft.number !== merged.number && draft.branch.startsWith('self-impl/') && !liveBranches.has(draft.branch)
|
|
119
145
|
&& Date.parse(draft.createdAt) < Date.parse(merged.mergedAt)) {
|
|
120
146
|
statuses.set(draft.number, await adapters.getRunStatus(draft, repository));
|
|
121
147
|
if (draft.changedFiles?.length && adapters.getLatestFileChanges) {
|
|
@@ -125,7 +151,7 @@ export async function supersedeDraftsOnMerge(input: {
|
|
|
125
151
|
}
|
|
126
152
|
for (const listedDraft of drafts) {
|
|
127
153
|
const draft = { ...listedDraft, latestFileChanges: latestChanges.get(listedDraft.number) };
|
|
128
|
-
if (draft.number === merged.number || liveBranches.has(draft.branch)
|
|
154
|
+
if (draft.number === merged.number || !draft.branch.startsWith('self-impl/') || liveBranches.has(draft.branch)
|
|
129
155
|
|| Date.parse(draft.createdAt) >= Date.parse(merged.mergedAt)) {
|
|
130
156
|
kept.push(draft.number);
|
|
131
157
|
continue;
|
|
@@ -134,7 +160,6 @@ export async function supersedeDraftsOnMerge(input: {
|
|
|
134
160
|
mergedTwins: [landed], liveBranches, ageHours: NaN });
|
|
135
161
|
if (decision.action !== 'close' || !decision.reason.startsWith(`superseded-by #${merged.number}`)
|
|
136
162
|
|| PR_LABELS.filter((entry) => entry.axis === 'state' && draft.labels.includes(entry.name)).length > 1
|
|
137
|
-
|| (draft.labels.length === 0 && !draft.branch.startsWith('self-impl/'))
|
|
138
163
|
|| closeAttempts >= DRAFT_SWEEP_CLOSE_CAP) {
|
|
139
164
|
kept.push(draft.number);
|
|
140
165
|
continue;
|
|
@@ -144,7 +169,8 @@ export async function supersedeDraftsOnMerge(input: {
|
|
|
144
169
|
try {
|
|
145
170
|
// Label first: a failed label write must never strand a closed, unlabelled PR outside open-draft sweeps.
|
|
146
171
|
if (!draft.labels.includes(supersededLabel)) await adapters.setLabels(repository, draft.number, { add: supersededLabel, remove });
|
|
147
|
-
await adapters.closeDraft(repository, draft.number,
|
|
172
|
+
await adapters.closeDraft(repository, draft.number,
|
|
173
|
+
`Draft sweep: superseded-by #${merged.number} (https://github.com/${repository}/pull/${merged.number}). Branch preserved.`);
|
|
148
174
|
closed.push(draft.number);
|
|
149
175
|
} catch (failure) {
|
|
150
176
|
kept.push(draft.number);
|
|
@@ -171,6 +197,46 @@ async function collectPages<T>(fetch: (page: number, perPage: number) => Promise
|
|
|
171
197
|
throw new Error('PR listing exceeded pagination limit');
|
|
172
198
|
}
|
|
173
199
|
|
|
200
|
+
/** First line of a failure, with no stack — the draft-cleanup loop log shows this line as-is. */
|
|
201
|
+
export function sweepFailureReason(error: unknown): string {
|
|
202
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
203
|
+
const line = message.split(/\r?\n/).map((part) => part.trim()).find((part) => part.length > 0 && !/^\s*at\s/.test(part));
|
|
204
|
+
return line && line.length > 0 ? line : 'sweep failed';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function harnessDraft(draft: SweepDraft): boolean {
|
|
208
|
+
return draft.branch.startsWith('self-impl/') || draft.labels.some((name) => name.startsWith('elanous:'));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Census of harness drafts older than 24h. Same-goal landing uses `sameGoalPr` unchanged.
|
|
213
|
+
* A draft counts as closable when a same-goal merged PR exists, harvestable when review PASS and the gate passed,
|
|
214
|
+
* and blocked when must-fix remains. Unknown review/gate is neither harvestable nor blocked.
|
|
215
|
+
*/
|
|
216
|
+
export function draftSweepDaily(
|
|
217
|
+
drafts: readonly SweepDraft[],
|
|
218
|
+
merged: readonly SweepMergedPr[],
|
|
219
|
+
now: Date,
|
|
220
|
+
reviewGate: ReadonlyMap<number, SweepReviewGate | undefined>,
|
|
221
|
+
): DraftSweepDaily {
|
|
222
|
+
const cutoff = now.getTime() - STALLED_DRAFT_HOURS * 3_600_000;
|
|
223
|
+
let over24h = 0;
|
|
224
|
+
let closable = 0;
|
|
225
|
+
let harvestable = 0;
|
|
226
|
+
let blocked = 0;
|
|
227
|
+
for (const draft of drafts) {
|
|
228
|
+
if (!harnessDraft(draft)) continue;
|
|
229
|
+
const created = Date.parse(draft.createdAt);
|
|
230
|
+
if (!Number.isFinite(created) || created > cutoff) continue;
|
|
231
|
+
over24h += 1;
|
|
232
|
+
if (merged.some((pr) => pr.number !== draft.number && sameGoalPr(draft, pr))) closable += 1;
|
|
233
|
+
const posture = reviewGate.get(draft.number);
|
|
234
|
+
if (posture?.mustFix === true) blocked += 1;
|
|
235
|
+
else if (posture?.review === 'pass' && posture.gate === 'pass') harvestable += 1;
|
|
236
|
+
}
|
|
237
|
+
return { date: now.toISOString().slice(0, 10), over24h, closable, harvestable, blocked };
|
|
238
|
+
}
|
|
239
|
+
|
|
174
240
|
/** A failed inventory or liveness lookup is never treated as proof that a draft can be closed. */
|
|
175
241
|
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date() }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
176
242
|
const result: DraftSweepResult = { repository, apply, complete: false, entries: [], counts: {} };
|
|
@@ -181,10 +247,12 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
181
247
|
};
|
|
182
248
|
const finish = (): DraftSweepResult => {
|
|
183
249
|
debug.log('drafts.cleanup', 'summary', result.counts);
|
|
250
|
+
if (result.daily) debug.log('harness.drafts', 'daily', result.daily);
|
|
251
|
+
if (!result.complete && result.error) debug.log('drafts.cleanup', 'failed', { reason: sweepFailureReason(result.error) });
|
|
184
252
|
return result;
|
|
185
253
|
};
|
|
186
|
-
let drafts: SweepDraft[];
|
|
187
|
-
let merged: SweepMergedPr[];
|
|
254
|
+
let drafts: SweepDraft[] = [];
|
|
255
|
+
let merged: SweepMergedPr[] = [];
|
|
188
256
|
let liveBranches: ReadonlySet<string> | undefined;
|
|
189
257
|
try {
|
|
190
258
|
[drafts, merged, liveBranches] = await Promise.all([
|
|
@@ -196,7 +264,8 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
196
264
|
if (drafts.some((pr) => !Number.isInteger(pr.number) || !pr.branch || !Array.isArray(pr.labels) || !Number.isFinite(Date.parse(pr.createdAt)))
|
|
197
265
|
|| merged.some((pr) => !Number.isInteger(pr.number) || !pr.branch)) throw new Error('Invalid PR inventory');
|
|
198
266
|
} catch (error) {
|
|
199
|
-
result.error =
|
|
267
|
+
result.error = sweepFailureReason(error);
|
|
268
|
+
if (drafts.length > 0) result.daily = draftSweepDaily(drafts, merged, now, new Map());
|
|
200
269
|
return finish();
|
|
201
270
|
}
|
|
202
271
|
let statuses: Map<number, string | undefined>;
|
|
@@ -218,9 +287,19 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
218
287
|
}
|
|
219
288
|
}
|
|
220
289
|
} catch (error) {
|
|
221
|
-
result.error =
|
|
290
|
+
result.error = sweepFailureReason(error);
|
|
222
291
|
return finish();
|
|
223
292
|
}
|
|
293
|
+
let reviewGate = new Map<number, SweepReviewGate | undefined>();
|
|
294
|
+
if (adapters.getReviewGate) {
|
|
295
|
+
try {
|
|
296
|
+
for (const draft of drafts) reviewGate.set(draft.number, await adapters.getReviewGate(draft, repository));
|
|
297
|
+
} catch (error) {
|
|
298
|
+
result.error = sweepFailureReason(error);
|
|
299
|
+
return finish();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
result.daily = draftSweepDaily(drafts, merged, now, reviewGate);
|
|
224
303
|
result.complete = true;
|
|
225
304
|
let closes = 0;
|
|
226
305
|
let unobserved = 0;
|
|
@@ -330,7 +409,8 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
330
409
|
if (action === 'close') {
|
|
331
410
|
await adapters.closeDraft(repository, draft.number, decision.reason === 'stale-unobserved'
|
|
332
411
|
? `Draft sweep: run unobserved — no run record reachable here, no host worktree for this branch, idle ≥${STALLED_DRAFT_HOURS}h. Closed as stalled. Branch preserved; reopen to restore.`
|
|
333
|
-
: `Draft sweep: ${decision.reason}.
|
|
412
|
+
: `Draft sweep: ${decision.reason}${decision.reason.startsWith('superseded-by #')
|
|
413
|
+
? ` (https://github.com/${repository}/pull/${decision.reason.slice('superseded-by #'.length).match(/^\d+/)![0]})` : ''}. Branch preserved.`);
|
|
334
414
|
}
|
|
335
415
|
entry.applied = labelsChanged || action === 'close';
|
|
336
416
|
} catch (error) {
|
|
@@ -38,6 +38,21 @@ const PROTECTED_LABELS: ReadonlySet<string> = new Set<string>([...PR_LABELS
|
|
|
38
38
|
const goalId = (branch: string): string | undefined => /(?:^|[-/])goalid-([a-f0-9]+)(?=-|\/|$)/i.exec(branch)?.[1]?.toLowerCase();
|
|
39
39
|
export const branchStem = (branch: string): string | undefined => /^self-impl\/(.+)-[a-f0-9]{8}-r[a-f0-9]+$/i.exec(branch)?.[1];
|
|
40
40
|
const slot = (body?: string): string | undefined => /^칸:\s*(.+?)\s*$/m.exec(body ?? '')?.[1];
|
|
41
|
+
const goalText = (body?: string): string | undefined => /^골:\s*(\S.*?)\s*$/m.exec(body ?? '')?.[1];
|
|
42
|
+
// Auto titles name only files («src/harness: harness-queue.ts») — different goals share them, so they never identify a goal.
|
|
43
|
+
export const isAutoTitle = (title: string): boolean =>
|
|
44
|
+
/^[\w./-]+:\s*[^\s,]+\.[a-z0-9]+(?:\s*,\s*[^\s,]+\.[a-z0-9]+)*$/i.test(title.trim());
|
|
45
|
+
|
|
46
|
+
/** Same goal (TC 10-05): ① both carry a goal identifier → compare it ② otherwise exact title ⊕ both harness drafts ⊕ same branch stem, never an auto title ③ else false. */
|
|
47
|
+
export function sameGoalPr(a: DraftTriagePr, b: DraftTriagePr): boolean {
|
|
48
|
+
const idA = goalId(a.branch), idB = goalId(b.branch);
|
|
49
|
+
if (idA && idB) return idA === idB;
|
|
50
|
+
const textA = goalText(a.body), textB = goalText(b.body);
|
|
51
|
+
if (textA && textB) return textA === textB;
|
|
52
|
+
if (!a.title || a.title !== b.title || isAutoTitle(a.title)) return false;
|
|
53
|
+
const stemA = branchStem(a.branch);
|
|
54
|
+
return Boolean(stemA && a.branch.startsWith('self-impl/') && b.branch.startsWith('self-impl/') && stemA === branchStem(b.branch));
|
|
55
|
+
}
|
|
41
56
|
const referencesDraft = (text: string, number: number): boolean =>
|
|
42
57
|
new RegExp(`(?:\\(수확\\s*#${number}\\s*\\)|\\bsuperseded\\s*#${number}(?!\\d))`, 'i').test(text);
|
|
43
58
|
const landingCommentReferencesDraft = (text: string, number: number): boolean =>
|
|
@@ -55,28 +70,30 @@ export function decideDraft({ draft, runStatus, mergedTwins, openDrafts, ageHour
|
|
|
55
70
|
return { action: 'keep', reason: 'live' };
|
|
56
71
|
}
|
|
57
72
|
const lineage = goalId(draft.branch);
|
|
58
|
-
const
|
|
59
|
-
(draft.title && pr.title === draft.title) || (lineage && goalId(pr.branch) === lineage)
|
|
60
|
-
));
|
|
61
|
-
if (twin) return { action: 'close', reason: `superseded-by #${twin.number}` };
|
|
73
|
+
const draftSlot = slot(draft.body);
|
|
62
74
|
const stem = branchStem(draft.branch);
|
|
75
|
+
const compatible = (pr: DraftTriagePr): boolean =>
|
|
76
|
+
!(lineage && goalId(pr.branch) && goalId(pr.branch) !== lineage)
|
|
77
|
+
&& !(draftSlot && slot(pr.body) && slot(pr.body) !== draftSlot);
|
|
78
|
+
const twin = mergedTwins.find((pr) => pr.number !== draft.number && compatible(pr) && sameGoalPr(draft, pr));
|
|
79
|
+
if (twin) return { action: 'close', reason: `superseded-by #${twin.number}` };
|
|
63
80
|
const createdAt = Date.parse(draft.createdAt ?? '');
|
|
64
81
|
const newer = stem && draft.title && Number.isFinite(createdAt) ? openDrafts
|
|
65
|
-
?.filter((pr) => pr.number !== draft.number && pr.title === draft.title && branchStem(pr.branch) === stem
|
|
82
|
+
?.filter((pr) => pr.number !== draft.number && pr.title === draft.title && branchStem(pr.branch) === stem && sameGoalPr(draft, pr)
|
|
66
83
|
&& Number.isFinite(Date.parse(pr.createdAt ?? '')) && Date.parse(pr.createdAt!) > createdAt)
|
|
67
84
|
.sort((a, b) => Date.parse(b.createdAt!) - Date.parse(a.createdAt!) || b.number - a.number)[0] : undefined;
|
|
68
85
|
if (newer) return { action: 'close', reason: `duplicate-of-open #${newer.number}` };
|
|
69
|
-
const harvest = mergedTwins.find((pr) => pr.number !== draft.number && (
|
|
86
|
+
const harvest = mergedTwins.find((pr) => pr.number !== draft.number && compatible(pr) && (
|
|
70
87
|
[pr.mergeCommitMessage, pr.body].some((text) => text && referencesDraft(text, draft.number))
|
|
71
88
|
|| pr.landingVerifiedComments?.some((text) => landingCommentReferencesDraft(text, draft.number))
|
|
72
89
|
));
|
|
73
90
|
if (harvest) return { action: 'close', reason: `superseded-by #${harvest.number} (harvest #${draft.number})` };
|
|
74
91
|
const created = Date.parse(draft.createdAt ?? '');
|
|
75
92
|
const files = draft.changedFiles;
|
|
76
|
-
const draftSlot = slot(draft.body);
|
|
77
93
|
const later = mergedTwins.filter((pr) => pr.number !== draft.number && Number.isFinite(created)
|
|
78
94
|
&& Number.isFinite(Date.parse(pr.mergedAt ?? '')) && Date.parse(pr.mergedAt!) > created
|
|
79
|
-
&& ((lineage && goalId(pr.branch) === lineage)
|
|
95
|
+
&& compatible(pr) && ((lineage && goalId(pr.branch) === lineage)
|
|
96
|
+
|| (draftSlot && slot(pr.body) === draftSlot) || (stem && branchStem(pr.branch) === stem)));
|
|
80
97
|
if (files?.length && files.every((file) => {
|
|
81
98
|
const changed = Date.parse(draft.latestFileChanges?.[file] ?? '');
|
|
82
99
|
return Number.isFinite(changed) && changed >= created && later.some((pr) =>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { findNativeTool, isNativeToolModelExposed } from '../native-tool-catalog.js';
|
|
2
2
|
|
|
3
|
-
export type EntranceStatus = 'live' | 'retired';
|
|
3
|
+
export type EntranceStatus = 'live' | 'retired' | 'closed';
|
|
4
4
|
|
|
5
5
|
export type EntranceStampability = 'stampable' | 'structurally-unstampable' | 'unknown';
|
|
6
6
|
|
|
@@ -181,12 +181,14 @@ const ENTRANCE_DECLARATIONS = [
|
|
|
181
181
|
// `dev --ask` 와 ***같은*** `runAskLaunchFlow` 를 탄다. 두 문의 차이는 `entrance` 태그뿐이다.
|
|
182
182
|
// ⇒ 판정값이 `'verified' | 'unknown'` 둘뿐이라 「구조적 부재」를 적을 칸이 없다. `unknown` 으로 둔다.
|
|
183
183
|
// ⛔ 그러니 이 `unknown` 을 「미완」으로 읽지 마라 — 그 구분은 이 주석이 canonical 이다.
|
|
184
|
-
|
|
184
|
+
// OLD-DOOR-CLOSE — a direct `dev --ask` from a terminal or seat session refuses.
|
|
185
|
+
// Harness-internal calls still pass, marked with the ONEDOOR-1 entrance stamp.
|
|
186
|
+
{ id: 'cli-dev-ask', surface: 'cli', status: 'closed', verification: { actualMission: 'verified', legacyParity: 'unknown' } },
|
|
185
187
|
// `elanous drive` 는 `elanous dev` 의 Commander alias 로 살아 있고, buildDriveAliasDevSpec 이 entrance 를
|
|
186
188
|
// `cli-drive` 로 넘기며 completion 을 `worktree-only` 로 못 박는다. 그래서 별도 무인 권한 축이 아니다.
|
|
187
189
|
{ id: 'cli-drive', surface: 'cli', status: 'live' },
|
|
188
|
-
{ id: 'cli-self-implement', surface: 'cli', status: '
|
|
189
|
-
{ id: 'cli-self-orchestrate', surface: 'cli', status: '
|
|
190
|
+
{ id: 'cli-self-implement', surface: 'cli', status: 'closed' },
|
|
191
|
+
{ id: 'cli-self-orchestrate', surface: 'cli', status: 'closed' },
|
|
190
192
|
// ⭐ 2026-08-22 · 🅣 — ***사람이 «돌려 보고» 적은 판정***이다(⛔ 도구가 추측한 값이 아니다).
|
|
191
193
|
// actualMission: 그 입구로 실제 골을 «끝까지» 돌렸다 — 17발 · 자동 병합 5 · 회수 착지 7.
|
|
192
194
|
// 📏 원장 각인이 그것을 말한다: `"entrance":"cli-harness-ask"` (아침엔 0건이었다).
|
|
@@ -331,6 +333,7 @@ export function summarizeEntrances(registry: readonly EntranceDeclaration[] = EN
|
|
|
331
333
|
readonly total: number;
|
|
332
334
|
readonly live: number;
|
|
333
335
|
readonly retired: number;
|
|
336
|
+
readonly closed: number;
|
|
334
337
|
readonly bySurface: ReadonlyArray<{ surface: EntranceSurface; total: number; retired: number }>;
|
|
335
338
|
} {
|
|
336
339
|
const surfaces = [...new Set(registry.map((e) => e.surface))];
|
|
@@ -338,6 +341,7 @@ export function summarizeEntrances(registry: readonly EntranceDeclaration[] = EN
|
|
|
338
341
|
total: registry.length,
|
|
339
342
|
live: registry.filter((e) => e.status === 'live').length,
|
|
340
343
|
retired: registry.filter((e) => e.status === 'retired').length,
|
|
344
|
+
closed: registry.filter((e) => e.status === 'closed').length,
|
|
341
345
|
bySurface: surfaces.map((surface) => ({
|
|
342
346
|
surface,
|
|
343
347
|
total: registry.filter((e) => e.surface === surface).length,
|
|
@@ -350,12 +354,12 @@ export function summarizeEntrances(registry: readonly EntranceDeclaration[] = EN
|
|
|
350
354
|
export function renderLaunchEntrances(registry: readonly EntranceDeclaration[] = ENTRANCE_REGISTRY): string {
|
|
351
355
|
const summary = summarizeEntrances(registry);
|
|
352
356
|
const rows = listEntrancesWithModelExposure(registry)
|
|
353
|
-
.map((e) => ` ${e.status === 'retired' ? '🪦' : '✅'} ${e.surface.padEnd(7)} ${e.id} (${e.stampability}) verification=actualMission:${e.verification.actualMission},legacyParity:${e.verification.legacyParity} imprintEvidence=${e.imprintEvidence} evidenceSource=${e.stampabilityEvidenceSource} evidenceSourceFilePath=${e.evidenceSourceFilePath ?? 'missing'} modelExposed=${e.modelExposed ?? 'missing'}`);
|
|
357
|
+
.map((e) => ` ${e.status === 'retired' ? '🪦' : e.status === 'closed' ? '닫힘' : '✅'} ${e.surface.padEnd(7)} ${e.id} (${e.stampability}) verification=actualMission:${e.verification.actualMission},legacyParity:${e.verification.legacyParity} imprintEvidence=${e.imprintEvidence} evidenceSource=${e.stampabilityEvidenceSource} evidenceSourceFilePath=${e.evidenceSourceFilePath ?? 'missing'} modelExposed=${e.modelExposed ?? 'missing'}`);
|
|
354
358
|
const surfaces = summary.bySurface
|
|
355
359
|
.map((s) => `${s.surface}=${s.total}${s.retired > 0 ? `(은퇴 ${s.retired})` : ''}`)
|
|
356
360
|
.join(' · ');
|
|
357
361
|
return [
|
|
358
|
-
`launch entrances: ${summary.total} (live ${summary.live} · retired ${summary.retired})`,
|
|
362
|
+
`launch entrances: ${summary.total} (live ${summary.live} · retired ${summary.retired} · closed ${summary.closed})`,
|
|
359
363
|
` 표면별: ${surfaces}`,
|
|
360
364
|
...rows,
|
|
361
365
|
].join('\n');
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OLD-DOOR-CLOSE — the three outside doors refuse a direct call.
|
|
3
|
+
*
|
|
4
|
+
* `elanous dev --ask`, `elanous self implement`, and `elanous self orchestrate`
|
|
5
|
+
* stay callable from inside the harness. The harness marks those calls with
|
|
6
|
+
* the same stamp ONEDOOR-1 uses for a door (`ELANOUS_HARNESS_ENTRANCE`) or with
|
|
7
|
+
* the explicit internal flag `--harness-internal`. A terminal or seat session
|
|
8
|
+
* carries neither, so it exits non-zero and is told where to go.
|
|
9
|
+
*/
|
|
10
|
+
import type { LaunchDoor } from '../harness/launch-stamp.js';
|
|
11
|
+
|
|
12
|
+
export const OLD_DOORS = ['dev-ask', 'self-implement', 'self-orchestrate'] as const;
|
|
13
|
+
export type OldDoor = (typeof OLD_DOORS)[number];
|
|
14
|
+
|
|
15
|
+
/** Same env ONEDOOR-1 already stamps onto a harness launch. */
|
|
16
|
+
export const OLD_DOOR_STAMP_ENV = 'ELANOUS_HARNESS_ENTRANCE';
|
|
17
|
+
/** Same meaning as the env, for a caller that can pass an argument but not an env. */
|
|
18
|
+
export const OLD_DOOR_STAMP_FLAG = '--harness-internal';
|
|
19
|
+
|
|
20
|
+
const STAMP_BY_DOOR: Readonly<Record<OldDoor, readonly string[]>> = {
|
|
21
|
+
'dev-ask': ['dev-ask', 'cli-dev-ask', 'cli-drive', 'harness-say', 'cli-harness-say', 'harness-ask', 'cli-harness-ask', 'queue-tick', 'agent-mission', 'daemon-tool'],
|
|
22
|
+
'self-implement': ['self-implement', 'cli-self-implement', 'nl-self-implement', 'daemon-self-implement', 'daemon-tool', 'harness-say', 'cli-harness-say', 'harness-ask', 'cli-harness-ask', 'queue-tick', 'agent-mission'],
|
|
23
|
+
'self-orchestrate': ['self-orchestrate', 'cli-self-orchestrate', 'nl-self-orchestrate', 'cli-harness-orchestrate', 'harness-say', 'cli-harness-say', 'harness-ask', 'cli-harness-ask', 'queue-tick', 'agent-mission', 'daemon-tool'],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export interface OldDoorRefusal {
|
|
27
|
+
readonly door: OldDoor;
|
|
28
|
+
readonly caller: 'outside';
|
|
29
|
+
readonly exitCode: 1;
|
|
30
|
+
readonly message: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function oldDoorStampAccepted(door: OldDoor, stamp: string | undefined | null): boolean {
|
|
34
|
+
const value = stamp?.trim();
|
|
35
|
+
if (!value) return false;
|
|
36
|
+
return (STAMP_BY_DOOR[door] as readonly string[]).includes(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** A harness-internal call carries the stamp in the environment or on the argv. Anything else is outside. */
|
|
40
|
+
export function isOldDoorInternalCall(
|
|
41
|
+
door: OldDoor,
|
|
42
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
43
|
+
argv: readonly string[] = process.argv,
|
|
44
|
+
): boolean {
|
|
45
|
+
if (argv.includes(OLD_DOOR_STAMP_FLAG)) return true;
|
|
46
|
+
return oldDoorStampAccepted(door, env[OLD_DOOR_STAMP_ENV]);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Env a harness parent sets so the child door stays open. */
|
|
50
|
+
export function oldDoorInternalEnv(door: LaunchDoor | OldDoor): Record<string, string> {
|
|
51
|
+
return { [OLD_DOOR_STAMP_ENV]: door };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const REPLACEMENT: Readonly<Record<OldDoor, string>> = {
|
|
55
|
+
'dev-ask': 'elanous harness ask <goal.md>',
|
|
56
|
+
'self-implement': 'elanous harness say "<sentence>"',
|
|
57
|
+
'self-orchestrate': 'elanous harness say "<sentence>"',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const DOOR_LABEL: Readonly<Record<OldDoor, string>> = {
|
|
61
|
+
'dev-ask': 'elanous dev --ask',
|
|
62
|
+
'self-implement': 'elanous self implement',
|
|
63
|
+
'self-orchestrate': 'elanous self orchestrate',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** One line: the closed door, the harness door to use, and a command of the same meaning. */
|
|
67
|
+
export function oldDoorRefusalMessage(door: OldDoor): string {
|
|
68
|
+
return `${DOOR_LABEL[door]} 는 닫혔습니다 — harness say / harness ask 로. 예: ${REPLACEMENT[door]}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function refuseOldDoor(door: OldDoor): OldDoorRefusal {
|
|
72
|
+
return { door, caller: 'outside', exitCode: 1, message: oldDoorRefusalMessage(door) };
|
|
73
|
+
}
|
|
@@ -260,12 +260,23 @@ export interface SelfDevJobResult {
|
|
|
260
260
|
* (merged / pr-opened / gate-failed / review-blocked / pr-declined). */
|
|
261
261
|
stage?: string;
|
|
262
262
|
branch?: string;
|
|
263
|
+
/** Child confirmed the finished implementation was pushed for manual harvest. */
|
|
264
|
+
harvestable?: true;
|
|
263
265
|
worktreePath?: string;
|
|
264
266
|
prUrl?: string;
|
|
265
267
|
prNumber?: number;
|
|
266
268
|
merged?: boolean;
|
|
267
269
|
/** Child commit SHA, when observed by the Pod/host. */
|
|
268
270
|
checkedHeadCommit?: string;
|
|
271
|
+
/**
|
|
272
|
+
* This run's own `--base` (not main). A non-main completion mode
|
|
273
|
+
* (worktree-only, draft, `--base` other than main) lands commits here.
|
|
274
|
+
*/
|
|
275
|
+
base?: string;
|
|
276
|
+
/** Child finished with GOAL-COMPLETE (`ok=true`). Distinct from a main merge. */
|
|
277
|
+
ok?: boolean;
|
|
278
|
+
/** Commits this child added against its own `--base`. 0 is not completion progress. */
|
|
279
|
+
commitsAheadOfBase?: number;
|
|
269
280
|
/** A dependency is done but its result is not on main; no child was launched. */
|
|
270
281
|
blockReason?: 'parent-unlanded';
|
|
271
282
|
parentPrNumber?: number;
|
|
@@ -405,6 +416,7 @@ export type ResumeDisposition = 'skip' | 'rerun' | 'rerun-duplicate-risk';
|
|
|
405
416
|
*/
|
|
406
417
|
export function classifyResumeDisposition(result: SelfDevJobResult): ResumeDisposition {
|
|
407
418
|
if (hasDelivered(result)) return 'skip';
|
|
419
|
+
if (result.harvestable === true && result.branch) return 'skip';
|
|
408
420
|
if (result.stage === 'pr-opened') return 'rerun-duplicate-risk';
|
|
409
421
|
if (result.merged === false) return 'rerun';
|
|
410
422
|
if (result.status !== 'done') return 'rerun';
|
|
@@ -621,6 +633,7 @@ export function classifyFailure(
|
|
|
621
633
|
) {
|
|
622
634
|
return 'awaiting-human';
|
|
623
635
|
}
|
|
636
|
+
if (result.harvestable === true && result.branch) return 'main-sync-blocked';
|
|
624
637
|
if (result.status === 'done' && !hasDelivered(result)) return convergedFailureKind();
|
|
625
638
|
// ⭐ 상류가 죽어 «취소»된 조각 — 종전엔 status 가 failed 도 done 도 아니라 null 로 사라졌다.
|
|
626
639
|
// ⛔ 이것을 못 보면 「무엇이 상류를 기다리는가」를 슈퍼바이저가 영영 모른다.
|
|
@@ -1479,6 +1492,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
|
|
|
1479
1492
|
...(resumeDisposition ? { resumeDisposition } : {}),
|
|
1480
1493
|
...(disp?.stage ? { stage: disp.stage } : {}),
|
|
1481
1494
|
...(disp?.branch ? { branch: disp.branch } : {}),
|
|
1495
|
+
...(disp?.harvestable === true && disp.branch ? { harvestable: true } : {}),
|
|
1482
1496
|
...(disp?.worktreePath ? { worktreePath: disp.worktreePath } : {}),
|
|
1483
1497
|
...(disp?.prUrl ? { prUrl: disp.prUrl } : {}),
|
|
1484
1498
|
...(disp?.prNumber !== undefined ? { prNumber: disp.prNumber } : {}),
|
|
@@ -1526,7 +1540,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
|
|
|
1526
1540
|
const rm = opts.removeWorktree ?? defaultRemoveWorktree;
|
|
1527
1541
|
let removed = 0;
|
|
1528
1542
|
for (const r of out) {
|
|
1529
|
-
if (!r.worktreePath || r.prUrl) continue;
|
|
1543
|
+
if (!r.worktreePath || r.prUrl || r.harvestable) continue;
|
|
1530
1544
|
try { rm(r.worktreePath); removed++; } catch { /* fail-soft */ }
|
|
1531
1545
|
}
|
|
1532
1546
|
if (removed > 0) debug.log('self-dev.orchestrate', 'teardown', { removed });
|
|
@@ -73,13 +73,18 @@ export function buildReviewProviderAttempts(
|
|
|
73
73
|
const out: ReviewProviderAttempt[] = [primary];
|
|
74
74
|
const seen = new Set([primary.model]);
|
|
75
75
|
for (const f of fallbacks) {
|
|
76
|
-
if (!f.model.trim() || seen.has(f.model)) continue;
|
|
76
|
+
if (!f.model.trim() || seen.has(f.model) || (primary.provider && f.provider?.name === primary.provider.name)) continue;
|
|
77
77
|
seen.add(f.model);
|
|
78
78
|
out.push(f);
|
|
79
79
|
}
|
|
80
80
|
return out;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/** A distinct provider is available even when the optional config list is empty. */
|
|
84
|
+
export function defaultReviewFallbackModel(primaryProvider?: string): string {
|
|
85
|
+
return resolveModelAlias(primaryProvider === 'grok' ? 'claude' : 'grok')!;
|
|
86
|
+
}
|
|
87
|
+
|
|
83
88
|
export interface ReviewFallbackObservation {
|
|
84
89
|
readonly attempt: number;
|
|
85
90
|
readonly total: number;
|
|
@@ -10,6 +10,14 @@ import { sweepFrozenMerges } from '../self-implement/frozen-merges.js';
|
|
|
10
10
|
export interface SupervisorRound {
|
|
11
11
|
round: number;
|
|
12
12
|
landed: number;
|
|
13
|
+
/**
|
|
14
|
+
* Pieces that finished (`ok=true`) with at least one new commit against
|
|
15
|
+
* this run's own `--base` — not a main merge. Omitted on rounds that
|
|
16
|
+
* never measured it, so older history stays comparable.
|
|
17
|
+
*/
|
|
18
|
+
baseCompleted?: number;
|
|
19
|
+
/** The run's own `--base` those completions were counted against. */
|
|
20
|
+
base?: string;
|
|
13
21
|
actionable: number;
|
|
14
22
|
reviewMustFixTrend?: SupervisorDecision['reviewMustFixTrend'];
|
|
15
23
|
}
|
|
@@ -22,6 +30,7 @@ export type SupervisorStopReason =
|
|
|
22
30
|
| 'parent-signals-red'
|
|
23
31
|
| 'needs-human'
|
|
24
32
|
| 'no-actionable-work'
|
|
33
|
+
| 'harvestable-awaiting-human'
|
|
25
34
|
| 'handed-off-to-salvage'
|
|
26
35
|
| 'max-rounds'
|
|
27
36
|
| 'no-progress'
|
|
@@ -39,6 +48,7 @@ export const SUPERVISOR_STOP_REASONS = [
|
|
|
39
48
|
'parent-signals-red',
|
|
40
49
|
'needs-human',
|
|
41
50
|
'no-actionable-work',
|
|
51
|
+
'harvestable-awaiting-human',
|
|
42
52
|
'handed-off-to-salvage',
|
|
43
53
|
'max-rounds',
|
|
44
54
|
'no-progress',
|
|
@@ -105,9 +115,25 @@ export function countLanded(results: readonly SelfDevJobResult[]): number {
|
|
|
105
115
|
return results.filter(hasDelivered).length;
|
|
106
116
|
}
|
|
107
117
|
|
|
118
|
+
/** One base label for the round. Mixed or missing bases stay unnamed. */
|
|
119
|
+
export function roundBase(results: readonly SelfDevJobResult[]): string | undefined {
|
|
120
|
+
const bases = [...new Set(results.flatMap((result) => result.base === undefined ? [] : [result.base]))];
|
|
121
|
+
return bases.length === 1 ? bases[0] : undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Finished pieces (`ok=true`) that added at least one commit against this
|
|
126
|
+
* run's own `--base`. A main merge is not required, and a commit without
|
|
127
|
+
* `ok=true` is not completion.
|
|
128
|
+
*/
|
|
129
|
+
export function countBaseCompleted(results: readonly SelfDevJobResult[]): number {
|
|
130
|
+
return results.filter((result) => result.ok === true && (result.commitsAheadOfBase ?? 0) >= 1).length;
|
|
131
|
+
}
|
|
132
|
+
|
|
108
133
|
export function madeProgress(prev: SupervisorRound | undefined, next: SupervisorRound): boolean {
|
|
109
134
|
if (!prev) return true;
|
|
110
135
|
if (next.landed > 0) return true;
|
|
136
|
+
if ((next.baseCompleted ?? 0) > (prev.baseCompleted ?? 0)) return true;
|
|
111
137
|
if (next.actionable < prev.actionable) return true;
|
|
112
138
|
return next.reviewMustFixTrend === 'improving';
|
|
113
139
|
}
|
|
@@ -191,8 +217,16 @@ export function decideNextRun(input: {
|
|
|
191
217
|
const t = triageRun(activeResults, deployFindings, observation === 'failed');
|
|
192
218
|
const round = history.length;
|
|
193
219
|
const landed = countLanded(results);
|
|
220
|
+
const baseCompleted = countBaseCompleted(results);
|
|
221
|
+
const completionBase = roundBase(results);
|
|
194
222
|
const actionable = countActionable(t);
|
|
195
|
-
const thisRound: SupervisorRound = {
|
|
223
|
+
const thisRound: SupervisorRound = {
|
|
224
|
+
round,
|
|
225
|
+
landed,
|
|
226
|
+
...(baseCompleted > 0 || completionBase !== undefined ? { baseCompleted, ...(completionBase === undefined ? {} : { base: completionBase }) } : {}),
|
|
227
|
+
actionable,
|
|
228
|
+
reviewMustFixTrend,
|
|
229
|
+
};
|
|
196
230
|
const goalPlanRevisionObservation = formatGoalPlanRevisionObservation(results);
|
|
197
231
|
const withGoalPlanRevisionObservation = (why: string): string => goalPlanRevisionObservation
|
|
198
232
|
&& goalPlanRevisionObservation !== GOAL_PLAN_REVISION_OBSERVATION_UNAVAILABLE
|
|
@@ -226,6 +260,16 @@ export function decideNextRun(input: {
|
|
|
226
260
|
};
|
|
227
261
|
}
|
|
228
262
|
|
|
263
|
+
const harvestable = results.filter((result) => result.harvestable === true && !!result.branch);
|
|
264
|
+
if (harvestable.length > 0) {
|
|
265
|
+
return {
|
|
266
|
+
...base,
|
|
267
|
+
action: 'stop',
|
|
268
|
+
stopReason: 'harvestable-awaiting-human',
|
|
269
|
+
why: withGoalPlanRevisionObservation(`구현 완료 · 수확 대기 — ${harvestable.map((result) => result.branch).join(' · ')}`),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
229
273
|
if (deliverableMergeCompleteness === 'complete') {
|
|
230
274
|
return {
|
|
231
275
|
...base,
|
|
@@ -364,7 +408,7 @@ export function decideNextRun(input: {
|
|
|
364
408
|
...base,
|
|
365
409
|
action: 'stop',
|
|
366
410
|
stopReason: 'no-progress',
|
|
367
|
-
why: withNoProgressGoalPlanRevisionObservation(`${stallRounds}라운드 연속 제자리 —
|
|
411
|
+
why: withNoProgressGoalPlanRevisionObservation(`${stallRounds}라운드 연속 제자리 — base=${completionBase ?? 'main'} 기준 완료 ${baseCompleted} · 착지 ${landed} · 남은 조각도 안 줄었다(${actionable}). 골·불변식을 의심할 자리`),
|
|
368
412
|
};
|
|
369
413
|
}
|
|
370
414
|
}
|
|
@@ -390,9 +434,12 @@ export function appendRound(
|
|
|
390
434
|
reviewMustFixTrend?: SupervisorDecision['reviewMustFixTrend'],
|
|
391
435
|
): SupervisorRound[] {
|
|
392
436
|
const t = triageRun(results.filter((result) => result.salvage !== 'launched'));
|
|
437
|
+
const baseCompleted = countBaseCompleted(results);
|
|
438
|
+
const base = roundBase(results);
|
|
393
439
|
return [...history, {
|
|
394
440
|
round: history.length,
|
|
395
441
|
landed: countLanded(results),
|
|
442
|
+
...(baseCompleted > 0 || base !== undefined ? { baseCompleted, ...(base === undefined ? {} : { base }) } : {}),
|
|
396
443
|
actionable: countActionable(t),
|
|
397
444
|
...(reviewMustFixTrend === undefined ? {} : { reviewMustFixTrend }),
|
|
398
445
|
}];
|