elanous 0.2.10 → 0.2.12
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/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
- package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-cb169620945d1952.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-1efd0cb9e0ed9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9547b5cec7cf76bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
- package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -0
- package/apps/pwa/out/inside/index.txt +31 -0
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -0
- package/apps/pwa/out/outputs/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -24
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -24
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/context/nightly-condense.yaml +21 -0
- package/graphs/context/recipes.yaml +12 -0
- package/graphs/demo/inside-seed.yaml +20 -0
- package/graphs/demo/recipes.yaml +12 -0
- package/graphs/drafts/draft-cleanup.yaml +19 -0
- package/graphs/drafts/recipes.yaml +23 -0
- package/graphs/intake/intake-daily.yaml +2 -1
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/ops/secret-exposure.yaml +24 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -1
- package/graphs/video/explainer-line.yaml +2 -2
- package/package.json +2 -1
- package/plugins/card-followup/examples/sample-card.png +0 -0
- package/plugins/elanous-hwp/README.md +25 -0
- package/plugins/elanous-hwp/cli.ts +22 -0
- package/plugins/elanous-hwp/converter.ts +237 -0
- package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
- package/plugins/elanous-hwp/plugin.json +16 -0
- package/plugins/elanous-hwp/plugin.ts +40 -0
- package/scripts/ci-public-export-leak-gate.ts +75 -14
- package/scripts/ci-public-leak-gate.ts +44 -9
- package/scripts/context-hooks/claude-stop.sh +4 -0
- package/scripts/context-hooks/emit.ts +24 -0
- package/scripts/context-hooks/post-tool-use.sh +4 -0
- package/scripts/coord-channel-watch.sh +12 -0
- package/scripts/coord-requests-bridge.ts +143 -0
- package/scripts/field-feed/lib.ts +4 -0
- package/scripts/fleet/node-setup.sh +20 -3
- package/scripts/homebrew-formula-bump.ts +69 -0
- package/scripts/lib/telegram-inject-args.ts +31 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/measure-pod-memory-by-goal.ts +130 -0
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/checklist-gate-node.ts +2 -1
- package/scripts/release-loop/cut-branch.ts +84 -0
- package/scripts/release-loop/gate-node.ts +22 -15
- package/scripts/release-loop/mac-smoke-node.ts +229 -0
- package/scripts/release-loop/node-verdict.ts +3 -3
- package/scripts/release-loop/ops-upgrade-node.ts +47 -6
- package/scripts/release-loop/publish-node.ts +4 -1
- package/scripts/release-loop/tui-node-checks.ts +42 -0
- package/scripts/release-loop/tui-sim-node.ts +32 -8
- package/scripts/release-loop/unattended-release.ts +5 -3
- package/scripts/release-loop/version-node.ts +74 -13
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/telegram-inject.ts +14 -6
- package/scripts/test-diet/node.ts +1 -1
- package/scripts/test-diet/remeasure-list.ts +112 -0
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +247 -0
- package/scripts/ux/demo-seed.ts +108 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
- package/skills/diagram-master/SKILL.md +366 -0
- package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
- package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
- package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
- package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
- package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
- package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
- package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
- package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
- package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
- package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
- package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
- package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
- package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
- package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
- package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
- package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
- package/skills/diagram-master/references/examples/README.md +69 -0
- package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
- package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
- package/skills/diagram-master/references/pyproject.toml +16 -0
- package/skills/diagram-master/references/quality-checklist.md +33 -0
- package/skills/diagram-master/references/routing-guide.md +164 -0
- package/skills/diagram-master/references/uv.lock +1356 -0
- package/skills/google-workspace/SKILL.md +33 -0
- package/skills/google-workspace/scripts/gws-safe.sh +177 -0
- package/skills/grill-me/SKILL.md +1 -1
- package/skills/lecture-note-digitizer/SKILL.md +926 -0
- package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
- package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
- package/skills/lecture-note-digitizer/references/html-template.md +167 -0
- package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
- package/skills/omni-crawl/SKILL.md +21 -11
- package/skills/omni-crawl/scripts/main.ts +6 -6
- package/skills/omni-crawl/src/router.ts +3 -3
- package/skills/omni-digest/SKILL.md +17 -9
- package/skills/omni-digest/digest.md +2 -2
- package/skills/omni-digest/src/fetch.ts +30 -3
- package/skills/pitch-deck/SKILL.md +2 -2
- package/skills/pitch-deck/template.html +2 -2
- package/skills/youtube-master/SKILL.md +163 -0
- package/skills/youtube-master/package-lock.json +558 -0
- package/skills/youtube-master/package.json +13 -0
- package/skills/youtube-master/references/study-note-template.md +124 -0
- package/skills/youtube-master/scripts/main.ts +435 -0
- package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
- package/skills/youtube-master/src/audio.ts +63 -0
- package/skills/youtube-master/src/domain-staging.ts +50 -0
- package/skills/youtube-master/src/env.ts +36 -0
- package/skills/youtube-master/src/obsidian.ts +155 -0
- package/skills/youtube-master/src/router.ts +110 -0
- package/skills/youtube-master/src/stt.ts +199 -0
- package/skills/youtube-master/src/study-note.ts +175 -0
- package/skills/youtube-master/src/summarize.ts +358 -0
- package/skills/youtube-master/src/transcript.ts +76 -0
- package/skills/youtube-master/src/types.ts +91 -0
- package/skills/youtube-master/src/util.ts +93 -0
- package/skills/youtube-master/src/youtube.ts +70 -0
- package/skills/youtube-master/tsconfig.json +13 -0
- package/src/acp/server.ts +5 -2
- package/src/agent-mission/driver.ts +215 -23
- package/src/agent-mission/pty-decision.ts +71 -0
- package/src/agent-mission/review-loop.ts +30 -0
- package/src/autopilot/build/llm-conflict-merge.ts +16 -3
- package/src/autopilot/pty-control-loop.ts +4 -1
- package/src/autopilot/tool-registry.ts +2 -0
- package/src/boot/daemon-prompt-turn.ts +5 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/web-search.ts +3 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/index.ts +2 -0
- package/src/cli/drive-input-jail.ts +101 -0
- package/src/cli/hooks-cli.ts +17 -3
- package/src/cli/make-cli.ts +43 -0
- package/src/cli/persona-cli.ts +98 -9
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +36 -9
- package/src/cli/pod-memory-advice.ts +35 -0
- package/src/cli/pr-cli.ts +51 -15
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/release-cli.ts +63 -10
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/context-bus/claude-hooks-install.ts +10 -0
- package/src/context-bus/context-now-surfaces.ts +65 -0
- package/src/context-bus/context-now.ts +104 -0
- package/src/context-bus/coord-events.ts +2 -2
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/context-bus/nightly-condense.ts +153 -0
- package/src/context-bus/session-events.ts +35 -0
- package/src/dashboard/dashboard-status-lines.ts +2 -0
- package/src/dashboard/index.ts +17 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
- package/src/decisions/decision-cards.ts +10 -3
- package/src/decisions/decision-ledger.ts +13 -5
- package/src/discord/sprint21-runtime.ts +5 -1
- package/src/discord-self-message.ts +32 -0
- package/src/discord-slash-wire.ts +5 -1
- package/src/discord.ts +17 -1
- package/src/domains/core-tools.ts +3 -2
- package/src/domains/outbound-alert.ts +105 -32
- package/src/domains/outbound-log-probe.ts +8 -0
- package/src/domains/telegram-kind-route.ts +51 -13
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +10 -2
- package/src/exec-requests/runner.ts +20 -6
- package/src/exec-requests/store.ts +3 -0
- package/src/execution-loop/launch-gate.ts +109 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -0
- package/src/field-note/telegram.ts +142 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-cli.ts +61 -1
- package/src/graph-runner/graph-grow-llm.ts +47 -0
- package/src/graph-runner/graph-grow.ts +50 -0
- package/src/graph-runner/runner.ts +329 -33
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +375 -13
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +23 -4
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hooks/consult-intake.ts +153 -0
- package/src/hooks/dispatch.ts +82 -0
- package/src/hooks/expose.ts +254 -0
- package/src/hooks/github-shadow.ts +108 -0
- package/src/hooks/providers.ts +71 -5
- package/src/hooks/queue.ts +1 -1
- package/src/hooks/receiver.ts +94 -16
- package/src/index.ts +76 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +38 -2
- package/src/intake-plane/front-route-classifier.ts +33 -39
- package/src/intake-plane/persona-answer.ts +30 -0
- package/src/intake-plane/runtime-callables.ts +8 -1
- package/src/intake-plane/telegram-seat-work.ts +36 -2
- package/src/intake-plane/wish-card.ts +33 -0
- package/src/intake-plane/wish-folder.ts +67 -0
- package/src/intent-gate/gate.ts +30 -10
- package/src/live/detail-switch.ts +5 -0
- package/src/llm/difficulty.ts +57 -0
- package/src/llm/judge-layer.ts +101 -0
- package/src/llm/mission-router.ts +33 -19
- package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
- package/src/loops/contract/examples/steward.loop.yaml +50 -0
- package/src/loops/contract/loop-agent.schema.json +138 -0
- package/src/loops/contract/validate.ts +64 -0
- package/src/loops/registry.ts +20 -6
- package/src/market/signed-index.ts +4 -0
- package/src/maturity/bot-command-maturity.ts +45 -0
- package/src/maturity/feature-maturity.ts +27 -4
- package/src/model-tier/index.ts +2 -2
- package/src/model-tier/tier-resolver.ts +20 -20
- package/src/model-tier/types.ts +6 -6
- package/src/mss/logging/log-store.ts +15 -0
- package/src/nexus/api/config-model-tier.ts +5 -4
- package/src/nexus/api/fabric-plans.ts +53 -0
- package/src/nexus/api/harness-api.ts +5 -1
- package/src/nexus/api/health.ts +2 -0
- package/src/nexus/api/http-server.ts +67 -8
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +21 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-seats.ts +33 -0
- package/src/nexus/api/outbound-report.ts +40 -7
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/personas.ts +95 -53
- package/src/nexus/api/seat-requests.ts +44 -2
- package/src/nexus/api/sessions-store.ts +17 -38
- package/src/nexus/api/sub-seat-charters.ts +34 -0
- package/src/nexus/api/tabs-mutations.ts +3 -1
- package/src/nexus/api/task-cards-api.ts +19 -0
- package/src/nexus/api/trace.ts +18 -6
- package/src/nexus/api/workflow-history.ts +88 -0
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +132 -6
- package/src/nexus/index.ts +2 -0
- package/src/nexus/kinds/webterm.ts +2 -1
- package/src/nexus/outbound/delivery-ledger.ts +17 -8
- package/src/nexus/outbound/router.ts +8 -3
- package/src/nexus/webterm/pty.ts +6 -2
- package/src/onboarding/cli-auth-status.ts +80 -0
- package/src/onboarding/voice-ai.ts +3 -3
- package/src/org/seat-budget.ts +48 -0
- package/src/org/stall-escalation.ts +63 -0
- package/src/outputs/ledger.ts +120 -0
- package/src/persona/persona-todo.ts +79 -0
- package/src/persona/presets.ts +123 -2
- package/src/persona/team-set.ts +155 -0
- package/src/plugins/install/plugin-install.ts +14 -0
- package/src/plugins/maker/market-bundle.ts +110 -0
- package/src/plugins/maker/plugin-maker.ts +254 -11
- package/src/plugins/maker/wizard-generate.ts +103 -0
- package/src/pod-lease/admission.ts +150 -0
- package/src/pod-lease/dependency-state.ts +85 -0
- package/src/pod-lease/host-lease.ts +127 -0
- package/src/project/project-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +17 -5
- package/src/release-loop/feature-store.ts +29 -13
- package/src/release-loop/landed-but-yellow.ts +48 -0
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/seat-dispatch/seat-ask.ts +130 -0
- package/src/seat-dispatch/seat-questions.ts +100 -0
- package/src/seat-loop/seat-loop.ts +709 -29
- package/src/seat-loop/seat-report.ts +37 -2
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +37 -1
- package/src/self-dev/draft-sweep.ts +79 -40
- package/src/self-dev/draft-triage-rules.ts +62 -7
- package/src/self-dev/fabric-plan-core.ts +297 -0
- package/src/self-dev/orchestrate.ts +36 -4
- package/src/self-dev/release-path-guard.ts +62 -0
- package/src/self-dev/shard-aggregate.ts +230 -0
- package/src/self-dev/shard-placement.ts +60 -0
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-pod-run.ts +77 -0
- package/src/self-dev/shard-run.ts +105 -0
- package/src/self-implement/budget-gate.ts +29 -12
- package/src/self-implement/gate-baseline.ts +1 -1
- package/src/self-implement/gate-candidate-ranking.ts +60 -0
- package/src/self-implement/gate-cli.ts +40 -1
- package/src/self-implement/gate-scope.ts +44 -13
- package/src/self-implement/graph-variant.ts +171 -0
- package/src/self-implement/harness-policy-gates.ts +1 -1
- package/src/self-implement/headless-elanous-driver.ts +27 -3
- package/src/self-implement/host-regate.ts +22 -1
- package/src/self-implement/importer-test-index.ts +2 -1
- package/src/self-implement/l8-merge-queue.ts +130 -0
- package/src/self-implement/orchestrator.ts +257 -9
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/seams.ts +72 -11
- package/src/self-implement/test-seams.ts +2 -0
- package/src/self-implement/uncommitted-work.ts +59 -0
- package/src/session/index.ts +36 -13
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/launch.ts +42 -26
- package/src/steward/steward-cards.ts +17 -9
- package/src/steward/triage.ts +46 -14
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-orchestrator/mission.ts +5 -0
- package/src/task-orchestrator/store.ts +12 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
- package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
- package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
- package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
- package/src/task-orchestrator/types.ts +2 -0
- package/src/telegram-card-followup.ts +16 -96
- package/src/telegram-commands.ts +31 -1
- package/src/telegram-project-command.ts +145 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +61 -8
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +110 -24
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/grok.ts +7 -1
- package/src/web-search/index.ts +28 -1
- package/src/web-search/provider.ts +4 -0
- package/src/web-search/x-intent.ts +5 -0
- package/src/workflow-runtime/executor.ts +277 -47
- package/src/workflow-runtime/index.ts +1 -0
- package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
- package/src/workflow-runtime/plugin-kind-node.ts +1 -1
- package/src/workflow-runtime/schema.ts +79 -4
- package/src/workflow-runtime/types.ts +35 -4
- package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
- package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
- /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
|
@@ -6,7 +6,7 @@ import { promisify } from 'node:util';
|
|
|
6
6
|
import { debug } from '../debug/log.js';
|
|
7
7
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
8
8
|
import { getUserConfig, type SeatLoopConfig } from '../user-config.js';
|
|
9
|
-
import { seatDay, seatLedgerPath, type SeatEntry } from './seat-loop.js';
|
|
9
|
+
import { seatDay, seatLedgerPath, type OpCandidate, type SeatEntry } from './seat-loop.js';
|
|
10
10
|
|
|
11
11
|
export type SeatReportDeps = {
|
|
12
12
|
root?: string;
|
|
@@ -21,6 +21,21 @@ export type SeatReportResult = { seat: string; date: string; body: string; poste
|
|
|
21
21
|
const repoRoot = resolve(import.meta.dir, '../..');
|
|
22
22
|
const exec = promisify(execFile);
|
|
23
23
|
|
|
24
|
+
function opJudgment(candidate: OpCandidate): { kind: 'card' | 'todo'; text: string } | null {
|
|
25
|
+
if (candidate.kind === 'release-readiness') {
|
|
26
|
+
if (candidate.verdict === 'no-open-release') return null;
|
|
27
|
+
return { kind: 'todo', text: `판올림 준비 ${candidate.version} · ${candidate.verdict} · 빨강 ${candidate.red.join(', ') || '없음'} · 미결 ${candidate.undecided.join(', ') || '없음'} · 차단 ${candidate.blocked.join(', ') || '없음'}` };
|
|
28
|
+
}
|
|
29
|
+
if (candidate.kind === 'unassigned-cell') {
|
|
30
|
+
if (candidate.verdict === 'none' || !candidate.id) return null;
|
|
31
|
+
return { kind: 'todo', text: `빈 칸 분배 ${candidate.version} ${candidate.id} ${candidate.title ?? ''}`.trim() };
|
|
32
|
+
}
|
|
33
|
+
if (candidate.verdict === 'none' || !candidate.id) return null;
|
|
34
|
+
const text = `결정 대리 ${candidate.id} ${candidate.title ?? ''}`.trim();
|
|
35
|
+
return { kind: candidate.category && ['irreversible', 'money', 'security', 'secret', 'publish'].includes(candidate.category) ? 'card' : 'todo',
|
|
36
|
+
text: `${text} (${candidate.category ?? '범주 없음'})` };
|
|
37
|
+
}
|
|
38
|
+
|
|
24
39
|
async function defaultSend(body: string, seat: string, pr: number, repo: string): Promise<void> {
|
|
25
40
|
const dir = mkdtempSync(join(tmpdir(), 'seat-report-'));
|
|
26
41
|
try {
|
|
@@ -42,7 +57,25 @@ export async function seatReport(seat: string, deps: SeatReportDeps = {}): Promi
|
|
|
42
57
|
const entries = raw.split('\n').filter(Boolean).map((line) => JSON.parse(line) as SeatEntry);
|
|
43
58
|
// One line per item, its last state wins: an `attempting` row followed by `launched` is not «unconfirmed».
|
|
44
59
|
const latest = new Map<string, SeatEntry>();
|
|
60
|
+
const judgments = new Map<string, OpCandidate>();
|
|
45
61
|
for (const entry of entries) {
|
|
62
|
+
if (seat === 'OP' && entry.candidate) {
|
|
63
|
+
if (entry.candidate.verdict === 'none') {
|
|
64
|
+
if (entry.candidate.id) {
|
|
65
|
+
const key = entry.candidate.kind === 'unassigned-cell'
|
|
66
|
+
? `unassigned-cell:${JSON.stringify([entry.candidate.version, entry.candidate.id])}`
|
|
67
|
+
: `decision-delegation:${entry.candidate.id}`;
|
|
68
|
+
judgments.delete(key);
|
|
69
|
+
} else for (const key of judgments.keys()) if (key.startsWith(`${entry.candidate.kind}:`)) judgments.delete(key);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const key = entry.candidate.kind === 'unassigned-cell'
|
|
73
|
+
? `unassigned-cell:${JSON.stringify([entry.candidate.version, entry.candidate.id])}`
|
|
74
|
+
: entry.candidate.kind === 'decision-delegation' && entry.candidate.id
|
|
75
|
+
? `${entry.candidate.kind}:${entry.candidate.id}` : entry.candidate.kind;
|
|
76
|
+
judgments.set(key, entry.candidate);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
46
79
|
const key = entry.item ? `${entry.item.source}:${entry.item.version ?? ''}:${entry.item.id}` : `none:${entry.status}`;
|
|
47
80
|
latest.delete(key);
|
|
48
81
|
latest.set(key, entry);
|
|
@@ -55,7 +88,9 @@ export async function seatReport(seat: string, deps: SeatReportDeps = {}): Promi
|
|
|
55
88
|
if (entry.status === 'attempting' || entry.status === 'outcome-unknown') return `결과 확인 필요 ${entry.status} ${label}`;
|
|
56
89
|
return `건너뜀 ${entry.status} ${label}`;
|
|
57
90
|
});
|
|
58
|
-
const
|
|
91
|
+
const classified = [...judgments.values()].map(opJudgment).filter((row): row is NonNullable<typeof row> => row !== null);
|
|
92
|
+
const opDetail = classified.length ? ` · 결정 카드 후보: ${classified.filter((row) => row.kind === 'card').map((row) => row.text).join(' / ') || '없음'} · OP 가 할 일: ${classified.filter((row) => row.kind === 'todo').map((row) => row.text).join(' / ') || '없음'}` : '';
|
|
93
|
+
const body = `**[${seat}]** {{TS}} → 보고 ${date}: ${detail.join(' · ') || (classified.length ? 'OP 그림자 판단' : '원장 기록 없음')}${opDetail}`;
|
|
59
94
|
const pr = (deps.config ?? getUserConfig().loops?.seat)?.reportPr;
|
|
60
95
|
const posted = deps.post === true && pr !== undefined;
|
|
61
96
|
if (posted) await (deps.send ?? ((text, id, number) => defaultSend(text, id, number, deps.repo ?? repoRoot)))(body, seat, pr);
|
package/src/self-dev/dev-cli.ts
CHANGED
|
@@ -97,6 +97,8 @@ export interface DevCliOpts {
|
|
|
97
97
|
pollMs?: string;
|
|
98
98
|
model?: string;
|
|
99
99
|
attach?: string;
|
|
100
|
+
/** drive: DRIVE-JAIL boundary directory. */
|
|
101
|
+
jailHome?: string;
|
|
100
102
|
observeOnly?: boolean;
|
|
101
103
|
cols?: string;
|
|
102
104
|
rows?: string;
|
|
@@ -1748,7 +1750,7 @@ export function assertDevCliPathOptions(
|
|
|
1748
1750
|
if (foreign.length > 0) throw new DevPipelineError(formatForeignDevOptions(path, foreign));
|
|
1749
1751
|
}
|
|
1750
1752
|
|
|
1751
|
-
const DRIVE_ALIAS_OPTIONS = new Set(['goal', 'maxSteps', 'pollMs', 'model', 'cwd', 'worktree', 'json', 'attach']);
|
|
1753
|
+
const DRIVE_ALIAS_OPTIONS = new Set(['goal', 'maxSteps', 'pollMs', 'model', 'cwd', 'worktree', 'json', 'attach', 'jailHome']);
|
|
1752
1754
|
const DRIVE_ALIAS_ALLOWED_FLAGS = [...DRIVE_ALIAS_OPTIONS].map(toCliFlag).join(' · ');
|
|
1753
1755
|
|
|
1754
1756
|
export function assertDriveAliasOptions(explicitOptionNames: readonly string[]): void {
|
|
@@ -1947,6 +1949,7 @@ export function buildDevCliSpec(
|
|
|
1947
1949
|
...(opts.pollMs !== undefined ? { pollMs: parseNonNegativeInt(opts.pollMs, '--poll-ms') } : {}),
|
|
1948
1950
|
...(opts.model ? { model: opts.model } : {}),
|
|
1949
1951
|
...(opts.cwd ? { cwd: opts.cwd } : {}),
|
|
1952
|
+
...(opts.jailHome ? { jailHome: opts.jailHome } : {}),
|
|
1950
1953
|
},
|
|
1951
1954
|
};
|
|
1952
1955
|
}
|
|
@@ -25,6 +25,7 @@ import { createRepositoryReferencedFileReader, type ReferencedFileReader } from
|
|
|
25
25
|
import { parseGoalDocumentClarifications } from '../self-implement/goal-author-clarification.js';
|
|
26
26
|
import { requiredEvidenceFromGoal } from '../self-implement/off-diff-evidence.js';
|
|
27
27
|
import { debug } from '../debug/log.js';
|
|
28
|
+
import { releasePathHold, releasePathHoldComment, RELEASE_PATH_LABEL } from './release-path-guard.js';
|
|
28
29
|
import { runGitCommand } from '../git-fs/runner.js';
|
|
29
30
|
import type { GitRunResult } from '../git-fs/retry.js';
|
|
30
31
|
import { DEFAULT_BRANCH_WORKTREE_BASE, observeGitResidue, type GitResidueObservation } from '../git-fs/worktree.js';
|
|
@@ -135,6 +136,8 @@ export interface DevShellDriveOpts {
|
|
|
135
136
|
pollMs?: number;
|
|
136
137
|
model?: string;
|
|
137
138
|
cwd?: string;
|
|
139
|
+
/** DRIVE-JAIL boundary — inputs naming paths outside it are not sent to the PTY. */
|
|
140
|
+
jailHome?: string;
|
|
138
141
|
}
|
|
139
142
|
|
|
140
143
|
/** staged harness(plan-staged) 실행 옵션 — `harness run` front door의 무손실 재라우팅용.
|
|
@@ -1852,6 +1855,24 @@ async function observeDevTaskDispatch(spec: DevPipelineSpec, plan: ResolvedDevPl
|
|
|
1852
1855
|
}
|
|
1853
1856
|
}
|
|
1854
1857
|
|
|
1858
|
+
async function inspectReleasePathBeforeMerge(seams: SelfImplementSeams, number: number, cwd: string): Promise<string | undefined> {
|
|
1859
|
+
if (!seams.readPrFiles) throw new Error('release-path inspection unavailable — automatic merge refused');
|
|
1860
|
+
const files = await seams.readPrFiles({ number, cwd });
|
|
1861
|
+
if (!Array.isArray(files) || !files.every((path) => typeof path === 'string')) throw new Error('invalid PR file list — automatic merge refused');
|
|
1862
|
+
const path = releasePathHold(files);
|
|
1863
|
+
if (!path) return undefined;
|
|
1864
|
+
debug.log('self-dev.merge', 'release-path-hold', { number, path, label: RELEASE_PATH_LABEL });
|
|
1865
|
+
try {
|
|
1866
|
+
if (!seams.addPrLabel) throw new Error('addPrLabel seam unavailable');
|
|
1867
|
+
await seams.addPrLabel({ number, label: RELEASE_PATH_LABEL, cwd });
|
|
1868
|
+
} catch (error) { debug.log('self-dev.merge', 'release-path-annotation-failed', { number, path, action: 'label', error: String(error) }); }
|
|
1869
|
+
try {
|
|
1870
|
+
if (!seams.postPrComment) throw new Error('postPrComment seam unavailable');
|
|
1871
|
+
await seams.postPrComment({ number, body: releasePathHoldComment(path), cwd });
|
|
1872
|
+
} catch (error) { debug.log('self-dev.merge', 'release-path-annotation-failed', { number, path, action: 'comment', error: String(error) }); }
|
|
1873
|
+
return path;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1855
1876
|
async function runDevPipelineDispatch(
|
|
1856
1877
|
spec: DevPipelineSpec,
|
|
1857
1878
|
deps: DevPipelineDeps,
|
|
@@ -2071,7 +2092,22 @@ async function runDevPipelineDispatch(
|
|
|
2071
2092
|
const defaultSeams = deps.buildSelfImplementSeams
|
|
2072
2093
|
? await deps.buildSelfImplementSeams(plan)
|
|
2073
2094
|
: await buildDefaultSelfImplementSeams(plan, { progress: deps.progress });
|
|
2074
|
-
const
|
|
2095
|
+
const assembledSeams = deps.approver ? { ...defaultSeams, approvePr: deps.approver } : defaultSeams;
|
|
2096
|
+
// Guard even injected runSelfImplement implementations: do not trust a dispatched merge to
|
|
2097
|
+
// have used orchestrator's own PR-path check before requesting mergePr.
|
|
2098
|
+
const seams: SelfImplementSeams = {
|
|
2099
|
+
...assembledSeams,
|
|
2100
|
+
...(assembledSeams.mergePr ? { mergePr: async (input) => {
|
|
2101
|
+
let path: string | undefined;
|
|
2102
|
+
try { path = await inspectReleasePathBeforeMerge(assembledSeams, input.number, input.cwd); }
|
|
2103
|
+
catch (error) {
|
|
2104
|
+
debug.log('self-dev.merge', 'release-path-inspection-failed', { number: input.number, error: String(error) });
|
|
2105
|
+
return { merged: false, detail: `automatic merge refused: ${String(error)}` };
|
|
2106
|
+
}
|
|
2107
|
+
if (path) return { merged: false, detail: `OP approval required: ${path}` };
|
|
2108
|
+
return assembledSeams.mergePr!(input);
|
|
2109
|
+
} } : {}),
|
|
2110
|
+
};
|
|
2075
2111
|
// ⭐ 대표 지시(2026-09-08) — ***걸음을 「위」로 흘린다.***
|
|
2076
2112
|
// 🩸 그 전까지 런 슈퍼바이저가 받는 것은 «시도의 요약 판정»뿐이었고(stage·stopReason·분류 …)
|
|
2077
2113
|
// 「어느 노드를 몇 번 밟았나」는 ***런 안에서 끝났다***(`onNodeEntry` 는 있는데 호출부 0).
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { CLAIM_IDLE_HOURS, PR_LABELS } from '../github/pr-labels.js';
|
|
1
|
+
import { CLAIM_IDLE_HOURS, PR_LABELS, STALLED_DRAFT_HOURS } from '../github/pr-labels.js';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
2
3
|
import { decideDraft, type DraftTriagePr } from './draft-triage-rules.js';
|
|
3
4
|
|
|
4
5
|
export interface SweepDraft extends DraftTriagePr {
|
|
5
6
|
readonly title: string;
|
|
6
7
|
readonly labels: readonly string[];
|
|
7
8
|
readonly createdAt: string;
|
|
8
|
-
/** Last PR update (push, label, comment). Missing ⇒
|
|
9
|
+
/** Last PR update (push, label, comment). Missing ⇒ no idle-based close; merged twins can still close. */
|
|
9
10
|
readonly updatedAt?: string;
|
|
10
11
|
readonly runId?: string | null;
|
|
11
12
|
}
|
|
@@ -18,7 +19,7 @@ export interface DraftSweepAdapters {
|
|
|
18
19
|
/** Each call returns one complete page; a rejection must not be mistaken for an empty page. */
|
|
19
20
|
listDrafts(page: number, perPage: number, repository: string): Promise<readonly SweepDraft[]>;
|
|
20
21
|
listMerged(page: number, perPage: number, repository: string): Promise<readonly SweepMergedPr[]>;
|
|
21
|
-
/** Undefined means no run assessment;
|
|
22
|
+
/** Undefined means no run assessment; a merged twin or 24h idle draft can still authorize a close. */
|
|
22
23
|
getRunStatus(draft: SweepDraft, repository: string): Promise<string | undefined>;
|
|
23
24
|
/** Undefined means liveness could not be established. */
|
|
24
25
|
listLiveBranches(repository: string): Promise<ReadonlySet<string> | undefined>;
|
|
@@ -26,6 +27,10 @@ export interface DraftSweepAdapters {
|
|
|
26
27
|
closeDraft(repository: string, number: number, comment: string): Promise<void>;
|
|
27
28
|
/** Resolve the latest claim comment owner; a failed lookup must not authorize a close. */
|
|
28
29
|
getClaimOwner?(repository: string, number: number): Promise<string | undefined>;
|
|
30
|
+
/** Whether the current owned run has a self-implement.result final observation, even if its worktree remains. */
|
|
31
|
+
hasFinalRunResult?(draft: SweepDraft, repository: string): Promise<boolean | undefined>;
|
|
32
|
+
/** Per-file last change on the draft branch; undefined means file coverage is unverified. */
|
|
33
|
+
getLatestFileChanges?(draft: SweepDraft, repository: string): Promise<Readonly<Record<string, string>> | undefined>;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
export interface DraftSweepOptions {
|
|
@@ -51,6 +56,7 @@ export interface DraftSweepResult {
|
|
|
51
56
|
apply: boolean;
|
|
52
57
|
complete: boolean;
|
|
53
58
|
entries: DraftSweepEntry[];
|
|
59
|
+
counts: Record<string, number>;
|
|
54
60
|
/** Drafts whose run could not be observed from here (kept, or closed by the idle rule). */
|
|
55
61
|
unobserved?: number;
|
|
56
62
|
/** Closes decided this tick (at most DRAFT_SWEEP_CLOSE_CAP). */
|
|
@@ -73,11 +79,8 @@ const stalledLabel = label('close', 'stalled');
|
|
|
73
79
|
const supersededLabel = label('close', 'superseded');
|
|
74
80
|
const approvalLabel = PR_LABELS.find((entry) => entry.axis === 'state' && entry.sweep.action === 'none')?.name;
|
|
75
81
|
const keepLabel = PR_LABELS.find((entry) => entry.sweep.action === 'exclude')?.name;
|
|
82
|
+
const releaseHoldLabel = PR_LABELS.find((entry) => entry.axis === 'addon' && entry.sweep.action === 'none')?.name;
|
|
76
83
|
const PAGE_SIZE = 100;
|
|
77
|
-
/** 🅢 2026-09-28 (lead decision, channel #20798 04:1x): a run the sweeper cannot see is closed as stalled only when its branch
|
|
78
|
-
* is not in a host worktree and the draft has been idle this long. A Pod lives at most POD_JOB_DEADLINE_SECONDS (3h), so a
|
|
79
|
-
* draft idle for 48h cannot belong to a running Pod — the «not in a running Pod» condition follows from the idle time. */
|
|
80
|
-
export const UNOBSERVED_IDLE_CLOSE_HOURS = 48;
|
|
81
84
|
/** At most this many closes per tick, so a wrong rule cannot close everything at once. */
|
|
82
85
|
export const DRAFT_SWEEP_CLOSE_CAP = 10;
|
|
83
86
|
|
|
@@ -94,7 +97,16 @@ async function collectPages<T>(fetch: (page: number, perPage: number) => Promise
|
|
|
94
97
|
|
|
95
98
|
/** A failed inventory or liveness lookup is never treated as proof that a draft can be closed. */
|
|
96
99
|
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date() }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
97
|
-
const result: DraftSweepResult = { repository, apply, complete: false, entries: [] };
|
|
100
|
+
const result: DraftSweepResult = { repository, apply, complete: false, entries: [], counts: {} };
|
|
101
|
+
const record = (entry: DraftSweepEntry): void => {
|
|
102
|
+
result.entries.push(entry);
|
|
103
|
+
result.counts[entry.reason] = (result.counts[entry.reason] ?? 0) + 1;
|
|
104
|
+
debug.log('drafts.cleanup', 'decided', { number: entry.number, action: entry.action, reason: entry.reason });
|
|
105
|
+
};
|
|
106
|
+
const finish = (): DraftSweepResult => {
|
|
107
|
+
debug.log('drafts.cleanup', 'summary', result.counts);
|
|
108
|
+
return result;
|
|
109
|
+
};
|
|
98
110
|
let drafts: SweepDraft[];
|
|
99
111
|
let merged: SweepMergedPr[];
|
|
100
112
|
let liveBranches: ReadonlySet<string> | undefined;
|
|
@@ -109,58 +121,90 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
109
121
|
|| merged.some((pr) => !Number.isInteger(pr.number) || !pr.branch)) throw new Error('Invalid PR inventory');
|
|
110
122
|
} catch (error) {
|
|
111
123
|
result.error = String(error);
|
|
112
|
-
return
|
|
124
|
+
return finish();
|
|
113
125
|
}
|
|
114
126
|
let statuses: Map<number, string | undefined>;
|
|
127
|
+
let finality: Map<number, boolean | undefined>;
|
|
128
|
+
let latestFileChanges: Map<number, Readonly<Record<string, string>> | undefined>;
|
|
115
129
|
try {
|
|
116
130
|
statuses = new Map<number, string | undefined>();
|
|
117
|
-
|
|
131
|
+
finality = new Map<number, boolean | undefined>();
|
|
132
|
+
latestFileChanges = new Map<number, Readonly<Record<string, string>> | undefined>();
|
|
133
|
+
for (const draft of drafts) {
|
|
134
|
+
const status = await adapters.getRunStatus(draft, repository);
|
|
135
|
+
// A prior final cannot terminate a new active run on the same draft.
|
|
136
|
+
const active = status === 'running' || status === 'probable-running';
|
|
137
|
+
const final = active ? false : await adapters.hasFinalRunResult?.(draft, repository);
|
|
138
|
+
finality.set(draft.number, final);
|
|
139
|
+
statuses.set(draft.number, final ? 'self-implement.result final' : status);
|
|
140
|
+
if (draft.changedFiles?.length && adapters.getLatestFileChanges) {
|
|
141
|
+
latestFileChanges.set(draft.number, await adapters.getLatestFileChanges(draft, repository));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
118
144
|
} catch (error) {
|
|
119
145
|
result.error = String(error);
|
|
120
|
-
return
|
|
146
|
+
return finish();
|
|
121
147
|
}
|
|
122
148
|
result.complete = true;
|
|
123
149
|
let closes = 0;
|
|
124
150
|
let unobserved = 0;
|
|
125
151
|
let claimed = 0;
|
|
126
152
|
let claimExpired = 0;
|
|
127
|
-
for (const
|
|
153
|
+
for (const listedDraft of drafts) {
|
|
154
|
+
const draft = { ...listedDraft, latestFileChanges: latestFileChanges.get(listedDraft.number) };
|
|
128
155
|
const runStatus = statuses.get(draft.number);
|
|
156
|
+
const finalRunResult = finality.get(draft.number);
|
|
129
157
|
const states = stateLabels.filter((state) => draft.labels.includes(state.name));
|
|
130
158
|
const contradiction = states.length > 1 || draft.labels.includes(approvalLabel ?? '');
|
|
131
|
-
if (!contradiction && draft.labels.includes(keepLabel ?? '')) {
|
|
132
|
-
|
|
159
|
+
if (draft.labels.includes(releaseHoldLabel ?? '') || (!contradiction && draft.labels.includes(keepLabel ?? ''))) {
|
|
160
|
+
const held = draft.labels.includes(keepLabel ?? '') ? keepLabel : releaseHoldLabel;
|
|
161
|
+
record({ number: draft.number, action: 'keep', reason: `label:${held}`, applied: false });
|
|
133
162
|
continue;
|
|
134
163
|
}
|
|
135
164
|
const isClaimed = !contradiction && draft.labels.includes(runningLabel);
|
|
136
165
|
const ageHours = (now.getTime() - Date.parse(draft.createdAt)) / 3_600_000;
|
|
166
|
+
const idleHours = typeof draft.updatedAt === 'string' && Number.isFinite(Date.parse(draft.updatedAt))
|
|
167
|
+
? (now.getTime() - Date.parse(draft.updatedAt)) / 3_600_000 : NaN;
|
|
137
168
|
// An unobserved claim may still have a merged twin: liveness/holds retain their priority,
|
|
138
169
|
// but a superseded draft must not be hidden by the six-hour claim window.
|
|
139
|
-
const mergedDecision = isClaimed ? decideDraft({ draft, runStatus
|
|
140
|
-
|
|
170
|
+
const mergedDecision = isClaimed ? decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
171
|
+
finalRunResult, ageHours: idleHours }) : undefined;
|
|
172
|
+
const supersededClaim = mergedDecision?.reason.startsWith('superseded-by #') === true
|
|
173
|
+
|| mergedDecision?.reason.startsWith('duplicate-of-open #') === true;
|
|
174
|
+
if (!contradiction && mergedDecision?.reason === 'branch-finality-unobserved') {
|
|
175
|
+
record({ number: draft.number, action: 'keep', reason: mergedDecision.reason, applied: false });
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
141
178
|
// Without an observed update time, neither expiration nor a fallback to creation time can authorize mutation —
|
|
142
179
|
// but a merged twin does not need the update time, so superseded keeps its priority over the unobserved claim.
|
|
143
180
|
if (isClaimed && !supersededClaim && (typeof draft.updatedAt !== 'string' || !Number.isFinite(Date.parse(draft.updatedAt)))) {
|
|
144
|
-
|
|
181
|
+
record({ number: draft.number, action: 'keep', reason: 'claim-update-unobserved', applied: false });
|
|
145
182
|
continue;
|
|
146
183
|
}
|
|
147
|
-
|
|
148
|
-
if (isClaimed && !supersededClaim && Number.isFinite(claimIdleHours) && claimIdleHours < CLAIM_IDLE_HOURS) {
|
|
184
|
+
if (isClaimed && !supersededClaim && Number.isFinite(idleHours) && idleHours < CLAIM_IDLE_HOURS) {
|
|
149
185
|
claimed += 1;
|
|
150
|
-
|
|
186
|
+
record({ number: draft.number, action: 'keep', reason: `label:running(<${CLAIM_IDLE_HOURS}h)`, applied: false });
|
|
151
187
|
continue;
|
|
152
188
|
}
|
|
153
|
-
if (isClaimed && !supersededClaim && Number.isFinite(
|
|
189
|
+
if (isClaimed && !supersededClaim && Number.isFinite(idleHours) && idleHours >= CLAIM_IDLE_HOURS) {
|
|
154
190
|
claimExpired += 1;
|
|
155
|
-
if (
|
|
156
|
-
|
|
191
|
+
if (liveBranches.has(draft.branch) && finalRunResult === undefined
|
|
192
|
+
&& runStatus !== 'running' && runStatus !== 'probable-running') {
|
|
193
|
+
record({ number: draft.number, action: 'keep', reason: 'branch-finality-unobserved', applied: false });
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (runStatus === 'running' || runStatus === 'probable-running' ||
|
|
197
|
+
(runStatus !== 'self-implement.result final' && liveBranches.has(draft.branch))) {
|
|
198
|
+
record({ number: draft.number, action: 'keep', reason: 'claim-expired-but-live', applied: false });
|
|
157
199
|
continue;
|
|
158
200
|
}
|
|
159
201
|
const action = closes >= DRAFT_SWEEP_CLOSE_CAP ? 'keep' : 'close';
|
|
160
202
|
if (action === 'close') closes += 1;
|
|
161
|
-
const entry: DraftSweepEntry = { number: draft.number, action,
|
|
203
|
+
const entry: DraftSweepEntry = { number: draft.number, action,
|
|
204
|
+
reason: action === 'close' ? runStatus === 'self-implement.result final'
|
|
205
|
+
? 'claim-expired (self-implement.result final; worktree is not live)' : 'claim-expired' : 'close-cap',
|
|
162
206
|
...(action === 'close' ? { statusLabel: stalledLabel } : {}), applied: false };
|
|
163
|
-
|
|
207
|
+
record(entry);
|
|
164
208
|
if (!apply || action !== 'close') continue;
|
|
165
209
|
let labelsChanged = false;
|
|
166
210
|
try {
|
|
@@ -168,7 +212,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
168
212
|
await adapters.setLabels(repository, draft.number, { add: stalledLabel, remove: [runningLabel] });
|
|
169
213
|
labelsChanged = true;
|
|
170
214
|
await adapters.closeDraft(repository, draft.number,
|
|
171
|
-
`Draft sweep: 처리 중 표식이 ${CLAIM_IDLE_HOURS}시간 갱신 없음 — 런·워크트리 없음 · 주인 ${owner}. Closed as stalled. Branch preserved; reopen to restore.`);
|
|
215
|
+
`Draft sweep: 처리 중 표식이 ${CLAIM_IDLE_HOURS}시간 갱신 없음 — ${runStatus === 'self-implement.result final' ? 'self-implement.result final · 남은 워크트리는 live 아님' : '런·워크트리 없음'} · 주인 ${owner}. Closed as stalled. Branch preserved; reopen to restore.`);
|
|
172
216
|
entry.applied = true;
|
|
173
217
|
} catch (error) {
|
|
174
218
|
if (labelsChanged) entry.partialApplied = true;
|
|
@@ -178,17 +222,12 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
178
222
|
}
|
|
179
223
|
// Unlabelled non-harness drafts are outside the sweeper's jurisdiction.
|
|
180
224
|
if (!contradiction && !states.length && !draft.branch.startsWith('self-impl/')) {
|
|
181
|
-
|
|
225
|
+
record({ number: draft.number, action: 'keep', reason: 'outside-harness', applied: false });
|
|
182
226
|
continue;
|
|
183
227
|
}
|
|
184
|
-
let decision = supersededClaim ? mergedDecision! : decideDraft({ draft, runStatus, mergedTwins: merged, liveBranches,
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const idleHours = (now.getTime() - Date.parse(draft.updatedAt ?? draft.createdAt)) / 3_600_000;
|
|
188
|
-
if (!liveBranches.has(draft.branch) && Number.isFinite(idleHours) && idleHours >= UNOBSERVED_IDLE_CLOSE_HOURS) {
|
|
189
|
-
decision = { action: 'close', reason: 'unobserved-idle' };
|
|
190
|
-
}
|
|
191
|
-
}
|
|
228
|
+
let decision = supersededClaim ? mergedDecision! : decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
229
|
+
finalRunResult, ageHours: runStatus ? ageHours : idleHours });
|
|
230
|
+
if (!runStatus && (decision.reason === 'unobserved' || decision.reason === 'stale-unobserved')) unobserved += 1;
|
|
192
231
|
if (!contradiction && decision.action === 'close') {
|
|
193
232
|
if (closes >= DRAFT_SWEEP_CLOSE_CAP) decision = { action: 'keep', reason: 'close-cap' };
|
|
194
233
|
else closes += 1;
|
|
@@ -199,10 +238,10 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
199
238
|
: decision.reason;
|
|
200
239
|
const isLive = decision.reason === 'live';
|
|
201
240
|
const target = action === 'report' ? undefined : action === 'close'
|
|
202
|
-
? decision.reason.startsWith('superseded-by #') ? supersededLabel : stalledLabel
|
|
241
|
+
? decision.reason.startsWith('superseded-by #') || decision.reason.startsWith('duplicate-of-open #') ? supersededLabel : stalledLabel
|
|
203
242
|
: isLive ? (states.length ? runningLabel : undefined) : runStatus && (states[0]?.name === runningLabel || states.length === 0) ? stalledLabel : undefined;
|
|
204
243
|
const entry: DraftSweepEntry = { number: draft.number, action, reason, ...(target ? { statusLabel: target } : {}), applied: false };
|
|
205
|
-
|
|
244
|
+
record(entry);
|
|
206
245
|
if (!apply || action === 'report') continue;
|
|
207
246
|
let labelsChanged = false;
|
|
208
247
|
try {
|
|
@@ -213,8 +252,8 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
213
252
|
labelsChanged = true;
|
|
214
253
|
}
|
|
215
254
|
if (action === 'close') {
|
|
216
|
-
await adapters.closeDraft(repository, draft.number, decision.reason === 'unobserved
|
|
217
|
-
? `Draft sweep: run unobserved — no run record reachable here, no host worktree for this branch, idle ≥${
|
|
255
|
+
await adapters.closeDraft(repository, draft.number, decision.reason === 'stale-unobserved'
|
|
256
|
+
? `Draft sweep: run unobserved — no run record reachable here, no host worktree for this branch, idle ≥${STALLED_DRAFT_HOURS}h. Closed as stalled. Branch preserved; reopen to restore.`
|
|
218
257
|
: `Draft sweep: ${decision.reason}. Branch preserved.`);
|
|
219
258
|
}
|
|
220
259
|
entry.applied = labelsChanged || action === 'close';
|
|
@@ -227,5 +266,5 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
227
266
|
result.closed = closes;
|
|
228
267
|
result.claimed = claimed;
|
|
229
268
|
result.claimExpired = claimExpired;
|
|
230
|
-
return
|
|
269
|
+
return finish();
|
|
231
270
|
}
|
|
@@ -1,42 +1,97 @@
|
|
|
1
1
|
import { PR_LABELS, STALLED_DRAFT_HOURS } from '../github/pr-labels.js';
|
|
2
|
+
import { RELEASE_PATH_LABEL } from './release-path-guard.js';
|
|
2
3
|
|
|
3
4
|
export interface DraftTriagePr {
|
|
4
5
|
number: number;
|
|
5
6
|
title?: string;
|
|
6
7
|
branch: string;
|
|
7
8
|
labels?: readonly string[];
|
|
9
|
+
body?: string;
|
|
10
|
+
mergeCommitMessage?: string;
|
|
11
|
+
landingVerifiedComments?: readonly string[];
|
|
12
|
+
createdAt?: string;
|
|
13
|
+
mergedAt?: string;
|
|
14
|
+
changedFiles?: readonly string[];
|
|
15
|
+
/** Latest change to each draft file, from the draft branch's commit history. Missing is not creation time. */
|
|
16
|
+
latestFileChanges?: Readonly<Record<string, string>>;
|
|
8
17
|
}
|
|
9
18
|
|
|
10
19
|
export interface DraftTriageInput {
|
|
11
20
|
draft: DraftTriagePr;
|
|
12
21
|
runStatus: string | undefined;
|
|
13
22
|
mergedTwins: readonly DraftTriagePr[];
|
|
23
|
+
openDrafts?: readonly DraftTriagePr[];
|
|
14
24
|
ageHours: number;
|
|
15
25
|
liveBranches: ReadonlySet<string>;
|
|
26
|
+
/** false only when the current run's final result has actually been checked and ruled out. */
|
|
27
|
+
finalRunResult?: boolean;
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
export type DraftDecision = { action: 'close' | 'keep'; reason: string };
|
|
19
31
|
|
|
20
32
|
// Labels the sweeper must never close: an approval-waiting state and the human «keep» / release holds (R-PRK3).
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.
|
|
33
|
+
// RELGUARD's release-path hold waits for OP approval — a long wait is not «stale» (TC review #23217).
|
|
34
|
+
const PROTECTED_LABELS: ReadonlySet<string> = new Set<string>([...PR_LABELS
|
|
35
|
+
.filter((label) => label.sweep.action === 'exclude' || (label.sweep.action === 'none' && (label.axis === 'state' || label.axis === 'addon')))
|
|
36
|
+
.map((label) => label.name), RELEASE_PATH_LABEL]);
|
|
24
37
|
|
|
25
38
|
const goalId = (branch: string): string | undefined => /(?:^|[-/])goalid-([a-f0-9]+)(?=-|\/|$)/i.exec(branch)?.[1]?.toLowerCase();
|
|
39
|
+
export const branchStem = (branch: string): string | undefined => /^self-impl\/(.+)-[a-f0-9]{8}-r[a-f0-9]+$/i.exec(branch)?.[1];
|
|
40
|
+
const slot = (body?: string): string | undefined => /^칸:\s*(.+?)\s*$/m.exec(body ?? '')?.[1];
|
|
41
|
+
const referencesDraft = (text: string, number: number): boolean =>
|
|
42
|
+
new RegExp(`(?:\\(수확\\s*#${number}\\s*\\)|\\bsuperseded\\s*#${number}(?!\\d))`, 'i').test(text);
|
|
43
|
+
const landingCommentReferencesDraft = (text: string, number: number): boolean =>
|
|
44
|
+
new RegExp(`\\blanding-verified\\s*:\\s*(?:draft|superseded|수확)\\s*#${number}(?!\\d)\\b`, 'i').test(text);
|
|
26
45
|
|
|
27
|
-
export function decideDraft({ draft, runStatus, mergedTwins, ageHours, liveBranches }: DraftTriageInput): DraftDecision {
|
|
46
|
+
export function decideDraft({ draft, runStatus, mergedTwins, openDrafts, ageHours, liveBranches, finalRunResult }: DraftTriageInput): DraftDecision {
|
|
28
47
|
const held = draft.labels?.find((label) => PROTECTED_LABELS.has(label));
|
|
29
48
|
if (held) return { action: 'keep', reason: `label:${held}` };
|
|
30
|
-
if (runStatus
|
|
49
|
+
if (runStatus !== 'self-implement.result final' && draft.branch && liveBranches.has(draft.branch)
|
|
50
|
+
&& finalRunResult === undefined && runStatus !== 'running' && runStatus !== 'probable-running') {
|
|
51
|
+
return { action: 'keep', reason: 'branch-finality-unobserved' };
|
|
52
|
+
}
|
|
53
|
+
if (runStatus === 'running' || runStatus === 'probable-running' ||
|
|
54
|
+
(runStatus !== 'self-implement.result final' && draft.branch && liveBranches.has(draft.branch))) {
|
|
31
55
|
return { action: 'keep', reason: 'live' };
|
|
32
56
|
}
|
|
33
|
-
// A missing assessment never authorizes a close; unknown is the running-run query's non-running classification.
|
|
34
|
-
if (!runStatus) return { action: 'keep', reason: 'unobserved' }; // run status unknown — kept, and said so
|
|
35
57
|
const lineage = goalId(draft.branch);
|
|
36
58
|
const twin = mergedTwins.find((pr) => pr.number !== draft.number && (
|
|
37
59
|
(draft.title && pr.title === draft.title) || (lineage && goalId(pr.branch) === lineage)
|
|
38
60
|
));
|
|
39
61
|
if (twin) return { action: 'close', reason: `superseded-by #${twin.number}` };
|
|
62
|
+
const stem = branchStem(draft.branch);
|
|
63
|
+
const createdAt = Date.parse(draft.createdAt ?? '');
|
|
64
|
+
const newer = stem && draft.title && Number.isFinite(createdAt) ? openDrafts
|
|
65
|
+
?.filter((pr) => pr.number !== draft.number && pr.title === draft.title && branchStem(pr.branch) === stem
|
|
66
|
+
&& Number.isFinite(Date.parse(pr.createdAt ?? '')) && Date.parse(pr.createdAt!) > createdAt)
|
|
67
|
+
.sort((a, b) => Date.parse(b.createdAt!) - Date.parse(a.createdAt!) || b.number - a.number)[0] : undefined;
|
|
68
|
+
if (newer) return { action: 'close', reason: `duplicate-of-open #${newer.number}` };
|
|
69
|
+
const harvest = mergedTwins.find((pr) => pr.number !== draft.number && (
|
|
70
|
+
[pr.mergeCommitMessage, pr.body].some((text) => text && referencesDraft(text, draft.number))
|
|
71
|
+
|| pr.landingVerifiedComments?.some((text) => landingCommentReferencesDraft(text, draft.number))
|
|
72
|
+
));
|
|
73
|
+
if (harvest) return { action: 'close', reason: `superseded-by #${harvest.number} (harvest #${draft.number})` };
|
|
74
|
+
const created = Date.parse(draft.createdAt ?? '');
|
|
75
|
+
const files = draft.changedFiles;
|
|
76
|
+
const draftSlot = slot(draft.body);
|
|
77
|
+
const later = mergedTwins.filter((pr) => pr.number !== draft.number && Number.isFinite(created)
|
|
78
|
+
&& Number.isFinite(Date.parse(pr.mergedAt ?? '')) && Date.parse(pr.mergedAt!) > created
|
|
79
|
+
&& ((lineage && goalId(pr.branch) === lineage) || (draftSlot && slot(pr.body) === draftSlot)));
|
|
80
|
+
if (files?.length && files.every((file) => {
|
|
81
|
+
const changed = Date.parse(draft.latestFileChanges?.[file] ?? '');
|
|
82
|
+
return Number.isFinite(changed) && changed >= created && later.some((pr) =>
|
|
83
|
+
pr.changedFiles?.includes(file) && Date.parse(pr.mergedAt!) > changed);
|
|
84
|
+
})) {
|
|
85
|
+
const covering = later.filter((pr) => pr.changedFiles?.some((file) => files.includes(file)
|
|
86
|
+
&& Date.parse(pr.mergedAt!) > Date.parse(draft.latestFileChanges![file]!)));
|
|
87
|
+
return { action: 'close', reason: `superseded-by #${covering.map((pr) => pr.number).join(', #')} (all-files-landed)` };
|
|
88
|
+
}
|
|
89
|
+
if (!runStatus) return Number.isFinite(ageHours) && ageHours >= STALLED_DRAFT_HOURS
|
|
90
|
+
? { action: 'close', reason: 'stale-unobserved' }
|
|
91
|
+
: { action: 'keep', reason: 'unobserved' };
|
|
92
|
+
if (runStatus === 'self-implement.result final') return Number.isFinite(ageHours) && ageHours >= STALLED_DRAFT_HOURS
|
|
93
|
+
? { action: 'close', reason: 'stale-ended-run (self-implement.result final; worktree is not live)' }
|
|
94
|
+
: { action: 'keep', reason: 'recent (self-implement.result final; worktree is not live)' };
|
|
40
95
|
if (Number.isFinite(ageHours) && ageHours >= STALLED_DRAFT_HOURS) return { action: 'close', reason: 'stale-ended-run' };
|
|
41
96
|
return { action: 'keep', reason: 'recent' };
|
|
42
97
|
}
|