elanous 0.2.15 → 0.2.17
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-33ffcc49ab45123b.js → 1307-aac7332576c4d6fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6877-7c6208705c284124.js → 6877-fe94e76a5841ee9b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8401-4ce1c42c8d89903f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/899-f41be85e8a680651.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/9247-269e4464cc4b491c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/{page-0e2c57fe6add4b2a.js → page-3143b07a817d1da9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-e05a77df7e005b04.js → page-17ba086ef82d339b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-7eb661ff23af7da2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-6b8444914da74ca6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-b8c49f6b4fa2df91.js → page-6e5c3a867557298b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-7110f732f45bf944.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-976813c91d7394ea.js → page-9a41d65355fc25b9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-5e77cd1802567c89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/{page-1d4901eb7c2d8822.js → page-41afec0b255ed2bb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-72d3e7ff35a8c954.js → page-4187666132fc98c4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/{page-60c7a8e1a4fe62ce.js → page-09328d499162bae4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-2a52b316cb143d9c.js → page-29ff3a8f84f03b6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-c3ce483c8d5db370.js → page-80ec7401bc83f511.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ab93b240f687d69a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-96f074f6538e8a2c.js → page-fc7d86467291ae38.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{layout-e97be5334d83a9f5.js → layout-de43a186e5ba5683.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8b08cafad27759c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-0e2d6985fb42cd2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-13e4108999f58d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e8296ee284aa1293.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-c1343f9499d86f3f.js → page-043a9111e74f6b24.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{not-found-8739a2e0ae793130.js → not-found-23a4601ceb7f452e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1ed1324b1dc36754.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/{page-d23b12bb92242558.js → page-10d958605a77b3bd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-166745e51ac0c7b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/{page-c7fea475488201a8.js → page-a04260b8ccc968d4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-7a1d85e121065cc8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-1f50e3d4e13435f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-5efbf81124c474ae.js → page-12916918988ac97e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d8a3347a9d0c3f4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-a9117d2cd3093d36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-06ee266953d9c879.js → page-5a64cb5208c6a8fd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-153c2b3bcc89e8de.js → page-1407ec83ea64c1f9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-1d824510df025d18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-6e878ebbe1737d00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-0d6d23b40263a7ea.js → page-7f49fe645d5132f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-81a4e7f8dbfe74cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-27d71f131acd9320.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-3ab59d19913b200e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-bf85b2f5bf077925.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/{page-73735b64bfe1ae67.js → page-424659bacfb8cdd7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ab32a8f522a60371.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/{page-f7e631e9b4daf66e.js → page-fc2df261f8a2c7df.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-09461366af82ef13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-9817c7f9007466cc.js → page-5d4fef9ccd7d406b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ea90a8ac73ce2749.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/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 -1
- package/apps/pwa/out/ceo/index.txt +15 -15
- 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/intake/intake-daily.yaml +9 -2
- package/graphs/intake/news-sources.yaml +4 -0
- package/graphs/intake/recipes.yaml +6 -1
- package/graphs/orchestrator/orchestrator.yaml +7 -0
- package/graphs/orchestrator/recipes.yaml +3 -0
- package/graphs/steward/recipes.yaml +2 -1
- package/package.json +1 -1
- package/scripts/__fixtures__/intake-news.xml +7 -0
- 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 +34 -15
- package/scripts/docs/doc-rot.ts +164 -0
- package/scripts/docs/generate-graph-anatomy.ts +131 -9
- package/scripts/docs-cli-check.ts +4 -4
- package/scripts/goals/goal-census.ts +343 -0
- package/scripts/intake-news.ts +169 -0
- package/scripts/measure/author-section-contribution.ts +84 -0
- package/scripts/release-loop/cut-branch.ts +43 -13
- package/scripts/release-loop/docs-land-node.ts +69 -10
- package/scripts/release-loop/gate-node.ts +3 -1
- package/scripts/release-loop/publish-node.ts +2 -2
- package/scripts/release-loop/release-docs.ts +134 -0
- package/scripts/release-loop/vault-note-node.ts +19 -2
- package/scripts/release-loop/version-node.ts +7 -4
- package/scripts/release-story/draft.ts +42 -14
- package/scripts/rhythm/monthly.ts +97 -0
- package/src/acp/client.ts +17 -2
- package/src/agent-mission/driver.ts +104 -11
- package/src/agent-mission/supervisor-metrics-cli.ts +40 -0
- package/src/agent-mission/supervisor-metrics.ts +218 -0
- package/src/autopilot/track-agent-shadow.ts +2 -1
- package/src/autopilot/track-agent.ts +5 -3
- package/src/briefing/brief-items.ts +191 -36
- package/src/budget/usage-outcomes.ts +204 -0
- package/src/cli/autopilot-cli.ts +66 -0
- package/src/cli/brief-cli.ts +73 -0
- package/src/cli/decisions-cli.ts +4 -1
- package/src/cli/intake-cli.ts +1 -1
- package/src/cli/know-cli.ts +20 -0
- package/src/cli/log-event-names.ts +1 -0
- package/src/cli/logs-cli.ts +43 -1
- package/src/cli/pr-cli.ts +92 -13
- package/src/cli/provider-cli.ts +14 -0
- package/src/cli/release-cli.ts +11 -8
- package/src/cli/self-update-canary.ts +46 -0
- package/src/cli/self-update.ts +399 -1
- package/src/cli/usage-cli.ts +26 -0
- package/src/context-card/index.ts +45 -0
- package/src/context-card/task.ts +76 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +2 -0
- package/src/decisions/decision-ledger.ts +10 -1
- package/src/discord-self-message.ts +9 -0
- package/src/flow-loop/split.ts +24 -0
- package/src/harness/harness-cli-command.ts +178 -12
- package/src/harness/harness-pod-dispatch.ts +36 -55
- package/src/harness/harness-queue.ts +86 -7
- package/src/harness/harness-seams.ts +13 -3
- package/src/harness/helper-repair.ts +139 -8
- package/src/harness/helper-scan.ts +13 -2
- package/src/harness/nested-elanous-policy.ts +133 -0
- package/src/hq/fence-wrapper.ts +123 -0
- package/src/hq/hq.ts +16 -2
- package/src/hq/lease.ts +5 -3
- package/src/hq/transfer.ts +185 -0
- package/src/index.ts +168 -13
- package/src/intake-plane/digest.ts +85 -28
- package/src/knowledge/know-find.ts +105 -0
- package/src/llm.ts +75 -19
- package/src/loops/orchestrator/finish-rate.ts +14 -3
- package/src/loops/orchestrator/tick.ts +96 -25
- package/src/maturity/bot-slash-catalog.ts +11 -2
- package/src/maturity/feature-maturity.ts +2 -2
- package/src/maturity/tui-slash-availability.ts +9 -0
- package/src/nexus/api/grid.ts +61 -0
- package/src/nexus/api/http-server.ts +19 -1
- package/src/nexus/api/task-cards-api.ts +19 -0
- package/src/oauth/codex.ts +82 -2
- package/src/oauth/overload-failover-launch.ts +75 -0
- package/src/oauth/overload-failover.ts +137 -0
- package/src/release-loop/checklist.ts +10 -5
- package/src/release-loop/feature-store.ts +10 -9
- package/src/release-loop/landing-freeze.ts +18 -10
- package/src/release-loop/placement.ts +17 -8
- package/src/seat-dispatch/seat-ask.ts +33 -6
- package/src/seat-loop/seat-loop.ts +172 -21
- package/src/self-dev/ask-launch-flow.ts +48 -8
- 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 +6 -5
- package/src/self-dev/entrance-registry.ts +10 -6
- package/src/self-dev/old-door.ts +73 -0
- package/src/self-dev/run-store.ts +5 -1
- package/src/self-dev/run-supervisor.ts +7 -1
- package/src/self-dev/supervisor-verdict-edges.ts +46 -0
- 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 +25 -20
- package/src/self-implement/goal-author-clarification.ts +81 -0
- package/src/self-implement/goal-author-cli.ts +33 -5
- package/src/self-implement/goal-author.ts +107 -25
- package/src/self-implement/goal-clarification-escalation.ts +37 -1
- package/src/self-implement/goal-document-write.ts +28 -0
- package/src/self-implement/heal-intake.ts +4 -0
- package/src/self-implement/heal-triage.ts +44 -0
- package/src/self-implement/host-regate.ts +3 -1
- package/src/self-implement/orchestrator.ts +157 -8
- package/src/self-implement/run-ledger.ts +4 -0
- package/src/self-implement/seams.ts +44 -15
- 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/working-backwards.ts +16 -1
- package/src/task-agent/actions.ts +118 -0
- package/src/task-agent/judge.ts +96 -0
- package/src/task-cards/card-cli.ts +25 -0
- package/src/task-cards/card-store.ts +9 -4
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +33 -4
- package/src/task-orchestrator/surfaces/pod-lease.ts +5 -2
- 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 +95 -18
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +37 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +168 -37
- package/src/task-orchestrator/surfaces/self-implement.ts +2 -0
- package/src/telegram-commands.ts +6 -1
- package/src/telegram-loops-command.ts +21 -14
- package/src/telegram.ts +47 -0
- package/src/user-config.ts +59 -4
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/8827-e2f5b09a8d37e83b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/899-46946fe8363e1262.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9247-29d889b809288e65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-f544338193a9a762.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5491c115b1f9a923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-96398e364fbd4548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-28b9448091776c06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-13c7b53e0c2519a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-65e484302921a932.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-34d08facaf08f556.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-955ec2da3be4c560.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-9f88fbc15d9058d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-c9fc5706b8abaa11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8d47f45a0dc044ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-e2ee2896811e98d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-83b19dae8619de05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f1a1fc0a82738c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-da6c08aae0f92768.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-87a11e6a05f15199.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-7d4182964407c09c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-7e8c39241f8eb6d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-008c1a96618a4887.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5597e894c02cd33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-0337fdf7fb5e37b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8fcec4c9ea2e7f70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-4881b8f9f63694b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-97f9f43172a3a90e.js +0 -1
- package/apps/pwa/out/_next/static/css/1f7c958c41ffa3b9.css +0 -1
- package/src/launch-head/seat-goal-queue-lock.fixture.ts +0 -15
- package/src/launch-head/seat-goal-queue.ts +0 -198
- /package/apps/pwa/out/_next/static/{LZcstaO9_NXypPFmujolv → yRA5ur6DcPl0YHSRheH2O}/_buildManifest.js +0 -0
- /package/apps/pwa/out/_next/static/{LZcstaO9_NXypPFmujolv → yRA5ur6DcPl0YHSRheH2O}/_ssgManifest.js +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { readFileSync, realpathSync } from 'node:fs';
|
|
2
|
+
import { writeGoalDocumentAtomic } from './goal-document-write.js';
|
|
2
3
|
import { isAbsolute, relative, resolve } from 'node:path';
|
|
3
4
|
import { debug } from '../debug/log.js';
|
|
5
|
+
import { getUserConfig } from '../user-config.js';
|
|
4
6
|
import { parseAskProseTitle } from '../self-dev/launch-preflight.js';
|
|
5
7
|
import { createGoalAuthorDecomposeSteps, readRecentStepCountsFailOpen, type RecentStepCountReader } from './goal-author-decompose.js';
|
|
6
|
-
import { defaultGoalAuthorSelfResolve, parseGoalDocumentClarifications, seedGoalAuthorFromAnsweredClarification, seedGoalAuthorFromClarification } from './goal-author-clarification.js';
|
|
8
|
+
import { defaultGoalAuthorSelfResolve, parseGoalDocumentClarifications, seedGoalAuthorFromAnsweredClarification, seedGoalAuthorFromClarification, selfAnswerGoalDocumentClarifications } from './goal-author-clarification.js';
|
|
7
9
|
import { classifyGoalInterviewRound, type GoalInterviewRoundStatus } from './goal-author-closure.js';
|
|
8
10
|
import { recordGoalAsk } from './goal-ask-store.js';
|
|
9
11
|
import { pressDecisionSignal } from './decision-signal-press.js';
|
|
@@ -15,6 +17,8 @@ import {
|
|
|
15
17
|
verbatimOriginalAsk,
|
|
16
18
|
writeAuthoredGoal,
|
|
17
19
|
type GoalAuthorDeps,
|
|
20
|
+
type GoalAuthorGradeSelection,
|
|
21
|
+
resolveGoalAuthorGrade,
|
|
18
22
|
type GoalType,
|
|
19
23
|
type GoalFileLintFinding,
|
|
20
24
|
} from './goal-author.js';
|
|
@@ -77,6 +81,7 @@ interface GoalAuthorCliOptions {
|
|
|
77
81
|
supersedes?: string;
|
|
78
82
|
rootIntent?: string;
|
|
79
83
|
goalType?: string;
|
|
84
|
+
authorGrade?: GoalAuthorGradeSelection;
|
|
80
85
|
selfResolveClarifications?: boolean;
|
|
81
86
|
adversarialReview?: boolean;
|
|
82
87
|
disableAdversarialReview?: boolean;
|
|
@@ -97,6 +102,7 @@ export interface GoalAuthorCliDeps {
|
|
|
97
102
|
recentStepCountReader?: RecentStepCountReader;
|
|
98
103
|
/** Resolver supplied only by the explicit CLI self-resolution opt-in. */
|
|
99
104
|
selfResolveClarification?: NonNullable<GoalAuthorDeps['selfResolveClarification']>;
|
|
105
|
+
writeFile?: (path: string, document: string) => void;
|
|
100
106
|
recordAsk?: typeof recordGoalAsk;
|
|
101
107
|
}
|
|
102
108
|
|
|
@@ -268,8 +274,9 @@ export async function runGoalAuthorCli(
|
|
|
268
274
|
: opts.reauthorFromAnsweredClarification
|
|
269
275
|
? { origin: 'answered-clarification-reauthor' }
|
|
270
276
|
: { origin: 'direct-request' };
|
|
271
|
-
const
|
|
272
|
-
const
|
|
277
|
+
const authorGrade = opts.authorGrade ?? resolveGoalAuthorGrade(undefined, getUserConfig().harness?.authorGrade);
|
|
278
|
+
const recentStepCounts = authorGrade.grade === 'lite' ? undefined : readRecentStepCountsFailOpen(deps.recentStepCountReader);
|
|
279
|
+
const decomposeSteps = authorGrade.grade === 'lite' ? undefined : deps.decomposeSteps ?? (deps.createDecomposeSteps ?? createGoalAuthorDecomposeSteps)(undefined, {
|
|
273
280
|
...(adversarialReview !== undefined ? { adversarialReview, adversarialReviewSource: 'cli' as const } : {}),
|
|
274
281
|
...(recentStepCounts !== undefined ? { recentStepCounts } : {}),
|
|
275
282
|
});
|
|
@@ -283,13 +290,34 @@ export async function runGoalAuthorCli(
|
|
|
283
290
|
debug.log('goal-author', 'goal-title-forwarded', proseTitle === undefined
|
|
284
291
|
? { passed: false }
|
|
285
292
|
: { passed: true, titleChars: proseTitle.length });
|
|
293
|
+
const gradeDeps = authorGrade.grade === 'lite' || opts.authorGrade ? { authorGrade } : {};
|
|
286
294
|
const authorDeps: Partial<GoalAuthorDeps> = parentGoalFile && parentQuestionId
|
|
287
|
-
? { parent: { goalFile: parentGoalFile, questionId: parentQuestionId }, parentDocument, clarificationAnswers, decomposeSteps, ...selfResolutionDeps, ...progressDeps, ...launchPreflightDeps, ...(opts.rootIntent !== undefined && { rootIntent: opts.rootIntent }), ...(goalType !== undefined && { goalType }), ...goalTitleDeps }
|
|
288
|
-
: { ...(clarificationAnswers && { clarificationAnswers }), decomposeSteps, ...selfResolutionDeps, ...progressDeps, ...launchPreflightDeps, ...(opts.rootIntent !== undefined && { rootIntent: opts.rootIntent }), ...(goalType !== undefined && { goalType }), ...goalTitleDeps };
|
|
295
|
+
? { parent: { goalFile: parentGoalFile, questionId: parentQuestionId }, parentDocument, clarificationAnswers, ...(decomposeSteps ? { decomposeSteps } : {}), ...gradeDeps, ...selfResolutionDeps, ...progressDeps, ...launchPreflightDeps, ...(opts.rootIntent !== undefined && { rootIntent: opts.rootIntent }), ...(goalType !== undefined && { goalType }), ...goalTitleDeps }
|
|
296
|
+
: { ...(clarificationAnswers && { clarificationAnswers }), ...(decomposeSteps ? { decomposeSteps } : {}), ...gradeDeps, ...selfResolutionDeps, ...progressDeps, ...launchPreflightDeps, ...(opts.rootIntent !== undefined && { rootIntent: opts.rootIntent }), ...(goalType !== undefined && { goalType }), ...goalTitleDeps };
|
|
289
297
|
const write = deps.write ?? writeAuthoredGoal;
|
|
290
298
|
const result = opts.groundingCwd === undefined
|
|
291
299
|
? await write(ask, opts.cwd, authorDeps, superseded ? { supersedes: superseded } : undefined)
|
|
292
300
|
: await write(ask, opts.cwd, authorDeps, superseded ? { supersedes: superseded } : undefined, opts.groundingCwd);
|
|
301
|
+
if (opts.selfResolveClarifications) {
|
|
302
|
+
const rework = Boolean(supersededDocument || opts.reauthorFromAnsweredClarification);
|
|
303
|
+
{
|
|
304
|
+
try {
|
|
305
|
+
const resolved = await selfAnswerGoalDocumentClarifications(result.authored.document, {
|
|
306
|
+
path: rework ? 'rework' : 'say-first', ask, resolver: deps.selfResolveClarification ?? defaultGoalAuthorSelfResolve,
|
|
307
|
+
evidence: result.authored.facts
|
|
308
|
+
? [...(result.authored.facts.persistentEvidence ?? []), ...result.authored.facts.codeFacts, ...result.authored.facts.documentFacts]
|
|
309
|
+
: undefined,
|
|
310
|
+
});
|
|
311
|
+
if (resolved.newlyAnswered > 0) {
|
|
312
|
+
(deps.writeFile ?? writeGoalDocumentAtomic)(result.path, resolved.document);
|
|
313
|
+
result.authored.document = resolved.document;
|
|
314
|
+
}
|
|
315
|
+
} catch (error) {
|
|
316
|
+
// The previous goal file is left intact (atomic replace); implementation proceeds from it with the questions deferred.
|
|
317
|
+
debug.log('goal-author.clarify', 'self-answer-deferred', { reason: error instanceof Error ? error.message : String(error) });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
293
321
|
try {
|
|
294
322
|
const recorded = (deps.recordAsk ?? recordGoalAsk)({
|
|
295
323
|
authorRunId: result.authored.authorRunId,
|
|
@@ -18,6 +18,17 @@ function observeGoalAuthor(
|
|
|
18
18
|
debug.log(category === 'goal-author' ? 'harness.author' : 'harness.author.clarify', event, data);
|
|
19
19
|
}
|
|
20
20
|
import { getUserConfig } from '../user-config.js';
|
|
21
|
+
|
|
22
|
+
export type GoalAuthorGrade = 'full' | 'lite';
|
|
23
|
+
export type GoalAuthorGradeSource = 'flag' | 'config' | 'default';
|
|
24
|
+
export interface GoalAuthorGradeSelection { grade: GoalAuthorGrade; source: GoalAuthorGradeSource }
|
|
25
|
+
|
|
26
|
+
/** The flag is authoritative; malformed or absent configuration keeps the full pipeline. */
|
|
27
|
+
export function resolveGoalAuthorGrade(flag?: GoalAuthorGrade, configured?: unknown): GoalAuthorGradeSelection {
|
|
28
|
+
if (flag !== undefined) return { grade: flag, source: 'flag' };
|
|
29
|
+
if (configured === 'lite' || configured === 'full') return { grade: configured, source: 'config' };
|
|
30
|
+
return { grade: 'full', source: 'default' };
|
|
31
|
+
}
|
|
21
32
|
import type { ObserveOnlySource } from './observe-only.js';
|
|
22
33
|
import type { Question } from '../ask-user-question/types.js';
|
|
23
34
|
import { requestTestScenario as defaultRequestTestScenario, type TestScenarioRequestInput, type TestScenarioRequestResult } from './test-scenario-request.js';
|
|
@@ -45,6 +56,7 @@ type GoalEnhancement = Omit<Pick<EnhanceResult, 'original' | 'checklist' | 'verb
|
|
|
45
56
|
export interface GoalAuthorDeps {
|
|
46
57
|
ground: (ask: string, groundingDeps?: GoalAuthorGroundingDeps) => Promise<CodebaseGrounding>;
|
|
47
58
|
persistentGrounding?: GoalAuthorGroundingDeps;
|
|
59
|
+
authorGrade?: GoalAuthorGradeSelection;
|
|
48
60
|
enhance: (ask: string, opts?: EnhanceOpts) => Promise<GoalEnhancement>;
|
|
49
61
|
/** Additive enhancer options supplied by the file-writing entrypoint. */
|
|
50
62
|
enhanceOpts?: EnhanceOpts;
|
|
@@ -4925,6 +4937,17 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
4925
4937
|
}
|
|
4926
4938
|
// ⭐ 이 저작 «한 번»의 id. goalId 보다 «먼저» 있어야 ground·enhance 의 소요를 그 골에 붙일 수 있다.
|
|
4927
4939
|
const authorRunId = generateGoalId();
|
|
4940
|
+
const authorGrade = deps.authorGrade ?? resolveGoalAuthorGrade(undefined, getUserConfig().harness?.authorGrade);
|
|
4941
|
+
const lite = authorGrade.grade === 'lite';
|
|
4942
|
+
// lite 는 판정선을 남기는 대신 단계를 덜 한다 — 요청에 반증 줄이 하나도 없으면 판정선 없는 골이 나가므로 시작 전에 멈춘다.
|
|
4943
|
+
if (lite && !ask.split(/\r?\n/u).some((line) => /판정선|판정 신호|반증|decision signal/iu.test(line))) {
|
|
4944
|
+
try { observeGoalAuthor('goal-author', 'author-grade-refused', { authorRunId, reason: 'lite-without-falsifiable-signal' }); }
|
|
4945
|
+
catch { /* observation is fail-soft */ }
|
|
4946
|
+
throw new Error('lite authoring needs a falsifiable signal line (판정선/반증) in the ask — add one or use --author-grade full');
|
|
4947
|
+
}
|
|
4948
|
+
const skippedPhases = lite ? ['adversarial-review', 'goal-steps-decomposed', 'persistent-grounding'] : [];
|
|
4949
|
+
try { observeGoalAuthor('goal-author', 'author-grade', { authorRunId, grade: authorGrade.grade, source: authorGrade.source, skippedPhases }); }
|
|
4950
|
+
catch { /* observation is fail-soft */ }
|
|
4928
4951
|
const authorStartedAt = Date.now();
|
|
4929
4952
|
const enhanceTokens: GoalAuthorTokens = { inputTokens: null, outputTokens: null };
|
|
4930
4953
|
const onEnhanceUsage = (usage: LLMUsage): void => {
|
|
@@ -4934,18 +4957,20 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
4934
4957
|
};
|
|
4935
4958
|
let facts: CodebaseGrounding | null = null;
|
|
4936
4959
|
let groundingError = false;
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4960
|
+
if (!lite) {
|
|
4961
|
+
const persistentGrounding = resolveGoalAuthorPersistentGrounding('persistentGrounding' in deps ? deps.persistentGrounding : undefined);
|
|
4962
|
+
const groundStartedAt = startGoalAuthorPhase('ground', authorRunId, deps.onProgress);
|
|
4963
|
+
try {
|
|
4964
|
+
facts = await deps.ground(ask, persistentGrounding.deps);
|
|
4965
|
+
} catch {
|
|
4966
|
+
groundingError = true;
|
|
4967
|
+
} finally {
|
|
4968
|
+
endGoalAuthorPhase('ground', groundStartedAt, authorRunId, deps.onProgress);
|
|
4969
|
+
observeGoalAuthorPersistentGroundingResult(
|
|
4970
|
+
persistentGrounding.decision,
|
|
4971
|
+
goalAuthorPersistentGroundingMetrics(facts, groundingError, authorRunId),
|
|
4972
|
+
);
|
|
4973
|
+
}
|
|
4949
4974
|
}
|
|
4950
4975
|
|
|
4951
4976
|
const enhanceStartedAt = startGoalAuthorPhase('enhance', authorRunId, deps.onProgress);
|
|
@@ -4989,6 +5014,57 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
4989
5014
|
}
|
|
4990
5015
|
enhancement = { ...enhancement, original: ask };
|
|
4991
5016
|
|
|
5017
|
+
if (lite) {
|
|
5018
|
+
const goalType = deps.goalType ?? 'implement';
|
|
5019
|
+
const goalId = deps.goalId ?? generateGoalId();
|
|
5020
|
+
const signal = decisionSignalSection(null, ask, enhancement.decisionSignal);
|
|
5021
|
+
const falsifiableSignal = signal.filled > 0 ? signal.lines : [
|
|
5022
|
+
...signal.lines,
|
|
5023
|
+
...ask.split(/\r?\n/u).filter((line) => /판정선|판정 신호|반증|decision signal/iu.test(line) && !signal.lines.some((rendered) => rendered.includes(line.trim()))),
|
|
5024
|
+
];
|
|
5025
|
+
const targetPaths = [...new Set(declaredTargetPaths(ask))];
|
|
5026
|
+
const checklistIds = [...new Set(Array.from(ask.matchAll(/\b[A-Z][A-Z0-9]+-[A-Z0-9]+\b/g), (match) => match[0]))];
|
|
5027
|
+
const askFile = deps.askFile === undefined ? undefined : validateAskFile(deps.askFile);
|
|
5028
|
+
const inheritedRootIntent = deps.parentDocument === undefined ? null : parseRootIntent(deps.parentDocument);
|
|
5029
|
+
const rootIntent = validateRootIntent(deps.supersessionRootIntent ?? inheritedRootIntent ?? deps.rootIntent ?? goalSummary(ask));
|
|
5030
|
+
const document = [
|
|
5031
|
+
deps.goalTitle ?? goalSummary(ask),
|
|
5032
|
+
`- GoalId: ${goalId}`,
|
|
5033
|
+
`- RootIntent: ${rootIntent}`,
|
|
5034
|
+
`- GoalType: ${goalType}`,
|
|
5035
|
+
...(askFile === undefined ? [] : [`- AskFile: ${askFile}`]),
|
|
5036
|
+
'',
|
|
5037
|
+
'## PROBLEM',
|
|
5038
|
+
`- 왜: ${enhancement.complication ?? goalSummary(ask)}`,
|
|
5039
|
+
'',
|
|
5040
|
+
'## WHAT TO BUILD',
|
|
5041
|
+
`- 무엇: ${enhancement.situation ?? goalSummary(ask)}`,
|
|
5042
|
+
ORIGINAL_ASK_MARKER,
|
|
5043
|
+
fenceFor(ask), ask, fenceFor(ask),
|
|
5044
|
+
'',
|
|
5045
|
+
'## ACCEPTANCE CRITERIA',
|
|
5046
|
+
...enhancement.checklist.map(requestedCriterionLine),
|
|
5047
|
+
'',
|
|
5048
|
+
'## REQUIRED EVIDENCE',
|
|
5049
|
+
'- [requested] Verify the decision signal and the verbatim ask.',
|
|
5050
|
+
'',
|
|
5051
|
+
...(goalType === 'implement' ? ['## TRACED PATHS', ...(targetPaths.length ? targetPaths.map((path) => `- ${path}`) : ['- Target paths: not declared in the ask.']), ''] : []),
|
|
5052
|
+
'## SCOPE BOUNDARY',
|
|
5053
|
+
`- 대상 경로: ${targetPaths.length ? targetPaths.join(' · ') : 'not declared'}`,
|
|
5054
|
+
`- 칸 id: ${checklistIds.length ? checklistIds.join(' · ') : 'not declared'}`,
|
|
5055
|
+
'',
|
|
5056
|
+
'## 답하지 못하는 것',
|
|
5057
|
+
'- No persistent grounding was performed in lite authoring.',
|
|
5058
|
+
'',
|
|
5059
|
+
'## 불변식',
|
|
5060
|
+
'- No persistent grounding was performed in lite authoring.',
|
|
5061
|
+
'',
|
|
5062
|
+
'## 판정 신호',
|
|
5063
|
+
...falsifiableSignal,
|
|
5064
|
+
].join('\n');
|
|
5065
|
+
return { document, facts: null, grounded: false, authorRunId };
|
|
5066
|
+
}
|
|
5067
|
+
|
|
4992
5068
|
observeGoalAuthor('goal-author', 'constant-instruction-placement', {
|
|
4993
5069
|
authorRunId,
|
|
4994
5070
|
lines: CONSTANT_DOCUMENT_INSTRUCTION_POLICY.length,
|
|
@@ -5452,23 +5528,29 @@ async function authorGoalWithSupersededRootIntent(
|
|
|
5452
5528
|
assembleCompleted = true;
|
|
5453
5529
|
endGoalAuthorPhase('assemble', assembleStartedAt, authorRunId, deps.onProgress);
|
|
5454
5530
|
const lintStartedAt = startGoalAuthorPhase('lint', authorRunId, deps.onProgress);
|
|
5531
|
+
let lintPassed = false;
|
|
5455
5532
|
try {
|
|
5456
5533
|
assertRequiredBlocks(document);
|
|
5534
|
+
lintPassed = true;
|
|
5457
5535
|
} finally {
|
|
5458
|
-
|
|
5536
|
+
try {
|
|
5537
|
+
endGoalAuthorPhase('lint', lintStartedAt, authorRunId, deps.onProgress);
|
|
5538
|
+
} finally {
|
|
5539
|
+
try {
|
|
5540
|
+
observeGoalAuthor('goal-author', 'summary', {
|
|
5541
|
+
authorRunId,
|
|
5542
|
+
elapsedMs: Date.now() - authorStartedAt,
|
|
5543
|
+
inputTokens: enhanceTokens.inputTokens,
|
|
5544
|
+
outputTokens: enhanceTokens.outputTokens,
|
|
5545
|
+
totalTokens: enhanceTokens.inputTokens === null || enhanceTokens.outputTokens === null
|
|
5546
|
+
? null : enhanceTokens.inputTokens + enhanceTokens.outputTokens,
|
|
5547
|
+
goalChars: [...document].length,
|
|
5548
|
+
sectionChars: authoredGoalSectionChars(document),
|
|
5549
|
+
...(!lintPassed ? { outcome: 'lint-failed' } : {}),
|
|
5550
|
+
});
|
|
5551
|
+
} catch { /* observation is fail-soft */ }
|
|
5552
|
+
}
|
|
5459
5553
|
}
|
|
5460
|
-
try {
|
|
5461
|
-
observeGoalAuthor('goal-author', 'summary', {
|
|
5462
|
-
authorRunId,
|
|
5463
|
-
elapsedMs: Date.now() - authorStartedAt,
|
|
5464
|
-
inputTokens: enhanceTokens.inputTokens,
|
|
5465
|
-
outputTokens: enhanceTokens.outputTokens,
|
|
5466
|
-
totalTokens: enhanceTokens.inputTokens === null || enhanceTokens.outputTokens === null
|
|
5467
|
-
? null : enhanceTokens.inputTokens + enhanceTokens.outputTokens,
|
|
5468
|
-
goalChars: [...document].length,
|
|
5469
|
-
sectionChars: authoredGoalSectionChars(document),
|
|
5470
|
-
});
|
|
5471
|
-
} catch { /* observation is fail-soft */ }
|
|
5472
5554
|
return { document, facts, grounded: !groundingError && hasEvidence, authorRunId };
|
|
5473
5555
|
} finally {
|
|
5474
5556
|
endAssembleSubphase();
|
|
@@ -11,9 +11,13 @@ import {
|
|
|
11
11
|
writePendingQuestion,
|
|
12
12
|
} from '../ask-user-question/pending-questions.js';
|
|
13
13
|
import { debug } from '../debug/log.js';
|
|
14
|
+
import { writeGoalDocumentAtomic } from './goal-document-write.js';
|
|
14
15
|
import {
|
|
15
16
|
applyClarificationReply,
|
|
16
17
|
parseGoalDocumentClarifications,
|
|
18
|
+
selfAnswerGoalDocumentClarifications,
|
|
19
|
+
type GoalClarificationSelfResolver,
|
|
20
|
+
type GoalClarificationSelfAnswerPath,
|
|
17
21
|
} from './goal-author-clarification.js';
|
|
18
22
|
import type { HitlDelivery } from '../hitl/types.js';
|
|
19
23
|
|
|
@@ -49,6 +53,8 @@ export interface GoalClarificationEscalationInput {
|
|
|
49
53
|
resolveOriginDelivery?: (sessionId: string) => HitlDelivery | undefined;
|
|
50
54
|
/** Non-blocking terminal fallback for a non-TUI delivery with no installed resolver. */
|
|
51
55
|
fallback?: (message: string) => void;
|
|
56
|
+
selfResolveClarification?: GoalClarificationSelfResolver;
|
|
57
|
+
selfAnswerPath?: GoalClarificationSelfAnswerPath;
|
|
52
58
|
/** Fail-soft pending persistence for terminal fallbacks; injectable for focused tests. */
|
|
53
59
|
pendingQuestionPersistence?: {
|
|
54
60
|
create: typeof createPendingQuestion;
|
|
@@ -404,6 +410,7 @@ export async function escalateGoalDocumentClarifications(
|
|
|
404
410
|
const dispatchDelivery = delivery ?? 'modal';
|
|
405
411
|
const recordedDelivery = input.resolvedDelivery ?? dispatchDelivery;
|
|
406
412
|
let answersWritten = 0;
|
|
413
|
+
let selfAnswered = 0;
|
|
407
414
|
let questionIds: string[] = [];
|
|
408
415
|
const observeEscalation = (event: GoalClarificationObservationEvent, data: Record<string, unknown>): void => {
|
|
409
416
|
writeEscalationObservation(event, { ...data, deliverySource, answersWritten, questionIds });
|
|
@@ -430,6 +437,35 @@ export async function escalateGoalDocumentClarifications(
|
|
|
430
437
|
return result;
|
|
431
438
|
}
|
|
432
439
|
|
|
440
|
+
if (input.selfAnswerPath) {
|
|
441
|
+
try {
|
|
442
|
+
const resolution = await selfAnswerGoalDocumentClarifications(document, {
|
|
443
|
+
path: input.selfAnswerPath,
|
|
444
|
+
ask: document,
|
|
445
|
+
resolver: input.selfResolveClarification,
|
|
446
|
+
});
|
|
447
|
+
if (resolution.newlyAnswered > 0) {
|
|
448
|
+
writeGoalDocumentAtomic(input.goalFile, resolution.document);
|
|
449
|
+
answersWritten += resolution.newlyAnswered;
|
|
450
|
+
selfAnswered += resolution.newlyAnswered;
|
|
451
|
+
document = resolution.document;
|
|
452
|
+
clarifications = parseGoalDocumentClarifications(document);
|
|
453
|
+
unanswered = clarifications.filter((clarification) => !clarification.answered);
|
|
454
|
+
deliveryIds = mapClarificationDeliveryIds(clarifications);
|
|
455
|
+
questionIds = [...new Set(unanswered.map((clarification) => clarification.questionId))];
|
|
456
|
+
}
|
|
457
|
+
if (unanswered.length === 0) {
|
|
458
|
+
const result = { unanswered: 0, escalated: 0, delivery: recordedDelivery, outcome: 'skipped' as const, answeredBy: 'agent' as const };
|
|
459
|
+
observeEscalation(result.outcome, { goalFile: input.goalFile, ...result, reason: 'self-answered' });
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
} catch (error) {
|
|
463
|
+
debug.log(GOAL_CLARIFICATION_ESCALATION_CATEGORY, 'self-answer-failed', {
|
|
464
|
+
path: input.selfAnswerPath, reason: error instanceof Error ? error.message : String(error),
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
433
469
|
const dispatch = input.dispatch ?? dispatchAskUserQuestion;
|
|
434
470
|
const pendingQuestionPersistence = input.pendingQuestionPersistence ?? {
|
|
435
471
|
create: createPendingQuestion,
|
|
@@ -444,7 +480,7 @@ export async function escalateGoalDocumentClarifications(
|
|
|
444
480
|
// ⛔⭐⭐⭐ 여기서부터의 조기 반환·폴백은 이 «누적값»을 쓴다 — 'none' 을 하드코딩하면
|
|
445
481
|
// 앞 배치가 답했는데 뒤 배치가 취소·실패했을 때 「아무도 안 답했다」는 «거짓»이 된다
|
|
446
482
|
// (무인 리뷰 R2 must-fix · 실측 형태: 관측이 거짓말한다).
|
|
447
|
-
const seenProvenance = { explicit: new Set<'human' | 'agent'>(), unmarkedAnswer: false };
|
|
483
|
+
const seenProvenance = { explicit: new Set<'human' | 'agent'>(selfAnswered > 0 ? ['agent' as const] : []), unmarkedAnswer: false };
|
|
448
484
|
const aggregate = (): GoalClarificationAnsweredBy => {
|
|
449
485
|
const { explicit, unmarkedAnswer } = seenProvenance;
|
|
450
486
|
// ⭐ 표시 없는 답도 «한 출처»로 센다 — legacy 경로는 사람이다(레포 안 리졸버는 이제 전부 명시한다).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Atomic goal-document replacement for self-answered clarifications (POD-SELF-ANSWER). */
|
|
2
|
+
import { chmodSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
3
|
+
|
|
4
|
+
export interface GoalDocumentWriteIo {
|
|
5
|
+
writeFileSync: (path: string, data: string, options?: { mode?: number }) => void;
|
|
6
|
+
renameSync: (from: string, to: string) => void;
|
|
7
|
+
rmSync: (path: string, options: { force: boolean }) => void;
|
|
8
|
+
statSync: (path: string) => { mode: number };
|
|
9
|
+
chmodSync: (path: string, mode: number) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const realIo: GoalDocumentWriteIo = { writeFileSync, renameSync, rmSync, statSync, chmodSync };
|
|
13
|
+
|
|
14
|
+
/** Replace a goal document atomically (temp file next to it + rename) so a failed write never leaves a torn goal.
|
|
15
|
+
* The existing file's permission bits are kept, so a 0600 goal stays 0600 after replacement. */
|
|
16
|
+
export function writeGoalDocumentAtomic(path: string, document: string, io: GoalDocumentWriteIo = realIo): void {
|
|
17
|
+
let mode: number | undefined;
|
|
18
|
+
try { mode = io.statSync(path).mode & 0o777; } catch { mode = undefined; }
|
|
19
|
+
const temporary = `${path}.self-answer-${process.pid}-${Date.now()}.tmp`;
|
|
20
|
+
try {
|
|
21
|
+
io.writeFileSync(temporary, document, mode === undefined ? undefined : { mode });
|
|
22
|
+
if (mode !== undefined) io.chmodSync(temporary, mode);
|
|
23
|
+
io.renameSync(temporary, path);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
try { io.rmSync(temporary, { force: true }); } catch { /* best effort */ }
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -68,6 +68,10 @@ function liveHealRuns(root: string): Set<string> {
|
|
|
68
68
|
/** A test process must never start the real heal loop — it spawns external grounding (10-05 load 150 incident). */
|
|
69
69
|
export async function startHealLoop(file: string, options: HealLoopOptions, env: NodeJS.ProcessEnv = process.env,
|
|
70
70
|
run: StartHealLoop = async (graph, args) => (await import('../graph-runner/runner.js')).runGraph(graph, args)): Promise<unknown> {
|
|
71
|
+
if (env.ELANOUS_POD_NAME) {
|
|
72
|
+
debug.log('heal.intake', 'skipped-in-pod', { ref: options.input.failureEvent.ref });
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
71
75
|
if (env.NODE_ENV === 'test' || env.ELANOUS_TEST_HOME) {
|
|
72
76
|
debug.log('heal.intake', 'loop-start-skipped-test', { runId: options.runId });
|
|
73
77
|
return undefined;
|
|
@@ -156,6 +156,50 @@ export interface HealTriageResult {
|
|
|
156
156
|
readonly evidence: readonly string[];
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/** 수리 한도를 다 쓴 런의 결함 셋. 힐 루프가 이 셋 중 하나만 고른다. */
|
|
160
|
+
export type ReworkCapDefectClass = 'test-defect' | 'goal-defect' | 'code-defect';
|
|
161
|
+
|
|
162
|
+
/** 분류 뒤 힐 루프가 고르는 다음 행동. */
|
|
163
|
+
export type ReworkCapNextAction = 'harvest' | 'relaunch' | 'card';
|
|
164
|
+
|
|
165
|
+
export interface ReworkCapHealInput {
|
|
166
|
+
/** 게이트가 이번 diff 가 들여온 실패 수. 없으면 0. */
|
|
167
|
+
readonly introduced?: readonly string[];
|
|
168
|
+
/** 마지막 리뷰 must-fix. 없으면 빈 목록. */
|
|
169
|
+
readonly mustFix?: readonly string[];
|
|
170
|
+
readonly summary?: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface ReworkCapHealDecision {
|
|
174
|
+
readonly defectClass: ReworkCapDefectClass;
|
|
175
|
+
readonly nextAction: ReworkCapNextAction;
|
|
176
|
+
readonly evidence: readonly string[];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const GOAL_DEFECT = /골|goal|acceptance|수용 기준|요구가 모순|스펙|경계:/i;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 수리 한도 소진 런을 «시험 결함 · 골 결함 · 코드 결함» 중 하나로 가르고
|
|
183
|
+
* 수확·재발사·카드 중 하나를 고른다. 근거는 게이트 introduced 목록과 마지막 리뷰 지적이다.
|
|
184
|
+
* 도입 실패가 있으면 코드 결함(재발사). 리뷰가 골·수용 기준을 짚으면 골 결함(카드).
|
|
185
|
+
* 그 밖(리뷰만 있거나 근거가 비면)은 시험 결함(수확)이다.
|
|
186
|
+
*/
|
|
187
|
+
export function classifyReworkCapExhaustion(input: ReworkCapHealInput): ReworkCapHealDecision {
|
|
188
|
+
const introduced = (input.introduced ?? []).map((item) => item.trim()).filter(Boolean);
|
|
189
|
+
const mustFix = (input.mustFix ?? []).map((item) => item.trim()).filter(Boolean);
|
|
190
|
+
const evidence = [
|
|
191
|
+
...introduced.map((item) => `gate introduced: ${item}`),
|
|
192
|
+
...mustFix.map((item) => `review must-fix: ${item}`),
|
|
193
|
+
];
|
|
194
|
+
if (introduced.length > 0) {
|
|
195
|
+
return { defectClass: 'code-defect', nextAction: 'relaunch', evidence };
|
|
196
|
+
}
|
|
197
|
+
if (mustFix.some((item) => GOAL_DEFECT.test(item)) || (input.summary ? GOAL_DEFECT.test(input.summary) : false)) {
|
|
198
|
+
return { defectClass: 'goal-defect', nextAction: 'card', evidence };
|
|
199
|
+
}
|
|
200
|
+
return { defectClass: 'test-defect', nextAction: 'harvest', evidence };
|
|
201
|
+
}
|
|
202
|
+
|
|
159
203
|
const UNTESTABLE_EXT = new Set(['.md', '.json', '.yaml', '.yml', '.txt']);
|
|
160
204
|
const ENVIRONMENT_CLAIM = /할당량|자격|기판|quota|credential|substrate/i;
|
|
161
205
|
|
|
@@ -30,6 +30,8 @@ export type HostRegateDeps = {
|
|
|
30
30
|
acquire?: (repoRoot: string) => Promise<() => void>;
|
|
31
31
|
log?: (event: 'passed' | 'failed' | 'unmeasured' | 'base-raced', data: Record<string, unknown>) => void;
|
|
32
32
|
freezeRoot?: string;
|
|
33
|
+
/** Test seam for the operational freeze authority; production always uses the host root. */
|
|
34
|
+
prodFreezeRoot?: string;
|
|
33
35
|
runExposeGate?: typeof runExposeGate;
|
|
34
36
|
syncMergedChecklist?: typeof import('../release-loop/merged-pr-checklist.js').syncMergedPrChecklist;
|
|
35
37
|
};
|
|
@@ -241,7 +243,7 @@ export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps
|
|
|
241
243
|
// --match-head-commit pins the head. gh has no base pin, so the base was re-read just
|
|
242
244
|
// above; the seconds between that read and the merge are checked after the fact below.
|
|
243
245
|
if (input.verifyOnly) return result('passed');
|
|
244
|
-
const landing = admitLandingMerge({ prNumber: input.prNumber, headCommit: input.headCommit, repoRoot: input.repoRoot, ...(input.goalFile ? { goalFile: input.goalFile } : {}) }, deps.freezeRoot, {}, input.resumed ? undefined : { prNumber: input.prNumber, repoRoot: input.repoRoot, headCommit: input.headCommit });
|
|
246
|
+
const landing = admitLandingMerge({ prNumber: input.prNumber, headCommit: input.headCommit, repoRoot: input.repoRoot, ...(input.goalFile ? { goalFile: input.goalFile } : {}) }, deps.freezeRoot, {}, input.resumed ? undefined : { prNumber: input.prNumber, repoRoot: input.repoRoot, headCommit: input.headCommit }, { prodFreezeRoot: deps.prodFreezeRoot });
|
|
245
247
|
if (landing.kind !== 'merge') {
|
|
246
248
|
debug.log('harness.merge', 'frozen', { pr: input.prNumber, ...(landing.kind === 'held' ? { reason: landing.freeze.reason, until: landing.freeze.until } : { resumedElsewhere: true }) });
|
|
247
249
|
return { passed: true, failures: [], os: process.platform, status: 'frozen' };
|