elanous 0.2.27 → 0.2.28
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/{1454-a9c338f5bb556f42.js → 1454-29d1d773d5996a49.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{599-a914cc0468f56143.js → 599-56f2c0a5cc4a7295.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-07110da72c45e68f.js → page-24453f6a302816b4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-d2d76d4a7eae91bd.js → page-6c131d30bb1cf871.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-fa46d4588e8442c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-e5a9302c105725a3.js → page-dc0772b11861af51.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-66ad46ed0279feb9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/{page-6a16a48d1aa6e91f.js → page-256ffd365d32e100.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-39f82acf619cca23.js → page-4c741eb760f2f77c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-7c2c8f81b185f9c0.js → page-e9ba98f5f1440a21.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/{page-ae7aff07e32676bb.js → page-dafc901bb1b72b5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-482c60c1bc540d0a.js → page-2f6f303fa114ec24.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{layout-7cb996c1aa08b6f5.js → layout-1634081c5272006c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live/{page-623e08fe4477d606.js → page-ced0bcfc6542b3fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/{page-db460cd8aecb8490.js → page-bb1f05cd51c38944.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-ff27902d0b11ef4f.js → page-646b50f63b6fe732.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-1917ea87ea71ab6b.js → page-f736324afa2117c1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-25a302273b054fd7.js → page-6f131b51193a36f9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{not-found-670510eda8b9443f.js → not-found-435f5e2faf02bc01.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-4bb7556e2e97a750.js → page-8966452228753c5e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/{page-4eb96fc7241c2456.js → page-66a67eb19ebd976b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-0d64ff212dc55d03.js → page-c71267e7681da982.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/{page-7f096248993fc2d4.js → page-a21d1e1797172692.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-e47fc72049149a38.js → page-cb249e81ed339318.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-f7d808e31e005895.js → page-781cfc5114e097da.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/{page-5c2b24b5496dad73.js → page-478157214db6a023.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-76cdb531668b5191.js → page-86141f12cf090b7f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/{page-dab163b338e3b966.js → page-979d318a534e92da.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/{page-0260ffc7eda50db1.js → page-21050928a697ed7a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/{page-99c4e6c7345a9156.js → page-601fb77340e63c9a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +13 -13
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +13 -13
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +13 -13
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +13 -13
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +13 -13
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +13 -13
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +13 -13
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +13 -13
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +13 -13
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +13 -13
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +13 -13
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +13 -13
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +13 -13
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +13 -13
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +13 -13
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +13 -13
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +13 -13
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +13 -13
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +13 -13
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +13 -13
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +13 -13
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +13 -13
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +13 -13
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +13 -13
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +13 -13
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +13 -13
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +13 -13
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +13 -13
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +14 -14
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +13 -13
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +13 -13
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +13 -13
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +13 -13
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +13 -13
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +13 -13
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +13 -13
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +13 -13
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +13 -13
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +13 -13
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +13 -13
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +13 -13
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +13 -13
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +13 -13
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +13 -13
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +13 -13
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +13 -13
- package/graphs/implement-loop.yaml +38 -1
- package/graphs/steward/recipes.yaml +6 -0
- package/graphs/steward/release-day.yaml +23 -0
- package/graphs/steward/steward.yaml +9 -1
- package/graphs/work/code-pr.yaml +23 -0
- package/package.json +1 -1
- package/scripts/browser-observe-cycle.ts +76 -2
- package/scripts/ci-typecheck-changed.ts +50 -17
- package/scripts/detect-test-interference.ts +31 -1
- package/scripts/release-loop/docs-node.ts +51 -22
- package/scripts/release-loop/gate-node.ts +37 -4
- package/scripts/release-loop/node-verdict.ts +3 -1
- package/scripts/release-loop/publish-node.ts +3 -0
- package/scripts/release-loop/tui-node-checks.ts +5 -2
- package/scripts/skills/public-check.ts +5 -2
- package/scripts/test-deterministic.ts +520 -37
- package/scripts/ux-sim.ts +7 -1
- package/scripts/verify-kpack6-live.ts +230 -0
- package/src/acp/codex-plugins.ts +17 -0
- package/src/agent/task-notification.ts +2 -1
- package/src/agent-mission/in-agent-plugin.ts +8 -3
- package/src/agent-substrate/self-review-cli.ts +34 -10
- package/src/briefing/brief-items.ts +151 -35
- package/src/budget/llm-cost.ts +25 -2
- package/src/budget/usage-outcomes.ts +32 -0
- package/src/claims/claims-ledger.ts +23 -0
- package/src/claims/claims-render.ts +22 -2
- package/src/cli/brief-cli.ts +131 -10
- package/src/cli/claims-cli.ts +24 -4
- package/src/cli/msg-cli.ts +165 -9
- package/src/cli/plugin-cli.ts +11 -3
- package/src/cli/pr-cli.ts +80 -18
- package/src/cli/pr-land-refusal.ts +20 -0
- package/src/cli/release-cli.ts +2 -0
- package/src/cli/rfc-cli.ts +24 -0
- package/src/cli/tailscale-serve.ts +5 -8
- package/src/cli/tasks-cli.ts +393 -26
- package/src/cli/usage-cli.ts +9 -4
- package/src/dashboard/first-screen-band.ts +63 -13
- package/src/dashboard/index.ts +8 -3
- package/src/dashboard/skill-detection-runtime.ts +24 -4
- package/src/domains/morning-report.ts +3 -1
- package/src/github/pr-labels.ts +10 -4
- package/src/graph-runner/runner.ts +101 -14
- package/src/harness/harness-clean.ts +21 -3
- package/src/harness/harness-cli-command.ts +22 -6
- package/src/harness/harness-pod-dispatch.ts +11 -4
- package/src/hq/seats.ts +17 -3
- package/src/index.ts +34 -5
- package/src/intelligence-map/model-bench-scores.ts +102 -0
- package/src/loops/orchestrator/inbox.ts +73 -0
- package/src/loops/orchestrator/resync-shadow.ts +100 -12
- package/src/loops/orchestrator/tick.ts +73 -2
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/msg/msg-sse-server.ts +141 -0
- package/src/msg/msg-store.ts +84 -14
- package/src/patents/ledger.ts +128 -0
- package/src/plugins/install/market-fetch.ts +32 -1
- package/src/pod-lease/admission.ts +116 -41
- package/src/release-loop/checklist.ts +11 -0
- package/src/release-loop/merged-pr-checklist.ts +24 -5
- package/src/release-loop/rubric.ts +70 -0
- package/src/rfc-registry/registry.ts +88 -0
- package/src/seat-dispatch/seat-request-ledger.ts +4 -0
- package/src/seat-loop/knowhow-lint.ts +233 -0
- package/src/seat-loop/seat-pack.ts +16 -4
- package/src/seat-loop/traffic-signal.ts +7 -0
- package/src/self-dev/ask-launch-flow.ts +48 -8
- package/src/self-dev/ask-path-candidates.ts +69 -14
- package/src/self-dev/decompose-proposal.ts +43 -1
- package/src/self-dev/graph-journey-nodes.ts +2 -0
- package/src/self-dev/launch-preflight-text.ts +5 -1
- package/src/self-dev/launch-preflight.ts +143 -10
- package/src/self-implement/gate-cli.ts +6 -2
- package/src/self-implement/goal-author.ts +2 -1
- package/src/self-implement/goal-new-paths.ts +4 -5
- package/src/self-implement/graph-authority.ts +17 -3
- package/src/self-implement/graph-yaml.ts +15 -7
- package/src/self-implement/headless-elanous-driver.ts +16 -1
- package/src/self-implement/host-regate.ts +44 -9
- package/src/self-implement/orchestrator.ts +3 -10
- package/src/self-implement/rework-policy.ts +80 -2
- package/src/self-implement/speed-claims.ts +145 -6
- package/src/skills/tools/persistent-grounding.ts +59 -4
- package/src/skills/tools/shell.ts +79 -1
- package/src/steward/rejudge-tick.ts +12 -1
- package/src/steward/release-day.ts +158 -0
- package/src/steward/resync-tick.ts +123 -0
- package/src/task-agent/actions.ts +1 -0
- package/src/task-agent/adopt-pr.ts +140 -0
- package/src/task-agent/board.ts +11 -1
- package/src/task-agent/card-evidence.ts +37 -5
- package/src/task-agent/cover.ts +84 -17
- package/src/task-agent/failure-notify.ts +61 -0
- package/src/task-agent/green-sweep.ts +170 -0
- package/src/task-agent/land-worktree.ts +52 -5
- package/src/task-agent/live-move-history.ts +1 -0
- package/src/task-agent/live-moves.ts +43 -12
- package/src/task-agent/parent-host.ts +1 -1
- package/src/task-agent/postland-card.ts +139 -0
- package/src/task-agent/rejudge-on-head.ts +106 -7
- package/src/task-agent/remote-rejudge-bind.ts +62 -0
- package/src/task-agent/repair-branch-cas.ts +182 -0
- package/src/task-agent/repair-cycle.ts +275 -0
- package/src/task-agent/repair-next-move.ts +31 -0
- package/src/task-agent/repair-review.ts +24 -0
- package/src/task-agent/repair-worker.ts +87 -0
- package/src/task-agent/review-result-capture.ts +2 -1
- package/src/task-agent/shadow.ts +13 -7
- package/src/task-agent/task-hand.ts +115 -6
- package/src/task-orchestrator/surfaces/pod-repair-commit.ts +96 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +70 -12
- package/src/telegram.ts +30 -1
- package/src/user-config.ts +8 -1
- package/src/ux-sim/fault-sqlite-busy.ts +50 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-fcb06e305f515527.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-15c0a4095baddfba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +0 -1
- /package/apps/pwa/out/_next/static/{Ev2jivDMTSoEc-5rIXdcy → y1ltt7oCZxVpC6zVPhZ2O}/_buildManifest.js +0 -0
- /package/apps/pwa/out/_next/static/{Ev2jivDMTSoEc-5rIXdcy → y1ltt7oCZxVpC6zVPhZ2O}/_ssgManifest.js +0 -0
package/src/cli/plugin-cli.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
6
6
|
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
7
7
|
import { userConfigPath } from '../user-config.js';
|
|
8
8
|
import { debug, redactSecretText } from '../debug/log.js';
|
|
9
|
-
import { addMarket, ensureInternalMarketIndex, listMarkets, MarketFetchError, updateMarket } from '../plugins/install/market-fetch.js';
|
|
9
|
+
import { addMarket, codexPluginPackagePath, ensureInternalMarketIndex, listMarkets, MarketFetchError, updateMarket } from '../plugins/install/market-fetch.js';
|
|
10
|
+
import { readCodexPluginList } from '../acp/codex-plugins.js';
|
|
10
11
|
import { emitDecision } from '../live/detail-switch.js';
|
|
11
12
|
import { OFFICIAL_INDEX_KEYS } from '../market/official-keys.js';
|
|
12
13
|
import { installPlugin, listInstalledPlugins, PluginInstallError, removePlugin, type InstallEvent } from '../plugins/install/plugin-install.js';
|
|
@@ -118,15 +119,22 @@ export function registerPluginCommands(program: Command): void {
|
|
|
118
119
|
}
|
|
119
120
|
});
|
|
120
121
|
plugin.command('add <spec>').description('Install a local path, pinned git plugin or signed market plugin')
|
|
122
|
+
.option('--from-codex', 'Import an installed Codex plugin by name@marketplace')
|
|
121
123
|
.option('--yes', 'Accept requested capabilities')
|
|
122
124
|
.option('--json', 'NDJSON progress events')
|
|
123
125
|
.option('--allow-unsigned', 'Allow unsigned marketplace indices')
|
|
124
126
|
.option('--refresh', 'Refresh the signed marketplace index before installing')
|
|
125
|
-
.action(async (spec: string, opts: { yes?: boolean; json?: boolean; allowUnsigned?: boolean; refresh?: boolean }) => {
|
|
127
|
+
.action(async (spec: string, opts: { yes?: boolean; json?: boolean; allowUnsigned?: boolean; refresh?: boolean; fromCodex?: boolean }) => {
|
|
126
128
|
try {
|
|
127
129
|
const root = elanousStateRoot();
|
|
128
130
|
const nodeCount = { value: 0 };
|
|
129
|
-
|
|
131
|
+
let source = spec;
|
|
132
|
+
if (opts.fromCodex) {
|
|
133
|
+
const match = /^([a-z0-9][a-z0-9-]{1,39})@([a-z0-9][a-z0-9-]{1,39})$/.exec(spec);
|
|
134
|
+
if (!match) throw new PluginInstallError('io', 'Codex import requires name@marketplace');
|
|
135
|
+
source = codexPluginPackagePath(await readCodexPluginList(), match[1]!, match[2]!);
|
|
136
|
+
}
|
|
137
|
+
await installPlugin(source, {
|
|
130
138
|
root, marketDir: join(root, 'plugins', 'markets'), trustedKeys: keys(),
|
|
131
139
|
yes: opts.yes, allowUnsigned: opts.allowUnsigned, refresh: opts.refresh,
|
|
132
140
|
onEvent: event => outputEvent(event, !!opts.json, nodeCount),
|
package/src/cli/pr-cli.ts
CHANGED
|
@@ -58,7 +58,9 @@ import { parseReleaseNoteSection } from '../release-loop/release-note.js';
|
|
|
58
58
|
import { landingFreezeMessage } from '../release-loop/landing-freeze.js';
|
|
59
59
|
import { admitLandingMerge } from '../self-implement/frozen-merges.js';
|
|
60
60
|
import { verifyAncestorAutoPass, verifyOverlapEvidence } from './pr-land-overlap-evidence.js';
|
|
61
|
+
import { observePrLandRefusal } from './pr-land-refusal.js';
|
|
61
62
|
import { taskAgentStatePath } from '../task-agent/task-hand.js';
|
|
63
|
+
import { PR_LABEL_NAMES } from '../github/pr-labels.js';
|
|
62
64
|
import { enqueueL8ShadowQueue, runL8ShadowQueue, shadowPrNumber, statusL8ShadowQueue, type L8ShadowQueueDeps } from '../self-implement/l8-merge-queue.js';
|
|
63
65
|
|
|
64
66
|
export { branchLineageSlug, findSiblingPrs };
|
|
@@ -1143,8 +1145,36 @@ export function runPrGranularity(opts: PrGranularityOpts = {}, deps: PrLandDeps
|
|
|
1143
1145
|
const GITHUB_MERGEABLE = new Set(['MERGEABLE', 'CONFLICTING', 'UNKNOWN']);
|
|
1144
1146
|
const GITHUB_MERGE_STATE = new Set(['BEHIND', 'BLOCKED', 'CLEAN', 'DIRTY', 'DRAFT', 'HAS_HOOKS', 'UNKNOWN', 'UNSTABLE']);
|
|
1145
1147
|
|
|
1148
|
+
/** Read-only identity check shared by pinned landing and its dry-run. Later landing gates still run only on a real landing. */
|
|
1149
|
+
function inspectPinnedPr(run: CmdRunner, cwd: string, pr: number, expectedHead: string) {
|
|
1150
|
+
const viewed = run('gh', ['pr', 'view', String(pr), '--json', 'headRefOid,headRefName,state,isDraft,url'], { cwd });
|
|
1151
|
+
let value: { headRefOid?: string; headRefName?: string; state?: string; isDraft?: boolean; url?: string } = {};
|
|
1152
|
+
try {
|
|
1153
|
+
if (viewed.ok) {
|
|
1154
|
+
const parsed: unknown = JSON.parse(viewed.out);
|
|
1155
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) value = parsed as typeof value;
|
|
1156
|
+
}
|
|
1157
|
+
} catch { /* unreadable is not approval */ }
|
|
1158
|
+
const local = run('git', ['rev-parse', 'HEAD'], { cwd });
|
|
1159
|
+
const dirty = run('git', ['status', '--porcelain'], { cwd });
|
|
1160
|
+
const reasons: string[] = [];
|
|
1161
|
+
if (value.state !== 'OPEN') reasons.push('PR is not OPEN or its state is unavailable');
|
|
1162
|
+
if (value.isDraft !== false) reasons.push(value.isDraft === true ? 'PR is draft' : 'PR ready status is unavailable');
|
|
1163
|
+
if (value.headRefOid?.toLowerCase() !== expectedHead.toLowerCase()) reasons.push('PR head differs from --expected-head or is unavailable');
|
|
1164
|
+
if (!value.url?.endsWith(`/pull/${pr}`) || !value.headRefName) reasons.push('PR identity or head branch is unavailable');
|
|
1165
|
+
if (!local.ok || local.out.trim().toLowerCase() !== expectedHead.toLowerCase()) reasons.push('local HEAD differs from --expected-head or is unavailable');
|
|
1166
|
+
if (!dirty.ok || dirty.out.trim()) reasons.push(dirty.ok ? 'local worktree is dirty' : 'local worktree status is unavailable');
|
|
1167
|
+
return { ok: reasons.length === 0, reasons, branch: value.headRefName, url: value.url };
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1146
1170
|
export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): Promise<number> {
|
|
1147
1171
|
const out = deps.out ?? liveOut;
|
|
1172
|
+
// First slice: observe pinned identity/branch, overlap decision, and GitHub merge refusals.
|
|
1173
|
+
// Option syntax and prerequisite gate errors do not describe a merge recovery edge.
|
|
1174
|
+
const refuse = (message: string, context: { isDraft?: boolean } = {}): void => {
|
|
1175
|
+
out.error(message);
|
|
1176
|
+
observePrLandRefusal(message, context);
|
|
1177
|
+
};
|
|
1148
1178
|
if (opts.title !== undefined && opts.titleFile !== undefined) {
|
|
1149
1179
|
out.error('✗ title: --title과 --title-file은 함께 사용할 수 없습니다.');
|
|
1150
1180
|
return 1;
|
|
@@ -1248,6 +1278,31 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1248
1278
|
out.log('- Mutations (ready/edit/create/merge, git commit/push, worktree): NOT RUN');
|
|
1249
1279
|
return 0;
|
|
1250
1280
|
}
|
|
1281
|
+
if (opts.dryRun && pinned) {
|
|
1282
|
+
const pr = Number(opts.pr);
|
|
1283
|
+
if (!/^[1-9]\d*$/.test(opts.pr ?? '') || !Number.isSafeInteger(pr) || !/^[a-f0-9]{40}$/i.test(opts.expectedHead ?? '')) {
|
|
1284
|
+
out.error('✗ expected-head: --pr and --expected-head (full SHA) are required together without --hold');
|
|
1285
|
+
return 1;
|
|
1286
|
+
}
|
|
1287
|
+
if (opts.hold) {
|
|
1288
|
+
out.error('✗ dry-run: --hold 는 머리 고정 읽기 전용 예행과 함께 사용할 수 없습니다.');
|
|
1289
|
+
return 1;
|
|
1290
|
+
}
|
|
1291
|
+
if (opts.overlapEvidence !== undefined) {
|
|
1292
|
+
out.error('✗ dry-run: --overlap-evidence 는 머리 고정 읽기 전용 예행에서 사용할 수 없습니다.');
|
|
1293
|
+
return 1;
|
|
1294
|
+
}
|
|
1295
|
+
const inspected = inspectPinnedPr(run, cwd, pr, opts.expectedHead!);
|
|
1296
|
+
const branch = (deps.currentBranch ?? liveCurrentBranch)(cwd);
|
|
1297
|
+
const reasons = [...inspected.reasons];
|
|
1298
|
+
if (!branch || branch !== inspected.branch) reasons.push('current branch differs from the PR head branch or is unavailable');
|
|
1299
|
+
out.log(`[dry-run] pinned PR #${pr} · expected head ${opts.expectedHead}`);
|
|
1300
|
+
for (const reason of reasons) out.log(`[dry-run] ✗ preflight: ${reason}`);
|
|
1301
|
+
if (reasons.includes('PR is draft')) out.log(`[dry-run] 선행: eln gh pr ready ${pr}`);
|
|
1302
|
+
if (reasons.length === 0) out.log('[dry-run] ✓ preflight: PR OPEN non-draft, matching PR/local HEAD and branch, clean worktree');
|
|
1303
|
+
out.log('[dry-run] Remaining landing gates, freeze, overlap and merge: UNMEASURED; no PR or git state changed.');
|
|
1304
|
+
return reasons.length === 0 ? 0 : 1;
|
|
1305
|
+
}
|
|
1251
1306
|
if (opts.overlapEvidence !== undefined && (!pinned || !opts.overlapEvidence.trim())) {
|
|
1252
1307
|
out.error('✗ overlap-evidence: --overlap-evidence <file> 는 --pr ⊕ --expected-head 머리 고정 착지에서만 쓴다.');
|
|
1253
1308
|
return 1;
|
|
@@ -1256,30 +1311,26 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1256
1311
|
let pinnedUrl: string | undefined;
|
|
1257
1312
|
if (pinned) {
|
|
1258
1313
|
const pr = Number(opts.pr);
|
|
1259
|
-
if (!/^[1-9]\d*$/.test(opts.pr ?? '') || !Number.isSafeInteger(pr) || !/^[a-f0-9]{40}$/i.test(opts.expectedHead ?? '') || opts.hold
|
|
1260
|
-
out.error('✗ expected-head: --pr and --expected-head (full SHA) are required together without --hold
|
|
1314
|
+
if (!/^[1-9]\d*$/.test(opts.pr ?? '') || !Number.isSafeInteger(pr) || !/^[a-f0-9]{40}$/i.test(opts.expectedHead ?? '') || opts.hold) {
|
|
1315
|
+
out.error('✗ expected-head: --pr and --expected-head (full SHA) are required together without --hold');
|
|
1261
1316
|
return 1;
|
|
1262
1317
|
}
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
if (value.state !== 'OPEN' || value.isDraft !== false || value.headRefOid?.toLowerCase() !== opts.expectedHead!.toLowerCase()
|
|
1269
|
-
|| !value.url?.endsWith(`/pull/${pr}`) || !value.headRefName || !local.ok || local.out.trim().toLowerCase() !== opts.expectedHead!.toLowerCase()
|
|
1270
|
-
|| !dirty.ok || dirty.out.trim()) {
|
|
1271
|
-
out.error('✗ expected-head: PR OPEN non-draft, matching local HEAD and clean worktree required');
|
|
1318
|
+
const inspected = inspectPinnedPr(run, cwd, pr, opts.expectedHead!);
|
|
1319
|
+
if (!inspected.ok) {
|
|
1320
|
+
refuse('✗ expected-head: PR OPEN non-draft, matching local HEAD and clean worktree required', {
|
|
1321
|
+
isDraft: inspected.reasons.includes('PR is draft'),
|
|
1322
|
+
});
|
|
1272
1323
|
return 1;
|
|
1273
1324
|
}
|
|
1274
|
-
pinnedBranch =
|
|
1275
|
-
pinnedUrl =
|
|
1325
|
+
pinnedBranch = inspected.branch;
|
|
1326
|
+
pinnedUrl = inspected.url;
|
|
1276
1327
|
}
|
|
1277
1328
|
const resolveBase = deps.resolveBase ?? resolveDeliverableBase;
|
|
1278
1329
|
const branch = (deps.currentBranch ?? liveCurrentBranch)(cwd);
|
|
1279
1330
|
if (!branch || (pinned && branch !== pinnedBranch)) {
|
|
1280
1331
|
const detail = pinned ? 'PR head branch와 현재 브랜치가 다릅니다.' : '현재 브랜치를 해석하지 못했습니다.';
|
|
1281
1332
|
record('branch', false);
|
|
1282
|
-
|
|
1333
|
+
refuse(`✗ branch: ${detail}`);
|
|
1283
1334
|
return 1;
|
|
1284
1335
|
}
|
|
1285
1336
|
record('branch', true);
|
|
@@ -1664,6 +1715,7 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1664
1715
|
const hold = !!opts.hold || overlapDecision?.outcome === 'user-hold';
|
|
1665
1716
|
// TA-LAND-OVERLAP — 비대화형 «승인 불가»만 증거로 대신한다(사람의 hold 는 증거로 뒤집지 않는다) · 증거가 없거나 어긋나면 종전 거부 그대로.
|
|
1666
1717
|
let overlapEvidenceAccepted = false;
|
|
1718
|
+
let ancestorResyncNeeded = false;
|
|
1667
1719
|
if (pinned && overlapDecision?.outcome === 'unavailable' && opts.overlapEvidence !== undefined) {
|
|
1668
1720
|
const ref = resolveRemoteBranchRef(run, cwd, base);
|
|
1669
1721
|
const verdict = verifyOverlapEvidence({
|
|
@@ -1678,7 +1730,7 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1678
1730
|
? `✓ overlap-evidence: base-advanced-disjoint — gate base ${verdict.gateBase.slice(0, 12)} ⊂ head ${opts.expectedHead!.slice(0, 12)} · ${ref.remote}/${ref.branch} ${verdict.baseTip.slice(0, 12)} 까지 ${verdict.windowCommits}개 커밋이 PR 파일을 안 건드린다 · review pass|warn must-fix 0 (${verdict.reviewResult})`
|
|
1679
1731
|
: `✓ overlap-evidence: ${ref.remote}/${ref.branch} ${verdict.baseTip.slice(0, 12)} ⊂ head ${opts.expectedHead!.slice(0, 12)} · gate passed on that base · review pass must-fix 0 (${verdict.reviewResult})`);
|
|
1680
1732
|
}
|
|
1681
|
-
else
|
|
1733
|
+
else refuse(`✗ overlap-evidence: ${verdict.reason}`);
|
|
1682
1734
|
} else if (pinned && overlapDecision?.outcome === 'unavailable') {
|
|
1683
1735
|
// 증거 파일이 없을 때 — 겹친 착지가 전부 머리의 조상이고 표준 자리의 리뷰가 pass|warn ⊕ must-fix 0 이면 통과(아니면 종전 거부).
|
|
1684
1736
|
const verdict = verifyAncestorAutoPass({
|
|
@@ -1690,9 +1742,19 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1690
1742
|
if (verdict.ok) {
|
|
1691
1743
|
out.log(`✓ overlap-evidence: already-ancestor-auto — 겹친 최근 착지 ${overlappingLandings.length}개가 전부 head ${opts.expectedHead!.slice(0, 12)} 의 조상 · review pass|warn must-fix 0 (${verdict.reviewResult})`);
|
|
1692
1744
|
}
|
|
1693
|
-
else
|
|
1745
|
+
else {
|
|
1746
|
+
refuse(`✗ ancestor-auto: ${verdict.reason}`);
|
|
1747
|
+
ancestorResyncNeeded = verdict.reason.startsWith('ancestor-auto-not-ancestor:');
|
|
1748
|
+
}
|
|
1694
1749
|
}
|
|
1695
1750
|
if (pinned && overlapDecision && overlapDecision.outcome !== 'user-merge' && !overlapEvidenceAccepted) {
|
|
1751
|
+
// A clean GitHub PR can still be behind a recently landed overlapping head. Preserve the cue
|
|
1752
|
+
// across hosts; the current steward tick acts only if it can also prove local run ownership.
|
|
1753
|
+
if (ancestorResyncNeeded && !opts.dryRun) {
|
|
1754
|
+
const marked = run('gh', ['pr', 'edit', String(opts.pr), '--add-label', PR_LABEL_NAMES.needsRebase], { cwd });
|
|
1755
|
+
record('resync-marker', marked.ok, { pr: Number(opts.pr), reason: 'ancestor-auto-not-ancestor' });
|
|
1756
|
+
if (!marked.ok) out.error('⚠ resync-marker: needs-rebase 라벨을 남기지 못했습니다');
|
|
1757
|
+
}
|
|
1696
1758
|
out.error('✗ expected-head: overlap merge approval unavailable for the reviewed head');
|
|
1697
1759
|
return 1;
|
|
1698
1760
|
}
|
|
@@ -1753,7 +1815,7 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1753
1815
|
if (opts.hold) {
|
|
1754
1816
|
out.log(`[dry-run] ${existing.url ? '기존 PR을 갱신' : 'PR을 생성'}하고 --hold 로 병합하지 않고 멈춥니다.`);
|
|
1755
1817
|
} else {
|
|
1756
|
-
out.log(`[dry-run] ${existing.url ? '기존 PR을 갱신하고 ready 상태를 보장' : 'PR을 생성하고 ready 상태를 보장'}한 뒤 squash merge 합니다.`);
|
|
1818
|
+
out.log(`[dry-run] 머리 고정 없는 일반 착지: ${existing.url ? '기존 PR을 갱신하고 ready 상태를 보장' : 'PR을 생성하고 ready 상태를 보장'}한 뒤 squash merge 합니다.`);
|
|
1757
1819
|
}
|
|
1758
1820
|
return 0;
|
|
1759
1821
|
}
|
|
@@ -1927,7 +1989,7 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
|
|
|
1927
1989
|
...(mergeable ? { mergeable } : {}),
|
|
1928
1990
|
...(mergeStateStatus ? { mergeStateStatus } : {}),
|
|
1929
1991
|
});
|
|
1930
|
-
|
|
1992
|
+
refuse(`✗ merge: ${detail}`);
|
|
1931
1993
|
if (mergeable === 'CONFLICTING') {
|
|
1932
1994
|
out.error(' ↳ 충돌 — 이 브랜치가 기준 브랜치의 최근 착지와 같은 줄을 고쳤다. `bun bin/elanous.mjs git fetch origin` → `bun bin/elanous.mjs git rebase origin/<기준>` 로 풀고 다시 pr land.');
|
|
1933
1995
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readJourneyEdge, recordJourneyEdge } from '../self-dev/graph-journey-route.js';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
|
|
4
|
+
/** The five outcomes of an observed `pr land` refusal. This function never retries a landing. */
|
|
5
|
+
export type PrLandRefusal = 'draft' | 'head-branch' | 'not-ancestor' | 'review-missing' | 'other';
|
|
6
|
+
|
|
7
|
+
export function classifyPrLandRefusal(message: string, context: { isDraft?: boolean } = {}): PrLandRefusal {
|
|
8
|
+
if (context.isDraft === true && message.startsWith('✗ expected-head: PR OPEN non-draft')) return 'draft';
|
|
9
|
+
if (message.startsWith('✗ branch: PR head branch와 현재 브랜치가 다릅니다.')) return 'head-branch';
|
|
10
|
+
if (message.startsWith('✗ ancestor-auto: ancestor-auto-not-ancestor:')) return 'not-ancestor';
|
|
11
|
+
if (/^✗ (?:ancestor-auto|overlap-evidence): (?:review-missing|review-not-reviewed|review-error|review-no-result|review-unreadable|review-pr-mismatch|review-head-mismatch|review-path-not-for-this-pr-head|review-verdict-null|review-must-fix-unknown)(?:\b|$)/.test(message)) return 'review-missing';
|
|
12
|
+
return 'other';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Read the declared recovery edge and observe the refusal. No recovery command runs here. */
|
|
16
|
+
export function observePrLandRefusal(message: string, context: { isDraft?: boolean } = {}): void {
|
|
17
|
+
const route = readJourneyEdge('merge', classifyPrLandRefusal(message, context));
|
|
18
|
+
if (route.to !== null) recordJourneyEdge(route, route.to, 'pr-land-refused; recovery-execution=none');
|
|
19
|
+
else debug.log('self-implement', 'graph-edge-unresolved', { from: 'merge', label: route.label, reason: 'pr-land-refused; recovery-execution=none' });
|
|
20
|
+
}
|
package/src/cli/release-cli.ts
CHANGED
|
@@ -53,6 +53,7 @@ import { autoStartScheduledRelease, type AutoStartDeferral } from '../release-lo
|
|
|
53
53
|
import { runRehearsalTick, type RehearsalDeps } from '../release-loop/rehearsal.js';
|
|
54
54
|
import { landingFreezeMessage, LandingFrozenError, readLandingFreeze } from '../release-loop/landing-freeze.js';
|
|
55
55
|
import { formatLightRc, runLightRc, type LightRcDeps } from '../release-loop/light-rc.js';
|
|
56
|
+
import { registerRfcCommands } from './rfc-cli.js';
|
|
56
57
|
|
|
57
58
|
export const DEFAULT_PUBLIC_REPO = 'ElanvitalAI/elanous';
|
|
58
59
|
const SEMVER = /^\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\.\d+)?$/;
|
|
@@ -623,6 +624,7 @@ function compareReleaseVersions(a: string, b: string): number {
|
|
|
623
624
|
}
|
|
624
625
|
|
|
625
626
|
export function registerReleaseCommands(program: Command, releaseRunDeps: UnattendedReleaseDeps = {}, landedDeps: LandedButYellowDeps = {}, hqDeps: HqDeps = {}, lightRcDeps: LightRcDeps = {}, rehearsalDeps: RehearsalDeps = {}): void {
|
|
627
|
+
registerRfcCommands(program);
|
|
626
628
|
const release = program.command('release').description('공개 배포 한 판 — prepare(로컬) → publish(--yes) → verify (docs/manual/MANUAL-versioning-and-release-2026-09-25.md)');
|
|
627
629
|
const schedule = release.command('schedule').description('판별 컷·착지 마감 조회·갱신');
|
|
628
630
|
const scheduleLedgerRoot = () => releaseRunDeps.ledgerRoot ?? releaseLedgerRoot();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { CliUserError } from './cli-user-error.js';
|
|
3
|
+
import { listRfcs, showRfc } from '../rfc-registry/registry.js';
|
|
4
|
+
|
|
5
|
+
/** RFC-REGISTRY first slice: list/show initialize an empty registry if needed, then only read rows. */
|
|
6
|
+
export function registerRfcCommands(program: Command): void {
|
|
7
|
+
const rfc = program.command('rfc').description('RFC registry (list/show initialize the database when absent)');
|
|
8
|
+
rfc.command('list').description('registered RFCs').option('--json', 'JSON rows')
|
|
9
|
+
.action((opts: { json?: boolean }) => {
|
|
10
|
+
const rows = listRfcs();
|
|
11
|
+
if (opts.json) console.log(JSON.stringify(rows));
|
|
12
|
+
else for (const row of rows) console.log(`${row.id} · ${row.status} · ${row.title}`);
|
|
13
|
+
});
|
|
14
|
+
rfc.command('show <id>').description('RFC and its items').option('--json', 'JSON record')
|
|
15
|
+
.action((id: string, opts: { json?: boolean }) => {
|
|
16
|
+
const row = showRfc(id);
|
|
17
|
+
if (!row) throw new CliUserError(`없는 RFC: ${id}`);
|
|
18
|
+
if (opts.json) console.log(JSON.stringify(row));
|
|
19
|
+
else {
|
|
20
|
+
console.log(`${row.id} · ${row.status} · ${row.title}`);
|
|
21
|
+
for (const item of row.items) console.log(` ${item.id} · ${item.status} · ${item.title}${item.links.length ? ` → ${item.links.map((link) => link.target_item_id).join(', ')}` : ''}`);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
// Unified Tailscale Serve helper — single source of truth for the
|
|
2
2
|
// two transport modes monad-agent uses on macOS:
|
|
3
3
|
//
|
|
4
|
-
// - `https-443` —
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// `pwa-start`). HTTP/2 forwarder · NOT WebSocket-
|
|
8
|
-
// friendly (Upgrade returns 502).
|
|
4
|
+
// - `https-443` — explicit legacy mode on the host's standard HTTPS:443.
|
|
5
|
+
// HTTP/2 forwarding does not preserve WebSocket Upgrade
|
|
6
|
+
// (the daily PWA sharing path no longer selects it).
|
|
9
7
|
//
|
|
10
8
|
// - `tls-tcp` — per-port TLS terminator forwarding plaintext TCP
|
|
11
9
|
// (HTTP/1.1) to a backend on `localhost:<port>`.
|
|
12
|
-
// Used by `pwa
|
|
13
|
-
//
|
|
14
|
-
// (the iPad-side multi-LLM dispatch needs this).
|
|
10
|
+
// Used by `pwa share enable`, `pwa-start` auto-share and
|
|
11
|
+
// `pwa test --https`. WebSocket Upgrade returns 101.
|
|
15
12
|
//
|
|
16
13
|
// Why unify? Before this lift, `defaultServe` (https-443) and
|
|
17
14
|
// `mountTailscaleTestServe` (tls-tcp) duplicated:
|