elanous 0.2.8 → 0.2.10
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/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +1 -0
- package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8067-87ce253ec2f23697.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5080-1613752891fcadb4.js → 8195-6fde3d7a39859206.js} +5 -5
- package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-d4b6df905f185055.js → page-54b32bd27726588d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-186fc6952f027acc.js → page-f8116559c7424da7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-cbbe03c0da7b081a.js → page-54e1f966ab60a4dc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/{page-c0c0d19d51342d3e.js → page-b31610deda76337b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2e002ad8faa43291.js → page-6cb0e1bbefe5fb3d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-7464c1987dd76e6d.js → page-e168fa1030af0548.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/{page-d8ab4d1489223459.js → page-4fddc90b23feb215.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +1 -0
- package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +30 -29
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +30 -29
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +30 -29
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +27 -26
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +27 -26
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +27 -26
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +30 -29
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +30 -29
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +30 -29
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +30 -29
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +30 -29
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +30 -29
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +27 -26
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +30 -29
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +30 -29
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +27 -26
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +27 -26
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +30 -29
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +30 -29
- package/apps/pwa/out/ops/checklist/index.html +1 -0
- package/apps/pwa/out/ops/checklist/index.txt +30 -0
- package/apps/pwa/out/ops/release/index.html +1 -0
- package/apps/pwa/out/ops/release/index.txt +30 -0
- package/apps/pwa/out/ops/seats/index.html +1 -0
- package/apps/pwa/out/ops/seats/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +28 -27
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +30 -29
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +27 -26
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +30 -29
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +30 -29
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +30 -29
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +30 -29
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +30 -29
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +27 -26
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +30 -29
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +30 -29
- package/apps/pwa/out/today/index.html +1 -0
- package/apps/pwa/out/today/index.txt +33 -0
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +30 -29
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +30 -29
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +30 -29
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +30 -29
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +30 -29
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +30 -29
- package/graphs/field/field-feed.yaml +2 -0
- package/graphs/implement-loop.yaml +1 -1
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +3 -1
- package/graphs/test-diet/nightly-audit.yaml +18 -0
- package/graphs/test-diet/recipes.yaml +3 -0
- package/package.json +1 -1
- package/plugins/card-followup/graphs/run-step.ts +48 -13
- package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
- package/plugins/doc-draft/graphs/run-step.ts +14 -7
- package/scripts/ci-pwa-build-gate.ts +160 -0
- package/scripts/coord-channel-watch.sh +42 -8
- package/scripts/coord-digest.ts +199 -0
- package/scripts/coord-post.sh +60 -3
- package/scripts/install.ps1 +68 -9
- package/scripts/install.sh +39 -12
- package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
- package/scripts/lib/tui-regress-checks.ts +146 -0
- package/scripts/memory-lifecycle-cycle.ts +2 -2
- package/scripts/ops-now-probe.ts +327 -0
- package/scripts/publish-internal-dist.ts +11 -1
- package/scripts/release-loop/cutoff.ts +31 -2
- package/scripts/release-loop/export-check-node.ts +85 -0
- package/scripts/release-loop/gate-node.ts +18 -4
- package/scripts/release-loop/node-verdict.ts +8 -1
- package/scripts/release-loop/ops-upgrade-node.ts +72 -16
- package/scripts/release-loop/release-readiness.ts +9 -0
- package/scripts/release-loop/version-node.ts +58 -10
- package/scripts/repo-watch-cycle.ts +1 -1
- package/scripts/retro-cycle.ts +2 -2
- package/scripts/schedule-health-report.ts +1 -1
- package/scripts/storyboard/storyboard.ts +5 -161
- package/scripts/test-diet/lib.ts +31 -1
- package/scripts/test-diet/node.ts +134 -17
- package/scripts/test-timeout-audit.ts +114 -0
- package/scripts/tree-sync-alert.ts +1 -1
- package/scripts/tui-regress.ts +71 -0
- package/scripts/waitlist-daily-digest.ts +1 -1
- package/skills/explainer-video/SKILL.md +4 -0
- package/skills/explainer-video/engine/reel.mjs +18 -13
- package/skills/explainer-video/engine/reel.sh +24 -5
- package/skills/explainer-video/engine/stitch.mjs +145 -0
- package/skills/pitch-deck/SKILL.md +36 -0
- package/skills/pitch-deck/template.html +80 -0
- package/src/acp/codex-approval-adapter.ts +9 -3
- package/src/acp/core-turn-bridge.ts +117 -18
- package/src/acp/fact-question.ts +11 -0
- package/src/acp/server.ts +48 -7
- package/src/acp/tool-approval.ts +126 -0
- package/src/acp/turn-runner.ts +36 -0
- package/src/agent/monad-agent-turn.ts +8 -0
- package/src/ask-user-question/pending-questions.ts +25 -10
- package/src/ask-user-question/types.ts +9 -0
- package/src/auth/setup-link-tokens.fixture.ts +19 -0
- package/src/auth/setup-link-tokens.ts +164 -0
- package/src/autopilot/build/integrity-gate.ts +12 -0
- package/src/boot/daemon-prompt-turn.ts +3 -0
- package/src/boot/daemon-tools/index.ts +8 -0
- package/src/boot/daemon-tools/types.ts +2 -0
- package/src/boot/daemon-tools/web-search.ts +1 -0
- package/src/budget/unified-usage.ts +75 -0
- package/src/channel-bot-token.ts +37 -10
- package/src/chat/ctrl-c-in-input.ts +14 -0
- package/src/chat/index.ts +61 -9
- package/src/chat/pickers/state.ts +6 -2
- package/src/cli/agent-cli.ts +7 -0
- package/src/cli/decisions-cli.ts +25 -3
- package/src/cli/doctor-bundle-upload.ts +68 -0
- package/src/cli/doctor-cli.ts +38 -4
- package/src/cli/op-proxy-sync.ts +83 -0
- package/src/cli/ops-cli.ts +20 -0
- package/src/cli/pod-cli.ts +49 -0
- package/src/cli/pr-cli.ts +37 -4
- package/src/cli/pwa-stop.ts +163 -13
- package/src/cli/pwa-test.ts +3 -0
- package/src/cli/release-cli.ts +98 -15
- package/src/cli/self-update.ts +14 -0
- package/src/cli/storyboard-cli.ts +37 -0
- package/src/cli/test-state-dir-flag.ts +11 -4
- package/src/connectors/linear.ts +146 -0
- package/src/context-bus/coord-events.ts +115 -0
- package/src/dashboard/dashboard-boot-fixture.ts +23 -0
- package/src/dashboard/dashboard-status-lines.ts +45 -0
- package/src/dashboard/first-screen-band.ts +35 -0
- package/src/dashboard/index.ts +128 -34
- package/src/dashboard/provider-slash-runtime.ts +28 -11
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +17 -0
- package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
- package/src/dashboard/turn-stream-formatter.ts +1 -1
- package/src/decisions/decision-cards.ts +50 -2
- package/src/decisions/decision-ledger.ts +75 -4
- package/src/decisions/decision-linear-projection.ts +157 -0
- package/src/decisions/web-push-decision-cards.ts +50 -0
- package/src/directive/interpretation-card.ts +36 -0
- package/src/discord.ts +2 -1
- package/src/domains/coo-admin-tool.ts +62 -0
- package/src/domains/core-tools.ts +11 -3
- package/src/domains/elanous-card.ts +29 -0
- package/src/domains/ops-facts-tool.ts +76 -0
- package/src/domains/outbound-alert.ts +41 -13
- package/src/domains/release-tool.ts +168 -0
- package/src/domains/telegram-kind-route.ts +19 -1
- package/src/exec-requests/planner.ts +98 -28
- package/src/exec-requests/runner.ts +107 -10
- package/src/exec-requests/store.ts +8 -2
- package/src/field/field-media.ts +10 -7
- package/src/field/field-reel.ts +14 -4
- package/src/git-fs/worktree.ts +45 -6
- package/src/graph-runner/graph-approval-card.ts +113 -0
- package/src/graph-runner/graph-cli.ts +129 -4
- package/src/graph-runner/graph-notify.ts +25 -3
- package/src/graph-runner/runner.ts +142 -16
- package/src/harness/browser-verify.ts +25 -2
- package/src/harness/harness-cli-command.ts +231 -35
- package/src/harness/harness-incidents-writer.fixture.ts +24 -0
- package/src/harness/harness-incidents.ts +129 -0
- package/src/harness/harness-stop.ts +53 -3
- package/src/hitl/clarification-policy.ts +3 -1
- package/src/index.ts +172 -41
- package/src/intake-plane/author-goals.ts +37 -4
- package/src/intake-plane/check.ts +3 -0
- package/src/intake-plane/discord-seat-work.ts +47 -2
- package/src/intake-plane/seat-doc-route.ts +170 -6
- package/src/intake-plane/telegram-seat-work.ts +44 -2
- package/src/intake-plane/telegram-work.ts +1 -0
- package/src/maturity/cli-maturity.ts +34 -0
- package/src/maturity/feature-maturity.ts +100 -1
- package/src/maturity/tui-slash-maturity.ts +31 -0
- package/src/memory.ts +32 -4
- package/src/nexus/api/exec-requests.ts +33 -3
- package/src/nexus/api/http-server.ts +73 -1
- package/src/nexus/api/meta-api.ts +38 -0
- package/src/nexus/api/operator.ts +61 -0
- package/src/nexus/api/ops-api.ts +148 -0
- package/src/nexus/api/ops-seats-sources.ts +95 -0
- package/src/nexus/api/ops-seats.ts +124 -0
- package/src/nexus/api/public-routes.ts +14 -1
- package/src/nexus/api/seat-requests.ts +88 -8
- package/src/nexus/api/sessions-store.ts +63 -0
- package/src/nexus/api/setup-claim.ts +21 -0
- package/src/nexus/api/setup-codex-login.ts +160 -0
- package/src/nexus/api/usage-api.ts +102 -0
- package/src/nexus/config/secrets/file-backend.ts +56 -18
- package/src/nexus/index.ts +45 -4
- package/src/onboarding/first-run-doctor.ts +54 -0
- package/src/onboarding/first-run.ts +89 -0
- package/src/onboarding/lan-address.ts +45 -0
- package/src/onboarding/web-first.ts +119 -24
- package/src/onboarding.ts +4 -0
- package/src/ops-now/ops-now-refresh.ts +100 -0
- package/src/project/project-store.ts +115 -0
- package/src/release-loop/checklist.ts +76 -61
- package/src/release-loop/feature-store.ts +460 -0
- package/src/release-loop/manifest.ts +59 -5
- package/src/release-loop/release-schedule.ts +53 -0
- package/src/repl/index.ts +7 -0
- package/src/seat-dispatch/ceo-commands.ts +98 -0
- package/src/seat-dispatch/ceo-intent.ts +38 -0
- package/src/seat-loop/seat-loop.ts +231 -0
- package/src/seat-loop/seat-report.ts +64 -0
- package/src/self-dev/decompose.ts +66 -11
- package/src/self-dev/run-store.ts +10 -1
- package/src/self-implement/execution-clarification.ts +115 -0
- package/src/self-implement/gate-cli.ts +6 -3
- package/src/self-implement/orchestrator.ts +37 -3
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/run-status-mapping.ts +5 -3
- package/src/session/chat.ts +2 -0
- package/src/session/index.ts +9 -0
- package/src/shell-env-bootstrap.ts +17 -0
- package/src/skills/tools/usage-slash.ts +8 -7
- package/src/steward/directive.ts +51 -2
- package/src/steward/launch.ts +250 -0
- package/src/steward/outcome-notify.ts +115 -0
- package/src/steward/steward-cards.ts +8 -2
- package/src/steward/triage-plan.ts +32 -4
- package/src/steward/triage.ts +93 -9
- package/src/steward/working-backwards.ts +64 -0
- package/src/storyboard/storyboard.ts +141 -0
- package/src/task-cards/card-store.ts +2 -2
- package/src/task-orchestrator/surfaces/pod-lease.ts +260 -0
- package/src/telegram-card-followup.ts +233 -0
- package/src/telegram-commands.ts +16 -0
- package/src/telegram-report.ts +15 -9
- package/src/telegram-run.ts +90 -13
- package/src/telegram.ts +29 -8
- package/src/thinking-line.ts +28 -20
- package/src/tool-runtime/types.ts +4 -0
- package/src/tui/chat/execution-badge.ts +1 -1
- package/src/tui-client/dashboard-session.ts +2 -0
- package/src/user-config.ts +118 -11
- package/src/ux-sim/turn-states.ts +1 -1
- package/src/version/packed-revision.json +1 -1
- package/src/web-push/notify-exec-request.ts +32 -0
- package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4836-3084c58c1725a40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-7317998f6cb97d8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-a3e0953307216c58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-9aa47b0bc6d570ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f4d2ecbbae6088d6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-2053e49930c82748.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a70ba27c33003dd0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-18166f885d831d3e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-1c9d6cfe68b121c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c108ff1fdb665c97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-147a328753d983e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-799395a9df7d95aa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-6a8158b71d1fe9d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9567560270857531.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e7ed3d010153d818.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b672e02e4bec8deb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-1ba4a5d857276334.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-9db2226f38c542fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-70ee65f5f7a151dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-0bb8e43203efb23b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-092e1bcf27d751cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-eb52580c4b75b905.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-e573437b0a1c728f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-294300625e49e4d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-085847b088675978.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-9fe9d38c36999eb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6141f67f531d8b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-295a02b1026b8255.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1eb9a0e1e054209d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-82efa177a30f3741.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d0be51cec4f62606.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-2e367075ffdbc062.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-647ed2b66c1d49f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ba058c56e38f2792.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +0 -1
- package/apps/pwa/out/_next/static/css/5ef72a618a8994f3.css +0 -1
- package/apps/pwa/out/_next/static/lywc8m_HDzH9MKSDQhyEj/_buildManifest.js +0 -1
- package/src/dashboard/turn-typeahead-echo.ts +0 -23
- /package/apps/pwa/out/_next/static/{lywc8m_HDzH9MKSDQhyEj → 2DsiDfDCks44g1cPUMhiW}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
import { createPendingQuestion, writePendingQuestion } from '../ask-user-question/pending-questions.js';
|
|
4
|
+
import { createFileAskUserQuestionResolver } from '../ask-user-question/tool.js';
|
|
5
|
+
import { debug } from '../debug/log.js';
|
|
6
|
+
import {
|
|
7
|
+
decideAndObserveClarification,
|
|
8
|
+
defaultClarificationBudget,
|
|
9
|
+
toAskUserQuestionRequest,
|
|
10
|
+
type ClarificationCandidate,
|
|
11
|
+
type ClarificationContext,
|
|
12
|
+
} from '../hitl/clarification-policy.js';
|
|
13
|
+
import { getUserConfig } from '../user-config.js';
|
|
14
|
+
import { appendRunLedgerEntry, type RunLedgerWriter } from './run-ledger.js';
|
|
15
|
+
|
|
16
|
+
export interface ExecutionClarificationContext {
|
|
17
|
+
runId: string;
|
|
18
|
+
budget?: ClarificationContext['budget'];
|
|
19
|
+
pendingQuestionCount?: number;
|
|
20
|
+
config?: { hitl?: { executionDeadlineMinutes?: number } };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ExecutionClarificationResult =
|
|
24
|
+
| { choice: string; by: 'assumed' | 'owner' | 'auto-recommended' }
|
|
25
|
+
| { deferred: true }
|
|
26
|
+
| { parked: true; reason: 'critical-unanswered'; questionId: string };
|
|
27
|
+
|
|
28
|
+
export interface ExecutionClarificationDeps {
|
|
29
|
+
now?: () => number;
|
|
30
|
+
createId?: () => string;
|
|
31
|
+
resolver?: typeof createFileAskUserQuestionResolver;
|
|
32
|
+
resolverDeps?: Parameters<typeof createFileAskUserQuestionResolver>[1];
|
|
33
|
+
writeRunLedger?: RunLedgerWriter;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A single execution-phase decision; the file resolver owns the pending/answer lifecycle. */
|
|
37
|
+
export async function askAtExecution(
|
|
38
|
+
candidate: ClarificationCandidate,
|
|
39
|
+
ctx: ExecutionClarificationContext,
|
|
40
|
+
deps: ExecutionClarificationDeps = {},
|
|
41
|
+
): Promise<ExecutionClarificationResult> {
|
|
42
|
+
const recommended = candidate.options.filter(option => option.recommended);
|
|
43
|
+
if (candidate.options.length < 2 || candidate.options.length > 4 || recommended.length !== 1
|
|
44
|
+
|| new Set(candidate.options.map(option => option.label)).size !== candidate.options.length) {
|
|
45
|
+
throw new Error('Execution clarification requires 2–4 distinct options and exactly one recommendation.');
|
|
46
|
+
}
|
|
47
|
+
const observe = (event: 'assumed' | 'asked' | 'answered' | 'auto-recommended' | 'parked', questionId?: string): void => {
|
|
48
|
+
try {
|
|
49
|
+
debug.log('hitl.execution', event, { runId: ctx.runId, questionId, impact: candidate.impact });
|
|
50
|
+
} catch { /* Logging must not decide the user's choice. */ }
|
|
51
|
+
};
|
|
52
|
+
const record = (event: 'assumed' | 'auto-recommended' | 'parked', data: Record<string, unknown>): void => {
|
|
53
|
+
(deps.writeRunLedger ?? appendRunLedgerEntry)({
|
|
54
|
+
timestamp: new Date((deps.now ?? Date.now)()).toISOString(),
|
|
55
|
+
runId: ctx.runId,
|
|
56
|
+
event,
|
|
57
|
+
data: { impact: candidate.impact, ...data },
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const decision = decideAndObserveClarification(candidate, {
|
|
61
|
+
phase: 'execution',
|
|
62
|
+
budget: ctx.budget ?? defaultClarificationBudget('execution'),
|
|
63
|
+
pendingQuestionCount: ctx.pendingQuestionCount,
|
|
64
|
+
}, { consumer: 'self-implement-execution' });
|
|
65
|
+
if (decision.action === 'defer') return { deferred: true };
|
|
66
|
+
if (decision.action === 'assume') {
|
|
67
|
+
record('assumed', { choice: recommended[0]!.label, assumption: decision.assumption });
|
|
68
|
+
observe('assumed');
|
|
69
|
+
return { choice: recommended[0]!.label, by: 'assumed' };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const request = toAskUserQuestionRequest(decision);
|
|
73
|
+
if (!request) throw new Error('Execution clarification policy approved a question without a valid wire request.');
|
|
74
|
+
const configured = ctx.config === undefined
|
|
75
|
+
? getUserConfig().hitl?.executionDeadlineMinutes
|
|
76
|
+
: ctx.config.hitl?.executionDeadlineMinutes;
|
|
77
|
+
const minutes = configured === undefined ? 30 : configured;
|
|
78
|
+
if (!Number.isSafeInteger(minutes) || minutes < 1 || minutes > 35_791) {
|
|
79
|
+
throw new Error('hitl.executionDeadlineMinutes must be a positive integer within the resolver timer limit.');
|
|
80
|
+
}
|
|
81
|
+
const questionId = (deps.createId ?? (() => `execution:${ctx.runId}:${randomUUID()}`))();
|
|
82
|
+
let expired = false;
|
|
83
|
+
let written = false;
|
|
84
|
+
const resolver = (deps.resolver ?? createFileAskUserQuestionResolver)(minutes * 60_000, {
|
|
85
|
+
...deps.resolverDeps,
|
|
86
|
+
observe: (state, data) => {
|
|
87
|
+
if (state === 'answer-missing') expired = true;
|
|
88
|
+
deps.resolverDeps?.observe?.(state, data);
|
|
89
|
+
},
|
|
90
|
+
createId: () => questionId,
|
|
91
|
+
write: (pending) => {
|
|
92
|
+
const question = createPendingQuestion(questionId, { ...request, runId: ctx.runId }, undefined,
|
|
93
|
+
{ now: () => new Date((deps.now ?? Date.now)()) },
|
|
94
|
+
{ surface: 'file', delivery: 'file', expiresAt: pending.expiresAt });
|
|
95
|
+
(deps.resolverDeps?.write ?? writePendingQuestion)(question);
|
|
96
|
+
written = true;
|
|
97
|
+
observe('asked', questionId);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const answer = await resolver({ ...request, runId: ctx.runId });
|
|
101
|
+
const chosen = answer.answers[candidate.id];
|
|
102
|
+
if (written && !expired && !answer.cancelled && typeof chosen === 'string' && candidate.options.some(option => option.label === chosen)) {
|
|
103
|
+
observe('answered', questionId);
|
|
104
|
+
return { choice: chosen, by: 'owner' };
|
|
105
|
+
}
|
|
106
|
+
if (!written || !expired) throw new Error('Execution clarification was cancelled or could not read its answer before expiry.');
|
|
107
|
+
if (candidate.impact === 'critical') {
|
|
108
|
+
record('parked', { questionId, reason: 'critical-unanswered' });
|
|
109
|
+
observe('parked', questionId);
|
|
110
|
+
return { parked: true, reason: 'critical-unanswered', questionId };
|
|
111
|
+
}
|
|
112
|
+
record('auto-recommended', { questionId, choice: recommended[0]!.label, by: 'auto-recommended' });
|
|
113
|
+
observe('auto-recommended', questionId);
|
|
114
|
+
return { choice: recommended[0]!.label, by: 'auto-recommended' };
|
|
115
|
+
}
|
|
@@ -7,6 +7,7 @@ import { runModelHardcodeGate } from '../../scripts/ci-model-hardcode-gate.js';
|
|
|
7
7
|
import { runDaemonPortGate } from '../../scripts/ci-daemon-port-gate.js';
|
|
8
8
|
import { runAndroidUnitTestGate } from '../../scripts/ci-android-unit-tests.js';
|
|
9
9
|
import { runIosUnitTestGate } from '../../scripts/ci-ios-unit-tests.js';
|
|
10
|
+
import { runPwaBuildGate } from '../../scripts/ci-pwa-build-gate.js';
|
|
10
11
|
import { runMockModuleRestoreGate } from '../../scripts/ci-mock-module-restore-gate.js';
|
|
11
12
|
import { parseReviewDepthFromFilesJson } from '../agent-mission/review-depth.js';
|
|
12
13
|
import { buildGateBaselineReport, calculateGateTestCountChange, formatGateBaselineNote, formatGateTestCountNote, isGateTestFile, runGateBaseline, type BaselineProcessResult, type BaselineProcessStatus, type GateTestFailure } from './gate-baseline.js';
|
|
@@ -83,6 +84,7 @@ interface SelfGateCliDeps {
|
|
|
83
84
|
runAndroidGate?: (out: GateOutput) => number;
|
|
84
85
|
/** iOS 순수-로직 시험 게이트 심(시험 주입용). */
|
|
85
86
|
runIosGate?: (out: GateOutput) => number;
|
|
87
|
+
runPwaGate?: (out: GateOutput) => number;
|
|
86
88
|
listPrWorktrees?: (cwd: string) => PrWorktreeListEntry[] | { lookupFailed: string };
|
|
87
89
|
inspectWorktreeDirtiness?: (path: string) => { dirty: boolean } | { lookupFailed: string };
|
|
88
90
|
}
|
|
@@ -619,11 +621,12 @@ export function runSelfGateCli(cwd: string, options: SelfGateCliOptions = {}, de
|
|
|
619
621
|
const androidPassed = runAdditionalGate('android-gate', deps.runAndroidGate ?? runAndroidUnitTestGate, selection.files, cwd, lines);
|
|
620
622
|
// 🍎 iOS 축 — 안드로이드와 «같은 자리»에 둔다(skipTestStep 앞). Swift 만 바뀐 PR 도 여기서 조기 리턴한다.
|
|
621
623
|
const iosPassed = runAdditionalGate('ios-gate', deps.runIosGate ?? runIosUnitTestGate, selection.files, cwd, lines);
|
|
624
|
+
const pwaPassed = runAdditionalGate('pwa-gate', deps.runPwaGate ?? runPwaBuildGate, selection.files, cwd, lines);
|
|
622
625
|
|
|
623
626
|
if (scope.skipTestStep) {
|
|
624
627
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
625
628
|
logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
|
|
626
|
-
return { exitCode: androidPassed && iosPassed && policyPassed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests };
|
|
629
|
+
return { exitCode: androidPassed && iosPassed && pwaPassed && policyPassed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests };
|
|
627
630
|
}
|
|
628
631
|
|
|
629
632
|
const test = (deps.runTests ?? ((dir, files) => (deps.runCommand ?? defaultRunCommand)('bun', ['test', ...files], dir)))(cwd, testFiles);
|
|
@@ -632,7 +635,7 @@ export function runSelfGateCli(cwd: string, options: SelfGateCliOptions = {}, de
|
|
|
632
635
|
lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, `tests: pass (${testFiles.length} files)`));
|
|
633
636
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
634
637
|
logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
|
|
635
|
-
return { exitCode: policyPassed && androidPassed && iosPassed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests };
|
|
638
|
+
return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests };
|
|
636
639
|
}
|
|
637
640
|
|
|
638
641
|
if (worktreeLog.includes('deterministic environment setup failed')) lines.push(worktreeLog);
|
|
@@ -653,6 +656,6 @@ export function runSelfGateCli(cwd: string, options: SelfGateCliOptions = {}, de
|
|
|
653
656
|
});
|
|
654
657
|
lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, formatGateBaselineNote(report, unrunImporterTotal ?? 0)));
|
|
655
658
|
const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
|
|
656
|
-
const exitCode = !androidPassed || !iosPassed || !policyPassed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
|
|
659
|
+
const exitCode = !androidPassed || !iosPassed || !pwaPassed || !policyPassed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
|
|
657
660
|
return { exitCode, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests };
|
|
658
661
|
}
|
|
@@ -79,6 +79,7 @@ import { classifyReviewProviderFailure } from '../self-dev/review-provider-fallb
|
|
|
79
79
|
import { classifyError } from '../session-runtime/retry-policy.js';
|
|
80
80
|
import { decomposeSelfDevGoal, inferHotPaths, type SelfDevDecomposeOptions } from '../self-dev/decompose.js';
|
|
81
81
|
import { boundaryGlobs, boundaryViolations } from './goal-boundary.js';
|
|
82
|
+
import { askAtExecution, type ExecutionClarificationResult } from './execution-clarification.js';
|
|
82
83
|
import { targetScopedGoalText } from './goal-text-path-scope.js';
|
|
83
84
|
import type { SelfDevGoalType } from '../self-dev/orchestrate.js';
|
|
84
85
|
import { DEFAULT_BRANCH_WORKTREE_BASE, gateGitResidue, observeGitResidue } from '../git-fs/worktree.js';
|
|
@@ -967,6 +968,8 @@ export interface SelfImplementSeams {
|
|
|
967
968
|
/** 변경 파일 목록 — 게이트 «라우터»가 「코드가 바뀌었나」를 판정하는 입력.
|
|
968
969
|
* ⛔ 미지정이면 실물 `changedFiles(cwd)` 를 쓴다. 못 얻으면 `undefined` 이고, 라우터는 그때 «돌린다»(fail-safe). */
|
|
969
970
|
changedFilesForGateRoute?: (cwd: string) => readonly string[] | undefined;
|
|
971
|
+
/** An execution choice is made only after a measured change crosses the authored target paths. */
|
|
972
|
+
askExecutionClarification?: typeof askAtExecution;
|
|
970
973
|
/** ★ ⑤ 내부 리뷰 seam(2026-07-21·review-gated merge) — gate 통과 diff 를 리뷰어(reviewPullRequest·
|
|
971
974
|
* agent-substrate·staged 하니스와 동일 엔진)가 비평. verdict fail(mustFix) → rework 재주입(A 확장),
|
|
972
975
|
* clean(pass/warn) → 병합 결정. 미주입 시 리뷰 스킵(gate 통과=바로 결정·종전 동작). */
|
|
@@ -1082,7 +1085,7 @@ export const SELF_IMPLEMENT_PROGRESS_STAGES = [
|
|
|
1082
1085
|
'gating', 'gated', 'reviewing', 'reviewed', 'awaiting-approval',
|
|
1083
1086
|
'pr-opening', 'pr-opened', 'merging', 'merged', 'worktree-completed',
|
|
1084
1087
|
'aborted', 'gate-failed', 'review-blocked', 'merge-conflict', 'pr-declined',
|
|
1085
|
-
'awaiting-clarification',
|
|
1088
|
+
'awaiting-clarification', 'parked',
|
|
1086
1089
|
// ⭐⭐ 🩸 2026-09-12 — ***「선언한 대상을 «하나도» 안 만들고 끝났다」를 사람 표면에 낸다.***
|
|
1087
1090
|
// ⛔ 기존 단계 이름을 «빌려 쓰지 않는다» — `progress()` 는 단계 이름으로 원장 행을 만들므로
|
|
1088
1091
|
// 빌려 쓰면 그 단계 집계가 오염된다([T] 2026-09-12 · `#17767` 이후 계약).
|
|
@@ -6268,6 +6271,39 @@ async function runSelfImplementInner(
|
|
|
6268
6271
|
return { ok: false, stage: 'aborted', node: 'implement', ...resolveRunOutcome({ termination: 'abandoned' }), sessionId, worktreePath: wt.path, branch: wt.branch, quotaExhaustionAssessment: quotaExhaustionAssessmentForRun(), ...(impl.completionDisposition ? { completionDisposition: impl.completionDisposition } : {}), ...(pr ? { prUrl: pr.url, prNumber: pr.number } : {}), detail: impl.summary };
|
|
6269
6272
|
}
|
|
6270
6273
|
|
|
6274
|
+
// Measure the existing declared-target boundary after implementation, before gate/PR.
|
|
6275
|
+
// Unknown declaration or changed files cannot justify an invented choice.
|
|
6276
|
+
let gateRouteFiles: readonly string[] | undefined;
|
|
6277
|
+
try { gateRouteFiles = (s.changedFilesForGateRoute ?? changedFiles)(wt.path); } catch { gateRouteFiles = undefined; }
|
|
6278
|
+
if (opts.goalFile) {
|
|
6279
|
+
let goalDocument: string | undefined;
|
|
6280
|
+
try { goalDocument = readFileSync(opts.goalFile, 'utf8'); } catch { /* unknown scope */ }
|
|
6281
|
+
const scope = detectDeclaredScopeDiff({ goalDocument, changedFiles: gateRouteFiles?.filter(file => !harnessSeededPaths.includes(file)), nameCap: gateRouteFiles?.length });
|
|
6282
|
+
if (scope.status === 'known' && scope.outsideCount !== null && scope.outsideCount > 0) {
|
|
6283
|
+
const result: ExecutionClarificationResult = await (s.askExecutionClarification ?? askAtExecution)({
|
|
6284
|
+
id: 'execution_scope', decision: 'Changing files outside the authored target paths',
|
|
6285
|
+
prompt: 'Implementation changed files outside the authored target paths. Keep the original scope or expand it?',
|
|
6286
|
+
whyNow: 'Continuing to gate or publish these edits would expand the requested scope.',
|
|
6287
|
+
impact: scope.outsideNames.some(file => {
|
|
6288
|
+
if (existsSync(join(wt.path, file))) return false;
|
|
6289
|
+
const tracked = runGitCommand(wt.path, ['ls-files', '--error-unmatch', '--', file], { encoding: 'utf8', timeout: 20_000 });
|
|
6290
|
+
return tracked.status === 0;
|
|
6291
|
+
}) ? 'critical' : 'high',
|
|
6292
|
+
options: [
|
|
6293
|
+
{ label: 'Stay in scope', description: 'Do not accept out-of-scope changes.', recommended: true },
|
|
6294
|
+
{ label: 'Expand scope', description: 'Accept the changed files outside the target paths.' },
|
|
6295
|
+
],
|
|
6296
|
+
}, { runId }, { writeRunLedger: s.writeRunLedger });
|
|
6297
|
+
if ('parked' in result || 'deferred' in result || result.choice !== 'Expand scope') {
|
|
6298
|
+
finalizeSupervisorDeliveries('execution-scope-not-approved');
|
|
6299
|
+
observe('execution-scope-held', { outsideCount: scope.outsideCount, disposition: 'parked' in result ? 'parked' : 'in-scope-only' });
|
|
6300
|
+
if ('parked' in result) progress('parked', `critical 질문 ${result.questionId} 미응답 — 이 런만 대기`);
|
|
6301
|
+
return { ok: false, stage: 'parked' in result ? 'parked' : 'soft-stopped', node: 'implement', ...resolveRunOutcome({ termination: 'abandoned' }), sessionId, worktreePath: wt.path, branch: wt.branch,
|
|
6302
|
+
detail: 'parked' in result ? `critical-unanswered: ${result.questionId}` : 'Out-of-scope edits held in the worktree; gate and publication skipped.' };
|
|
6303
|
+
}
|
|
6304
|
+
}
|
|
6305
|
+
}
|
|
6306
|
+
|
|
6271
6307
|
// ⛔⭐ 이 템플릿이 `gate` 노드를 «안 가지면» 그 단계는 돌지 않는다.
|
|
6272
6308
|
// 📌 research-loop 이 그렇다 — 문서만 바뀐 판에는 «변경 파일 범위» 게이트가 돌 시험이 없다.
|
|
6273
6309
|
// ⚠️ 꺼진 상태에서는 언제나 implement-loop 이라 참이다 ⇒ 오늘과 «같은» 걸음이다.
|
|
@@ -6275,8 +6311,6 @@ async function runSelfImplementInner(
|
|
|
6275
6311
|
// 기본이 꺼짐이라 지금 폭발 반경은 0이고, 기본을 켜기 «전»에 이 구멍을 먼저 막아야 한다.
|
|
6276
6312
|
// ⛔⭐ 라우터가 판정한다 — 값은 «코드»가 낸다(RFC §4.3 ⑵). 「모른다」는 «돌린다» 쪽이다.
|
|
6277
6313
|
// 🚨 이 줄이 2026-09-08 승격의 구멍 ⓐ 를 닫는다: research 골이 «코드»를 만지면 시험이 돈다.
|
|
6278
|
-
let gateRouteFiles: readonly string[] | undefined;
|
|
6279
|
-
try { gateRouteFiles = (s.changedFilesForGateRoute ?? changedFiles)(wt.path); } catch { gateRouteFiles = undefined; }
|
|
6280
6314
|
const gateRoute = routeGate(graphTemplate, gateRouteFiles);
|
|
6281
6315
|
const runsGate = gateRoute.runsGate;
|
|
6282
6316
|
progress('gating', !runsGate
|
|
@@ -13,7 +13,7 @@ export type PipelineNodeId =
|
|
|
13
13
|
|
|
14
14
|
/** Each pipeline node's possible terminal stages. Nodes without a terminal exit use an empty array. */
|
|
15
15
|
export const TERMINAL_STAGES_BY_NODE = {
|
|
16
|
-
implement: ['aborted', 'timed-out', 'soft-stopped'],
|
|
16
|
+
implement: ['aborted', 'timed-out', 'soft-stopped', 'parked'],
|
|
17
17
|
gate: [],
|
|
18
18
|
review: ['review-blocked'],
|
|
19
19
|
rework: ['gate-failed', 'review-blocked'],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RunStatus = 'completed' | 'failed' | 'cancelled';
|
|
1
|
+
export type RunStatus = 'completed' | 'failed' | 'cancelled' | 'parked';
|
|
2
2
|
/** ⭐ `crashed` — ***잡히지 않은 예외로 죽어 종결을 스스로 못 적은*** 런 (2026-08-11 · 🅣⊕🅢 어휘 합의).
|
|
3
3
|
* ⛔ `aborted`(스스로 중단을 «판정»했다)와 다른 값이다 — 이쪽은 «판정할 겨를이 없었다».
|
|
4
4
|
* 📏 왜 생겼나: 실측 미완 57 중 ≈38 이 어느 원장에도 종결이 없었고, 멈춘 자리가 전부 「노드 안」이었다. */
|
|
@@ -20,7 +20,8 @@ export type SelfImplementStage =
|
|
|
20
20
|
| 'aborted'
|
|
21
21
|
| 'timed-out'
|
|
22
22
|
| 'pr-declined'
|
|
23
|
-
| 'soft-stopped'
|
|
23
|
+
| 'soft-stopped'
|
|
24
|
+
| 'parked';
|
|
24
25
|
|
|
25
26
|
const STAGE_OUTCOMES = {
|
|
26
27
|
merged: { runStatus: 'completed' },
|
|
@@ -34,9 +35,10 @@ const STAGE_OUTCOMES = {
|
|
|
34
35
|
'timed-out': { runStatus: 'failed', failureKind: 'timed-out' },
|
|
35
36
|
'pr-declined': { runStatus: 'cancelled' },
|
|
36
37
|
'soft-stopped': { runStatus: 'cancelled' },
|
|
38
|
+
parked: { runStatus: 'parked' },
|
|
37
39
|
} satisfies Record<SelfImplementStage, MappedRunOutcome>;
|
|
38
40
|
|
|
39
|
-
const RUN_STATUSES = new Set<RunStatus>(['completed', 'failed', 'cancelled']);
|
|
41
|
+
const RUN_STATUSES = new Set<RunStatus>(['completed', 'failed', 'cancelled', 'parked']);
|
|
40
42
|
|
|
41
43
|
/** Runtime guard for the run-status payload produced by observeRunOutcome. */
|
|
42
44
|
export function isRunStatus(value: unknown): value is RunStatus {
|
package/src/session/chat.ts
CHANGED
|
@@ -109,6 +109,8 @@ export interface RunTurnOpts {
|
|
|
109
109
|
* delegated coding agent's approval prompts back to the originating
|
|
110
110
|
* chat via `delegate_code_agent`. */
|
|
111
111
|
hitlConfirmChannel?: import('../hitl/confirm.js').ConfirmChannel;
|
|
112
|
+
/** Verified by the hosting bot from the inbound user id against its server-side owner allowlist. */
|
|
113
|
+
verifiedOwner?: { id: string };
|
|
112
114
|
/** Paired multi-option question channel (Telegram sets this). Surface
|
|
113
115
|
* runTurnImpls thread it into `delegate_code_agent` so a delegated
|
|
114
116
|
* agent's structured questions render as option buttons in the
|
package/src/session/index.ts
CHANGED
|
@@ -202,6 +202,8 @@ export interface SessionMeta {
|
|
|
202
202
|
* 아님). ~/.elanous 공유 스토어 세션은 전부 'prod'. append 는 이 값을 보존(생성자 귀속).
|
|
203
203
|
* 구 세션엔 부재(tolerant read) — 미상 = 필터 비매치. */
|
|
204
204
|
originInstance?: string;
|
|
205
|
+
/** Project association, omitted for sessions without an assigned project (including legacy records). */
|
|
206
|
+
projectId?: string;
|
|
205
207
|
/** For telegram-sourced sessions; undefined for cli. */
|
|
206
208
|
tgChatId?: number;
|
|
207
209
|
tgThreadId?: number;
|
|
@@ -383,6 +385,7 @@ export interface CreateSessionOpts {
|
|
|
383
385
|
tgBotId?: string;
|
|
384
386
|
/** Stable identity for a persona's resident conversation. */
|
|
385
387
|
personaId?: string;
|
|
388
|
+
projectId?: string;
|
|
386
389
|
title?: string;
|
|
387
390
|
/** 표면 origin(cli/pwa/tg/dc/harness) — source 유니온 밖의 세밀 라벨(PWA 챗 구분용). */
|
|
388
391
|
origin?: string;
|
|
@@ -534,6 +537,7 @@ export function createSession(opts: CreateSessionOpts = {}, root: string = sessi
|
|
|
534
537
|
tgThreadId: opts.tgThreadId,
|
|
535
538
|
...(opts.tgBotId ? { tgBotId: opts.tgBotId } : {}),
|
|
536
539
|
...(opts.personaId ? { personaId: opts.personaId } : {}),
|
|
540
|
+
...(opts.projectId !== undefined ? { projectId: opts.projectId } : {}),
|
|
537
541
|
tgSessionKey,
|
|
538
542
|
};
|
|
539
543
|
writeFileSync(sessionFile(id, root), '', 'utf-8');
|
|
@@ -575,6 +579,7 @@ export function adoptSession(id: string, opts: CreateSessionOpts = {}, root: str
|
|
|
575
579
|
sourceKind: opts.sourceKind ?? defaultSessionSourceKind(source),
|
|
576
580
|
...(opts.forkedFromId ? { forkedFromId: opts.forkedFromId } : {}),
|
|
577
581
|
...(origin ? { origin } : {}),
|
|
582
|
+
...(opts.projectId !== undefined ? { projectId: opts.projectId } : {}),
|
|
578
583
|
originInstance: resolveInstanceName(),
|
|
579
584
|
...(opts.tgChatId != null ? { tgChatId: opts.tgChatId } : {}),
|
|
580
585
|
...(opts.tgThreadId != null ? { tgThreadId: opts.tgThreadId } : {}),
|
|
@@ -601,6 +606,7 @@ export function forkSessionFromHistory(
|
|
|
601
606
|
tgThreadId: opts.tgThreadId,
|
|
602
607
|
title: opts.title,
|
|
603
608
|
origin: opts.origin,
|
|
609
|
+
projectId: opts.projectId,
|
|
604
610
|
}, root);
|
|
605
611
|
for (const msg of opts.messages) {
|
|
606
612
|
const content = typeof msg.content === 'string' ? msg.content : '';
|
|
@@ -738,6 +744,8 @@ export interface ListSessionsOpts {
|
|
|
738
744
|
tgThreadId?: number;
|
|
739
745
|
/** 생성 인스턴스 정확 일치(prod · test:<repo> …). 구 세션(부재)은 비매치. */
|
|
740
746
|
originInstance?: string;
|
|
747
|
+
/** Project id exact match; sessions without the field do not match. */
|
|
748
|
+
projectId?: string;
|
|
741
749
|
/** 표면 origin 정확 일치(cli | pwa | tg | dc | harness). */
|
|
742
750
|
origin?: string;
|
|
743
751
|
/** 제외할 origin(들) — 예: ['harness'] 로 하니스 자식 세션을 사용자 대화 목록에서 숨김. */
|
|
@@ -774,6 +782,7 @@ export function listSessions(opts: ListSessionsOpts = {}, root: string = session
|
|
|
774
782
|
idx = idx.filter(m => !m.sourceKind || !opts.excludeSourceKinds!.includes(m.sourceKind));
|
|
775
783
|
}
|
|
776
784
|
if (opts.originInstance) idx = idx.filter(m => m.originInstance === opts.originInstance);
|
|
785
|
+
if (opts.projectId !== undefined) idx = idx.filter(m => m.projectId === opts.projectId);
|
|
777
786
|
if (opts.origin) idx = idx.filter(m => m.origin === opts.origin);
|
|
778
787
|
if (opts.excludeOrigins && opts.excludeOrigins.length > 0) {
|
|
779
788
|
idx = idx.filter((m) => {
|
|
@@ -210,6 +210,23 @@ export function capturedEnvAvailable(): boolean {
|
|
|
210
210
|
return captured && cached !== null;
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
/** Append login-shell PATH entries to the target without replacing its existing environment. */
|
|
214
|
+
export function mergeCapturedPath(target: NodeJS.ProcessEnv = process.env, opts: { capture?: boolean } = {}): number {
|
|
215
|
+
// capture: 아직 캡처 전이면 여기서 한 번 캡처한다(호출부가 getCapturedEnv 를 직접 부르지 않게 — identity-env 래칫).
|
|
216
|
+
const capturedPath = opts.capture || capturedEnvAvailable() ? getCapturedEnv().PATH : undefined;
|
|
217
|
+
const seen = new Set((target.PATH ?? '').split(':'));
|
|
218
|
+
const missing: string[] = [];
|
|
219
|
+
for (const entry of capturedPath?.split(':') ?? []) {
|
|
220
|
+
if (!entry || seen.has(entry)) continue;
|
|
221
|
+
missing.push(entry);
|
|
222
|
+
seen.add(entry);
|
|
223
|
+
}
|
|
224
|
+
if (missing.length) target.PATH = target.PATH ? `${target.PATH}:${missing.join(':')}` : missing.join(':');
|
|
225
|
+
const added = missing.length;
|
|
226
|
+
debug.log('shell.envbootstrap.capture', 'path-merged', { added });
|
|
227
|
+
return added;
|
|
228
|
+
}
|
|
229
|
+
|
|
213
230
|
/** Reset cache — test seam. */
|
|
214
231
|
export function resetCapturedEnvForTesting(): void {
|
|
215
232
|
cached = null;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
// Slash
|
|
2
|
-
//
|
|
3
|
-
// Screen does not compute. It prints the same structured report the
|
|
4
|
-
// `elanous usage` command produces.
|
|
1
|
+
// Slash commands: /usage and /remaining — compact TUI view of the unified report.
|
|
5
2
|
|
|
6
|
-
import { collectUnifiedUsage,
|
|
3
|
+
import { collectUnifiedUsage, formatUsageCompact, type UnifiedUsageDeps } from '../../budget/unified-usage.js';
|
|
4
|
+
import { visibleWidth } from '../../tui.js';
|
|
7
5
|
import type { SlashExecuteRequest, SlashExecuteResult } from './dashboard-slash.js';
|
|
8
6
|
|
|
9
7
|
export interface UsageSlashResult extends SlashExecuteResult {
|
|
@@ -12,15 +10,18 @@ export interface UsageSlashResult extends SlashExecuteResult {
|
|
|
12
10
|
}
|
|
13
11
|
|
|
14
12
|
export async function executeUsageSlash(
|
|
15
|
-
req: SlashExecuteRequest,
|
|
13
|
+
req: SlashExecuteRequest & { width?: number },
|
|
16
14
|
deps: UnifiedUsageDeps = {},
|
|
17
15
|
): Promise<UsageSlashResult | null> {
|
|
18
16
|
if (req.name !== 'usage' && req.name !== 'remaining') return null;
|
|
19
17
|
const report = await collectUnifiedUsage(deps);
|
|
18
|
+
const width = req.width ?? 120;
|
|
19
|
+
const hint = ['자세히: elanous usage', 'elanous usage', 'elanous…', '…']
|
|
20
|
+
.find((text) => visibleWidth(text) <= width) ?? '';
|
|
20
21
|
return {
|
|
21
22
|
ok: true,
|
|
22
23
|
name: req.name,
|
|
23
24
|
args: req.args,
|
|
24
|
-
logLines:
|
|
25
|
+
logLines: [...formatUsageCompact(report, { width, nowMs: Date.now() }), hint],
|
|
25
26
|
};
|
|
26
27
|
}
|
package/src/steward/directive.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
2
5
|
import { getSecretAsync } from '../nexus/config/secrets/index.js';
|
|
3
6
|
import { getUserConfig } from '../user-config.js';
|
|
4
7
|
|
|
5
8
|
export type DirectiveSource = 'telegram' | 'pwa' | 'tui' | 'cli';
|
|
6
9
|
export interface DirectiveIssue { id: string; identifier: string; title: string; description?: string | null }
|
|
10
|
+
export interface DirectiveOrigin { chatId: number; botId?: string; threadId?: number }
|
|
7
11
|
export interface DirectiveDeps {
|
|
12
|
+
root?: string;
|
|
8
13
|
fetch?: typeof fetch;
|
|
9
14
|
getSecret?: (id: string) => Promise<string | undefined>;
|
|
10
15
|
team?: string;
|
|
@@ -31,8 +36,50 @@ async function graphql<T>(key: string, query: string, variables: Record<string,
|
|
|
31
36
|
return payload.data;
|
|
32
37
|
}
|
|
33
38
|
|
|
39
|
+
function originPath(root: string, identifier: string): string {
|
|
40
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(identifier)) throw new Error('Invalid directive identifier');
|
|
41
|
+
return join(root, 'steward', 'origins', `${identifier}.json`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type TelegramOrigin = import('../autopilot/mission-origin.js').MissionOrigin & { channel: 'telegram'; chatId: number };
|
|
45
|
+
|
|
46
|
+
function validOrigin(value: unknown): value is TelegramOrigin {
|
|
47
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
48
|
+
const origin = value as Record<string, unknown>;
|
|
49
|
+
return origin.channel === 'telegram' && Number.isSafeInteger(origin.chatId) &&
|
|
50
|
+
(origin.botId === undefined || typeof origin.botId === 'string' && /^\d+$/.test(origin.botId)) &&
|
|
51
|
+
(origin.threadId === undefined || Number.isSafeInteger(origin.threadId));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function loadDirectiveOrigins(root: string, identifier: string): TelegramOrigin[] {
|
|
55
|
+
try {
|
|
56
|
+
const value: unknown = JSON.parse(readFileSync(originPath(root, identifier), 'utf8'));
|
|
57
|
+
const origins = Array.isArray(value) ? value : [value];
|
|
58
|
+
return origins.filter(validOrigin);
|
|
59
|
+
} catch { return []; }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function saveDirectiveOrigin(root: string, identifier: string, origin: DirectiveOrigin): void {
|
|
63
|
+
if (!Number.isSafeInteger(origin.chatId) || origin.threadId !== undefined && !Number.isSafeInteger(origin.threadId)) throw new Error('Invalid directive origin');
|
|
64
|
+
const path = originPath(root, identifier);
|
|
65
|
+
const next: TelegramOrigin = { channel: 'telegram', chatId: origin.chatId,
|
|
66
|
+
...(origin.botId && /^\d+$/.test(origin.botId) ? { botId: origin.botId } : {}),
|
|
67
|
+
...(origin.threadId !== undefined ? { threadId: origin.threadId } : {}) };
|
|
68
|
+
const origins = loadDirectiveOrigins(root, identifier);
|
|
69
|
+
if (origins.some(item => JSON.stringify(item) === JSON.stringify(next))) return;
|
|
70
|
+
origins.push(next);
|
|
71
|
+
mkdirSync(join(root, 'steward', 'origins'), { recursive: true });
|
|
72
|
+
const temp = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
73
|
+
writeFileSync(temp, JSON.stringify(origins.length === 1 ? next : origins));
|
|
74
|
+
renameSync(temp, path);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function loadDirectiveOrigin(root: string, identifier: string): TelegramOrigin | null {
|
|
78
|
+
return loadDirectiveOrigins(root, identifier)[0] ?? null;
|
|
79
|
+
}
|
|
80
|
+
|
|
34
81
|
/** The same entry point is used by the CLI and conversational surfaces. */
|
|
35
|
-
export async function addDirective(text: string, options: { source?: DirectiveSource; dryRun?: boolean } = {}, deps: DirectiveDeps = {}): Promise<{ status: 'created' | 'repeated' | 'dry-run'; issue?: string; hash: string }> {
|
|
82
|
+
export async function addDirective(text: string, options: { source?: DirectiveSource; dryRun?: boolean; origin?: DirectiveOrigin } = {}, deps: DirectiveDeps = {}): Promise<{ status: 'created' | 'repeated' | 'dry-run'; issue?: string; hash: string }> {
|
|
36
83
|
const original = text.trim();
|
|
37
84
|
if (!original) throw new Error('directive text is required');
|
|
38
85
|
const source = options.source ?? 'cli';
|
|
@@ -74,6 +121,7 @@ export async function addDirective(text: string, options: { source?: DirectiveSo
|
|
|
74
121
|
'mutation($input:CommentCreateInput!){commentCreate(input:$input){success}}',
|
|
75
122
|
{ input: { issueId: duplicate.id, body: `다시 말함 · ${source} · ${at}\n\n${original}` } });
|
|
76
123
|
if (!result.commentCreate?.success) throw new Error('Linear comment creation failed');
|
|
124
|
+
if (source === 'telegram' && options.origin) saveDirectiveOrigin(deps.root ?? effectiveInstanceRoot(), duplicate.identifier, options.origin);
|
|
77
125
|
return { status: 'repeated', issue: duplicate.identifier, hash };
|
|
78
126
|
}
|
|
79
127
|
const labels = await request<{ issueLabels: { nodes: Array<{ id: string; name: string }> } }>(
|
|
@@ -90,6 +138,7 @@ export async function addDirective(text: string, options: { source?: DirectiveSo
|
|
|
90
138
|
'mutation($input:IssueCreateInput!){issueCreate(input:$input){success issue{id identifier title}}}',
|
|
91
139
|
{ input: { teamId, title: original.slice(0, 240), description: `${original}\n\n출처: ${source}\n시각: ${at}\n[directive-hash:${hash}]`, labelIds: [labelId], priority: 0 } });
|
|
92
140
|
if (!created.issueCreate?.success || !created.issueCreate.issue?.identifier) throw new Error('Linear issue creation failed');
|
|
141
|
+
if (source === 'telegram' && options.origin) saveDirectiveOrigin(deps.root ?? effectiveInstanceRoot(), created.issueCreate.issue.identifier, options.origin);
|
|
93
142
|
return { status: 'created', issue: created.issueCreate.issue.identifier, hash };
|
|
94
143
|
}
|
|
95
144
|
|