elanous 0.2.14 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/{1307-6e7e0377c1db0bdc.js → 1307-b46d45b705e8c9ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +1 -0
- package/apps/pwa/out/_next/static/chunks/899-46946fe8363e1262.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9103-7a3ae7f60af3b99f.js → 9103-60fbef33e66f0a46.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-79c3ed84baaedd03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-7b2b4f378354869a.js → page-3cb52e5ea8fc2fa5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-a424ef80885d1743.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-c1e20d7d338713f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-1512d91c7491ed62.js → page-482c5dbde699947c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-1e962b31d1f11081.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-a627db94ec6904a0.js → page-8c2d9526164f5d09.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-ffff6d819fbc6e0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/{page-e6b84ab07d3567d5.js → page-a0e2a6d1bfb52fc5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c53598cfce6156f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/{page-fed69f9759d248d0.js → page-13a63953f53c6a23.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-15374909d8f1aebd.js → page-5d3c8429d04f3831.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-012a742f81218b01.js → page-3193bdc0bbab047a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-76270efaee638f17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-99effd9d893a43dc.js → page-6107ca8ddd5e3bdd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{layout-938de57ae0315e46.js → layout-dce686e582c23937.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d3d53b146416e422.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-160089123a40dd91.js → page-1a61c7ca1ceb3ae7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/{page-629e1ede482ec6eb.js → page-51f811fa119308b6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-dacff46049e1557e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-27e99b4e54a849d4.js → page-4167348049166852.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-de52e8fdf9095f7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-36a7d994f4ca0299.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/{page-32cde713be47cddb.js → page-ca3952cd78a83ca2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-e7e10cd3386222e5.js → page-5b042736aa113756.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-acb749f1e432bcf3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-cd78862707999911.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-54b9ef8afe6278fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-e64caff084f7ce21.js → page-1ebfe049c640e171.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-db07eaffba0df7e3.js → page-57924393e3e4e539.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9e0ce6c8129fa641.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-31fa1ce4c4aff9ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-86f91034bd5cabe5.js → page-0f5cd57ca928f42b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-abe8e3b74bea1ffc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-4364ef9f4e7c7f0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-ce4d8a1215ce53a3.js → page-d28573d6792b4275.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/{page-58043db78ba519ae.js → page-59f03fda76c03d22.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/{page-357750dfb91bf960.js → page-d751de5f8062ff5e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/term/{page-274703bc41b71333.js → page-fe1759f94003b32b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-d64c984e855c8c68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-86914b0dee8ab7f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/{page-3b7e821dc492bdfd.js → page-9afdee66b820c76e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d4aef67abf264874.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-f8da5dc6f3752276.js → page-1ea64acadd704ace.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-2f810b18d89ecba6.js → page-3544f154c87b43ee.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-30c2073bfc21c004.js +1 -0
- package/apps/pwa/out/_next/static/css/001d5fbaee388a25.css +1 -0
- package/apps/pwa/out/_next/static/css/{04dabcbcc4bfa6db.css → 085673d826b98b62.css} +1 -1
- package/apps/pwa/out/_next/static/rv9cierV0jSOvDBm1g0XB/_buildManifest.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +15 -15
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +15 -15
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +15 -15
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +15 -15
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +15 -15
- package/apps/pwa/out/ceo/index.html +1 -0
- package/apps/pwa/out/ceo/index.txt +33 -0
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +15 -15
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +15 -15
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +15 -15
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +15 -15
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +15 -15
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +15 -15
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +15 -15
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +15 -15
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +15 -15
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +15 -15
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +15 -15
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +15 -15
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +15 -15
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +15 -15
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +15 -15
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +15 -15
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +15 -15
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +15 -15
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +15 -15
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +15 -15
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +16 -16
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +15 -15
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +15 -15
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +15 -15
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +15 -15
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +15 -15
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +15 -15
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +15 -15
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +15 -15
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +15 -15
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +15 -15
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +15 -15
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +15 -15
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +15 -15
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +15 -15
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +15 -15
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +15 -15
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +15 -15
- package/graphs/doc-gen/doc-gen.yaml +24 -0
- package/graphs/doc-gen/recipes.yaml +3 -0
- package/graphs/heal/heal-loop.yaml +1 -1
- package/graphs/implement-loop.yaml +1 -1
- package/graphs/orchestrator/orchestrator.yaml +7 -0
- package/graphs/orchestrator/recipes.yaml +3 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -2
- package/graphs/steward/recipes.yaml +2 -1
- package/package.json +1 -1
- package/scripts/brand/check.ts +7 -5
- package/scripts/ci-public-export-import-gate.ts +154 -0
- package/scripts/ci-test-interference-gate.ts +5 -1
- package/scripts/ci-typecheck-changed.ts +82 -31
- package/scripts/docs/doc-rot.ts +164 -0
- package/scripts/docs/generate-graph-anatomy.ts +437 -0
- package/scripts/docs-cli-check.ts +4 -4
- package/scripts/expose-rubric-suggest.ts +18 -12
- package/scripts/goals/goal-census.ts +343 -0
- package/scripts/lecture-note/node.ts +31 -11
- package/scripts/lessons/handbook-page.ts +30 -3
- package/scripts/marketing/generate-ax-brief.ts +140 -0
- package/scripts/marketing/generate-feature-map.ts +118 -0
- package/scripts/measure/author-section-contribution.ts +84 -0
- package/scripts/release-loop/checklist-gate-node.ts +53 -14
- package/scripts/release-loop/cut-branch.ts +43 -13
- package/scripts/release-loop/gate-node.ts +82 -14
- package/scripts/release-loop/vault-note-node.ts +257 -8
- package/scripts/release-story/draft.ts +57 -9
- package/scripts/rhythm/daily.ts +263 -76
- package/scripts/rhythm/monthly.ts +97 -0
- package/scripts/rhythm/weekly.ts +30 -9
- package/scripts/smart-merge/resync-shadow.ts +147 -0
- package/src/acp/client.ts +17 -2
- package/src/agent-env/profile.ts +161 -0
- package/src/agent-mission/driver.ts +51 -1
- package/src/agent-mission/supervisor-metrics-cli.ts +40 -0
- package/src/agent-mission/supervisor-metrics.ts +218 -0
- package/src/agent-substrate/pr-reviewer.ts +2 -0
- package/src/ask-user-question/pending-questions.ts +5 -0
- package/src/auth/github-app-token.ts +112 -13
- package/src/autopilot/build/llm-conflict-merge.ts +32 -6
- package/src/autopilot/track-agent-shadow.ts +2 -1
- package/src/briefing/brief-items.ts +276 -0
- package/src/budget/usage-outcomes.ts +204 -0
- package/src/claims/claims-render.ts +14 -5
- package/src/cli/agent-env-cli.ts +21 -0
- package/src/cli/brief-cli.ts +73 -0
- package/src/cli/decisions-cli.ts +9 -0
- package/src/cli/doctor-cli.ts +23 -1
- package/src/cli/doctor-node-modules.ts +147 -0
- package/src/cli/intake-cli.ts +46 -17
- package/src/cli/know-cli.ts +20 -0
- package/src/cli/logs-cli.ts +43 -1
- package/src/cli/pod-cli.ts +2 -0
- package/src/cli/pr-cli.ts +80 -12
- package/src/cli/release-cli.ts +66 -29
- package/src/cli/seat-requests-cli.ts +52 -0
- package/src/cli/self-update.ts +200 -1
- package/src/cli/usage-cli.ts +26 -0
- package/src/context-bus/context-now-public.ts +16 -6
- package/src/context-bus/context-now.ts +3 -1
- package/src/context-bus/coord-events.ts +6 -4
- package/src/decisions/decision-cards.ts +33 -7
- package/src/decisions/proact-meter.ts +286 -0
- package/src/decisions/proact1-lite.ts +86 -0
- package/src/decisions/web-push-decision-cards.ts +1 -1
- package/src/discord-self-message.ts +9 -0
- package/src/domains/alert-audit.ts +271 -0
- package/src/domains/core-tools.ts +4 -3
- package/src/domains/ops-facts-tool.ts +31 -1
- package/src/flow-loop/split.ts +24 -0
- package/src/harness/harness-cli-command.ts +147 -17
- package/src/harness/harness-incidents.ts +2 -0
- package/src/harness/harness-pod-dispatch.ts +67 -8
- package/src/harness/harness-queue.ts +380 -50
- package/src/harness/harness-seams.ts +13 -3
- package/src/harness/helper-repair.ts +218 -0
- package/src/harness/helper-scan.ts +27 -4
- package/src/harness/launch-stamp.ts +236 -0
- package/src/harness/ledger-write-guard-child.fixture.ts +12 -0
- package/src/harness/ledger-write-guard.ts +35 -0
- package/src/harness/nested-elanous-policy.ts +114 -0
- package/src/harness/pod-memory-policy.ts +15 -0
- package/src/harness/repository-name.ts +55 -0
- package/src/hq/fence-audit.ts +90 -0
- package/src/hq/hq.ts +70 -6
- package/src/hq/lease.ts +9 -7
- package/src/hq/move-plan.ts +126 -0
- package/src/hq/promote.ts +31 -0
- package/src/hq/transfer.ts +185 -0
- package/src/index.ts +189 -13
- package/src/intake-plane/check.ts +63 -0
- package/src/intake-plane/digest.ts +65 -21
- package/src/intake-plane/front-classifier.ts +6 -0
- package/src/intake-plane/items.ts +3 -2
- package/src/intake-plane/lens.ts +177 -0
- package/src/intake-plane/route.ts +145 -1
- package/src/knowledge/know-find.ts +105 -0
- package/src/llm.ts +75 -19
- package/src/loops/budget.ts +36 -5
- package/src/loops/checker.ts +2 -2
- package/src/loops/orchestrator/author-depth.ts +65 -9
- package/src/loops/orchestrator/author-input-check.ts +8 -3
- package/src/loops/orchestrator/author-ledger.ts +3 -1
- package/src/loops/orchestrator/finish-rate.ts +14 -3
- package/src/loops/orchestrator/seat-share.ts +56 -0
- package/src/loops/orchestrator/tick.ts +107 -29
- package/src/loops/orchestrator/traffic.ts +117 -11
- package/src/loops/registry.ts +142 -61
- package/src/maturity/bot-slash-catalog.ts +11 -2
- package/src/maturity/feature-maturity.ts +4 -3
- package/src/maturity/tui-slash-availability.ts +40 -0
- package/src/mss/logging/log-store.ts +35 -4
- package/src/nexus/api/http-server.ts +28 -14
- package/src/nexus/api/loop-edges.ts +173 -0
- package/src/nexus/api/schedules-read.ts +13 -0
- package/src/nexus/api/seat-requests.ts +79 -56
- package/src/oauth/overload-failover-launch.ts +75 -0
- package/src/oauth/overload-failover.ts +137 -0
- package/src/prompt-enhance/enhance.ts +6 -1
- package/src/release-loop/auto-start.ts +6 -3
- package/src/release-loop/checklist.ts +19 -5
- package/src/release-loop/feature-store.ts +59 -31
- package/src/release-loop/merged-pr-checklist.ts +125 -0
- package/src/release-loop/placement.ts +98 -29
- package/src/seat-dispatch/seat-ask.ts +33 -6
- package/src/seat-dispatch/seat-request-eligibility.ts +19 -0
- package/src/seat-dispatch/seat-request-ledger.ts +133 -0
- package/src/seat-loop/seat-loop.ts +215 -12
- package/src/self-dev/ask-launch-flow.ts +22 -1
- package/src/self-dev/authored-goal-trace.ts +64 -0
- package/src/self-dev/dev-cli.ts +19 -1
- package/src/self-dev/dev-pipeline.ts +14 -9
- package/src/self-dev/draft-sweep.ts +90 -10
- package/src/self-dev/draft-triage-rules.ts +25 -8
- package/src/self-dev/entrance-registry.ts +10 -6
- package/src/self-dev/old-door.ts +73 -0
- package/src/self-dev/orchestrate.ts +15 -1
- package/src/self-dev/review-provider-fallback.ts +6 -1
- package/src/self-dev/run-supervisor.ts +49 -2
- package/src/self-implement/app-api-budget.ts +166 -0
- package/src/self-implement/budget-gate.ts +7 -5
- package/src/self-implement/follow-up-goals.ts +289 -0
- package/src/self-implement/frozen-merges.ts +3 -2
- package/src/self-implement/goal-author.ts +50 -6
- package/src/self-implement/goal-clarification-escalation.ts +5 -0
- package/src/self-implement/heal-intake.ts +120 -2
- package/src/self-implement/heal-triage.ts +44 -0
- package/src/self-implement/host-regate.ts +9 -2
- package/src/self-implement/l8-merge-queue.ts +132 -0
- package/src/self-implement/orchestrator.ts +325 -47
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/revert-guard.ts +42 -7
- package/src/self-implement/run-ledger.ts +6 -0
- package/src/self-implement/run-status-mapping.ts +2 -0
- package/src/self-implement/seams.ts +45 -16
- package/src/self-implement/self-implement-cli.ts +1 -0
- package/src/self-implement/speed-claims.ts +338 -0
- package/src/session-runtime/index.ts +2 -0
- package/src/session-runtime/retry-api.ts +87 -0
- package/src/session-runtime/retry-policy.ts +107 -6
- package/src/steward/triage.ts +74 -3
- package/src/steward/working-backwards.ts +20 -2
- package/src/task-cards/card-cli.ts +25 -0
- package/src/task-cards/card-store.ts +5 -3
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +63 -48
- package/src/task-orchestrator/surfaces/pod-command-job.ts +84 -9
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +4 -3
- package/src/task-orchestrator/surfaces/pod-ledger-prod-sink.ts +75 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +70 -9
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +37 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +166 -46
- package/src/task-orchestrator/surfaces/self-implement.ts +7 -1
- package/src/telegram-commands.ts +5 -0
- package/src/telegram.ts +72 -4
- package/src/user-config.ts +64 -7
- package/src/version/packed-revision.json +1 -1
- package/src/workflow-runtime/nodes/bash.ts +9 -1
- package/apps/pwa/out/_next/static/chunks/4562-071d8bac44a01069.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-2df489622a52a33a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-74383f890f075511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-c496bb16da85385f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-1abfe3aec3be6bdc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-fb260b9283dbf646.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-61ec1d2e92bdd50a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-fd7e200d4d83fbd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d47266766766d227.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2ce5471926761fdd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-e995d30f6800b6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-39f89c53038a51d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-5a753bb4ec0cc511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-04250f0e2c0d03df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-341480ed8e3c1ea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8ac8d71c2adf9c8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e1e47d8d940aba3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-94dc383d3d54db1a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-b3759cc14da80908.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-194dce4a83143fce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-35bdeae2e2c17147.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-16bef3da05a900c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-134c1bc762aee62c.js +0 -1
- package/apps/pwa/out/_next/static/css/2e33713c444d5b39.css +0 -1
- package/apps/pwa/out/_next/static/x6mjI6vqOkVVu0jFuDkz1/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{x6mjI6vqOkVVu0jFuDkz1 → rv9cierV0jSOvDBm1g0XB}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync, readSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { getElanousConfigDir } from '../elanous-config-dir.js';
|
|
5
|
+
import { getUserConfig } from '../user-config.js';
|
|
6
|
+
import { defaultSshRunner, localShellRunner, parseLease, sshLeaseStore, type LeaseStore, type SshRunner } from './lease.js';
|
|
7
|
+
import { promoteHq, type PromoteResult } from './promote.js';
|
|
8
|
+
|
|
9
|
+
type Direction = 'promote' | 'handback';
|
|
10
|
+
export interface TransferStep { step: string; status: 'done' | 'failed' | 'ready'; measurement: string }
|
|
11
|
+
export interface TransferResult { ok: boolean; direction: Direction; from: string; to: string; runId: string; journal: string | null; steps: TransferStep[] }
|
|
12
|
+
export interface TransferDeps {
|
|
13
|
+
store: LeaseStore;
|
|
14
|
+
run: SshRunner;
|
|
15
|
+
confirm: (question: string) => boolean;
|
|
16
|
+
promote: (host: string) => PromoteResult;
|
|
17
|
+
journalDir: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const aliases: Record<string, string[]> = { mbp: ['mbp', 'MacBookProM5'], node-b: ['node-b', 'MacStudioB1'] };
|
|
21
|
+
const valid = (alias: string, holder: string) => aliases[alias]?.includes(holder) ?? false;
|
|
22
|
+
const leaseCommand = (action: 'release' | 'acquire', expected?: { holder: string; generation: number }) =>
|
|
23
|
+
`elanous hq lease ${action}${expected ? ` --expected-holder '${expected.holder}' --expected-generation ${expected.generation}` : ''} --json`;
|
|
24
|
+
const identityCommand = `python3 - <<'PY'
|
|
25
|
+
import json, pathlib
|
|
26
|
+
home=pathlib.Path.home()
|
|
27
|
+
local=home/'.elanous-hq/host'
|
|
28
|
+
config=home/'.elanous-hqcfg/config.json'
|
|
29
|
+
name=local.read_text().strip() if local.exists() else json.loads(config.read_text())['hq']['hostName']
|
|
30
|
+
print(name)
|
|
31
|
+
PY`;
|
|
32
|
+
const cronCommand = `crontab -l && printf '\\n---HQ-AUDIT---\\n' && elanous hq fence-audit --json`;
|
|
33
|
+
const fenceCommand = `elanous hq fence --role cron -- sh -c 'printf "HQ_FENCE_ALLOWED:%s\\n" "$ELANOUS_HQ_GENERATION"'`;
|
|
34
|
+
|
|
35
|
+
export function defaultTransferDeps(): TransferDeps {
|
|
36
|
+
const arbiter = getUserConfig().hq?.arbiter ?? 'cloud-vm';
|
|
37
|
+
return {
|
|
38
|
+
store: sshLeaseStore(arbiter, arbiter === 'local' ? localShellRunner : defaultSshRunner),
|
|
39
|
+
run: defaultSshRunner,
|
|
40
|
+
confirm: (question) => {
|
|
41
|
+
if (!process.stdin.isTTY) return false;
|
|
42
|
+
process.stderr.write(`${question}\nType TRANSFER to continue: `);
|
|
43
|
+
const buffer = Buffer.alloc(128);
|
|
44
|
+
const count = requireRead(buffer);
|
|
45
|
+
return buffer.toString('utf8', 0, count).trim() === 'TRANSFER';
|
|
46
|
+
},
|
|
47
|
+
promote: (host) => promoteHq(host, true),
|
|
48
|
+
journalDir: join(getElanousConfigDir(), 'hq', 'transfers'),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function requireRead(buffer: Buffer): number {
|
|
53
|
+
// Read one terminal line without treating EOF or a non-interactive caller as consent.
|
|
54
|
+
let size = 0;
|
|
55
|
+
while (size < buffer.length) {
|
|
56
|
+
const n = requireReadByte(buffer, size);
|
|
57
|
+
if (n === 0) break;
|
|
58
|
+
size += n;
|
|
59
|
+
if (buffer[size - 1] === 10) break;
|
|
60
|
+
}
|
|
61
|
+
return size;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function requireReadByte(buffer: Buffer, offset: number): number {
|
|
65
|
+
return readSync(0, buffer, offset, 1, null);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function transferHq(direction: Direction, apply = false, deps: TransferDeps = defaultTransferDeps()): TransferResult {
|
|
69
|
+
const from = direction === 'promote' ? 'mbp' : 'node-b';
|
|
70
|
+
const to = direction === 'promote' ? 'node-b' : 'mbp';
|
|
71
|
+
const runId = randomUUID();
|
|
72
|
+
const journal = apply ? join(deps.journalDir, `${runId}.jsonl`) : null;
|
|
73
|
+
const steps: TransferStep[] = [];
|
|
74
|
+
const result = (ok: boolean): TransferResult => ({ ok, direction, from, to, runId, journal, steps });
|
|
75
|
+
const record = (step: string, status: TransferStep['status'], measurement: string) => {
|
|
76
|
+
const row = { step, status, measurement };
|
|
77
|
+
steps.push(row);
|
|
78
|
+
if (journal) {
|
|
79
|
+
mkdirSync(deps.journalDir, { recursive: true, mode: 0o700 });
|
|
80
|
+
appendFileSync(journal, `${JSON.stringify({ at: new Date().toISOString(), runId, direction, from, to, ...row })}\n`, { mode: 0o600 });
|
|
81
|
+
}
|
|
82
|
+
return status !== 'failed';
|
|
83
|
+
};
|
|
84
|
+
const lease = () => {
|
|
85
|
+
const { now, raw } = deps.store.read();
|
|
86
|
+
const current = parseLease(raw);
|
|
87
|
+
return { current, now };
|
|
88
|
+
};
|
|
89
|
+
const remote = (host: string, command: string) => {
|
|
90
|
+
const r = deps.run(host, command);
|
|
91
|
+
if (r.status !== 0) throw new Error(`${host}: ${r.stderr.trim() || r.stdout.trim() || `exit=${r.status}`}`);
|
|
92
|
+
return r.stdout.trim();
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
const before = lease();
|
|
96
|
+
if (!before.current || !valid(from, before.current.holder) || before.current.renewedAt + before.current.ttlSeconds < before.now) {
|
|
97
|
+
record('① current lease', 'failed', `holder=${before.current?.holder ?? 'none'} generation=${before.current?.generation ?? 'none'} expired=${before.current ? before.current.renewedAt + before.current.ttlSeconds < before.now : true}`);
|
|
98
|
+
return result(false);
|
|
99
|
+
}
|
|
100
|
+
const source = remote(from, identityCommand);
|
|
101
|
+
const target = remote(to, identityCommand);
|
|
102
|
+
if (source !== before.current.holder || !valid(to, target) || source === target) {
|
|
103
|
+
record('② host identities', 'failed', `source=${source} holder=${before.current.holder} target=${target}`);
|
|
104
|
+
return result(false);
|
|
105
|
+
}
|
|
106
|
+
record('① current lease', 'done', `holder=${source} generation=${before.current.generation}`);
|
|
107
|
+
record('② host identities', 'done', `source=${source} target=${target}`);
|
|
108
|
+
for (const host of [from, to]) {
|
|
109
|
+
const inventory = remote(host, cronCommand);
|
|
110
|
+
const marker = '\n---HQ-AUDIT---\n';
|
|
111
|
+
const index = inventory.lastIndexOf(marker);
|
|
112
|
+
if (index < 0) throw new Error(`${host}: missing cron audit`);
|
|
113
|
+
const cron = inventory.slice(0, index);
|
|
114
|
+
const audit = JSON.parse(inventory.slice(index + marker.length)) as unknown;
|
|
115
|
+
const live = cron.split('\n').filter(line => line.trim() && !line.trimStart().startsWith('#'));
|
|
116
|
+
if (!Array.isArray(audit) || audit.length > 0 || !live.some(line => /hq heartbeat\b/.test(line)) || !live.some(line => /hq fence --role cron\b/.test(line))) {
|
|
117
|
+
record(`③ cron fence ${host}`, 'failed', `unfenced=${Array.isArray(audit) ? audit.length : 'invalid'} heartbeat=${live.some(line => /hq heartbeat\b/.test(line))} fenced=${live.some(line => /hq fence --role cron\b/.test(line))}`);
|
|
118
|
+
return result(false);
|
|
119
|
+
}
|
|
120
|
+
record(`③ cron fence ${host}`, 'done', `unfenced=0 heartbeat=true fenced=true`);
|
|
121
|
+
}
|
|
122
|
+
const oldFence = remote(from, fenceCommand);
|
|
123
|
+
const newFence = remote(to, fenceCommand);
|
|
124
|
+
if (oldFence !== `HQ_FENCE_ALLOWED:${before.current.generation}` || newFence.includes('HQ_FENCE_ALLOWED:')) {
|
|
125
|
+
record('④ pre-transfer fence', 'failed', `source=${oldFence} target=${newFence}`);
|
|
126
|
+
return result(false);
|
|
127
|
+
}
|
|
128
|
+
record('④ pre-transfer fence', 'done', `source=allowed generation=${before.current.generation} target=skipped`);
|
|
129
|
+
if (!apply) {
|
|
130
|
+
record('⑤ human confirmation', 'ready', 'dry-run: no writes; --apply requires interactive TRANSFER confirmation');
|
|
131
|
+
return result(true);
|
|
132
|
+
}
|
|
133
|
+
if (!deps.confirm(`Release ${source} generation ${before.current.generation}, acquire ${target}, and switch cron fence? This cannot undo work already sent.`)) {
|
|
134
|
+
record('⑤ human confirmation', 'failed', 'confirmation declined');
|
|
135
|
+
return result(false);
|
|
136
|
+
}
|
|
137
|
+
record('⑤ human confirmation', 'done', 'operator typed TRANSFER');
|
|
138
|
+
const still = lease().current;
|
|
139
|
+
if (!still || still.holder !== source || still.generation !== before.current.generation || still.renewedAt + still.ttlSeconds < deps.store.read().now) {
|
|
140
|
+
record('⑥ release old lease', 'failed', 'lease changed before release');
|
|
141
|
+
return result(false);
|
|
142
|
+
}
|
|
143
|
+
let released: { ok?: boolean; record?: { holder?: string; generation?: number } };
|
|
144
|
+
try { released = JSON.parse(remote(from, leaseCommand('release', { holder: source, generation: before.current.generation }))); }
|
|
145
|
+
catch (error) {
|
|
146
|
+
record('⑥ release old lease', 'failed', error instanceof Error ? error.message : String(error));
|
|
147
|
+
return result(false);
|
|
148
|
+
}
|
|
149
|
+
if (released.ok !== true || released.record?.holder !== source || released.record.generation !== before.current.generation) {
|
|
150
|
+
record('⑥ release old lease', 'failed', 'release not confirmed');
|
|
151
|
+
return result(false);
|
|
152
|
+
}
|
|
153
|
+
record('⑥ release old lease', 'done', `holder=${source} generation=${released.record.generation} released=true`);
|
|
154
|
+
const acquired = JSON.parse(remote(to, leaseCommand('acquire'))) as { ok?: boolean; record?: { holder?: string; generation?: number } };
|
|
155
|
+
const current = lease().current;
|
|
156
|
+
if (acquired.ok !== true || acquired.record?.holder !== target || acquired.record.generation !== before.current.generation + 1 || current?.holder !== target || current.generation !== acquired.record.generation) {
|
|
157
|
+
record('⑦ acquire new lease', 'failed', `expected=${target} generation=${before.current.generation + 1} observed=${current?.holder ?? 'none'} generation=${current?.generation ?? 'none'}; keep old host fenced, recover manually`);
|
|
158
|
+
return result(false);
|
|
159
|
+
}
|
|
160
|
+
record('⑦ acquire new lease', 'done', `holder=${target} generation=${current.generation}`);
|
|
161
|
+
if (direction === 'promote') {
|
|
162
|
+
const promoted = deps.promote(to);
|
|
163
|
+
for (const line of promoted.lines) record(`⑧ promotion ${line.step}`, line.status, line.measurement);
|
|
164
|
+
if (!promoted.ok) return result(false);
|
|
165
|
+
}
|
|
166
|
+
const sourceAfter = remote(from, fenceCommand);
|
|
167
|
+
const targetAfter = remote(to, fenceCommand);
|
|
168
|
+
const observed = lease().current;
|
|
169
|
+
if (sourceAfter.includes('HQ_FENCE_ALLOWED:') || targetAfter !== `HQ_FENCE_ALLOWED:${current.generation}` || observed?.holder !== target || observed.generation !== current.generation) {
|
|
170
|
+
record('⑨ final fence', 'failed', `source=${sourceAfter} target=${targetAfter} lease=${observed?.holder ?? 'none'} generation=${observed?.generation ?? 'none'}`);
|
|
171
|
+
return result(false);
|
|
172
|
+
}
|
|
173
|
+
record('⑨ final fence', 'done', `source=skipped target=allowed generation=${current.generation}`);
|
|
174
|
+
return result(true);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
record('halt', 'failed', error instanceof Error ? error.message : String(error));
|
|
177
|
+
return result(false);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function formatTransfer(result: TransferResult): string {
|
|
182
|
+
return [`hq ${result.direction}: ${result.ok ? 'ok' : 'failed'} · ${result.from} → ${result.to} · run=${result.runId}`,
|
|
183
|
+
...result.steps.map(s => `${s.step}: ${s.status} · ${s.measurement}`),
|
|
184
|
+
...(result.journal ? [`journal=${result.journal}`] : [])].join('\n');
|
|
185
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -27,10 +27,13 @@ import { installDevCompletionGuard } from './self-dev/dev-completion-guard.js';
|
|
|
27
27
|
import { buildOrchestrateDecomposePrepareArgs, normalizeOrchestrateRequest, splitOrchestrateGoalTexts } from './self-dev/self-orchestrate-runtime.js';
|
|
28
28
|
import { CLI_ENTRANCE_BASELINE, evaluateCommandEntranceBaseline } from './self-dev/entrance-baseline.js';
|
|
29
29
|
import { CLI_HARNESS_DOGFOOD_ENTRANCE, CLI_HARNESS_ORCHESTRATE_ENTRANCE, describeEntranceCommand, listEntrancesWithModelExposure, renderLaunchEntrances, summarizeEntrances, type EntranceId } from './self-dev/entrance-registry.js';
|
|
30
|
+
import { isOldDoorInternalCall, refuseOldDoor } from './self-dev/old-door.js';
|
|
30
31
|
import { collectCommandEntrances, renderCommandEntrances } from './self-dev/entrance-inventory.js';
|
|
31
32
|
import { isGoalAuthorFileName } from './self-implement/goal-document.js';
|
|
32
33
|
import { DEV_PIPELINE_SINK_SURFACE } from './self-implement/self-cli-sink-surface.js';
|
|
33
34
|
import { registerPrivateLedgerCommands } from './cli/private-ledger-commands.js';
|
|
35
|
+
import { registerKnowCommand } from './cli/know-cli.js';
|
|
36
|
+
import { registerSeatRequestsCommands } from './cli/seat-requests-cli.js';
|
|
34
37
|
import { applyTestStateDirFlagFromArgv } from './cli/test-state-dir-flag.js';
|
|
35
38
|
import { applyTestFlagFromArgv, observeTestFlagOwnership, uncoveredTestFlagPaths, staleTestFlagPaths } from './cli/test-flag.js';
|
|
36
39
|
import { registerPtyTakeoverCommands } from './cli/pty-takeover-cli.js';
|
|
@@ -46,11 +49,13 @@ import { registerPublishCommands } from './cli/publish-cli.js';
|
|
|
46
49
|
import { registerAutopilotCommands } from './cli/autopilot-cli.js';
|
|
47
50
|
import { registerRoleCommands } from './cli/role-cli.js';
|
|
48
51
|
import { registerMachineCommands } from './cli/machine-cli.js';
|
|
52
|
+
import { registerAgentEnvCommands } from './cli/agent-env-cli.js';
|
|
49
53
|
import { registerScheduleCommands } from './cli/schedule-cli.js';
|
|
50
54
|
export { runSchedule, scheduleCreatePlan } from './cli/schedule-cli.js';
|
|
51
55
|
export type { ScheduleDispatch } from './cli/schedule-cli.js';
|
|
52
56
|
import { registerReviewLoopOptions, buildReviewLoopOpts } from './agent-mission/review-loop-cli.js';
|
|
53
57
|
import { registerCapabilitiesCommand } from './agent-mission/capabilities-cli.js';
|
|
58
|
+
import { registerSupervisorMetricsCommand } from './agent-mission/supervisor-metrics-cli.js';
|
|
54
59
|
import { agentBackendNames } from './agent-mission/driver.js';
|
|
55
60
|
import { registerWhereCommand } from './cli/where-cli.js';
|
|
56
61
|
import { registerShadowCommand } from './cli/shadow-cli.js';
|
|
@@ -68,6 +73,7 @@ import { registerFlowCommands } from './cli/flow-cli.js';
|
|
|
68
73
|
import { registerModelWatchCommand } from './cli/model-watch-cli.js';
|
|
69
74
|
import { registerIntakeCommands } from './cli/intake-cli.js';
|
|
70
75
|
import { registerTasksCommands } from './cli/tasks-cli.js';
|
|
76
|
+
import { registerBriefCommands } from './cli/brief-cli.js';
|
|
71
77
|
import { registerLabelsCommands } from './cli/labels-cli.js';
|
|
72
78
|
import { registerMsgCommands } from './cli/msg-cli.js';
|
|
73
79
|
import { registerDoctorCommand } from './cli/doctor-cli.js';
|
|
@@ -80,6 +86,7 @@ import { registerStartCommand } from './cli/start-cli.js';
|
|
|
80
86
|
import { registerGroundingSourcesCli } from './grounding/sources-cli.js';
|
|
81
87
|
import { registerGraphCommands } from './graph-runner/graph-cli.js';
|
|
82
88
|
import { registerLoopCommands } from './loops/loop-cli.js';
|
|
89
|
+
import { registerHqMovePlanCommand } from './hq/hq.js';
|
|
83
90
|
import { registerCardCommand } from './task-cards/card-cli.js';
|
|
84
91
|
import { registerLaunchHeadCommands } from './launch-head/launch-head-cli.js';
|
|
85
92
|
import { acpServerHelpText } from './boot/acp-server-help.js';
|
|
@@ -856,6 +863,7 @@ registerPrCommands(program);
|
|
|
856
863
|
registerRepoCommands(program);
|
|
857
864
|
registerRoleCommands(program);
|
|
858
865
|
registerMachineCommands(program);
|
|
866
|
+
registerAgentEnvCommands(program);
|
|
859
867
|
// CLI entry: where action → resolveCurrentInstance → resolveInstance (instance universe).
|
|
860
868
|
registerWhereCommand(program);
|
|
861
869
|
registerShadowCommand(program);
|
|
@@ -871,6 +879,7 @@ registerUsageCommand(program);
|
|
|
871
879
|
registerLiveCommands(program);
|
|
872
880
|
registerResearchCommand(program);
|
|
873
881
|
registerReleaseCommands(program);
|
|
882
|
+
registerKnowCommand(program);
|
|
874
883
|
registerFreezeCommands(program);
|
|
875
884
|
registerFlowCommands(program);
|
|
876
885
|
// HQ-HB · HQ-FENCE (10-04): one writer across mbp · node-b · cloud-vm — lease on the arbiter, 2-of-3 quorum, generation fencing.
|
|
@@ -889,24 +898,42 @@ hqCmd.command('host').description('이 머신의 HQ 호스트 이름 설정')
|
|
|
889
898
|
});
|
|
890
899
|
hqCmd.command('lease').argument('<action>', 'acquire|renew|status|release')
|
|
891
900
|
.option('--host <name>', '이 호스트 이름(기본 ~/.elanous-hq/host · hq.hostName · os.hostname)')
|
|
901
|
+
.option('--expected-holder <name>', 'release CAS: 해제할 임대의 예상 소유자')
|
|
902
|
+
.option('--expected-generation <number>', 'release CAS: 해제할 임대의 예상 세대')
|
|
892
903
|
.option('--json', 'JSON 출력')
|
|
893
|
-
.action(async (action: string, opts: { host?: string; json?: boolean }) => {
|
|
904
|
+
.action(async (action: string, opts: { host?: string; expectedHolder?: string; expectedGeneration?: string; json?: boolean }) => {
|
|
894
905
|
try {
|
|
895
906
|
if (!['acquire', 'renew', 'status', 'release'].includes(action)) throw new CliUserError(`hq lease: unknown action ${action}`, 'acquire|renew|status|release');
|
|
907
|
+
if ((opts.expectedHolder !== undefined || opts.expectedGeneration !== undefined) && action !== 'release')
|
|
908
|
+
throw new CliUserError('hq lease: expected holder/generation are only valid for release');
|
|
909
|
+
if ((opts.expectedHolder === undefined) !== (opts.expectedGeneration === undefined)
|
|
910
|
+
|| (opts.expectedGeneration !== undefined && (!/^[1-9]\d*$/.test(opts.expectedGeneration) || !Number.isSafeInteger(Number(opts.expectedGeneration)))))
|
|
911
|
+
throw new CliUserError('hq lease release: supply both --expected-holder and --expected-generation (positive integer)');
|
|
896
912
|
await hqSink();
|
|
897
913
|
const { hqLease } = await import('./hq/hq.js');
|
|
898
|
-
const result = hqLease(action as 'acquire', {},
|
|
914
|
+
const result = hqLease(action as 'acquire', {}, {
|
|
915
|
+
...(opts.host ? { host: opts.host } : {}),
|
|
916
|
+
...(opts.expectedHolder !== undefined ? { expectedHolder: opts.expectedHolder, expectedGeneration: Number(opts.expectedGeneration) } : {}),
|
|
917
|
+
});
|
|
899
918
|
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
900
919
|
else console.log(result.ok ? `hq lease ${action}: ok${'record' in result && result.record ? ` · holder ${result.record.holder} · generation ${result.record.generation}` : ''}` : `hq lease ${action}: refused — ${'reason' in result ? result.reason : ''}`);
|
|
901
920
|
if (!result.ok) process.exitCode = 2;
|
|
902
921
|
} catch (error) { if (error instanceof CliUserError) throw error; console.error(`hq lease: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
903
922
|
});
|
|
904
923
|
hqCmd.command('promote').description('HQ 승격 런북 (기본 dry-run · --apply 일 때만 변경)')
|
|
905
|
-
.
|
|
906
|
-
.option('--apply', '
|
|
924
|
+
.option('--to <host>', '기존 임대 취득 후 승격 대상 호스트 (생략하면 mbp → node-b 전환 포함)')
|
|
925
|
+
.option('--apply', '임대 이전 및 승격 실행 · 터미널 확인 필수 (기존 --to 경로는 임대 보유 필요)')
|
|
907
926
|
.option('--json', 'JSON 출력')
|
|
908
927
|
.action(async (opts: { to: string; apply?: boolean; json?: boolean }) => {
|
|
909
928
|
try {
|
|
929
|
+
if (!opts.to) {
|
|
930
|
+
const { transferHq, formatTransfer } = await import('./hq/transfer.js');
|
|
931
|
+
const result = transferHq('promote', opts.apply === true);
|
|
932
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
933
|
+
else console.log(formatTransfer(result));
|
|
934
|
+
if (!result.ok) process.exitCode = 1;
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
910
937
|
const { promoteHq, formatPromote } = await import('./hq/promote.js');
|
|
911
938
|
const result = promoteHq(opts.to, opts.apply === true);
|
|
912
939
|
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
@@ -914,6 +941,18 @@ hqCmd.command('promote').description('HQ 승격 런북 (기본 dry-run · --appl
|
|
|
914
941
|
if (!result.ok) process.exitCode = 1;
|
|
915
942
|
} catch (error) { console.error(`hq promote: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
916
943
|
});
|
|
944
|
+
hqCmd.command('handback').description('node-b → mbp 임대·크론 울타리 복귀 (기본 읽기 전용)')
|
|
945
|
+
.option('--apply', '각 검사를 통과한 뒤 터미널 확인을 받고 이전 실행')
|
|
946
|
+
.option('--json', '단계별 결과·저널 경로 JSON 출력')
|
|
947
|
+
.action(async (opts: { apply?: boolean; json?: boolean }) => {
|
|
948
|
+
try {
|
|
949
|
+
const { transferHq, formatTransfer } = await import('./hq/transfer.js');
|
|
950
|
+
const result = transferHq('handback', opts.apply === true);
|
|
951
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
952
|
+
else console.log(formatTransfer(result));
|
|
953
|
+
if (!result.ok) process.exitCode = 1;
|
|
954
|
+
} catch (error) { console.error(`hq handback: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
955
|
+
});
|
|
917
956
|
hqCmd.command('heartbeat').description('보유자는 갱신 · 아니면 대기(보유자에 닿는지 중재자에 보고)').option('--json', 'JSON 출력')
|
|
918
957
|
.action(async (opts: { json?: boolean }) => {
|
|
919
958
|
try {
|
|
@@ -937,6 +976,18 @@ hqCmd.command('seen').description('이 호스트가 본 가장 높은 임대 세
|
|
|
937
976
|
else console.log(result.seen ? `hq seen: generation ${result.generation}` : 'hq seen: never');
|
|
938
977
|
process.exitCode = result.seen ? 0 : 3;
|
|
939
978
|
});
|
|
979
|
+
registerHqMovePlanCommand(hqCmd);
|
|
980
|
+
hqCmd.command('fence-audit').description('운영 crontab 의 HQ 울타리 밖 쓰기 잡 목록과 감싼 줄 제안(읽기 전용)')
|
|
981
|
+
.option('--json', 'JSON 출력')
|
|
982
|
+
.action(async (opts: { json?: boolean }) => {
|
|
983
|
+
try {
|
|
984
|
+
await hqSink();
|
|
985
|
+
const rows = (await import('./hq/fence-audit.js')).hqFenceAudit();
|
|
986
|
+
if (opts.json) await writeStdoutJson(`${JSON.stringify(rows)}\n`);
|
|
987
|
+
else if (!rows.length) console.log('hq fence-audit: unfenced 0');
|
|
988
|
+
else for (const row of rows) console.log(`${row.raw}\n role: ${row.recommendedRole}\n suggested: ${row.suggestedLine}`);
|
|
989
|
+
} catch (error) { console.error(`hq fence-audit: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
990
|
+
});
|
|
940
991
|
hqCmd.command('fence').description('이 호스트가 임대를 쥐었을 때만 명령 실행(아니면 건너뜀 · exit 0)')
|
|
941
992
|
.requiredOption('--role <role>', 'telegram-poller|cron|seat-loop|release-run|conatus|git-push')
|
|
942
993
|
.argument('<command...>', '-- 뒤의 명령')
|
|
@@ -947,12 +998,63 @@ hqCmd.command('fence').description('이 호스트가 임대를 쥐었을 때만
|
|
|
947
998
|
process.exitCode = hqFenceRun(opts.role as 'cron', command);
|
|
948
999
|
});
|
|
949
1000
|
const seatCmd = program.command('seat').description('분배된 자리의 하루 루프와 보고');
|
|
1001
|
+
registerSeatRequestsCommands(seatCmd);
|
|
950
1002
|
seatCmd.command('answer <askId> <answer>').description('자리 질문에 답을 남기고 원래 표면으로 회신 예약')
|
|
951
1003
|
.action(async (askId: string, answer: string) => {
|
|
952
1004
|
try {
|
|
953
|
-
|
|
1005
|
+
try { await (await import('./domains/standalone-log-sink.js')).registerStandaloneLogSink('seat-answer'); } catch { /* file trail remains available */ }
|
|
1006
|
+
const { debug } = await import('./debug/log.js');
|
|
1007
|
+
const { answerSeatAsk, deliverSeatAnswers, seatAskDeliveryInProgress, seatAskReplyInfo } = await import('./seat-dispatch/seat-ask.js');
|
|
954
1008
|
answerSeatAsk(askId, answer);
|
|
1009
|
+
const { origin, askedAt, answeredAt } = seatAskReplyInfo(askId);
|
|
955
1010
|
console.log(`자리 답변 기록: ${askId}`);
|
|
1011
|
+
if (origin.channel !== 'telegram') {
|
|
1012
|
+
debug.log('seat.ask', 'reply-no-target', { id: askId, via: origin.channel });
|
|
1013
|
+
console.log(`전달 대상 없음: ${askId} (${origin.channel})`);
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
const token = process.env.TELEGRAM_BOT_TOKEN?.trim();
|
|
1017
|
+
const elapsedMs = askedAt === null ? null : Math.max(0, answeredAt - askedAt);
|
|
1018
|
+
if (!token) {
|
|
1019
|
+
debug.log('seat.ask', 'reply-failed', { id: askId, via: 'telegram', reason: 'token-missing', elapsedMs });
|
|
1020
|
+
console.log(`텔레그램 토큰 없음 (TELEGRAM_BOT_TOKEN): ${askId} · 회신 대기`);
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
const botId = token.split(':')[0];
|
|
1024
|
+
if (origin.botId && origin.botId !== botId) {
|
|
1025
|
+
debug.log('seat.ask', 'reply-no-target', { id: askId, via: 'telegram', reason: 'bot-mismatch' });
|
|
1026
|
+
console.log(`전달 대상 없음: ${askId} (수신 봇 불일치) · 회신 대기`);
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
try {
|
|
1030
|
+
let sent = false;
|
|
1031
|
+
await deliverSeatAnswers({ askId, channel: 'telegram', botId, send: async (target, text) => {
|
|
1032
|
+
if (target.channel !== 'telegram') throw new Error('seat ask belongs to another surface');
|
|
1033
|
+
const response = await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
|
|
1034
|
+
method: 'POST', headers: { 'content-type': 'application/json' },
|
|
1035
|
+
body: JSON.stringify({ chat_id: target.chatId, text, reply_to_message_id: target.messageId,
|
|
1036
|
+
...(target.threadId === undefined ? {} : { message_thread_id: target.threadId }) }),
|
|
1037
|
+
});
|
|
1038
|
+
const result = await response.json() as { ok?: boolean; description?: string };
|
|
1039
|
+
if (!response.ok || result.ok !== true) throw new Error(result.description ?? `Telegram HTTP ${response.status}`);
|
|
1040
|
+
sent = true;
|
|
1041
|
+
} });
|
|
1042
|
+
if (!sent) {
|
|
1043
|
+
if (seatAskDeliveryInProgress(askId)) {
|
|
1044
|
+
debug.log('seat.ask', 'reply-in-progress', { id: askId, via: 'telegram', reason: 'claimed-by-other-worker' });
|
|
1045
|
+
console.log(`다른 작업자가 전달 중: ${askId}`);
|
|
1046
|
+
} else {
|
|
1047
|
+
debug.log('seat.ask', 'reply-no-target', { id: askId, via: 'telegram', reason: 'not-claimed' });
|
|
1048
|
+
console.log(`전달 대상 없음: ${askId} (회신 대기)`);
|
|
1049
|
+
}
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
debug.log('seat.ask', 'reply-sent', { id: askId, via: 'telegram', elapsedMs });
|
|
1053
|
+
console.log(`텔레그램 회신 전달: ${askId} · 지연 ${elapsedMs === null ? '미상' : `${elapsedMs}ms`}`);
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
debug.log('seat.ask', 'reply-failed', { id: askId, via: 'telegram', reason: error instanceof Error ? error.message : String(error), elapsedMs });
|
|
1056
|
+
console.log(`텔레그램 회신 실패: ${askId} · 회신 대기`);
|
|
1057
|
+
}
|
|
956
1058
|
} catch (error) { console.error(`seat answer: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
957
1059
|
});
|
|
958
1060
|
seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
|
|
@@ -962,10 +1064,10 @@ seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
|
|
|
962
1064
|
try {
|
|
963
1065
|
// V3 F5: without the sink, the seat loop's judgment lines (seat.loop) never reach the log store when cron runs it.
|
|
964
1066
|
await (await import('./domains/standalone-log-sink.js')).registerStandaloneLogSink('seat-loop');
|
|
965
|
-
const { runSeatLoopTurn } = await import('./seat-loop/seat-loop.js');
|
|
1067
|
+
const { runSeatLoopTurn, seatLoopTickLine } = await import('./seat-loop/seat-loop.js');
|
|
966
1068
|
const result = await runSeatLoopTurn(opts.seat);
|
|
967
1069
|
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
968
|
-
else console.log(
|
|
1070
|
+
else console.log(seatLoopTickLine(result));
|
|
969
1071
|
} catch (error) { console.error(`seat loop: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
970
1072
|
});
|
|
971
1073
|
seatCmd.command('report').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
|
|
@@ -1161,8 +1263,10 @@ program.command('self-update')
|
|
|
1161
1263
|
.option('--keep <n>', '설치 뒤 남길 최근 판 수(설치본은 current·직전 판, 체크아웃은 current·데몬 판 보호 · 0 이면 정리 안 함)', '3')
|
|
1162
1264
|
.option('--alert', '실패(exit≠0)를 알림으로도 보냄 — 크론(무인) 실행용')
|
|
1163
1265
|
.option('--skip-pwa-build', '체크아웃 설치 전 PWA 빌드를 명시적으로 건너뜀')
|
|
1266
|
+
.option('--dev', '판 사이 dev 빌드 설치 — versions/<판>-dev.<sha12> · install.json channel=dev · 이전 versionDir 보존 (사람 승인 · 자동 아님)')
|
|
1267
|
+
.option('--rollback', 'install.json 의 이전 versionDir 로 current 를 되돌린다 (이전이 없으면 거부)')
|
|
1164
1268
|
.option('--auto <on|off|status>', '자동 갱신 — macOS launchd · Linux systemd 타이머가 매일 04:17 에 `self-update --restart --alert` (크론이 이미 부르면 켜지 않는다)')
|
|
1165
|
-
.action(async (opts: { from?: string; version?: string; restart?: boolean; json?: boolean; keep?: string; alert?: boolean; skipPwaBuild?: boolean; auto?: string }) => {
|
|
1269
|
+
.action(async (opts: { from?: string; version?: string; restart?: boolean; json?: boolean; keep?: string; alert?: boolean; skipPwaBuild?: boolean; dev?: boolean; rollback?: boolean; auto?: string }) => {
|
|
1166
1270
|
if (opts.auto !== undefined) {
|
|
1167
1271
|
if (!['on', 'off', 'status'].includes(opts.auto)) { console.error(`--auto 는 on · off · status 중 하나: ${opts.auto}`); process.exitCode = 2; return; }
|
|
1168
1272
|
const { runAutoUpdate } = await import('./cli/update-auto.js');
|
|
@@ -3457,6 +3561,22 @@ selfCmd
|
|
|
3457
3561
|
}
|
|
3458
3562
|
});
|
|
3459
3563
|
|
|
3564
|
+
selfCmd
|
|
3565
|
+
.command('speed-claims')
|
|
3566
|
+
.description('런 원장 발사→종결 시간의 자리별·결과별 분포를 읽기 전용으로 출력한다')
|
|
3567
|
+
.option('--json', '구조화된 JSON으로 출력한다')
|
|
3568
|
+
.action(async (opts: { json?: boolean }) => {
|
|
3569
|
+
try {
|
|
3570
|
+
const { measureSpeedClaims, renderSpeedClaims } = await import('./self-implement/speed-claims.js');
|
|
3571
|
+
const result = measureSpeedClaims();
|
|
3572
|
+
if (opts.json) await writeStdoutJson(JSON.stringify(result) + '\n');
|
|
3573
|
+
else console.log(renderSpeedClaims(result));
|
|
3574
|
+
} catch (error) {
|
|
3575
|
+
console.error(`speed-claims measurement failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3576
|
+
process.exitCode = 1;
|
|
3577
|
+
}
|
|
3578
|
+
});
|
|
3579
|
+
|
|
3460
3580
|
selfCmd
|
|
3461
3581
|
.command('goal-source-distribution')
|
|
3462
3582
|
.description('self-implement 런 원장의 start goalSource 분포를 읽기 전용으로 출력한다')
|
|
@@ -4226,6 +4346,12 @@ selfCmd
|
|
|
4226
4346
|
.option('--supervise-rounds <n>', '슈퍼바이저 재개 라운드 상한 (기본 3 · 끄려면 --no-supervise)')
|
|
4227
4347
|
.option('--json', '구조화 출력 {stage, ok, branch, worktree, prUrl?, merged?}')
|
|
4228
4348
|
.action(async (parts: string[], opts: { featureFile?: string; base?: string; draft?: boolean; openPr?: boolean; autoMerge?: boolean; autoReview?: boolean; maxWait?: string; json?: boolean; plan?: boolean; enhance?: boolean; ground?: boolean; observeOnly?: boolean }) => {
|
|
4349
|
+
if (!isOldDoorInternalCall('self-implement')) {
|
|
4350
|
+
const refused = refuseOldDoor('self-implement');
|
|
4351
|
+
debug.log('harness.entrance', 'old-door-refused', { door: refused.door, caller: refused.caller });
|
|
4352
|
+
ui.error(refused.message);
|
|
4353
|
+
process.exit(refused.exitCode);
|
|
4354
|
+
}
|
|
4229
4355
|
if (opts.featureFile && parts.length > 0) { ui.error('--feature-file 과 위치 인자 feature 는 함께 줄 수 없다'); process.exit(2); }
|
|
4230
4356
|
let feature: string;
|
|
4231
4357
|
try { feature = (opts.featureFile ? readFileSync(opts.featureFile, 'utf8') : parts.join(' ')).trim(); }
|
|
@@ -4379,9 +4505,18 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4379
4505
|
.option('--no-pod-rebuild', 'pod: 이미지 판(elanous.commit)이 HEAD 와 달라도 다시 굽지 않는다 — 측정은 «이미지 판»을 잰다')
|
|
4380
4506
|
.option('--pod-pass-env <keys>', 'pod: 호스트 env 에서 Pod 로 넘길 키(쉼표) — 예 OPENROUTER_API_KEY,ANTHROPIC_API_KEY(벤치마크 과금 경로)')
|
|
4381
4507
|
.option('--bench-arms <spec>', 'pod 벤치마크: 골 1개를 팔마다 «라벨 한 줄만 다르게» 복제해 동시에 — "id=provider[:model][@KEY+KEY];…" (예 codex=openai-codex;or-kimi=openrouter:openrouter/moonshotai/kimi-k3@OPENROUTER_API_KEY) · --auto-merge 거부 · RFC fleet 슈퍼바이저 §A3')
|
|
4508
|
+
.addOption(new Option('--child-llm-provider <id>', 'pod: 구현 자식 LLM provider(openai-codex|grok) — 하니스 --child-llm-provider 가 이 자리로 온다(10-05)').hideHelp())
|
|
4509
|
+
.addOption(new Option('--child-llm-model <id>', 'pod: 구현 자식 LLM model(--child-llm-provider 와 함께)').hideHelp())
|
|
4510
|
+
.addOption(new Option('--child-llm-effort <level>', 'pod: 구현 자식 추론 노력(--child-llm-provider 와 함께)').hideHelp())
|
|
4382
4511
|
.option('--help-all', '모든 orchestrate 옵션 표시')
|
|
4383
4512
|
.action(function (this: Command, parts: string[], opts: { goalFile?: string[]; concurrency?: string; autoMerge?: boolean; autoReview?: boolean; openPr?: boolean; base?: string; teardown?: boolean; resume?: string; board?: boolean; decompose?: boolean; fabricDecompose?: boolean; maxTasks?: string; supervise?: boolean; superviseRounds?: string; json?: boolean }) {
|
|
4384
4513
|
return (async () => {
|
|
4514
|
+
if (!isOldDoorInternalCall('self-orchestrate')) {
|
|
4515
|
+
const refused = refuseOldDoor('self-orchestrate');
|
|
4516
|
+
debug.log('harness.entrance', 'old-door-refused', { door: refused.door, caller: refused.caller });
|
|
4517
|
+
ui.error(refused.message);
|
|
4518
|
+
process.exit(refused.exitCode);
|
|
4519
|
+
}
|
|
4385
4520
|
// 위치 인자는 종전처럼 분리하고 파일 입력은 파일당 한 골이다.
|
|
4386
4521
|
let inputGoals: ReturnType<typeof readSelfOrchestrateGoals>;
|
|
4387
4522
|
try { inputGoals = readSelfOrchestrateGoals(parts, opts.goalFile); }
|
|
@@ -4613,6 +4748,19 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4613
4748
|
let rotationAccounts: readonly string[] | undefined;
|
|
4614
4749
|
let podProvider: 'openai-codex' | 'grok' = 'openai-codex';
|
|
4615
4750
|
let grokApiKeyOptIn = false;
|
|
4751
|
+
{
|
|
4752
|
+
// 10-05 PODPROVIDER: refuse child choices this Pod launch cannot honour instead of dropping them.
|
|
4753
|
+
const child = opts as { childLlmProvider?: string; childLlmModel?: string; childLlmEffort?: string };
|
|
4754
|
+
const named = child.childLlmProvider?.trim();
|
|
4755
|
+
const refuse = !named && (child.childLlmModel?.trim() || child.childLlmEffort?.trim())
|
|
4756
|
+
? 'pod: --child-llm-model/--child-llm-effort 는 --child-llm-provider 와 함께'
|
|
4757
|
+
: named && benchArms
|
|
4758
|
+
? 'pod: --child-llm-provider 는 --bench-arms 와 함께 못 쓴다(팔마다 모델이 하나다)'
|
|
4759
|
+
: named === 'grok' && explicitPodAccount
|
|
4760
|
+
? 'pod: --child-llm-provider grok 은 --pod-account 와 함께 못 쓴다(그것은 codex 계정을 고정한다)'
|
|
4761
|
+
: undefined;
|
|
4762
|
+
if (refuse) { ui.error(refuse); debug.log('self-implement.pod', 'child-provider-refused', { provider: named ?? null, reason: refuse }); process.exit(2); }
|
|
4763
|
+
}
|
|
4616
4764
|
if (!explicitPodAccount && !benchArms) {
|
|
4617
4765
|
const { inspectCodexRotation } = await import('./oauth/codex-account-store.js');
|
|
4618
4766
|
const { planPodProvider, makePodAccountBroker } = await import('./task-orchestrator/surfaces/pod-account-broker.js');
|
|
@@ -4651,17 +4799,31 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4651
4799
|
if (!opts.json) ui.warn(podGrokSkippedLine(grokCheck));
|
|
4652
4800
|
}
|
|
4653
4801
|
}
|
|
4654
|
-
|
|
4802
|
+
// 10-05 PODPROVIDER: a launch that named the child provider gets it, or is refused — never a silent codex.
|
|
4803
|
+
const namedChild = (opts as { childLlmProvider?: string }).childLlmProvider?.trim();
|
|
4804
|
+
const { podNamedChildProvider, podFallbackCredentials, podGrokSubscriptionUsable: namedGrokUsable } = await import('./task-orchestrator/surfaces/self-implement-pod.js');
|
|
4805
|
+
const namedChildDecision = podNamedChildProvider(namedChild, {
|
|
4806
|
+
grokSubscription: namedChild === 'grok' && credential?.kind === 'subscription' && (grokSubscriptionUsable || namedGrokUsable().usable),
|
|
4807
|
+
grokApiKey: credential?.kind === 'api_key' && grokApiKeyOptIn,
|
|
4808
|
+
});
|
|
4809
|
+
if (namedChildDecision.refuse) { ui.error(namedChildDecision.refuse); debug.log('self-implement.pod', 'child-provider-refused', { provider: namedChild, reason: namedChildDecision.refuse }); process.exit(2); }
|
|
4810
|
+
// A named codex child must stay codex — the plan may not fall back to grok (post-review must-fix).
|
|
4811
|
+
const namedCodex = namedChildDecision.provider === 'openai-codex';
|
|
4812
|
+
const plan: import('./task-orchestrator/surfaces/pod-account-broker.js').PodProviderPlan = namedChildDecision.provider === 'grok'
|
|
4813
|
+
? { provider: 'grok', excluded: [], grokSubscriptionEligible: credential?.kind === 'subscription' }
|
|
4814
|
+
: planPodProvider({
|
|
4655
4815
|
codexCandidates: inspectCodexRotation().candidates,
|
|
4656
4816
|
// Per-account caps (대표 default:97) override the Pod default cap — without them default was dropped at 60%.
|
|
4657
4817
|
thresholdPercentByAccount: getUserConfig().llm?.codexAccountRotationThresholdPercentByAccount,
|
|
4658
4818
|
// 대표 한도 정책 한 값(`llm.codexQuotaPolicy`) — 크레딧·폴백을 같이 정한다.
|
|
4659
4819
|
creditsAllowed: codexPolicyAllowsCredits(quotaPolicy),
|
|
4660
|
-
|
|
4661
|
-
|
|
4820
|
+
...podFallbackCredentials(namedChildDecision.provider, {
|
|
4821
|
+
grokSubscription: codexPolicyAllowsFallback(quotaPolicy) && grokSubscriptionUsable,
|
|
4822
|
+
grokApiKey: codexPolicyAllowsFallback(quotaPolicy) && credential?.kind === 'api_key',
|
|
4823
|
+
}),
|
|
4662
4824
|
grokApiKeyOptIn,
|
|
4663
4825
|
});
|
|
4664
|
-
if (plan.provider === null) { ui.error(`pod: 쓸 codex 계정이 없다 — ${plan.reasons.join(' · ')} · 계정을 명시하려면 --pod-account <이름>`); process.exit(2); }
|
|
4826
|
+
if (plan.provider === null) { ui.error(`pod: 쓸 codex 계정이 없다 — ${plan.reasons.join(' · ')}${namedCodex ? ' · child provider 를 openai-codex 로 지정해 grok 으로 넘기지 않는다' : ''} · 계정을 명시하려면 --pod-account <이름>`); process.exit(2); }
|
|
4665
4827
|
podProvider = plan.provider;
|
|
4666
4828
|
if (plan.provider === 'openai-codex') {
|
|
4667
4829
|
accountBroker = makePodAccountBroker({ usable: plan.accounts, excluded: plan.excluded });
|
|
@@ -4670,6 +4832,10 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4670
4832
|
{ const { emitDecision } = await import('./live/detail-switch.js');
|
|
4671
4833
|
emitDecision({ kind: 'ROUTE', what: `Pod 계정 배분 ${plan.accounts.join(' → ')}`, reason: plan.excluded.length ? `뺌 ${plan.excluded.map((x) => `${x.name}(${x.why})`).join(', ')}` : '모든 계정 여유', purpose: plan.creditAccounts ? '구독 잔량 0 — 정책상 크레딧으로 병렬 조각을 돌린다' : '병렬 조각이 한 계정에 몰리지 않게 잔량 순으로 돌려 준다', phase: 'dispatch', target: `Pod ${plan.accounts.length}계정`, paths: plan.accounts.length + plan.excluded.length }); }
|
|
4672
4834
|
if (!opts.json) ui.info(`[pod] 계정 배분(잔량 순 · 돌려 가며): ${plan.accounts.join(' → ')}${plan.creditAccounts ? ' · 💳 크레딧(구독 잔량 0 · 허가됨)' : ''}${plan.excluded.length ? ` · 뺌 ${plan.excluded.map((x) => `${x.name}(${x.why})`).join(', ')}` : ''}`);
|
|
4835
|
+
} else if (namedChildDecision.provider === 'grok') {
|
|
4836
|
+
const model = (opts as { childLlmModel?: string }).childLlmModel?.trim() || defaultGrokModel().id;
|
|
4837
|
+
debug.log('self-implement.pod', 'provider-named', { provider: 'grok', model, credential: credential?.kind ?? null });
|
|
4838
|
+
if (!opts.json) ui.info(`[pod] child provider = grok(모델 ${model}) — 발사 인자로 지정됨`);
|
|
4673
4839
|
} else {
|
|
4674
4840
|
const model = defaultGrokModel().id;
|
|
4675
4841
|
debug.log('self-implement.pod', 'provider-fallback', { from: 'openai-codex', to: 'grok', excluded: plan.excluded, model });
|
|
@@ -4697,7 +4863,10 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4697
4863
|
...(podSource.kind === 'bundle' ? { headCommit: podSource.headCommit, sizeBytes: podSource.sizeBytes } : {}),
|
|
4698
4864
|
});
|
|
4699
4865
|
}
|
|
4700
|
-
const
|
|
4866
|
+
const childFlags = opts as { childLlmProvider?: string; childLlmModel?: string; childLlmEffort?: string };
|
|
4867
|
+
const podChildLlm = childFlags.childLlmProvider?.trim() ? { childProviderExplicit: true, ...(childFlags.childLlmModel?.trim() ? { childModel: childFlags.childLlmModel.trim() } : {}), ...(childFlags.childLlmEffort?.trim() ? { childEffort: childFlags.childLlmEffort.trim() } : {}) } : {};
|
|
4868
|
+
if (childFlags.childLlmProvider?.trim()) debug.log('self-implement.pod', 'child-provider-named', { provider: childFlags.childLlmProvider.trim(), model: childFlags.childLlmModel ?? null, podProvider });
|
|
4869
|
+
const podBase = { hostSupervised: opts.supervise === true, ...podChildLlm, ...(remoteOnlyPool ? { imageCommit: image.imageCommit } : {}), account: podProvider === 'grok' ? 'grok' : explicitPodAccount ?? 'team', ...(accountBroker ? { accountBroker, rotationAccounts } : {}), ...(podProvider === 'grok' ? { provider: 'grok' as const, grokApiKeyOptIn } : {}), passEnv, ...(pool ? { pool } : {}), ...((opts as { podSkillEnv?: boolean }).podSkillEnv ? { skillEnv: true } : {}), ...(podSource ? { source: podSource } : {}) };
|
|
4701
4870
|
if (benchArms) {
|
|
4702
4871
|
const { benchPodSpawn } = await import('./task-orchestrator/surfaces/self-implement-pod.js');
|
|
4703
4872
|
podSpawn = benchPodSpawn(benchArms, podBase);
|
|
@@ -5873,6 +6042,7 @@ agentCmd.hook('preAction', async (_thisCommand, actionCommand) => {
|
|
|
5873
6042
|
});
|
|
5874
6043
|
|
|
5875
6044
|
registerCapabilitiesCommand(agentCmd);
|
|
6045
|
+
registerSupervisorMetricsCommand(agentCmd);
|
|
5876
6046
|
|
|
5877
6047
|
agentCmd.command('install-from-docs <tool>')
|
|
5878
6048
|
.description('공식 설치 문서를 읽고 안전한 설치 줄을 선택한다 — sudo는 사람에게 넘긴다')
|
|
@@ -6744,6 +6914,11 @@ const selfDevCmd = program
|
|
|
6744
6914
|
// ⭐ `--ask`/`--say` — 발사 절차 넷을 «한 로직»으로. 저작 → 전제 검사 → 발사.
|
|
6745
6915
|
// ⛔ 여기서 저작한 골 파일을 아래 `--file` 자리에 그대로 넘긴다(새 실행 경로를 만들지 않는다).
|
|
6746
6916
|
let askAuthoredFile: string | undefined;
|
|
6917
|
+
if (opts.ask !== undefined && !isOldDoorInternalCall('dev-ask')) {
|
|
6918
|
+
const refused = refuseOldDoor('dev-ask');
|
|
6919
|
+
debug.log('harness.entrance', 'old-door-refused', { door: refused.door, caller: refused.caller });
|
|
6920
|
+
throw new DevPipelineError(refused.message);
|
|
6921
|
+
}
|
|
6747
6922
|
const retirementInput = opts.ask !== undefined
|
|
6748
6923
|
? { kind: 'ask' as const, value: opts.ask }
|
|
6749
6924
|
: opts.say !== undefined
|
|
@@ -7468,6 +7643,7 @@ missionCmd
|
|
|
7468
7643
|
});
|
|
7469
7644
|
|
|
7470
7645
|
registerTasksCommands(program);
|
|
7646
|
+
registerBriefCommands(program);
|
|
7471
7647
|
registerLabelsCommands(program);
|
|
7472
7648
|
registerMsgCommands(program);
|
|
7473
7649
|
|