elanous 0.2.10 → 0.2.11
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/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.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/2310-7a59f043f6db207e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.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-a39d1d9921e10d43.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/507-5acd98bd6dab2d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -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/{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/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-ea5bee9dfae512c7.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/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-b12b6d2f8d2d1aea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.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-50cb2a0eb15e6c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-35414e0a007b4082.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.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-239c17b911b84e72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.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/543f56bcb1f79fca.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/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/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/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -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/cut-branch.ts +84 -0
- package/scripts/release-loop/gate-node.ts +14 -13
- package/scripts/release-loop/mac-smoke-node.ts +229 -0
- package/scripts/release-loop/node-verdict.ts +3 -3
- 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 +61 -10
- 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/test-diet/node.ts +1 -1
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +243 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +73 -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 +80 -10
- 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/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 +1 -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 +90 -4
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +19 -9
- 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 +17 -4
- 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 +48 -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/dashboard/index.ts +9 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -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 +6 -1
- 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 +100 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -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 +37 -0
- package/src/graph-runner/graph-grow.ts +47 -0
- package/src/graph-runner/runner.ts +317 -25
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +247 -7
- 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/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 +21 -20
- package/src/index.ts +52 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +10 -0
- 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-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 +26 -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 +36 -0
- 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/outputs-route.ts +44 -0
- 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/trace.ts +18 -6
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +80 -6
- package/src/nexus/index.ts +2 -0
- package/src/nexus/kinds/webterm.ts +2 -1
- 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 +116 -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 +109 -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 +2 -2
- package/src/release-loop/feature-store.ts +5 -3
- 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 +548 -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 +38 -33
- package/src/self-dev/draft-triage-rules.ts +8 -5
- 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/gate-baseline.ts +1 -1
- package/src/self-implement/gate-cli.ts +40 -1
- package/src/self-implement/gate-scope.ts +37 -7
- 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 +22 -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 +242 -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 +1 -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 +29 -7
- 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 +214 -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 +10 -1
- package/src/telegram-project-command.ts +71 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +29 -3
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +102 -20
- 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 → Y4zKzL62sakG5momz3SoQ}/_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>;
|
|
@@ -51,6 +52,7 @@ export interface DraftSweepResult {
|
|
|
51
52
|
apply: boolean;
|
|
52
53
|
complete: boolean;
|
|
53
54
|
entries: DraftSweepEntry[];
|
|
55
|
+
counts: Record<string, number>;
|
|
54
56
|
/** Drafts whose run could not be observed from here (kept, or closed by the idle rule). */
|
|
55
57
|
unobserved?: number;
|
|
56
58
|
/** Closes decided this tick (at most DRAFT_SWEEP_CLOSE_CAP). */
|
|
@@ -73,11 +75,8 @@ const stalledLabel = label('close', 'stalled');
|
|
|
73
75
|
const supersededLabel = label('close', 'superseded');
|
|
74
76
|
const approvalLabel = PR_LABELS.find((entry) => entry.axis === 'state' && entry.sweep.action === 'none')?.name;
|
|
75
77
|
const keepLabel = PR_LABELS.find((entry) => entry.sweep.action === 'exclude')?.name;
|
|
78
|
+
const releaseHoldLabel = PR_LABELS.find((entry) => entry.axis === 'addon' && entry.sweep.action === 'none')?.name;
|
|
76
79
|
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
80
|
/** At most this many closes per tick, so a wrong rule cannot close everything at once. */
|
|
82
81
|
export const DRAFT_SWEEP_CLOSE_CAP = 10;
|
|
83
82
|
|
|
@@ -94,7 +93,16 @@ async function collectPages<T>(fetch: (page: number, perPage: number) => Promise
|
|
|
94
93
|
|
|
95
94
|
/** A failed inventory or liveness lookup is never treated as proof that a draft can be closed. */
|
|
96
95
|
export async function runDraftSweep({ repository, adapters, apply = false, now = new Date() }: DraftSweepOptions): Promise<DraftSweepResult> {
|
|
97
|
-
const result: DraftSweepResult = { repository, apply, complete: false, entries: [] };
|
|
96
|
+
const result: DraftSweepResult = { repository, apply, complete: false, entries: [], counts: {} };
|
|
97
|
+
const record = (entry: DraftSweepEntry): void => {
|
|
98
|
+
result.entries.push(entry);
|
|
99
|
+
result.counts[entry.reason] = (result.counts[entry.reason] ?? 0) + 1;
|
|
100
|
+
debug.log('drafts.cleanup', 'decided', { number: entry.number, action: entry.action, reason: entry.reason });
|
|
101
|
+
};
|
|
102
|
+
const finish = (): DraftSweepResult => {
|
|
103
|
+
debug.log('drafts.cleanup', 'summary', result.counts);
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
98
106
|
let drafts: SweepDraft[];
|
|
99
107
|
let merged: SweepMergedPr[];
|
|
100
108
|
let liveBranches: ReadonlySet<string> | undefined;
|
|
@@ -109,7 +117,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
109
117
|
|| merged.some((pr) => !Number.isInteger(pr.number) || !pr.branch)) throw new Error('Invalid PR inventory');
|
|
110
118
|
} catch (error) {
|
|
111
119
|
result.error = String(error);
|
|
112
|
-
return
|
|
120
|
+
return finish();
|
|
113
121
|
}
|
|
114
122
|
let statuses: Map<number, string | undefined>;
|
|
115
123
|
try {
|
|
@@ -117,7 +125,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
117
125
|
for (const draft of drafts) statuses.set(draft.number, await adapters.getRunStatus(draft, repository));
|
|
118
126
|
} catch (error) {
|
|
119
127
|
result.error = String(error);
|
|
120
|
-
return
|
|
128
|
+
return finish();
|
|
121
129
|
}
|
|
122
130
|
result.complete = true;
|
|
123
131
|
let closes = 0;
|
|
@@ -128,39 +136,41 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
128
136
|
const runStatus = statuses.get(draft.number);
|
|
129
137
|
const states = stateLabels.filter((state) => draft.labels.includes(state.name));
|
|
130
138
|
const contradiction = states.length > 1 || draft.labels.includes(approvalLabel ?? '');
|
|
131
|
-
if (!contradiction && draft.labels.includes(keepLabel ?? '')) {
|
|
132
|
-
|
|
139
|
+
if (draft.labels.includes(releaseHoldLabel ?? '') || (!contradiction && draft.labels.includes(keepLabel ?? ''))) {
|
|
140
|
+
const held = draft.labels.includes(keepLabel ?? '') ? keepLabel : releaseHoldLabel;
|
|
141
|
+
record({ number: draft.number, action: 'keep', reason: `label:${held}`, applied: false });
|
|
133
142
|
continue;
|
|
134
143
|
}
|
|
135
144
|
const isClaimed = !contradiction && draft.labels.includes(runningLabel);
|
|
136
145
|
const ageHours = (now.getTime() - Date.parse(draft.createdAt)) / 3_600_000;
|
|
146
|
+
const idleHours = typeof draft.updatedAt === 'string' && Number.isFinite(Date.parse(draft.updatedAt))
|
|
147
|
+
? (now.getTime() - Date.parse(draft.updatedAt)) / 3_600_000 : NaN;
|
|
137
148
|
// An unobserved claim may still have a merged twin: liveness/holds retain their priority,
|
|
138
149
|
// but a superseded draft must not be hidden by the six-hour claim window.
|
|
139
|
-
const mergedDecision = isClaimed ? decideDraft({ draft, runStatus
|
|
150
|
+
const mergedDecision = isClaimed ? decideDraft({ draft, runStatus, mergedTwins: merged, liveBranches, ageHours: idleHours }) : undefined;
|
|
140
151
|
const supersededClaim = mergedDecision?.reason.startsWith('superseded-by #') === true;
|
|
141
152
|
// Without an observed update time, neither expiration nor a fallback to creation time can authorize mutation —
|
|
142
153
|
// but a merged twin does not need the update time, so superseded keeps its priority over the unobserved claim.
|
|
143
154
|
if (isClaimed && !supersededClaim && (typeof draft.updatedAt !== 'string' || !Number.isFinite(Date.parse(draft.updatedAt)))) {
|
|
144
|
-
|
|
155
|
+
record({ number: draft.number, action: 'keep', reason: 'claim-update-unobserved', applied: false });
|
|
145
156
|
continue;
|
|
146
157
|
}
|
|
147
|
-
|
|
148
|
-
if (isClaimed && !supersededClaim && Number.isFinite(claimIdleHours) && claimIdleHours < CLAIM_IDLE_HOURS) {
|
|
158
|
+
if (isClaimed && !supersededClaim && Number.isFinite(idleHours) && idleHours < CLAIM_IDLE_HOURS) {
|
|
149
159
|
claimed += 1;
|
|
150
|
-
|
|
160
|
+
record({ number: draft.number, action: 'keep', reason: `label:running(<${CLAIM_IDLE_HOURS}h)`, applied: false });
|
|
151
161
|
continue;
|
|
152
162
|
}
|
|
153
|
-
if (isClaimed && !supersededClaim && Number.isFinite(
|
|
163
|
+
if (isClaimed && !supersededClaim && Number.isFinite(idleHours) && idleHours >= CLAIM_IDLE_HOURS) {
|
|
154
164
|
claimExpired += 1;
|
|
155
165
|
if (runStatus === 'running' || runStatus === 'probable-running' || liveBranches.has(draft.branch)) {
|
|
156
|
-
|
|
166
|
+
record({ number: draft.number, action: 'keep', reason: 'claim-expired-but-live', applied: false });
|
|
157
167
|
continue;
|
|
158
168
|
}
|
|
159
169
|
const action = closes >= DRAFT_SWEEP_CLOSE_CAP ? 'keep' : 'close';
|
|
160
170
|
if (action === 'close') closes += 1;
|
|
161
171
|
const entry: DraftSweepEntry = { number: draft.number, action, reason: action === 'close' ? 'claim-expired' : 'close-cap',
|
|
162
172
|
...(action === 'close' ? { statusLabel: stalledLabel } : {}), applied: false };
|
|
163
|
-
|
|
173
|
+
record(entry);
|
|
164
174
|
if (!apply || action !== 'close') continue;
|
|
165
175
|
let labelsChanged = false;
|
|
166
176
|
try {
|
|
@@ -178,17 +188,12 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
178
188
|
}
|
|
179
189
|
// Unlabelled non-harness drafts are outside the sweeper's jurisdiction.
|
|
180
190
|
if (!contradiction && !states.length && !draft.branch.startsWith('self-impl/')) {
|
|
181
|
-
|
|
191
|
+
record({ number: draft.number, action: 'keep', reason: 'outside-harness', applied: false });
|
|
182
192
|
continue;
|
|
183
193
|
}
|
|
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
|
-
}
|
|
194
|
+
let decision = supersededClaim ? mergedDecision! : decideDraft({ draft, runStatus, mergedTwins: merged, liveBranches,
|
|
195
|
+
ageHours: runStatus ? ageHours : idleHours });
|
|
196
|
+
if (!runStatus && (decision.reason === 'unobserved' || decision.reason === 'stale-unobserved')) unobserved += 1;
|
|
192
197
|
if (!contradiction && decision.action === 'close') {
|
|
193
198
|
if (closes >= DRAFT_SWEEP_CLOSE_CAP) decision = { action: 'keep', reason: 'close-cap' };
|
|
194
199
|
else closes += 1;
|
|
@@ -202,7 +207,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
202
207
|
? decision.reason.startsWith('superseded-by #') ? supersededLabel : stalledLabel
|
|
203
208
|
: isLive ? (states.length ? runningLabel : undefined) : runStatus && (states[0]?.name === runningLabel || states.length === 0) ? stalledLabel : undefined;
|
|
204
209
|
const entry: DraftSweepEntry = { number: draft.number, action, reason, ...(target ? { statusLabel: target } : {}), applied: false };
|
|
205
|
-
|
|
210
|
+
record(entry);
|
|
206
211
|
if (!apply || action === 'report') continue;
|
|
207
212
|
let labelsChanged = false;
|
|
208
213
|
try {
|
|
@@ -213,8 +218,8 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
213
218
|
labelsChanged = true;
|
|
214
219
|
}
|
|
215
220
|
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 ≥${
|
|
221
|
+
await adapters.closeDraft(repository, draft.number, decision.reason === 'stale-unobserved'
|
|
222
|
+
? `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
223
|
: `Draft sweep: ${decision.reason}. Branch preserved.`);
|
|
219
224
|
}
|
|
220
225
|
entry.applied = labelsChanged || action === 'close';
|
|
@@ -227,5 +232,5 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
227
232
|
result.closed = closes;
|
|
228
233
|
result.claimed = claimed;
|
|
229
234
|
result.claimExpired = claimExpired;
|
|
230
|
-
return
|
|
235
|
+
return finish();
|
|
231
236
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
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;
|
|
@@ -18,9 +19,10 @@ export interface DraftTriageInput {
|
|
|
18
19
|
export type DraftDecision = { action: 'close' | 'keep'; reason: string };
|
|
19
20
|
|
|
20
21
|
// Labels the sweeper must never close: an approval-waiting state and the human «keep» / release holds (R-PRK3).
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.
|
|
22
|
+
// RELGUARD's release-path hold waits for OP approval — a long wait is not «stale» (TC review #23217).
|
|
23
|
+
const PROTECTED_LABELS: ReadonlySet<string> = new Set<string>([...PR_LABELS
|
|
24
|
+
.filter((label) => label.sweep.action === 'exclude' || (label.sweep.action === 'none' && (label.axis === 'state' || label.axis === 'addon')))
|
|
25
|
+
.map((label) => label.name), RELEASE_PATH_LABEL]);
|
|
24
26
|
|
|
25
27
|
const goalId = (branch: string): string | undefined => /(?:^|[-/])goalid-([a-f0-9]+)(?=-|\/|$)/i.exec(branch)?.[1]?.toLowerCase();
|
|
26
28
|
|
|
@@ -30,13 +32,14 @@ export function decideDraft({ draft, runStatus, mergedTwins, ageHours, liveBranc
|
|
|
30
32
|
if (runStatus === 'running' || runStatus === 'probable-running' || (draft.branch && liveBranches.has(draft.branch))) {
|
|
31
33
|
return { action: 'keep', reason: 'live' };
|
|
32
34
|
}
|
|
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
35
|
const lineage = goalId(draft.branch);
|
|
36
36
|
const twin = mergedTwins.find((pr) => pr.number !== draft.number && (
|
|
37
37
|
(draft.title && pr.title === draft.title) || (lineage && goalId(pr.branch) === lineage)
|
|
38
38
|
));
|
|
39
39
|
if (twin) return { action: 'close', reason: `superseded-by #${twin.number}` };
|
|
40
|
+
if (!runStatus) return Number.isFinite(ageHours) && ageHours >= STALLED_DRAFT_HOURS
|
|
41
|
+
? { action: 'close', reason: 'stale-unobserved' }
|
|
42
|
+
: { action: 'keep', reason: 'unobserved' };
|
|
40
43
|
if (Number.isFinite(ageHours) && ageHours >= STALLED_DRAFT_HOURS) return { action: 'close', reason: 'stale-ended-run' };
|
|
41
44
|
return { action: 'keep', reason: 'recent' };
|
|
42
45
|
}
|