elanous 0.2.17 → 0.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/J5H7BvqgSI8DUjtRRcA_S/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1157-cba0e8553d35a980.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{726.83532d69452ee24b.js → 1470.98a6ab61ccb4131c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/171-23a877ed11720de9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2336-e830c777eb6bce04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9247-269e4464cc4b491c.js → 2375-e061bb24cd2b5cde.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{211-9c9090c59e2c5907.js → 2977-e38442e86289f1d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → 2ea96958.e8c7e112de50b067.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3094.67339318c7f72a3a.js +2 -0
- package/apps/pwa/out/_next/static/chunks/338-ceb956612dcfaa86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3395-835e4ceaa6335ba4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3441-be82e3595aef3a20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3689-89905039bf3e7257.js +1 -0
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3822-6f268bc26c6a84ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 4323.c5dfb6f503304775.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4457-d7df81c90f9d0268.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4551-77dadae76f6cbace.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 4847.56f5bc454fbcc827.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4978.6fd93b974441e87f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5012-f746f6549b869f91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 6062-73e68343a9814f6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/62-5bfed1e23790b745.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6320-9bc8561fde416e07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/649-ca96d1c5d09e02b8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6726-85a7db59b288c53f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6735-33267c4630d0d963.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7633-141682015873beb6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{935.4ddaa99fc1d1126c.js → 7647.2fcd30d894d5ee30.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f6231284-45726550aba08fca.js → 8046cadf-211ca3c0e00f2b72.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8067-143791231c99bd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8430-a10cfba8ef282d4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8870-9614a213b990b10b.js +25 -0
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9454-12c2f30dea62291c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/976-4a9b4ebdca7c739a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9989-15cdf568bafa9fc8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ae787e4c-e5b1ef00b2dbceca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-deef5ee191830f14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-b193da485f9a14b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-b6e1a79df0e214f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-e84df4d907f703c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a5fb9a5db89ae4ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-1499f481d7fc52d6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c7cf753aeb648790.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4118469e514e10fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-e968f7630654332a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-505915052f947022.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c2f962fb4a3b06c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7b5ed0bd8a589ec4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-cf8193250dd42dd4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-cf3f5dfa35dea8e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-5b29d9b06ceadade.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a15e7fcc283e9ca7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d2915e7b70ff3d0e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-b70cd005d9169e25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2595f0eba29f57e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-c776322454156e36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-77bbd17f4435aa10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-049689e611ecc936.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-85954a4fb09c44eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e773e552e1068ee6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5633c4bfa7684b4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d829b92bd01b4994.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-061c317fc771becf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a45ece8865ed4b6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-0be990618c0d56bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-bfea4865dc244b73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d6ba8e337741484.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-76a88b55d816482e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-bba1542df59f61ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4185c95689bb372e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b699e1a8d5d34b8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c225e338c31bf274.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-449353f70507ca1f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-90b889714102476d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f1ee7fbeb7f96ddc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-d59a95e1434dfaa0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-71491a23414d1a47.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-de7112bdb65fa4fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-feb4d0d88079660d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f17d887b40dd6b1d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-8da77be2192bcd5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-72c3b9a5e9582b29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3afe4c8d0c48c39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-b9308f2d8a931531.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-6f35f9d892fa630b.js +1 -0
- package/apps/pwa/out/_next/static/css/{e99e3cff94ced78a.css → 599369d853c61df7.css} +1 -1
- package/apps/pwa/out/_next/static/css/85f53c6f35d11382.css +1 -0
- package/apps/pwa/out/_next/static/css/d3427996da11e480.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -0
- package/apps/pwa/out/decisions/index.txt +30 -0
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +25 -24
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +24 -23
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +28 -27
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/ops/guardian.yaml +26 -0
- package/graphs/ops/recipes.yaml +3 -0
- package/package.json +2 -1
- package/samples/workflows/templates/approval-gated-deploy.yaml +30 -0
- package/samples/workflows/templates/chat-driven-research.yaml +35 -0
- package/samples/workflows/templates/discord-listen-and-respond.yaml +29 -0
- package/samples/workflows/templates/http-poll-then-alert.yaml +30 -0
- package/samples/workflows/templates/manual-quickstart.yaml +21 -0
- package/samples/workflows/templates/scheduled-daily-digest.yaml +30 -0
- package/samples/workflows/templates/webhook-deploy-hook.yaml +27 -0
- package/scripts/ci-public-export-import-gate.ts +7 -2
- package/scripts/ci-typecheck-changed.ts +21 -6
- package/scripts/coord-channel-watch.sh +2 -2
- package/scripts/discord-seat-probe.ts +6 -3
- package/scripts/docs/generate-cli-anatomy.ts +162 -0
- package/scripts/goals/authoring-metrics.ts +73 -0
- package/scripts/landing-heal/must-fix-match.ts +7 -7
- package/scripts/landing-heal/run-mission.ts +3 -2
- package/scripts/lib/pch-regress-map.ts +23 -0
- package/scripts/morning-report.ts +18 -4
- package/scripts/pch-regress.ts +88 -0
- package/scripts/public-export-test-run.ts +37 -2
- package/scripts/release-loop/checklist-gate-node.ts +13 -11
- package/scripts/release-loop/cut-branch.ts +2 -1
- package/scripts/release-loop/cutoff.ts +4 -2
- package/scripts/release-loop/docs-land-node.ts +8 -1
- package/scripts/release-loop/docs-node.ts +1 -1
- package/scripts/release-loop/gate-diff.ts +18 -0
- package/scripts/release-loop/gate-node.ts +436 -59
- package/scripts/release-loop/gate-partial.ts +106 -0
- package/scripts/release-loop/gate-timing.ts +120 -0
- package/scripts/release-loop/node-verdict.ts +2 -1
- package/scripts/release-loop/npm-publish-node.ts +11 -7
- package/scripts/release-loop/ops-upgrade-node.ts +8 -1
- package/scripts/release-loop/preflight.ts +246 -0
- package/scripts/release-loop/publish-node.ts +8 -1
- package/scripts/release-loop/release-readiness.ts +11 -6
- package/scripts/release-loop/release-version.ts +48 -0
- package/scripts/release-loop/resume-release.ts +174 -0
- package/scripts/release-loop/shard-plan.ts +65 -0
- package/scripts/release-loop/unattended-release.ts +45 -7
- package/scripts/release-loop/version-node.ts +145 -40
- package/scripts/rhythm/daily.ts +25 -4
- package/scripts/skills/public-check.ts +62 -12
- package/scripts/test-deterministic.ts +51 -33
- package/scripts/test-diet/effectiveness.ts +62 -1
- package/scripts/test-diet/lib.ts +1 -1
- package/scripts/test-diet/node.ts +8 -1
- package/scripts/video/scene-table.ts +159 -0
- package/src/acp/core-turn-bridge.ts +39 -2
- package/src/agent-mission/review-loop.ts +4 -3
- package/src/agent-substrate/pr-comment-meta.ts +20 -0
- package/src/autopilot/build/llm-conflict-merge.ts +28 -8
- package/src/away/presence.ts +40 -0
- package/src/away/release-watch.ts +255 -0
- package/src/briefing/brief-items.ts +86 -17
- package/src/chat/index.ts +2 -1
- package/src/chat/short-question.ts +3 -40
- package/src/cli/autopilot-cli.ts +30 -11
- package/src/cli/away-cli.ts +68 -0
- package/src/cli/brief-cli.ts +36 -2
- package/src/cli/freeze-cli.ts +3 -2
- package/src/cli/guardian-cli.ts +49 -0
- package/src/cli/intake-cli.ts +85 -7
- package/src/cli/log-event-names.ts +1 -0
- package/src/cli/notify-cli.ts +75 -0
- package/src/cli/pod-cli.ts +5 -1
- package/src/cli/provider-cli.ts +12 -2
- package/src/cli/pty-drive-cli.ts +14 -3
- package/src/cli/release-cli.ts +128 -19
- package/src/cli/setup-cli.ts +31 -1
- package/src/cli/tasks-cli.ts +403 -4
- package/src/context-bus/condense.ts +19 -3
- package/src/context-bus/context-day.ts +77 -24
- package/src/context-bus/context-first.ts +33 -0
- package/src/context-bus/context-now-public.ts +1 -1
- package/src/context-bus/context-now-surfaces.ts +16 -6
- package/src/context-bus/context-now.ts +97 -3
- package/src/core-turn/short-question.ts +100 -0
- package/src/dashboard/dashboard-status-lines.ts +24 -4
- package/src/dashboard/index.ts +50 -5
- package/src/dashboard/input/slash-executor.ts +6 -2
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +63 -36
- package/src/dashboard/slash-runtime/decide-slash.ts +60 -0
- package/src/dashboard/slash-runtime/help-from-registry.ts +21 -8
- package/src/dashboard/slash-runtime/help-groups.ts +44 -0
- package/src/dashboard/slash-runtime/model-choices.ts +125 -0
- package/src/discord-self-message.ts +20 -2
- package/src/discord-slash-wire.ts +1 -0
- package/src/domains/guardian-tick.ts +138 -0
- package/src/domains/outbound-alert.ts +244 -40
- package/src/domains/outbound-log-probe.ts +16 -1
- package/src/domains/release-tool.ts +2 -2
- package/src/domains/schedule-registry.ts +23 -0
- package/src/domains/telegram-kind-route.ts +39 -0
- package/src/domains/watch-default-scheduler.ts +95 -0
- package/src/esc-abort-gate.ts +44 -0
- package/src/execution-loop/gates.ts +11 -2
- package/src/flow-loop/split.ts +8 -4
- package/src/git-fs/worktree.ts +23 -3
- package/src/graph-runner/runner.ts +25 -5
- package/src/harness/harness-cli-command.ts +12 -2
- package/src/harness/harness-queue.ts +388 -33
- package/src/harness/harness-salvage-cli.ts +78 -0
- package/src/harness/harness-worktree-add.ts +68 -0
- package/src/harness/helper-scan.ts +10 -3
- package/src/harness/ledger-write-guard.ts +6 -16
- package/src/hq/hq.ts +6 -1
- package/src/hq/seats.ts +369 -0
- package/src/index.ts +185 -18
- package/src/instance/test-write-guard-spy-first.fixture.ts +13 -0
- package/src/instance/test-write-guard.ts +200 -0
- package/src/intake-plane/adopt-gate.ts +49 -0
- package/src/intake-plane/check.ts +3 -0
- package/src/intake-plane/collect-github.ts +57 -25
- package/src/intake-plane/digest.ts +39 -15
- package/src/intake-plane/discord-seat-work.ts +8 -2
- package/src/intake-plane/harness-target.ts +4 -3
- package/src/intake-plane/intake-sources.ts +1 -0
- package/src/intake-plane/items.ts +1 -0
- package/src/intake-plane/requirement-funnel.ts +316 -0
- package/src/knowledge/know-find.ts +10 -1
- package/src/loops/budget.ts +36 -0
- package/src/loops/orchestrator/degradation.ts +57 -0
- package/src/loops/orchestrator/finish-rate.ts +106 -4
- package/src/loops/orchestrator/grid-place.ts +11 -0
- package/src/loops/orchestrator/tick.ts +450 -54
- package/src/maturity/feature-maturity.ts +8 -5
- package/src/maturity/tui-slash-maturity.ts +1 -0
- package/src/mss/logging/log-store.ts +3 -0
- package/src/nexus/api/decisions-route.ts +11 -1
- package/src/nexus/api/http-server.ts +16 -5
- package/src/nexus/api/loop-edges.ts +352 -23
- package/src/nexus/api/ops-api.ts +96 -28
- package/src/nexus/api/ops-seats-sources.ts +2 -2
- package/src/nexus/api/workflow-templates.ts +3 -0
- package/src/nexus/index.ts +7 -0
- package/src/oauth/codex.ts +38 -0
- package/src/onboarding/first-chat-gate.ts +29 -0
- package/src/release-loop/checklist.ts +106 -6
- package/src/release-loop/feature-store.ts +64 -16
- package/src/release-loop/landing-freeze.ts +6 -4
- package/src/release-loop/light-rc.ts +173 -0
- package/src/release-loop/placement.ts +64 -20
- package/src/release-loop/rubric.ts +136 -0
- package/src/seat-dispatch/seat-ask.ts +79 -16
- package/src/seat-loop/seat-loop.ts +12 -6
- package/src/self-dev/ask-launch-flow.ts +24 -3
- package/src/self-dev/ask-path-candidates.ts +68 -0
- package/src/self-dev/dev-cli.ts +36 -0
- package/src/self-dev/dev-pipeline.ts +4 -0
- package/src/self-dev/draft-triage-rules.ts +1 -1
- package/src/self-dev/orchestrate-cli.ts +22 -0
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/pr-preview.ts +179 -0
- package/src/self-dev/round-pr-supersede.ts +244 -0
- package/src/self-dev/run-supervisor.ts +14 -0
- package/src/self-dev/shard-run.ts +23 -7
- package/src/self-implement/follow-up-goals.ts +2 -2
- package/src/self-implement/gate-cli.ts +29 -8
- package/src/self-implement/gate-remote.ts +427 -0
- package/src/self-implement/goal-author-clarification.ts +88 -13
- package/src/self-implement/goal-author.ts +8 -3
- package/src/self-implement/goal-clarification-escalation.ts +2 -0
- package/src/self-implement/l8-merge-queue.ts +29 -5
- package/src/self-implement/orchestrator.ts +61 -13
- package/src/self-implement/prior-draft-findings.ts +4 -3
- package/src/self-implement/salvage-branches.ts +254 -0
- package/src/skills/skill-feedback.ts +76 -0
- package/src/task-agent/actions.ts +101 -7
- package/src/task-agent/board.ts +132 -0
- package/src/task-agent/card-evidence.ts +203 -0
- package/src/task-agent/completion-evidence.ts +126 -0
- package/src/task-agent/judge.ts +49 -5
- package/src/task-agent/live-moves.ts +176 -0
- package/src/task-agent/mission.ts +449 -0
- package/src/task-agent/shadow.ts +258 -0
- package/src/task-agent/task-hand.ts +337 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +64 -4
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +10 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +142 -13
- package/src/task-orchestrator/surfaces/pod-pool.ts +13 -5
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +88 -20
- package/src/telegram-away-command.ts +38 -0
- package/src/telegram-commands.ts +11 -0
- package/src/telegram-loops-command.ts +1 -1
- package/src/telegram-report-log-probe.ts +21 -0
- package/src/telegram-report.ts +27 -3
- package/src/telegram.ts +5 -20
- package/src/tui-client/dashboard-session.ts +1 -0
- package/src/user-config.ts +196 -4
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-aac7332576c4d6fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1844-9ec4b1d12f6e80eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1948.15f356b15a625597.js +0 -5
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
- package/apps/pwa/out/_next/static/chunks/224-798346143007ff65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2699-63b73fa4d3bcf6ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4144-a0041c8dc3be57ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4554-3565eea1f1495ba7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4614-21403aac730d4586.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5135-44008fe8b1f2aa41.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5233-bf28bd6bd7a32099.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5994-ae92c0de046ab9ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6158.9c0449a9a8d0064b.js +0 -2
- package/apps/pwa/out/_next/static/chunks/6877-fe94e76a5841ee9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7395-164e238f471b5d7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7787-02a1c0b04e25e811.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8401-4ce1c42c8d89903f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8868-10a3a4440fb0ccd8.js +0 -25
- package/apps/pwa/out/_next/static/chunks/8949-ecb4128a0858b911.js +0 -1
- package/apps/pwa/out/_next/static/chunks/899-f41be85e8a680651.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-7865aba0f4d2ee49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3143b07a817d1da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-17ba086ef82d339b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-7eb661ff23af7da2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-6b8444914da74ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-6e5c3a867557298b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-7110f732f45bf944.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9a41d65355fc25b9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-5e77cd1802567c89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-41afec0b255ed2bb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-4187666132fc98c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-09328d499162bae4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-29ff3a8f84f03b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-80ec7401bc83f511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ab93b240f687d69a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-fc7d86467291ae38.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-de43a186e5ba5683.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8b08cafad27759c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-0e2d6985fb42cd2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-13e4108999f58d13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e8296ee284aa1293.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-043a9111e74f6b24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-23a4601ceb7f452e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1ed1324b1dc36754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-10d958605a77b3bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-166745e51ac0c7b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-a04260b8ccc968d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-7a1d85e121065cc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-1f50e3d4e13435f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-12916918988ac97e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d8a3347a9d0c3f4a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-a9117d2cd3093d36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-5a64cb5208c6a8fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1407ec83ea64c1f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-1d824510df025d18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-6e878ebbe1737d00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-7f49fe645d5132f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-81a4e7f8dbfe74cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-27d71f131acd9320.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-3ab59d19913b200e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-bf85b2f5bf077925.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-424659bacfb8cdd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ab32a8f522a60371.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-fc2df261f8a2c7df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-09461366af82ef13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5d4fef9ccd7d406b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ea90a8ac73ce2749.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-539cde99554be20f.js +0 -1
- package/apps/pwa/out/_next/static/css/001d5fbaee388a25.css +0 -1
- package/apps/pwa/out/_next/static/yRA5ur6DcPl0YHSRheH2O/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{yRA5ur6DcPl0YHSRheH2O → J5H7BvqgSI8DUjtRRcA_S}/_ssgManifest.js +0 -0
package/src/cli/brief-cli.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
|
-
import { BRIEF_DOMAINS, BRIEF_PRIORITIES, BRIEF_SLOTS, BriefItemsInputError, BriefItemsLedger, type BriefDomain, type BriefPriority } from '../briefing/brief-items.js';
|
|
2
|
+
import { BRIEF_DOMAINS, BRIEF_PRIORITIES, BRIEF_SLOTS, BriefItemsInputError, BriefItemsLedger, type BriefDomain, type BriefPriority, type BriefSlot } from '../briefing/brief-items.js';
|
|
3
|
+
import { kindRouteTarget } from '../domains/telegram-kind-route.js';
|
|
4
|
+
import { sendTelegramReturningId } from '../autopilot/mission-notify.js';
|
|
5
|
+
import { getUserConfig } from '../user-config.js';
|
|
3
6
|
|
|
4
7
|
export interface BriefCliDeps {
|
|
5
8
|
ledger?: BriefItemsLedger;
|
|
@@ -7,6 +10,7 @@ export interface BriefCliDeps {
|
|
|
7
10
|
now?: () => Date;
|
|
8
11
|
output?: (line: string) => void;
|
|
9
12
|
error?: (line: string) => void;
|
|
13
|
+
send?: (markdown: string) => number | null;
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
export function registerBriefCommands(program: Command, deps: BriefCliDeps = {}): void {
|
|
@@ -20,7 +24,7 @@ export function registerBriefCommands(program: Command, deps: BriefCliDeps = {})
|
|
|
20
24
|
error(`brief ${verb}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
21
25
|
process.exitCode = cause instanceof BriefItemsInputError ? 2 : 1;
|
|
22
26
|
};
|
|
23
|
-
const brief = program.command('brief').description('대표 브리핑 항목
|
|
27
|
+
const brief = program.command('brief').description('대표 브리핑 항목 원장과 슬롯 발송');
|
|
24
28
|
|
|
25
29
|
brief.command('add')
|
|
26
30
|
.description('주장 한 줄을 원장에 추가한다 (원문 그대로)')
|
|
@@ -70,4 +74,34 @@ export function registerBriefCommands(program: Command, deps: BriefCliDeps = {})
|
|
|
70
74
|
try { output(ledger().compose(opts.slot)); }
|
|
71
75
|
catch (cause) { fail('compose', cause); }
|
|
72
76
|
});
|
|
77
|
+
|
|
78
|
+
brief.command('send')
|
|
79
|
+
.description('슬롯 이전의 미발송 항목을 한 장 발송하고 성공한 항목만 표시한다')
|
|
80
|
+
.requiredOption('--slot <slot>', `슬롯 (${BRIEF_SLOTS.join('|')})`)
|
|
81
|
+
.option('--dry-run', '한 장만 출력하고 발송·표시하지 않는다')
|
|
82
|
+
.action((opts: { slot: string; dryRun?: boolean }) => {
|
|
83
|
+
try {
|
|
84
|
+
const store = ledger();
|
|
85
|
+
if (opts.dryRun) {
|
|
86
|
+
const { markdown, ids } = store.composeWithIds(opts.slot);
|
|
87
|
+
output(ids.length === 0 ? '(보낼 항목 없음)' : markdown);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const result = store.withSendLock(opts.slot, ({ markdown, ids }, markSent) => {
|
|
91
|
+
if (ids.length === 0) return '(보낼 항목 없음)';
|
|
92
|
+
const send = deps.send ?? ((text: string) => {
|
|
93
|
+
const target = kindRouteTarget(getUserConfig(), 'ops-report');
|
|
94
|
+
if (!target) return null;
|
|
95
|
+
return sendTelegramReturningId(target.botToken, target.chatId, text);
|
|
96
|
+
});
|
|
97
|
+
const messageId = send(markdown);
|
|
98
|
+
if (typeof messageId !== 'number' || !Number.isFinite(messageId) || messageId <= 0) {
|
|
99
|
+
throw new Error('발송 실패: 양수 메시지 id 없음');
|
|
100
|
+
}
|
|
101
|
+
markSent(ids, opts.slot as BriefSlot);
|
|
102
|
+
return `sent ${messageId} (${ids.length} items)`;
|
|
103
|
+
});
|
|
104
|
+
output(result);
|
|
105
|
+
} catch (cause) { fail('send', cause); }
|
|
106
|
+
});
|
|
73
107
|
}
|
package/src/cli/freeze-cli.ts
CHANGED
|
@@ -7,8 +7,9 @@ import { pendingFrozenMerges, sweepFrozenMerges } from '../self-implement/frozen
|
|
|
7
7
|
export function registerFreezeCommands(program: Command): void {
|
|
8
8
|
const freeze = program.command('freeze').description('착지 동결 상태 on/off/status');
|
|
9
9
|
freeze.command('on').option('--reason <text>', '동결 이유').option('--until <timestamp>', '끝 시각(타임존 포함 ISO)')
|
|
10
|
+
.option('--hold-launches', '착지와 함께 새 하니스 launch도 보류')
|
|
10
11
|
.option('--wait-seconds <n>', '이미 동결 검사를 지난 병합이 끝나기를 기다릴 최대 초', '600')
|
|
11
|
-
.action(async (opts: { reason?: string; until?: string; waitSeconds: string }) => {
|
|
12
|
+
.action(async (opts: { reason?: string; until?: string; holdLaunches?: boolean; waitSeconds: string }) => {
|
|
12
13
|
const waitSeconds = Number(opts.waitSeconds);
|
|
13
14
|
if (!/^\d+$/.test(opts.waitSeconds.trim()) || !Number.isSafeInteger(waitSeconds) || waitSeconds > 86_400) {
|
|
14
15
|
throw new CliUserError(`잘못된 --wait-seconds: ${opts.waitSeconds}`, '0 이상 86400 이하의 정수 초');
|
|
@@ -34,7 +35,7 @@ export function registerFreezeCommands(program: Command): void {
|
|
|
34
35
|
const state = readLandingFreeze();
|
|
35
36
|
const pending = pendingFrozenMerges();
|
|
36
37
|
if (opts.json) console.log(JSON.stringify({ frozen: state !== null, freeze: state, pendingMerges: pending }));
|
|
37
|
-
else console.log(`${state ? landingFreezeMessage(state) : '동결 없음'} · 보류 병합 ${pending}건`);
|
|
38
|
+
else console.log(`${state ? landingFreezeMessage(state) : '동결 없음'} · launch 보류 ${state?.holdLaunches === true ? '예' : '아니오'} · 보류 병합 ${pending}건`);
|
|
38
39
|
});
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Database } from 'bun:sqlite';
|
|
3
|
+
import type { GuardianPlan } from '../domains/guardian-tick.js';
|
|
4
|
+
import { getUserConfig } from '../user-config.js';
|
|
5
|
+
import { writeStdoutJson } from './stdout-json.js';
|
|
6
|
+
|
|
7
|
+
// Domain modules (schedules.db · schedule-runner → node-cron) load lazily inside the actions,
|
|
8
|
+
// so registering `guardian` adds no static dependency to the CLI boot path.
|
|
9
|
+
async function guardianPlan(): Promise<{ db: Database; plan: GuardianPlan }> {
|
|
10
|
+
const { listSchedules, openSchedulesDb } = await import('../domains/schedule-registry.js');
|
|
11
|
+
const db = openSchedulesDb();
|
|
12
|
+
try {
|
|
13
|
+
return { db, plan: { jobs: listSchedules(db) } };
|
|
14
|
+
} catch (error) {
|
|
15
|
+
db.close();
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function registerGuardianCommands(program: Command): void {
|
|
21
|
+
const guardian = program.command('guardian').description('크론 수호자 그림자 관측(기존 크론·알림 무변경)');
|
|
22
|
+
guardian.command('tick').description('현재 시각에 발화했을 잡을 관측(잡은 실행하지 않음)')
|
|
23
|
+
.action(async () => {
|
|
24
|
+
const { guardianTick } = await import('../domains/guardian-tick.js');
|
|
25
|
+
const { db, plan } = await guardianPlan();
|
|
26
|
+
try {
|
|
27
|
+
const cfg = getUserConfig();
|
|
28
|
+
// Live activation (and crontab retirement) is a separate operational change.
|
|
29
|
+
if (cfg.guardian?.mode === 'live') throw new Error('guardian live activation is outside GUARD-ONE-a');
|
|
30
|
+
const result = await guardianTick(new Date(), plan, { config: cfg });
|
|
31
|
+
await writeStdoutJson(JSON.stringify(result, null, 2) + '\n');
|
|
32
|
+
} finally { db.close(); }
|
|
33
|
+
});
|
|
34
|
+
guardian.command('compare').description('하루의 예정 발화와 기록된 실제 발화 비교')
|
|
35
|
+
.requiredOption('--day <YYYY-MM-DD>', '비교할 달력 날짜')
|
|
36
|
+
.option('--json', 'JSON 출력')
|
|
37
|
+
.action(async (opts: { day: string; json?: boolean }) => {
|
|
38
|
+
const { guardianShadowDay } = await import('../domains/guardian-tick.js');
|
|
39
|
+
const { db, plan } = await guardianPlan();
|
|
40
|
+
try {
|
|
41
|
+
const result = guardianShadowDay(opts.day, { db, plan });
|
|
42
|
+
if (opts.json) await writeStdoutJson(JSON.stringify(result, null, 2) + '\n');
|
|
43
|
+
else {
|
|
44
|
+
console.log(`guardian ${result.day}: ${result.same ? 'same' : 'diff'} (현재 레지스트리 cron·활성 기준 재계산 · alertsActual=null: 발송 수 미측정)`);
|
|
45
|
+
for (const row of result.jobs) console.log(` ${row.job}: would=${row.would} actual=${row.actual} alertsActual=${row.alertsActual ?? '미측정'}`);
|
|
46
|
+
}
|
|
47
|
+
} finally { db.close(); }
|
|
48
|
+
});
|
|
49
|
+
}
|
package/src/cli/intake-cli.ts
CHANGED
|
@@ -12,6 +12,9 @@ import { runGitCommand } from '../git-fs/runner.js';
|
|
|
12
12
|
import { debug } from '../debug/log.js';
|
|
13
13
|
import { getUserConfig } from '../user-config.js';
|
|
14
14
|
import { registerIntakeSourceCommands } from './intake-source-cli.js';
|
|
15
|
+
import type { IntakeItem } from '../intake-plane/items.js';
|
|
16
|
+
import type { TaskCard } from '../task-cards/card-store.js';
|
|
17
|
+
import { collectFunnelCandidates, type FunnelDirectiveRow } from '../intake-plane/requirement-funnel.js';
|
|
15
18
|
|
|
16
19
|
export interface IntakeToTasksCliDeps {
|
|
17
20
|
root: string;
|
|
@@ -21,6 +24,63 @@ export interface IntakeToTasksCliDeps {
|
|
|
21
24
|
llm?: (input: IntakeTaskInput) => Promise<string>;
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
export interface IntakeCandidatesCliDeps {
|
|
28
|
+
directives?: () => FunnelDirectiveRow[] | Promise<FunnelDirectiveRow[]>;
|
|
29
|
+
intakeItems?: () => IntakeItem[] | Promise<IntakeItem[]>;
|
|
30
|
+
cards?: () => TaskCard[] | Promise<TaskCard[]>;
|
|
31
|
+
write?: (text: string) => Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** `--limit` 원 문자열 → 0 이상의 정수. 숫자만(`/^\d+$/`) 받고 나머지('' · 공백 · 음수 · 소수)는 거부한다. */
|
|
35
|
+
export function parseCandidatesLimit(raw: string): number {
|
|
36
|
+
const limit = /^\d+$/.test(raw) ? Number(raw) : NaN;
|
|
37
|
+
if (!Number.isSafeInteger(limit)) throw new Error(`--limit 는 0 이상의 정수여야 한다: ${JSON.stringify(raw)}`);
|
|
38
|
+
return limit;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runIntakeCandidatesCli(
|
|
42
|
+
opts: { json?: boolean; limit?: string },
|
|
43
|
+
deps: IntakeCandidatesCliDeps = {},
|
|
44
|
+
): Promise<void> {
|
|
45
|
+
// 원 문자열을 «먼저» 본다 — `Number('')`·`Number(' ')` 는 0 이라 빈 목록으로 조용히 통과한다.
|
|
46
|
+
const limit = opts.limit === undefined ? undefined : parseCandidatesLimit(opts.limit);
|
|
47
|
+
const directives = deps.directives ?? (async () => {
|
|
48
|
+
const [{ Database }, { existsSync }, { directiveDbPath }] = await Promise.all([
|
|
49
|
+
// The directive index is excluded from the public export; load it at run time only (proact-meter · know-find pattern).
|
|
50
|
+
import('bun:sqlite'), import('node:fs'), import(['..', 'directives', 'directive-index.js'].join('/')) as Promise<{ directiveDbPath: () => string }>,
|
|
51
|
+
]);
|
|
52
|
+
const path = directiveDbPath();
|
|
53
|
+
if (!existsSync(path)) return [];
|
|
54
|
+
const db = new Database(path, { readonly: true });
|
|
55
|
+
try { return db.query('SELECT * FROM directives ORDER BY ts DESC').all() as FunnelDirectiveRow[]; }
|
|
56
|
+
finally { db.close(); }
|
|
57
|
+
});
|
|
58
|
+
const intakeItems = deps.intakeItems ?? (async () => {
|
|
59
|
+
const [{ listIntakeItems }, { effectiveInstanceRoot }] = await Promise.all([
|
|
60
|
+
import('../intake-plane/items.js'), import('../instance/resolve.js'),
|
|
61
|
+
]);
|
|
62
|
+
return listIntakeItems(effectiveInstanceRoot());
|
|
63
|
+
});
|
|
64
|
+
const cards = deps.cards ?? (async () => {
|
|
65
|
+
const [{ existsSync }, { CardStore, cardIndexPath }] = await Promise.all([
|
|
66
|
+
import('node:fs'), import('../task-cards/card-store.js'),
|
|
67
|
+
]);
|
|
68
|
+
if (!existsSync(cardIndexPath())) return [];
|
|
69
|
+
const store = new CardStore(undefined, true);
|
|
70
|
+
try { return store.listCards({ open: true }); }
|
|
71
|
+
finally { store.close(); }
|
|
72
|
+
});
|
|
73
|
+
const all = collectFunnelCandidates({
|
|
74
|
+
directives: await directives(), intakeItems: await intakeItems(), cards: await cards(),
|
|
75
|
+
});
|
|
76
|
+
const candidates = limit === undefined ? all : all.slice(0, limit);
|
|
77
|
+
if (opts.json) await (deps.write ?? writeStdoutFully)(JSON.stringify({ candidates }) + '\n');
|
|
78
|
+
else await (deps.write ?? writeStdoutFully)([
|
|
79
|
+
`요구 후보 ${candidates.length}건`,
|
|
80
|
+
...candidates.map((row) => `${row.source}\t${row.id}\t${row.score ?? '-'}\t${row.grade ?? '-'}\t${row.title}`),
|
|
81
|
+
].join('\n') + '\n');
|
|
82
|
+
}
|
|
83
|
+
|
|
24
84
|
export interface IntakeDigestCliDeps {
|
|
25
85
|
root?: string;
|
|
26
86
|
annotateLens?: (root: string, day: string) => Promise<unknown>;
|
|
@@ -85,14 +145,15 @@ export async function runIntakeToTasksCli(
|
|
|
85
145
|
|
|
86
146
|
/** `--telegram` 다이제스트. 렌즈는 digest 를 만들기 전에 돈다. 렌즈 실패는 보고를 막지 않는다. */
|
|
87
147
|
export async function runIntakeDigestCli(
|
|
88
|
-
opts: { day?: string; json?: boolean; telegram?: boolean; vault?: string; note?: string },
|
|
148
|
+
opts: { day?: string; json?: boolean; telegram?: boolean; vault?: string; note?: string; seat?: string },
|
|
89
149
|
deps: IntakeDigestCliDeps = {},
|
|
90
150
|
): Promise<{ sent?: boolean; empty?: boolean }> {
|
|
91
|
-
const { buildIntakeDigest, renderDigestMarkdown, renderDigestTelegram } = await import('../intake-plane/digest.js');
|
|
151
|
+
const { buildIntakeDigest, recordSeatBriefed, renderDigestMarkdown, renderDigestTelegram } = await import('../intake-plane/digest.js');
|
|
92
152
|
const { effectiveInstanceRoot } = await import('../instance/resolve.js');
|
|
93
153
|
const root = deps.root ?? effectiveInstanceRoot();
|
|
94
154
|
const day = opts.day ?? new Date(Date.now() + 9 * 3600_000).toISOString().slice(0, 10);
|
|
95
|
-
|
|
155
|
+
// A seat briefing ignores lens rows (digest drops them), so it does not pay for a lens pass over other seats' items.
|
|
156
|
+
if (opts.telegram && opts.seat === undefined) {
|
|
96
157
|
const annotate = deps.annotateLens ?? (async (lensRoot, lensDay) => {
|
|
97
158
|
const { annotateIntakeLens } = await import('../intake-plane/lens.js');
|
|
98
159
|
return annotateIntakeLens(lensRoot, lensDay);
|
|
@@ -100,9 +161,10 @@ export async function runIntakeDigestCli(
|
|
|
100
161
|
try { await annotate(root, day); }
|
|
101
162
|
catch (error) { debug.log('intake.lens', 'annotate-failed', { day, reason: error instanceof Error ? error.message : String(error) }); }
|
|
102
163
|
}
|
|
103
|
-
const
|
|
164
|
+
const seat = opts.seat === undefined ? undefined : (await import('../intake-plane/intake-sources.js')).canonicalSeat(opts.seat);
|
|
165
|
+
const d = (deps.buildDigest ?? buildIntakeDigest)(root, day, undefined, undefined, seat);
|
|
104
166
|
if (opts.telegram) {
|
|
105
|
-
if (!d.absorbed.length && !d.news?.length) { console.log(`텔레그램: ${day} 흡수 0 — 보내지 않음`); return { empty: true }; }
|
|
167
|
+
if (!seat && !d.absorbed.length && !d.news?.length) { console.log(`텔레그램: ${day} 흡수 0 — 보내지 않음`); return { empty: true }; }
|
|
106
168
|
const text = renderDigestTelegram(d, { ...(opts.vault ? { vaultRoot: opts.vault } : {}), ...(opts.note ? { notePath: opts.note } : {}) });
|
|
107
169
|
const sent = deps.sendTelegram
|
|
108
170
|
? await deps.sendTelegram(text)
|
|
@@ -112,6 +174,8 @@ export async function runIntakeDigestCli(
|
|
|
112
174
|
return sendTelegramReport(getUserConfig(), text, { markdown: true, kind: 'intake' });
|
|
113
175
|
})();
|
|
114
176
|
debug.log('intake.digest', 'telegram', { day, absorbed: d.absorbed.length, goals: d.goals.length, sent });
|
|
177
|
+
if (seat && sent) recordSeatBriefed(root, seat, day, d.absorbed.map((entry) => entry.id));
|
|
178
|
+
if (seat === 'user') debug.log('watch.default', 'brief', { topics: (await import('../intake-plane/intake-sources.js')).listSources({ seat }, root).length, items: d.absorbed.length, sent });
|
|
115
179
|
console.log(sent ? `텔레그램 보고 채널로 보냈다 (${day} · 흡수 ${d.absorbed.length} · 골 후보 ${d.goals.length})` : '텔레그램 보고 채널 설정이 없다(telegram.reportChannel) — 보내지 않음');
|
|
116
180
|
if (!sent) process.exitCode = 3;
|
|
117
181
|
return { sent };
|
|
@@ -134,7 +198,7 @@ export function resolveIntakeCheckRoot(
|
|
|
134
198
|
}
|
|
135
199
|
}
|
|
136
200
|
|
|
137
|
-
export function registerIntakeCommands(program: Command): void {
|
|
201
|
+
export function registerIntakeCommands(program: Command, candidateDeps: IntakeCandidatesCliDeps = {}): void {
|
|
138
202
|
// ── intake check — 바깥 사실을 elanous 현재와 대조 (태스크 등록 없음) ──
|
|
139
203
|
const intakeCmd = program.command('intake').description('바깥 사실·문서를 elanous 현재와 대조하거나 태스크로 받는다');
|
|
140
204
|
registerIntakeSourceCommands(intakeCmd);
|
|
@@ -229,6 +293,19 @@ export function registerIntakeCommands(program: Command): void {
|
|
|
229
293
|
}
|
|
230
294
|
});
|
|
231
295
|
|
|
296
|
+
intakeCmd
|
|
297
|
+
.command('candidates')
|
|
298
|
+
.description('지시·흡수·소원에서 읽기 전용 요구 후보를 모은다')
|
|
299
|
+
.option('--json', '구조화 출력')
|
|
300
|
+
.option('--limit <n>', '출력할 후보 상한')
|
|
301
|
+
.action(async (opts: { json?: boolean; limit?: string }) => {
|
|
302
|
+
if (opts.limit !== undefined) {
|
|
303
|
+
try { parseCandidatesLimit(opts.limit); }
|
|
304
|
+
catch (error) { console.error((error as Error).message); process.exitCode = 2; return; }
|
|
305
|
+
}
|
|
306
|
+
await runIntakeCandidatesCli(opts, candidateDeps);
|
|
307
|
+
});
|
|
308
|
+
|
|
232
309
|
// 정기 외부 흡수 원장 — RFC-regular-external-intake-and-normalization-pipeline §3 (① 모양 · ② 중복).
|
|
233
310
|
intakeCmd
|
|
234
311
|
.command('collect-pod <dir>')
|
|
@@ -325,9 +402,10 @@ export function registerIntakeCommands(program: Command): void {
|
|
|
325
402
|
.option('--day <YYYY-MM-DD>', 'KST 날짜 (기본 오늘)')
|
|
326
403
|
.option('--json', '구조화 출력')
|
|
327
404
|
.option('--telegram', '텔레그램 보고 채널(telegram.reportChannel)로 짧은 판을 보낸다')
|
|
405
|
+
.option('--seat <id>', '자리 id (user 아침 브리핑)')
|
|
328
406
|
.option('--vault <root>', '옵시디언 볼트 뿌리 — 텔레그램 판에 노트 열기 주소를 싣는다')
|
|
329
407
|
.option('--note <path>', '열기 주소가 가리킬 노트(그날 트렌드 노트)')
|
|
330
|
-
.action(async (opts: { day?: string; json?: boolean; telegram?: boolean; vault?: string; note?: string }) => {
|
|
408
|
+
.action(async (opts: { day?: string; json?: boolean; telegram?: boolean; vault?: string; note?: string; seat?: string }) => {
|
|
331
409
|
await runIntakeDigestCli(opts);
|
|
332
410
|
});
|
|
333
411
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { inQuietHours, sendOutbound, userRecentlyActive } from '../domains/outbound-alert.js';
|
|
3
|
+
import { isTradingKind } from '../domains/telegram-kind-route.js';
|
|
4
|
+
|
|
5
|
+
export type NotifyPlan = { ok: true; kind: string } | { ok: false; exitCode: 2; message: string };
|
|
6
|
+
|
|
7
|
+
export function planNotify({ kind = 'op-report', text }: { kind?: string; text: string }): NotifyPlan {
|
|
8
|
+
if (isTradingKind(kind)) {
|
|
9
|
+
return { ok: false, exitCode: 2, message: `매매 kind(${kind})는 운영 보고에 쓸 수 없습니다 — op-report 또는 ops-alert 를 쓰세요` };
|
|
10
|
+
}
|
|
11
|
+
if (!kind.trim() || /[\r\n]/.test(kind)) {
|
|
12
|
+
return { ok: false, exitCode: 2, message: 'kind 가 비었거나 줄바꿈을 포함합니다 — op-report 또는 ops-alert 를 쓰세요' };
|
|
13
|
+
}
|
|
14
|
+
if (!text.trim()) return { ok: false, exitCode: 2, message: '본문이 비었습니다 — elanous notify <text...> 또는 --stdin' };
|
|
15
|
+
return { ok: true, kind };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface NotifyCliDeps {
|
|
19
|
+
send?: (text: string, kind: string) => boolean | Promise<boolean>;
|
|
20
|
+
quiet?: () => boolean;
|
|
21
|
+
readStdin?: () => Promise<string>;
|
|
22
|
+
output?: (line: string) => void;
|
|
23
|
+
error?: (line: string) => void;
|
|
24
|
+
setExitCode?: (code: number) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function registerNotifyCommand(program: Command, deps: NotifyCliDeps = {}): void {
|
|
28
|
+
const send = deps.send ?? sendOutbound;
|
|
29
|
+
const quiet = deps.quiet ?? (() => inQuietHours() && !userRecentlyActive());
|
|
30
|
+
const readStdin = deps.readStdin ?? (async () => {
|
|
31
|
+
if (process.stdin.isTTY) throw new Error('--stdin requires redirected input');
|
|
32
|
+
const chunks: Buffer[] = [];
|
|
33
|
+
for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
|
|
34
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
35
|
+
});
|
|
36
|
+
const output = deps.output ?? ((line: string) => console.log(line));
|
|
37
|
+
const error = deps.error ?? ((line: string) => console.error(line));
|
|
38
|
+
const setExitCode = deps.setExitCode ?? ((code: number) => { process.exitCode = code; });
|
|
39
|
+
|
|
40
|
+
program.command('notify [text...]')
|
|
41
|
+
.description('대표에게 운영 보고를 발송한다 (기본 kind: op-report)')
|
|
42
|
+
.option('--kind <kind>', '운영 알림 kind (매매 report|alert|digest 거부)')
|
|
43
|
+
.option('--stdin', '본문을 표준 입력에서 읽는다')
|
|
44
|
+
.option('--json', '결과를 JSON 한 줄로 출력한다')
|
|
45
|
+
.action(async (parts: string[], opts: { kind?: string; stdin?: boolean; json?: boolean }) => {
|
|
46
|
+
const kind = opts.kind ?? 'op-report';
|
|
47
|
+
if (opts.stdin && parts.length) {
|
|
48
|
+
if (opts.json) output(JSON.stringify({ ok: false, kind, chars: 0, deferred: false }));
|
|
49
|
+
else error('--stdin 과 본문 인자는 함께 쓸 수 없습니다');
|
|
50
|
+
setExitCode(2);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const text = opts.stdin ? await readStdin() : parts.join(' ');
|
|
55
|
+
const plan = planNotify({ kind, text });
|
|
56
|
+
if (!plan.ok) {
|
|
57
|
+
if (opts.json) output(JSON.stringify({ ok: false, kind, chars: [...text].length, deferred: false }));
|
|
58
|
+
else error(plan.message);
|
|
59
|
+
setExitCode(plan.exitCode);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const deferred = quiet();
|
|
63
|
+
const ok = await send(text, plan.kind);
|
|
64
|
+
const chars = [...text].length;
|
|
65
|
+
if (opts.json) output(JSON.stringify({ ok, kind: plan.kind, chars, deferred: ok && deferred }));
|
|
66
|
+
else if (ok) output(`${deferred ? '보류됨' : '보냄'}(${plan.kind}) · ${chars}자`);
|
|
67
|
+
else error(`못 보냄(${plan.kind}) — elanous logs --category outbound.send 로 확인`);
|
|
68
|
+
setExitCode(ok ? 0 : 1);
|
|
69
|
+
} catch {
|
|
70
|
+
if (opts.json) output(JSON.stringify({ ok: false, kind, chars: 0, deferred: false }));
|
|
71
|
+
else error(`못 보냄(${kind}) — elanous logs --category outbound.send 로 확인`);
|
|
72
|
+
setExitCode(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
package/src/cli/pod-cli.ts
CHANGED
|
@@ -71,7 +71,7 @@ export function registerPodCommands(program: Command, deps: PodCliDeps = {}): vo
|
|
|
71
71
|
const current = spec ? null : kubectl(['config', 'current-context']);
|
|
72
72
|
const context = spec ?? (current?.status === 0 ? current.stdout.trim() : '');
|
|
73
73
|
const members = context ? parsePodPool(context) : [];
|
|
74
|
-
const measure: PoolLeaseMeasure = members.length ? measurePoolLease(members, { kubectl, dns: (context) => (deps.dns ?? probePoolDns)(context, kubectl) }) : { members: [] };
|
|
74
|
+
const measure: PoolLeaseMeasure = members.length ? measurePoolLease(members, { kubectl, dns: (context) => (deps.dns ?? probePoolDns)(context, kubectl), measureUsage: true }) : { members: [] };
|
|
75
75
|
let accounts: number | null = null;
|
|
76
76
|
let accountReason: string | null = null;
|
|
77
77
|
try { accounts = (deps.accounts ?? (() => listCodexAccountsInStore().length))(); }
|
|
@@ -96,6 +96,10 @@ export function registerPodCommands(program: Command, deps: PodCliDeps = {}): vo
|
|
|
96
96
|
}
|
|
97
97
|
io.log(`실측 점유: ${measure.members.map((m) => `${m.context} ${m.running === null || m.pending === null ? '못 쟀다' : m.running + m.pending}/${m.capacity}`).join(' · ') || '?'}`);
|
|
98
98
|
io.log(`권장 지금 ${decision.recommended ?? '?'} 개 더 (limitedBy=${decision.limitedBy ?? 'unknown'})${decision.reason ? ` · ${decision.reason}` : ''}`);
|
|
99
|
+
if (decision.admission) {
|
|
100
|
+
const g = (v: number | null) => v === null ? '?' : `${(v / 1024 ** 3).toFixed(1)}Gi`;
|
|
101
|
+
io.log(`골당 입장 ${g(decision.admission.admitBytes)} (실사용 표본 ${decision.admission.samples} · p95 ${g(decision.admission.p95Bytes)}${decision.admission.fallback ? ` · 폴백: ${decision.admission.fallback}` : ''})`);
|
|
102
|
+
}
|
|
99
103
|
io.log(`예약(저작 중) ${host.reserved} · 대기 Job ${waitingJobs ?? '?'} · 실행 ${decision.running ?? '?'}`);
|
|
100
104
|
io.log(`임대 없는 실행 ${decision.unleasedRunning ?? '?'}`);
|
|
101
105
|
io.log(`capacity: ${decision.capacitySlots ?? '?'} 칸 (상한 ${members.reduce((sum, m) => sum + m.capacity, 0)} − Running ${decision.running ?? '?'} − Pending ${decision.pending ?? '?'}; 권장 수에서 건강한 멤버의 임대 없는 실행 차감)`);
|
package/src/cli/provider-cli.ts
CHANGED
|
@@ -398,8 +398,18 @@ export function registerProviderCommands(program: Command): void {
|
|
|
398
398
|
.command('refresh <name>')
|
|
399
399
|
.description('그 계정의 codex 토큰을 호스트에서 갱신해 정본 스토어로 반영한다 (⛔ default 거부 · 토큰 값은 안 찍는다 · ⚠️ refresh 토큰은 갱신마다 회전 — 본부 한 곳에서만)')
|
|
400
400
|
.action(async (name: string) => {
|
|
401
|
-
const { refreshCodexAccountHome } = await import('../oauth/codex.js');
|
|
402
|
-
|
|
401
|
+
const { refreshCodexAccountHome, codexAccountRefreshLockPath, withCodexAccountRefreshLock, CodexRefreshLockUnavailableError } = await import('../oauth/codex.js');
|
|
402
|
+
// PREREFRESH-LOCK: the same per-account lock as the Pod pre-refresh — a hand refresh never races a launch.
|
|
403
|
+
// 이름 있는 계정의 잠금 자리를 못 구하면 잠금 없이 갱신하지 않는다(Pod 선갱신과 경합하는 자리) — default 는 refreshCodexAccountHome 이 거부한다.
|
|
404
|
+
const lockPath = name === 'default' ? null : codexAccountRefreshLockPath(name);
|
|
405
|
+
if (name !== 'default' && !lockPath) { console.error(`갱신 거부: ${name} 의 잠금 자리를 못 구했다(계정 홈 없음) — 잠금 없이 갱신하지 않는다`); process.exitCode = 1; return; }
|
|
406
|
+
let r: Awaited<ReturnType<typeof refreshCodexAccountHome>>;
|
|
407
|
+
try { r = await withCodexAccountRefreshLock(lockPath, () => refreshCodexAccountHome(name)); }
|
|
408
|
+
catch (lockError) {
|
|
409
|
+
if (!(lockError instanceof CodexRefreshLockUnavailableError)) throw lockError;
|
|
410
|
+
const why = lockError.reason === 'lock-timeout' ? '다른 갱신이 진행 중 — 잠시 뒤 다시' : `잠금 파일을 못 만들었다: ${lockError.message}`;
|
|
411
|
+
console.error(`갱신 거부: ${name} 의 갱신 잠금을 못 잡았다(${why})`); process.exitCode = 1; return;
|
|
412
|
+
}
|
|
403
413
|
if (!r.ok) { console.error(`갱신 실패(${r.kind}): ${r.message}`); process.exitCode = 1; return; }
|
|
404
414
|
const h = (v: number | null) => (v === null ? '?' : `${v}h`);
|
|
405
415
|
console.log(`✅ ${name} 갱신 — 남은 시간 ${h(r.beforeH)} → ${h(r.afterH)} · storeKey=${r.storeKey}`);
|
package/src/cli/pty-drive-cli.ts
CHANGED
|
@@ -51,6 +51,18 @@ export interface TuiWorkdirDecision {
|
|
|
51
51
|
readonly message?: string;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/** 「명시 격리」 판정 — `--test`(명시 플래그 층) 이거나 `--isolated-root` 를 줬을 때만 참.
|
|
55
|
+
*
|
|
56
|
+
* ⭐ 이 식은 «한 벌»이다 — `runPtyDriveInner`(거부)와 `src/index.ts` dev 의 자동 워크트리
|
|
57
|
+
* 판정(`decideAutoWorktree`)이 같이 쓴다. 둘이 갈리면 「자동으로 만들었어야 하는데 거부」나
|
|
58
|
+
* 「거부했어야 하는데 자동」이 조용히 생긴다. 3층(트리 파생)은 «명시»가 아니라서 빠진다. */
|
|
59
|
+
export function isExplicitlyIsolated(
|
|
60
|
+
resolution: { readonly kind: string; readonly layer: string },
|
|
61
|
+
isolatedRoot?: string,
|
|
62
|
+
): boolean {
|
|
63
|
+
return (resolution.kind === 'test' && resolution.layer === 'explicit-flag') || Boolean(isolatedRoot);
|
|
64
|
+
}
|
|
65
|
+
|
|
54
66
|
/** Reject the unsafe combination before a TUI child can inherit the caller's tree. */
|
|
55
67
|
export function decideTuiWorkdir(isolated: boolean, cwd: string | undefined): TuiWorkdirDecision {
|
|
56
68
|
const workdirProvided = Boolean(cwd?.trim());
|
|
@@ -62,7 +74,7 @@ export function decideTuiWorkdir(isolated: boolean, cwd: string | undefined): Tu
|
|
|
62
74
|
// ⛔⭐ 거부 문면은 **무엇을 주면 되는지**까지 말한다(교차 세션 제안 · 2026-08-02).
|
|
63
75
|
// 상대가 헤맨 이유가 *"어디에 config 를 쓰나"* 였다 — 실효 자리를 확인하는 한 줄을 함께 준다.
|
|
64
76
|
...(rejected
|
|
65
|
-
? { message: '격리 우주에서는 작업 디렉토리를 명시해야 한다 — `--cwd <worktree-path>` 를 주십시오. '
|
|
77
|
+
? { message: '격리 우주에서는 작업 디렉토리를 명시해야 한다 — `--worktree` 를 주거나 `--cwd <worktree-path>` 를 주십시오. '
|
|
66
78
|
+ '(안 주면 명령을 친 트리가 자식의 쓰기 허용 구역이 됩니다.) '
|
|
67
79
|
+ '지금 어느 우주인지는 `elanous where` 로 확인할 수 있습니다.' }
|
|
68
80
|
: {}),
|
|
@@ -499,8 +511,7 @@ async function runPtyDriveInner(opts: PtyDriveOpts): Promise<{ exitCode: number
|
|
|
499
511
|
const { effectiveInstanceRoot } = await import('../instance/resolve.js');
|
|
500
512
|
const scopeRoot = effectiveInstanceRoot();
|
|
501
513
|
const resolution = resolveCurrentInstance();
|
|
502
|
-
const explicitlyIsolated = (resolution
|
|
503
|
-
|| Boolean(opts.isolatedRoot);
|
|
514
|
+
const explicitlyIsolated = isExplicitlyIsolated(resolution, opts.isolatedRoot);
|
|
504
515
|
const workdirDecision = decideTuiWorkdir(explicitlyIsolated, opts.cwd);
|
|
505
516
|
debug.log('pty.drive', 'tui-workdir-decision', workdirDecision);
|
|
506
517
|
if (workdirDecision.rejected) throw new Error(workdirDecision.message);
|