elanous 0.2.17 → 0.2.18
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/P6YTVgzuZz5oTZhY4Din_/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1307-aac7332576c4d6fc.js → 1307-30dff22c9e1f3073.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3857-4f936cdb30322aa6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4554-5761612531d0146b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-a11f37254196b659.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6158.9c0449a9a8d0064b.js → 6158.af2e93b7adff709b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8401-8615a660c84cdb03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/{page-3143b07a817d1da9.js → page-d92f7ee3994e84c7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-17ba086ef82d339b.js → page-4733c967b56a4277.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-7eb661ff23af7da2.js → page-d22fd849cc22f104.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-bb742f995c6769e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-6e5c3a867557298b.js → page-02b073a2ac793b83.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-60c3da708f9a0ccc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-8a9b3594bc23289b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-5e77cd1802567c89.js → page-a0eb02638b1e6f31.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-308111abadf35670.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6eaf7bac37830c21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-4187666132fc98c4.js → page-5d97b2901e0d1ea6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/{page-09328d499162bae4.js → page-c39554c321576982.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-29ff3a8f84f03b6a.js → page-8c3d8e63ae2e1c98.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-80ec7401bc83f511.js → page-9b72a07d424701c6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-bd5d586429167fea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-fc7d86467291ae38.js → page-a572f58cd3ca5864.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-59b7834d497c2255.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-be5ea965a07fbc41.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-0e2d6985fb42cd2f.js → page-c130b63862437814.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/{page-13e4108999f58d13.js → page-fa244bd146a00ae8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-e8296ee284aa1293.js → page-44d56d6391965a6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-043a9111e74f6b24.js → page-83a700d4c754d802.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{not-found-23a4601ceb7f452e.js → not-found-7b3170f374f77b9d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-5f23d0c66a3b4793.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/{page-10d958605a77b3bd.js → page-a3c58f5c72a5f3f9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a2c4625596f8d69c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-0e9099531d239f11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-7a1d85e121065cc8.js → page-e8e1ecaea7cd71d2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-a1b7ffed710a93e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-12916918988ac97e.js → page-1467047104141297.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/{page-d8a3347a9d0c3f4a.js → page-2da6f9b8a38c6978.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-102310930791197a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-f331e38fefc00393.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-6ed0b73bae8351d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/{page-1d824510df025d18.js → page-44d5f767491692bf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-43336055451f6e37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-7f49fe645d5132f7.js → page-3cc47dca0922ab9a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a77ee355a2304ff0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/{page-27d71f131acd9320.js → page-b17cd46cf0e9b8cf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-61553851aa606146.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-a1f585e154e61c59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/{page-424659bacfb8cdd7.js → page-7bf54c9bb9274af8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-5150ef17b5383a57.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b9d8ce70792c1672.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-a5a3de231f2cc7d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-5d4fef9ccd7d406b.js → page-134da468538baf48.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31ac4afa2dcd915c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{webpack-539cde99554be20f.js → webpack-c2782b330447ffb6.js} +1 -1
- package/apps/pwa/out/_next/static/css/7fa358fec7da7c47.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +14 -14
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +14 -14
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +14 -14
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +14 -14
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +14 -14
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +14 -14
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +14 -14
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +14 -14
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +14 -14
- package/apps/pwa/out/decisions/index.html +1 -0
- package/apps/pwa/out/decisions/index.txt +30 -0
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +14 -14
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +14 -14
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +14 -14
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +14 -14
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +14 -14
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +14 -14
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +14 -14
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +14 -14
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +14 -14
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +14 -14
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +14 -14
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +14 -14
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +14 -14
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +14 -14
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +14 -14
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +14 -14
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +14 -14
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +15 -15
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +14 -14
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +14 -14
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +14 -14
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +14 -14
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +14 -14
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +14 -14
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +14 -14
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +14 -14
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +14 -14
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +14 -14
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +14 -14
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +14 -14
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +14 -14
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +14 -14
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +14 -14
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +14 -14
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +14 -14
- package/package.json +2 -1
- package/samples/workflows/templates/approval-gated-deploy.yaml +30 -0
- package/samples/workflows/templates/chat-driven-research.yaml +35 -0
- package/samples/workflows/templates/discord-listen-and-respond.yaml +29 -0
- package/samples/workflows/templates/http-poll-then-alert.yaml +30 -0
- package/samples/workflows/templates/manual-quickstart.yaml +21 -0
- package/samples/workflows/templates/scheduled-daily-digest.yaml +30 -0
- package/samples/workflows/templates/webhook-deploy-hook.yaml +27 -0
- package/scripts/ci-public-export-import-gate.ts +7 -2
- package/scripts/ci-typecheck-changed.ts +21 -6
- package/scripts/discord-seat-probe.ts +3 -2
- package/scripts/docs/generate-cli-anatomy.ts +162 -0
- package/scripts/goals/authoring-metrics.ts +73 -0
- package/scripts/landing-heal/must-fix-match.ts +7 -7
- package/scripts/landing-heal/run-mission.ts +3 -2
- package/scripts/public-export-test-run.ts +37 -2
- package/scripts/release-loop/checklist-gate-node.ts +13 -11
- package/scripts/release-loop/cut-branch.ts +2 -1
- package/scripts/release-loop/cutoff.ts +4 -2
- package/scripts/release-loop/docs-land-node.ts +8 -1
- package/scripts/release-loop/docs-node.ts +1 -1
- package/scripts/release-loop/gate-node.ts +99 -14
- package/scripts/release-loop/node-verdict.ts +2 -1
- package/scripts/release-loop/npm-publish-node.ts +11 -7
- package/scripts/release-loop/ops-upgrade-node.ts +8 -1
- package/scripts/release-loop/preflight.ts +246 -0
- package/scripts/release-loop/publish-node.ts +8 -1
- package/scripts/release-loop/release-readiness.ts +11 -6
- package/scripts/release-loop/release-version.ts +48 -0
- package/scripts/release-loop/resume-release.ts +115 -0
- package/scripts/release-loop/unattended-release.ts +43 -7
- package/scripts/release-loop/version-node.ts +145 -40
- package/scripts/rhythm/daily.ts +25 -4
- package/scripts/skills/public-check.ts +62 -12
- package/scripts/test-deterministic.ts +51 -33
- package/scripts/test-diet/effectiveness.ts +62 -1
- package/scripts/test-diet/lib.ts +1 -1
- package/scripts/test-diet/node.ts +8 -1
- package/src/agent-mission/review-loop.ts +4 -3
- package/src/agent-substrate/pr-comment-meta.ts +20 -0
- package/src/autopilot/build/llm-conflict-merge.ts +28 -8
- package/src/briefing/brief-items.ts +86 -17
- package/src/cli/autopilot-cli.ts +30 -11
- package/src/cli/brief-cli.ts +36 -2
- package/src/cli/freeze-cli.ts +3 -2
- package/src/cli/intake-cli.ts +73 -1
- package/src/cli/notify-cli.ts +75 -0
- package/src/cli/provider-cli.ts +12 -2
- package/src/cli/release-cli.ts +101 -17
- package/src/cli/tasks-cli.ts +309 -3
- package/src/context-bus/condense.ts +19 -3
- package/src/context-bus/context-day.ts +77 -24
- package/src/context-bus/context-first.ts +33 -0
- package/src/discord-self-message.ts +20 -2
- package/src/discord-slash-wire.ts +1 -0
- package/src/domains/outbound-alert.ts +200 -27
- package/src/domains/outbound-log-probe.ts +16 -1
- package/src/domains/release-tool.ts +2 -2
- package/src/execution-loop/gates.ts +11 -2
- package/src/flow-loop/split.ts +8 -4
- package/src/git-fs/worktree.ts +23 -3
- package/src/harness/harness-cli-command.ts +10 -2
- package/src/harness/harness-queue.ts +388 -33
- package/src/harness/helper-scan.ts +10 -3
- package/src/hq/seats.ts +369 -0
- package/src/index.ts +133 -15
- package/src/intake-plane/adopt-gate.ts +49 -0
- package/src/intake-plane/check.ts +3 -0
- package/src/intake-plane/collect-github.ts +57 -25
- package/src/intake-plane/discord-seat-work.ts +8 -2
- package/src/intake-plane/requirement-funnel.ts +316 -0
- package/src/knowledge/know-find.ts +10 -1
- package/src/loops/budget.ts +36 -0
- package/src/loops/orchestrator/finish-rate.ts +73 -1
- package/src/loops/orchestrator/grid-place.ts +11 -0
- package/src/loops/orchestrator/tick.ts +295 -20
- package/src/maturity/feature-maturity.ts +3 -2
- package/src/nexus/api/decisions-route.ts +11 -1
- package/src/nexus/api/loop-edges.ts +69 -13
- package/src/nexus/api/ops-seats-sources.ts +2 -2
- package/src/nexus/api/workflow-templates.ts +3 -0
- package/src/oauth/codex.ts +38 -0
- package/src/onboarding/first-chat-gate.ts +29 -0
- package/src/release-loop/checklist.ts +104 -6
- package/src/release-loop/feature-store.ts +10 -9
- package/src/release-loop/landing-freeze.ts +6 -4
- package/src/release-loop/placement.ts +13 -3
- package/src/release-loop/rubric.ts +80 -0
- package/src/seat-dispatch/seat-ask.ts +79 -16
- package/src/seat-loop/seat-loop.ts +12 -6
- package/src/self-dev/ask-launch-flow.ts +24 -3
- package/src/self-dev/ask-path-candidates.ts +68 -0
- package/src/self-dev/dev-pipeline.ts +4 -0
- package/src/self-dev/draft-triage-rules.ts +1 -1
- package/src/self-dev/orchestrate-cli.ts +22 -0
- package/src/self-dev/round-pr-supersede.ts +244 -0
- package/src/self-dev/run-supervisor.ts +14 -0
- package/src/self-implement/follow-up-goals.ts +2 -2
- package/src/self-implement/gate-remote.ts +427 -0
- package/src/self-implement/goal-author.ts +8 -3
- package/src/self-implement/l8-merge-queue.ts +29 -5
- package/src/self-implement/orchestrator.ts +59 -12
- package/src/self-implement/prior-draft-findings.ts +4 -3
- package/src/skills/skill-feedback.ts +76 -0
- package/src/task-agent/actions.ts +39 -6
- package/src/task-agent/judge.ts +31 -5
- package/src/task-agent/mission.ts +423 -0
- package/src/task-agent/shadow.ts +90 -0
- package/src/task-agent/task-hand.ts +235 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +10 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +86 -18
- package/src/telegram-loops-command.ts +1 -1
- package/src/telegram.ts +5 -20
- package/src/user-config.ts +63 -3
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/2699-63b73fa4d3bcf6ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4554-3565eea1f1495ba7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4614-21403aac730d4586.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5135-44008fe8b1f2aa41.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5233-bf28bd6bd7a32099.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6877-fe94e76a5841ee9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7395-164e238f471b5d7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7787-02a1c0b04e25e811.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8401-4ce1c42c8d89903f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8949-ecb4128a0858b911.js +0 -1
- package/apps/pwa/out/_next/static/chunks/899-f41be85e8a680651.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-6b8444914da74ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-7110f732f45bf944.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9a41d65355fc25b9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-41afec0b255ed2bb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ab93b240f687d69a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-de43a186e5ba5683.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8b08cafad27759c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1ed1324b1dc36754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-166745e51ac0c7b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-a04260b8ccc968d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-1f50e3d4e13435f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-a9117d2cd3093d36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-5a64cb5208c6a8fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1407ec83ea64c1f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-6e878ebbe1737d00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-81a4e7f8dbfe74cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-3ab59d19913b200e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-bf85b2f5bf077925.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ab32a8f522a60371.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-fc2df261f8a2c7df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-09461366af82ef13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ea90a8ac73ce2749.js +0 -1
- package/apps/pwa/out/_next/static/css/001d5fbaee388a25.css +0 -1
- package/apps/pwa/out/_next/static/yRA5ur6DcPl0YHSRheH2O/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{yRA5ur6DcPl0YHSRheH2O → P6YTVgzuZz5oTZhY4Din_}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: scheduled-daily-digest
|
|
2
|
+
description: |
|
|
3
|
+
Daily 9am Seoul-time digest workflow.
|
|
4
|
+
Triggers: schedule cron 0 9 * * * Asia/Seoul.
|
|
5
|
+
Does: crawls a fixed search term → omni-digest summary → saves to Obsidian.
|
|
6
|
+
Edit this template to swap the search term / Obsidian target.
|
|
7
|
+
|
|
8
|
+
_meta:
|
|
9
|
+
template:
|
|
10
|
+
title: Daily digest
|
|
11
|
+
description: Cron 9am → crawl → summarize → save
|
|
12
|
+
tags: [schedule, daily, digest]
|
|
13
|
+
|
|
14
|
+
nodes:
|
|
15
|
+
- id: tick
|
|
16
|
+
scheduleTrigger:
|
|
17
|
+
type: cron
|
|
18
|
+
cron: 0 9 * * *
|
|
19
|
+
timezone: Asia/Seoul
|
|
20
|
+
enabled: true
|
|
21
|
+
|
|
22
|
+
- id: crawl
|
|
23
|
+
skill: omni-crawl
|
|
24
|
+
arguments: "latest AI agent news"
|
|
25
|
+
depends_on: [tick]
|
|
26
|
+
|
|
27
|
+
- id: save
|
|
28
|
+
skill: omni-digest
|
|
29
|
+
arguments: $crawl.output
|
|
30
|
+
depends_on: [crawl]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: webhook-deploy-hook
|
|
2
|
+
description: |
|
|
3
|
+
Production deploy webhook receiver. CI posts to /hooks/deploy with
|
|
4
|
+
the build artifact id; the workflow builds, runs tests, and notifies
|
|
5
|
+
on Slack/Discord depending on result.
|
|
6
|
+
|
|
7
|
+
_meta:
|
|
8
|
+
template:
|
|
9
|
+
title: Webhook deploy hook
|
|
10
|
+
description: POST /hooks/deploy → build → notify
|
|
11
|
+
tags: [webhook, deploy, ci]
|
|
12
|
+
|
|
13
|
+
nodes:
|
|
14
|
+
- id: receive
|
|
15
|
+
webhookTrigger:
|
|
16
|
+
method: POST
|
|
17
|
+
path: /hooks/deploy
|
|
18
|
+
|
|
19
|
+
- id: build
|
|
20
|
+
bash: |
|
|
21
|
+
echo "building $ARGUMENTS" && sleep 1 && echo ok
|
|
22
|
+
depends_on: [receive]
|
|
23
|
+
|
|
24
|
+
- id: notify
|
|
25
|
+
bash: |
|
|
26
|
+
echo "deploy result: $build.output"
|
|
27
|
+
depends_on: [build]
|
|
@@ -88,9 +88,14 @@ export async function exportImportCheck(changedFiles: readonly string[], root: s
|
|
|
88
88
|
const tracked = trackedFiles(root);
|
|
89
89
|
if (!tracked) return { measured: false, hits: [], unseen: 0, detail: 'git ls-files 실패' };
|
|
90
90
|
let included: Set<string>;
|
|
91
|
+
let present: Set<string>;
|
|
91
92
|
try {
|
|
92
93
|
const { loadExportConfig, selectExportFiles } = await exportSelectors();
|
|
93
|
-
|
|
94
|
+
const config = loadExportConfig(root);
|
|
95
|
+
included = new Set(selectExportFiles(tracked, config));
|
|
96
|
+
// An import target also exists in the export when `replace` writes a public file at that path. Only targets use
|
|
97
|
+
// this — a replaced private original is not shipped, so it is not scanned as an importer.
|
|
98
|
+
present = new Set([...included, ...Object.keys(config.replace ?? {})]);
|
|
94
99
|
} catch (error) {
|
|
95
100
|
return { measured: false, hits: [], unseen: 0, detail: error instanceof Error ? error.message : '매니페스트를 못 읽었다' };
|
|
96
101
|
}
|
|
@@ -108,7 +113,7 @@ export async function exportImportCheck(changedFiles: readonly string[], root: s
|
|
|
108
113
|
const resolvedSpec = resolveSpecifier(file, specifier);
|
|
109
114
|
if (!resolvedSpec) return;
|
|
110
115
|
const target = candidatePaths(resolvedSpec).find((candidate) => trackedSet.has(candidate));
|
|
111
|
-
if (!target ||
|
|
116
|
+
if (!target || present.has(target)) return;
|
|
112
117
|
const key = `${index}\0${target}`;
|
|
113
118
|
if (seen.has(key)) return;
|
|
114
119
|
seen.add(key);
|
|
@@ -1032,14 +1032,29 @@ export function runGate(io: Partial<GateIo> = {}): void {
|
|
|
1032
1032
|
// ⭐ 그래서 막는 자리는 «여기»뿐이다 — 인-프로세스 호출자(`pr-cli.ts`·`seams.ts`)는
|
|
1033
1033
|
// argv 를 안 넘기고, 만약 여기서 `process.argv` 를 «읽으면» 형제 게이트가 경고한 그 사고가 난다
|
|
1034
1034
|
// (`elanous pr land` 의 인자를 자기 인자로 읽는다 — `src/cli/pr-cli.ts` 의 `args: []` 주석).
|
|
1035
|
-
if (import.meta.main) {
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1035
|
+
if (import.meta.main) void (async () => {
|
|
1036
|
+
// GATE-REMOTE (10-06): the only accepted arguments are the dispatch flags `--remote [host]` / `--local` — they choose
|
|
1037
|
+
// «where» the same commit is measured, never «what» (the base stays merge-base(origin/main) on both sides).
|
|
1038
|
+
const { extractGateRemoteFlags, dispatchHeavyCheck } = await import('../src/self-implement/gate-remote.js');
|
|
1039
|
+
const flags = extractGateRemoteFlags(process.argv.slice(2));
|
|
1040
|
+
const cliArgs = flags.rest;
|
|
1041
|
+
if (cliArgs.length > 0 || flags.error) {
|
|
1042
|
+
if (flags.error) console.error(`[tsc-gate] ⛔ ${flags.error}`);
|
|
1043
|
+
if (cliArgs.length > 0) console.error(`[tsc-gate] ⛔ 이 게이트는 인자를 받지 않는다(--remote/--local 제외) — 준 인자 ${cliArgs.length}개를 «조용히 삼키지 않고» 막는다: ${cliArgs.join(' ')}`);
|
|
1039
1044
|
console.error('[tsc-gate] 기준은 언제나 merge-base(origin/main) 다. 다른 기준으로 재려면 «그 트리에 서서» 돌려라:');
|
|
1040
1045
|
console.error('[tsc-gate] git worktree add --detach <경로> <커밋> && cd <경로> && bun run scripts/ci-typecheck-changed.ts');
|
|
1041
1046
|
console.error('[tsc-gate] ⇒ 그러면 merge-base 가 그때와 «같아진다». 이것이 재현의 유일한 길이다.');
|
|
1042
1047
|
process.exit(2);
|
|
1043
1048
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1049
|
+
const repo = sh('git rev-parse --show-toplevel').trim();
|
|
1050
|
+
const baseRef = process.env.TSC_BASE_REF;
|
|
1051
|
+
const passEnv = (sha: (ref: string) => string) => (['NODE_OPTIONS', 'TSC_BASE_REF', 'TSC_HEAP_MB'] as const).filter((key) => process.env[key])
|
|
1052
|
+
.map((key) => `${key}=${key === 'TSC_BASE_REF' && baseRef !== 'origin/main' ? sha(baseRef!) : process.env[key]}`);
|
|
1053
|
+
// exitCode, not exit(): piped stdout/stderr drain before the process ends.
|
|
1054
|
+
process.exitCode = await dispatchHeavyCheck({
|
|
1055
|
+
tool: 'ci-typecheck-changed', repo, flags,
|
|
1056
|
+
remoteArgv: (sha) => { const vars = passEnv(sha); return [...(vars.length ? ['env', ...vars] : []), 'bun', 'run', 'scripts/ci-typecheck-changed.ts', '--local']; },
|
|
1057
|
+
refs: baseRef ? [baseRef] : [],
|
|
1058
|
+
runLocal: () => { runGate(); return 0; },
|
|
1059
|
+
});
|
|
1060
|
+
})();
|
|
@@ -56,7 +56,8 @@ export async function probeDiscordSeatWork(text: string, options: ProbeOptions =
|
|
|
56
56
|
open: () => { const db = new Database(':memory:'); return { db, close: () => db.close() } as unknown as MsgStore; },
|
|
57
57
|
dispatch: async (seatId, forwarded) => {
|
|
58
58
|
capture('ask', seatId, forwarded);
|
|
59
|
-
|
|
59
|
+
// Since #24523 a seat *task* also travels this ask path (so the answer can come back) — the wording covers both.
|
|
60
|
+
return { channel: 'unknown', reply: `마른 실행 — ${seatId}에 맡길 예정 (실제 맡김 없음).` };
|
|
60
61
|
},
|
|
61
62
|
send: async () => { throw new Error('dry Discord delivery unavailable'); },
|
|
62
63
|
},
|
|
@@ -76,7 +77,7 @@ export async function probeDiscordSeatWork(text: string, options: ProbeOptions =
|
|
|
76
77
|
...options.liveDeps?.askDeps,
|
|
77
78
|
dispatch: async (seatId, forwarded, deps, extra) => {
|
|
78
79
|
capture('ask', seatId, forwarded);
|
|
79
|
-
return (options.liveDeps?.askDeps?.dispatch ?? dispatchCeoTask)(seatId, forwarded, deps, extra);
|
|
80
|
+
return (options.liveDeps?.askDeps?.dispatch ?? options.liveDeps?.dispatch ?? dispatchCeoTask)(seatId, forwarded, deps, extra);
|
|
80
81
|
},
|
|
81
82
|
// This CLI has no Discord transport: even live mode must not post to Discord.
|
|
82
83
|
send: async () => { throw new Error('probe does not send Discord messages'); },
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/** DOC-GEN — src/cli/ 의 정적 Commander 명령을 실행 없이 TypeScript AST 로 읽는다. */
|
|
3
|
+
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, join, relative } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import ts from 'typescript';
|
|
7
|
+
import { readCommit } from './generate-graph-anatomy.js';
|
|
8
|
+
|
|
9
|
+
export interface RenderCliAnatomyInput {
|
|
10
|
+
readonly cliRoot: string;
|
|
11
|
+
readonly repoRoot: string;
|
|
12
|
+
readonly commit: string;
|
|
13
|
+
readonly generatedAt: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface CommandRow {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly description: string;
|
|
19
|
+
readonly file: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function propertyCall(expression: ts.Expression, method: string): expression is ts.CallExpression & { expression: ts.PropertyAccessExpression } {
|
|
23
|
+
return ts.isCallExpression(expression) && ts.isPropertyAccessExpression(expression.expression)
|
|
24
|
+
&& expression.expression.name.text === method;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function literal(expression: ts.Expression | undefined): string | undefined {
|
|
28
|
+
return expression && (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression))
|
|
29
|
+
? expression.text : undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function descriptionOf(command: ts.CallExpression): string {
|
|
33
|
+
let current: ts.Expression = command;
|
|
34
|
+
while (ts.isPropertyAccessExpression(current.parent) && current.parent.expression === current
|
|
35
|
+
&& ts.isCallExpression(current.parent.parent) && current.parent.parent.expression === current.parent) {
|
|
36
|
+
const property = current.parent;
|
|
37
|
+
const call = current.parent.parent;
|
|
38
|
+
if (property.name.text === 'description') return literal(call.arguments[0]) ?? '';
|
|
39
|
+
if (property.name.text === 'command') break;
|
|
40
|
+
current = call;
|
|
41
|
+
}
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function rowsInFile(source: string, file: string): CommandRow[] {
|
|
46
|
+
const ast = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
47
|
+
interface Scope {
|
|
48
|
+
readonly owner: ts.Node;
|
|
49
|
+
readonly parent?: Scope;
|
|
50
|
+
readonly bindings: Map<string, ts.VariableDeclaration | null>;
|
|
51
|
+
}
|
|
52
|
+
const scopes = new Map<ts.Node, Scope>();
|
|
53
|
+
const gather = (node: ts.Node, outer?: Scope): void => {
|
|
54
|
+
const createsScope = ts.isSourceFile(node) || ts.isBlock(node) || ts.isModuleBlock(node)
|
|
55
|
+
|| ts.isCaseBlock(node) || ts.isCatchClause(node) || ts.isFunctionLike(node)
|
|
56
|
+
|| ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node);
|
|
57
|
+
const scope: Scope = createsScope ? { owner: node, parent: outer, bindings: new Map() } : outer!;
|
|
58
|
+
scopes.set(node, scope);
|
|
59
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
|
|
60
|
+
const list = node.parent;
|
|
61
|
+
const isVar = ts.isVariableDeclarationList(list) && (list.flags & ts.NodeFlags.BlockScoped) === 0;
|
|
62
|
+
let target = scope;
|
|
63
|
+
if (isVar) {
|
|
64
|
+
while (target.parent && !ts.isSourceFile(target.owner) && !ts.isFunctionLike(target.owner)) {
|
|
65
|
+
target = target.parent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
target.bindings.set(node.name.text, node);
|
|
69
|
+
}
|
|
70
|
+
if (ts.isFunctionLike(node)) {
|
|
71
|
+
for (const parameter of node.parameters) {
|
|
72
|
+
if (ts.isIdentifier(parameter.name)) scope.bindings.set(parameter.name.text, null);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (ts.isCatchClause(node) && node.variableDeclaration && ts.isIdentifier(node.variableDeclaration.name)) {
|
|
76
|
+
scope.bindings.set(node.variableDeclaration.name.text, null);
|
|
77
|
+
}
|
|
78
|
+
ts.forEachChild(node, (child) => gather(child, scope));
|
|
79
|
+
};
|
|
80
|
+
gather(ast);
|
|
81
|
+
|
|
82
|
+
const commandName = (expression: ts.Expression, seen: ReadonlySet<ts.VariableDeclaration> = new Set()): string => {
|
|
83
|
+
if (ts.isParenthesizedExpression(expression)) return commandName(expression.expression, seen);
|
|
84
|
+
if (ts.isIdentifier(expression)) {
|
|
85
|
+
let scope = scopes.get(expression);
|
|
86
|
+
while (scope && !scope.bindings.has(expression.text)) scope = scope.parent;
|
|
87
|
+
const declaration = scope?.bindings.get(expression.text);
|
|
88
|
+
if (!declaration || !declaration.initializer || seen.has(declaration)) return '';
|
|
89
|
+
return commandName(declaration.initializer, new Set([...seen, declaration]));
|
|
90
|
+
}
|
|
91
|
+
if (propertyCall(expression, 'command')) {
|
|
92
|
+
const name = literal(expression.arguments[0]);
|
|
93
|
+
if (name === undefined) return '';
|
|
94
|
+
const parent = commandName(expression.expression.expression, seen);
|
|
95
|
+
return parent ? `${parent} ${name}` : name;
|
|
96
|
+
}
|
|
97
|
+
if (ts.isCallExpression(expression) && ts.isPropertyAccessExpression(expression.expression)) {
|
|
98
|
+
return commandName(expression.expression.expression, seen);
|
|
99
|
+
}
|
|
100
|
+
return '';
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const rows: CommandRow[] = [];
|
|
104
|
+
const visit = (node: ts.Node): void => {
|
|
105
|
+
if (ts.isCallExpression(node) && propertyCall(node, 'command')) {
|
|
106
|
+
const name = literal(node.arguments[0]);
|
|
107
|
+
if (name !== undefined) rows.push({ name: commandName(node), description: descriptionOf(node), file });
|
|
108
|
+
}
|
|
109
|
+
ts.forEachChild(node, visit);
|
|
110
|
+
};
|
|
111
|
+
visit(ast);
|
|
112
|
+
return rows;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function cell(value: string): string {
|
|
116
|
+
return value.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** 지정된 src/cli/ 바로 아래 .ts 만 읽으며 import/명령을 실행하지 않는다. */
|
|
120
|
+
export function renderCliAnatomy(input: RenderCliAnatomyInput): string {
|
|
121
|
+
const rows = readdirSync(input.cliRoot, { withFileTypes: true })
|
|
122
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.ts')
|
|
123
|
+
&& !entry.name.endsWith('.test.ts') && !entry.name.endsWith('.spec.ts'))
|
|
124
|
+
.flatMap((entry) => {
|
|
125
|
+
const abs = join(input.cliRoot, entry.name);
|
|
126
|
+
return rowsInFile(readFileSync(abs, 'utf8'), relative(input.repoRoot, abs).replace(/\\/g, '/'));
|
|
127
|
+
})
|
|
128
|
+
.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : a.file < b.file ? -1 : a.file > b.file ? 1 : 0);
|
|
129
|
+
return [
|
|
130
|
+
'# CLI anatomy',
|
|
131
|
+
'',
|
|
132
|
+
'> 이 문서는 생성물이다 — 손으로 고치지 마라',
|
|
133
|
+
'',
|
|
134
|
+
`- generatedAt: ${input.generatedAt}`,
|
|
135
|
+
`- commit: ${input.commit}`,
|
|
136
|
+
'',
|
|
137
|
+
'| 명령 | 설명 | 정의 파일 |',
|
|
138
|
+
'| --- | --- | --- |',
|
|
139
|
+
...rows.map((row) => `| ${cell(row.name)} | ${cell(row.description)} | ${cell(row.file)} |`),
|
|
140
|
+
'',
|
|
141
|
+
].join('\n');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function defaultOutputPath(repoRoot: string): string {
|
|
145
|
+
return join(repoRoot, 'docs', 'generated', 'cli-anatomy.md');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function main(): void {
|
|
149
|
+
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
150
|
+
const argv = process.argv.slice(2);
|
|
151
|
+
const index = argv.indexOf('--out');
|
|
152
|
+
const outArg = index < 0 ? undefined : argv[index + 1];
|
|
153
|
+
if (index >= 0 && (!outArg || outArg.startsWith('--'))) throw new Error('--out 에는 경로가 필요하다');
|
|
154
|
+
const out = outArg ?? defaultOutputPath(repoRoot);
|
|
155
|
+
const markdown = renderCliAnatomy({ cliRoot: join(repoRoot, 'src', 'cli'), repoRoot,
|
|
156
|
+
commit: readCommit(repoRoot), generatedAt: new Date().toISOString() });
|
|
157
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
158
|
+
writeFileSync(out, markdown);
|
|
159
|
+
process.stdout.write(`${out}\n`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (import.meta.main) main();
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { inspectAskMarkers } from '../ask-marker-check.js';
|
|
4
|
+
|
|
5
|
+
export interface AuthoringMeasurement {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
readonly chars: number;
|
|
8
|
+
readonly bytes: number;
|
|
9
|
+
readonly sections: number;
|
|
10
|
+
readonly markerAxes: number;
|
|
11
|
+
readonly markerFailed: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type UnreadableMeasurement = { readonly path: string; readonly error: 'unreadable' };
|
|
15
|
+
type AuthoringRow = AuthoringMeasurement | UnreadableMeasurement;
|
|
16
|
+
|
|
17
|
+
export function measureAuthoring(path: string, text: string): AuthoringMeasurement {
|
|
18
|
+
const axes = inspectAskMarkers(text);
|
|
19
|
+
return {
|
|
20
|
+
path,
|
|
21
|
+
chars: text.length,
|
|
22
|
+
bytes: Buffer.byteLength(text, 'utf8'),
|
|
23
|
+
sections: text.split(/\r?\n/).filter((line) => /^#{1,6}\s/u.test(line)).length,
|
|
24
|
+
markerAxes: axes.length,
|
|
25
|
+
markerFailed: axes.filter((axis) => !(axis.marker && axis.extracted)).length,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function median(numbers: readonly number[]): number | null {
|
|
30
|
+
if (numbers.length === 0) return null;
|
|
31
|
+
const sorted = [...numbers].sort((a, b) => a - b);
|
|
32
|
+
const middle = Math.floor(sorted.length / 2);
|
|
33
|
+
return sorted.length % 2 === 1
|
|
34
|
+
? sorted[middle]!
|
|
35
|
+
: (sorted[middle - 1]! + sorted[middle]!) / 2;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function main(argv: readonly string[]): number {
|
|
39
|
+
const json = argv.includes('--json');
|
|
40
|
+
const paths = argv.filter((argument) => argument !== '--json');
|
|
41
|
+
const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
42
|
+
const rows: AuthoringRow[] = paths.map((path) => {
|
|
43
|
+
let text: string;
|
|
44
|
+
try {
|
|
45
|
+
text = decoder.decode(readFileSync(path));
|
|
46
|
+
} catch {
|
|
47
|
+
return { path, error: 'unreadable' };
|
|
48
|
+
}
|
|
49
|
+
return measureAuthoring(path, text);
|
|
50
|
+
});
|
|
51
|
+
const measured = rows.filter((row): row is AuthoringMeasurement => !('error' in row));
|
|
52
|
+
const summary = {
|
|
53
|
+
files: measured.length,
|
|
54
|
+
medianChars: median(measured.map((row) => row.chars)),
|
|
55
|
+
medianBytes: median(measured.map((row) => row.bytes)),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (json) {
|
|
59
|
+
for (const row of rows) console.log(JSON.stringify(row));
|
|
60
|
+
console.log(JSON.stringify(summary));
|
|
61
|
+
} else {
|
|
62
|
+
console.log('path\tchars\tbytes\tsections\tmarkerAxes\tmarkerFailed\terror');
|
|
63
|
+
for (const row of rows) {
|
|
64
|
+
console.log('error' in row
|
|
65
|
+
? `${row.path}\t\t\t\t\t\t${row.error}`
|
|
66
|
+
: `${row.path}\t${row.chars}\t${row.bytes}\t${row.sections}\t${row.markerAxes}\t${row.markerFailed}\t`);
|
|
67
|
+
}
|
|
68
|
+
console.log(`files\t${summary.files}\tmedianChars\t${summary.medianChars ?? '—'}\tmedianBytes\t${summary.medianBytes ?? '—'}`);
|
|
69
|
+
}
|
|
70
|
+
return rows.some((row) => 'error' in row) ? 1 : 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (import.meta.main) process.exitCode = main(process.argv.slice(2));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parse } from '../../src/agent-substrate/pr-comment-meta.js';
|
|
1
|
+
import { expandRecords, parse } from '../../src/agent-substrate/pr-comment-meta.js';
|
|
2
2
|
|
|
3
3
|
export type MustFixVerdict = 'resolved' | 'unresolved' | 'unknown';
|
|
4
4
|
export interface ReviewRoundMatch {
|
|
@@ -12,12 +12,12 @@ export interface ReviewRoundMatch {
|
|
|
12
12
|
const MUST_FIX_ROUND = /^Round \d+: reviewer requested \d+ must-fix change\(s\)\.$/m;
|
|
13
13
|
|
|
14
14
|
export function classifyReviewRounds(comments: Array<{ body?: string }>): ReviewRoundMatch[] {
|
|
15
|
-
const reviews = comments.flatMap(({ body }) =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const reviews = comments.flatMap(({ body }) =>
|
|
16
|
+
body ? expandRecords(body).flatMap((record) => {
|
|
17
|
+
const meta = parse(record);
|
|
18
|
+
return meta?.role === 'reviewer' && meta.run && meta.round !== undefined
|
|
19
|
+
? [{ body: record, run: meta.run, round: meta.round }] : [];
|
|
20
|
+
}) : []);
|
|
21
21
|
// 항목은 «must-fix 요청» 라운드에서만 센다 — «review completed (warn)» 의 요약 본문에도 «- » 글머리가 들어 있다(#21983 실물).
|
|
22
22
|
return reviews.flatMap(({ body, run, round }) => !MUST_FIX_ROUND.test(body) ? [] :
|
|
23
23
|
[...body.matchAll(/^- (.+)$/gm)].map((item) => ({
|
|
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from 'node:path';
|
|
|
5
5
|
import { githubAutomationToken } from '../../src/auth/github-app-token.js';
|
|
6
6
|
import { debug } from '../../src/debug/log.js';
|
|
7
7
|
import { emitDecision } from '../../src/live/detail-switch.js';
|
|
8
|
-
import { parse } from '../../src/agent-substrate/pr-comment-meta.js';
|
|
8
|
+
import { expandRecords, parse } from '../../src/agent-substrate/pr-comment-meta.js';
|
|
9
9
|
import { classifyReviewRounds, matchMustFix, type MustFixVerdict } from './must-fix-match.js';
|
|
10
10
|
import { verifyCleanCheckout, type CheckoutResult } from './clean-checkout.js';
|
|
11
11
|
|
|
@@ -116,7 +116,8 @@ export function runMission(mission: string, ctx: GraphContext, run: RunCommand =
|
|
|
116
116
|
const pages = JSON.parse(run(['api', `repos/{owner}/{repo}/pulls/${pr.number}/comments`, '--paginate', '--slurp'])) as Array<Array<{ body?: string }>>;
|
|
117
117
|
if (!Array.isArray(pages) || !pages.every(Array.isArray)) throw new Error(`invalid review comments for PR #${pr.number}`);
|
|
118
118
|
const inline = pages.flat();
|
|
119
|
-
const comments = [...(details.reviews ?? []), ...(details.comments ?? []), ...inline]
|
|
119
|
+
const comments = [...(details.reviews ?? []), ...(details.comments ?? []), ...inline]
|
|
120
|
+
.flatMap((comment) => comment.body ? expandRecords(comment.body).map((body) => ({ ...comment, body })) : [comment]);
|
|
120
121
|
const reviewRounds = comments.filter(({ body }) => {
|
|
121
122
|
const meta = body ? parse(body) : null;
|
|
122
123
|
return meta?.role === 'reviewer' && !!meta.run && meta.round !== undefined;
|
|
@@ -4,7 +4,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
4
4
|
import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync, symlinkSync } from 'node:fs';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
7
|
-
import { run as exportRun } from './public-export.js';
|
|
7
|
+
import { privateRedactionsPath, run as exportRun } from './public-export.js';
|
|
8
8
|
|
|
9
9
|
export interface Comparison {
|
|
10
10
|
exportOnly: string[];
|
|
@@ -118,4 +118,39 @@ export function run(argv: readonly string[], root = resolve(import.meta.dir, '..
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
// GATE-REMOTE (10-06): `--remote [host]` runs the same commit on that host and prints its result (JSON gains host · remote:true);
|
|
122
|
+
// `--local` forces this machine. Without either, a busy machine (1-min load > gateRemote.loadThreshold) dispatches on its own.
|
|
123
|
+
if (import.meta.main) void (async () => {
|
|
124
|
+
const { extractGateRemoteFlags, dispatchHeavyCheck, unreproducibleArgs, relativizeArgs } = await import('../src/self-implement/gate-remote.js');
|
|
125
|
+
const flags = extractGateRemoteFlags(process.argv.slice(2));
|
|
126
|
+
if (flags.error) { console.error(flags.error); process.exit(2); }
|
|
127
|
+
const repo = resolve(import.meta.dir, '..');
|
|
128
|
+
// The private redaction table changes exported file contents — the remote export must use the same one or the comparison differs.
|
|
129
|
+
const table = privateRedactionsPath();
|
|
130
|
+
const payloadFiles = existsSync(table) ? [{ env: 'ELANOUS_EXPORT_REDACTIONS', content: readFileSync(table, 'utf8') }] : [];
|
|
131
|
+
// File arguments, the --files list and its entries resolve against the repository root (as run() does).
|
|
132
|
+
const paths = flags.rest.filter((arg) => !arg.startsWith('--'));
|
|
133
|
+
const listIndex = flags.rest.indexOf('--files');
|
|
134
|
+
const list = listIndex >= 0 ? flags.rest[listIndex + 1] : undefined;
|
|
135
|
+
// List entries reach the host verbatim (only positional arguments are rewritten), so an absolute entry is not portable.
|
|
136
|
+
const absoluteEntries: string[] = [];
|
|
137
|
+
if (list) {
|
|
138
|
+
try {
|
|
139
|
+
const entries = readFileSync(resolve(repo, list), 'utf8').split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
|
|
140
|
+
absoluteEntries.push(...entries.filter((entry) => isAbsolute(entry)));
|
|
141
|
+
paths.push(...entries);
|
|
142
|
+
} catch { /* run() reports it */ }
|
|
143
|
+
}
|
|
144
|
+
process.exitCode = await dispatchHeavyCheck({
|
|
145
|
+
payloadFiles,
|
|
146
|
+
localOnlyReason: (() => {
|
|
147
|
+
// Each must be a tracked file inside the repository, or the remote checkout would measure something else.
|
|
148
|
+
const bad = [...new Set([...absoluteEntries, ...unreproducibleArgs(paths, repo)])];
|
|
149
|
+
return bad.length ? `file argument not reproducible on the host (outside the repository or not tracked at HEAD): ${bad.join(' ')}` : undefined;
|
|
150
|
+
})(),
|
|
151
|
+
tool: 'public-export-test-run', repo, flags, json: flags.rest.includes('--json'),
|
|
152
|
+
installPwa: paths.some((arg) => arg.includes('apps/pwa')),
|
|
153
|
+
remoteArgv: ['bun', 'scripts/public-export-test-run.ts', '--local', ...relativizeArgs(flags.rest, repo)],
|
|
154
|
+
runLocal: () => run(flags.rest),
|
|
155
|
+
});
|
|
156
|
+
})();
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import {
|
|
2
|
+
import { cutChecklistGate, listChecklist, summarizeChecklist } from '../../src/release-loop/checklist.js';
|
|
3
3
|
import * as store from '../../src/release-loop/feature-store.js';
|
|
4
4
|
import { getSchedule } from '../../src/release-loop/release-schedule.js';
|
|
5
5
|
import { debug } from '../../src/debug/log.js';
|
|
6
|
+
import { prereleaseKind } from './release-version.js';
|
|
6
7
|
import { emitNodeResult, errorResult, readGraphContext, type GraphContext } from './node-verdict.js';
|
|
7
8
|
|
|
9
|
+
/** RELEASE-REHEARSAL-RC: a prerelease rehearses the pipeline; it must not judge or carry the stable version's cells. */
|
|
10
|
+
export function prereleaseChecklistSkip(context: GraphContext) {
|
|
11
|
+
const version = context.input.version;
|
|
12
|
+
if (prereleaseKind(version) === null) return null;
|
|
13
|
+
debug.log('release-loop.checklist-gate', 'skipped', { version, reason: 'prerelease' });
|
|
14
|
+
return { outcome: 'ok' as const, verdict: 'pass' as const, summary: `checklist gate skipped — ${version} is a prerelease rehearsal`, skipped: 'prerelease' };
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
export function runChecklistGate(context: GraphContext = readGraphContext(), now: Date = new Date()) {
|
|
9
18
|
const version = context.input.version;
|
|
10
19
|
const data = listChecklist(version);
|
|
11
20
|
const schedule = getSchedule(version);
|
|
12
21
|
const deadline = schedule?.landBy;
|
|
13
|
-
const
|
|
14
|
-
const autoMoved = overdue ? data.items.filter((item) => item.status === 'yellow' && item.priority !== 'P0' && item.disposition === undefined).map((item) => item.id) : [];
|
|
15
|
-
const gate = checklistGate(version);
|
|
16
|
-
const p0 = data.items.filter((item) => item.status === 'yellow' && item.priority === 'P0').map((item) => item.id);
|
|
17
|
-
gate.undecided = gate.undecided.filter((id) => !autoMoved.includes(id) && !p0.includes(id));
|
|
18
|
-
gate.moved = gate.moved.filter((id) => !p0.includes(id)).concat(autoMoved);
|
|
19
|
-
gate.knownIssues = gate.knownIssues.filter((item) => !p0.includes(item.id));
|
|
20
|
-
gate.blocked.push(...p0.filter((id) => !gate.blocked.includes(id)));
|
|
21
|
-
gate.ok = gate.red.length === 0 && gate.undecided.length === 0 && gate.blocked.length === 0;
|
|
22
|
+
const { autoMoved, ...gate } = cutChecklistGate(version, deadline, now);
|
|
22
23
|
const [major, minor, patch] = version.split('.').map(Number);
|
|
23
24
|
const next = `${major}.${minor}.${patch! + 1}`;
|
|
24
25
|
const carried: string[] = [];
|
|
@@ -65,7 +66,8 @@ export function runChecklistGate(context: GraphContext = readGraphContext(), now
|
|
|
65
66
|
|
|
66
67
|
if (import.meta.main) {
|
|
67
68
|
try {
|
|
68
|
-
const
|
|
69
|
+
const context = readGraphContext();
|
|
70
|
+
const result = prereleaseChecklistSkip(context) ?? runChecklistGate(context);
|
|
69
71
|
emitNodeResult(result);
|
|
70
72
|
process.exitCode = result.outcome === 'ok' ? 0 : 1;
|
|
71
73
|
} catch (error) {
|
|
@@ -3,6 +3,7 @@ import { mkdtempSync, rmSync } from 'node:fs';
|
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { debug } from '../../src/debug/log.js';
|
|
6
|
+
import { isReleaseVersion } from './release-version.js';
|
|
6
7
|
|
|
7
8
|
export interface CutBranchOptions { version: string; base: string; pick: string[]; append?: boolean; dryRun?: boolean; repoRoot?: string; log?: (line: string) => void }
|
|
8
9
|
|
|
@@ -26,7 +27,7 @@ export function cutReleaseBranch(opts: CutBranchOptions): { branch: string; comm
|
|
|
26
27
|
const report = (event: 'created' | 'refused' | 'conflict' | 'appended', reason?: string, commit?: string, extra?: Record<string, string | string[]>) =>
|
|
27
28
|
debug.log('release-loop.cut-branch', event, { version: opts.version, branch, ...(commit ? { commit } : {}), ...(reason ? { reason } : {}), ...extra });
|
|
28
29
|
try {
|
|
29
|
-
if (
|
|
30
|
+
if (!isReleaseVersion(opts.version)) throw new Error(`invalid release version: ${opts.version}`);
|
|
30
31
|
if (!opts.pick.length) throw new Error('at least one --pick commit is required');
|
|
31
32
|
for (const sha of [opts.base, ...opts.pick]) if (!/^[0-9a-f]{7,40}$/i.test(sha)) throw new Error(`invalid commit SHA: ${sha}`);
|
|
32
33
|
git(repo, ['fetch', 'origin', 'main']);
|
|
@@ -25,8 +25,10 @@ function requiredGit(args: string[]): string {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function versionParts(value: string): number[] | null {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// A prerelease (0.2.18-rc.0) is placed by its base version — earlier stable tags are its baseline.
|
|
29
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-(?:rc|alpha|beta)\.\d+)?$/.exec(value);
|
|
30
|
+
if (!match) return null;
|
|
31
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
function compareVersions(a: number[], b: number[]): number {
|
|
@@ -7,6 +7,7 @@ import { recordDocsFollow, type DocsFollowItem } from './release-docs.js';
|
|
|
7
7
|
import { dirname, join } from 'node:path';
|
|
8
8
|
import { tmpdir } from 'node:os';
|
|
9
9
|
import { errorResult, finishNode, nodeOutput, readGraphContext, runCommand, type CommandRunner } from './node-verdict.js';
|
|
10
|
+
import { prereleaseKind } from './release-version.js';
|
|
10
11
|
|
|
11
12
|
export function runDocsLand(run: CommandRunner = runCommand, stateRoot = effectiveInstanceRoot(), ledgerRoot = releaseLedgerRoot()) {
|
|
12
13
|
const context = readGraphContext();
|
|
@@ -119,6 +120,12 @@ export function runDocsLand(run: CommandRunner = runCommand, stateRoot = effecti
|
|
|
119
120
|
|
|
120
121
|
if (import.meta.main) {
|
|
121
122
|
let version = '';
|
|
122
|
-
try {
|
|
123
|
+
try {
|
|
124
|
+
version = readGraphContext().input.version;
|
|
125
|
+
// RELEASE-REHEARSAL-RC: a prerelease never lands docs on main or upgrades the operating hosts.
|
|
126
|
+
process.exitCode = finishNode('docs-land', version, prereleaseKind(version) !== null
|
|
127
|
+
? { outcome: 'ok', verdict: 'pass', summary: `docs-land skipped — ${version} is a prerelease`, skipped: 'prerelease' }
|
|
128
|
+
: runDocsLand());
|
|
129
|
+
}
|
|
123
130
|
catch (error) { process.exitCode = finishNode('docs-land', version, errorResult(error)); }
|
|
124
131
|
}
|
|
@@ -72,7 +72,7 @@ export function runDocs(
|
|
|
72
72
|
}
|
|
73
73
|
throw new Error(`unknown argument: ${arg}`);
|
|
74
74
|
}
|
|
75
|
-
if (!version || !/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)
|
|
75
|
+
if (!version || !/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:rc|alpha|beta)\.(?:0|[1-9]\d*))?$/.test(version)) {
|
|
76
76
|
throw new Error('version required (--version or ELANOUS_GRAPH_CONTEXT.input.version): x.y.z');
|
|
77
77
|
}
|
|
78
78
|
root = resolve(root);
|