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
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { dlopen, FFIType } from 'bun:ffi';
|
|
2
3
|
import { createHash } from 'node:crypto';
|
|
3
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
4
5
|
import { constants as osConstants } from 'node:os';
|
|
5
|
-
import { resolve } from 'node:path';
|
|
6
|
+
import { resolve, sep } from 'node:path';
|
|
7
|
+
import { findGitDir } from '../git-fs/locate.js';
|
|
6
8
|
import { LogStore, logsDbPath } from '../mss/logging/log-store.js';
|
|
7
9
|
import { loadSelfDevRun } from '../self-dev/run-store.js';
|
|
8
10
|
import { normalizeRunId } from './harness-space.js';
|
|
@@ -20,8 +22,10 @@ import { DevPipelineError } from '../self-dev/dev-pipeline.js';
|
|
|
20
22
|
import { runDraftSweep, type DraftSweepAdapters, type DraftSweepResult, type SweepDraft, type SweepMergedPr } from '../self-dev/draft-sweep.js';
|
|
21
23
|
import { debug } from '../debug/log.js';
|
|
22
24
|
import { dispatchTask, type DispatchTaskInput, type DispatchTaskDeps } from '../execution-loop/dispatch-task.js';
|
|
25
|
+
import { launchRequestId, preLaunchGate, type PreLaunchGateDeps } from '../execution-loop/launch-gate.js';
|
|
23
26
|
import { PR_LABELS } from '../github/pr-labels.js';
|
|
24
|
-
import { decideBudget, readBudgetInputsLive, type BudgetDecision, type BudgetInputs } from '../self-implement/budget-gate.js';
|
|
27
|
+
import { CODEX_PROVIDER, GROK_PROVIDER, decideBudget, readBudgetInputsLive, type BudgetDecision, type BudgetInputs } from '../self-implement/budget-gate.js';
|
|
28
|
+
import { DEFAULT_FALLBACK_CHAIN } from '../oauth/fallback-chain.js';
|
|
25
29
|
import { installDeliverableVerifyCliCommand, type InstallDeliverableVerifyCliDeps } from './deliverable-verify-cli.js';
|
|
26
30
|
import { getUserConfig } from '../user-config.js';
|
|
27
31
|
import { installHarnessCliSinkHook } from './harness-cli-sink.js';
|
|
@@ -92,6 +96,7 @@ export interface HarnessAskSayOptions {
|
|
|
92
96
|
target?: string;
|
|
93
97
|
yes?: boolean;
|
|
94
98
|
forcePreflight?: boolean;
|
|
99
|
+
forceGate?: boolean;
|
|
95
100
|
autoMerge?: boolean;
|
|
96
101
|
mergeByHost?: boolean;
|
|
97
102
|
observeOnly?: boolean;
|
|
@@ -249,12 +254,14 @@ function registerHarnessAskSayOptions(command: Command): Command {
|
|
|
249
254
|
.option('--correlation <id>', '요청과 런을 잇는 불투명 correlation 값')
|
|
250
255
|
.addOption(new Option('--goal-type <type>', `골 종류 (${GOAL_TYPES.join('|')})`).choices([...GOAL_TYPES]))
|
|
251
256
|
.option('--force-preflight', '전제 검사 막힘을 명시 요청으로 우회(관측에 남음)')
|
|
257
|
+
.option('--force-gate', '같은 골 실행 중 막힘을 명시 요청으로 우회(관측에 남음; 예산 막힘은 우회 불가)')
|
|
252
258
|
.option('--child-llm-provider <id>', 'self: 구현 자식 LLM provider(--child-llm-model과 함께)')
|
|
253
259
|
.option('--child-llm-model <id>', 'self: 구현 자식 LLM model(--child-llm-provider와 함께)')
|
|
254
260
|
.option('--child-llm-effort <level>', 'self: 구현 자식 추론 노력 minimal|low|medium|high|xhigh|max — 모델 상한을 넘으면 «거부»한다(--child-llm-provider와 함께)')
|
|
255
261
|
.addOption(new Option('--substrate <kind>', '실행 칸 — local(설정 없을 때 기본 · 이 기계) | pod(k8s Pod · 같은 그래프가 원격에서 돈다)').choices(['local', 'pod']))
|
|
256
262
|
.option('--pod-pool <spec>', 'pod: 풀 — 인자 > ELANOUS_POD_POOL > harness.podPool > 기존 pod.pool > 현재 컨텍스트')
|
|
257
|
-
.addOption(new Option('--pod-memory <tier>', 'pod: 메모리 등급 — standard(16Gi) | high(32Gi) · 없으면 골 문면 `Pod 메모리:
|
|
263
|
+
.addOption(new Option('--pod-memory <tier>', 'pod: 메모리 등급 — lite(2Gi · 문서·조사·네트워크 스킬 골 · OOM 이면 high 로 한 번 재시도) | standard(16Gi) | high(32Gi) · 없으면 골 문면 `Pod 메모리: <등급>` 한 줄 · 그것도 없으면 골이 apps/pwa/ 를 담을 때 high').choices(['lite', 'standard', 'high']))
|
|
264
|
+
.option('--after <goal-or-pr>', 'pod: 선행 — 이 골 ID(16자) 또는 PR(#N) 이 병합될 때까지 Pod 발사가 큐에서 이유와 함께 기다린다(병합 없이 닫히면 blocked) · 골 문면 `선행: #N` 한 줄과 같다 · 대상 파일만 겹치면 선행이 아니다(경고만)')
|
|
258
265
|
.option('--source <spec>', 'pod: 원천 — commit:<40자 sha> | pr:<정수> | worktree:<경로> | files:<경로>[,<경로>…] · `--substrate pod` 와 함께');
|
|
259
266
|
}
|
|
260
267
|
|
|
@@ -320,7 +327,7 @@ function assertHarnessChildLlmModel(opts: HarnessAskSayChildLlmOptions): void {
|
|
|
320
327
|
}
|
|
321
328
|
|
|
322
329
|
/** Shared post-parse gate: validate child model before any ask/say early return (including `--dry-run`). */
|
|
323
|
-
type HarnessSubstrateOpts = { substrate?: 'local' | 'pod'; podPool?: string; podMemory?: string; autoMerge?: boolean; base?: string; json?: boolean; target?: string; source?: string };
|
|
330
|
+
type HarnessSubstrateOpts = { substrate?: 'local' | 'pod'; podPool?: string; podMemory?: string; after?: string; autoMerge?: boolean; base?: string; json?: boolean; target?: string; source?: string };
|
|
324
331
|
function resolveLaunchSubstrate(opts: HarnessSubstrateOpts): ResolvedHarnessSubstrate {
|
|
325
332
|
const resolved = resolveHarnessSubstrate({ flag: opts, config: getUserConfig(), env: process.env });
|
|
326
333
|
debug.log('harness.substrate', 'resolved', resolved);
|
|
@@ -525,6 +532,11 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
|
|
|
525
532
|
process.exitCode = 2;
|
|
526
533
|
return;
|
|
527
534
|
}
|
|
535
|
+
if (o.after !== undefined && !/^(?:#?[1-9]\d*|[a-f0-9]{16})$/.test(o.after.trim())) {
|
|
536
|
+
console.error(`--after 는 PR 번호(#N) 또는 골 ID(16자 16진수)여야 한다: ${o.after}`);
|
|
537
|
+
process.exitCode = 2;
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
528
540
|
warnRecentIncidentBurst();
|
|
529
541
|
let dispatchRecorded = false;
|
|
530
542
|
try {
|
|
@@ -544,7 +556,7 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
|
|
|
544
556
|
const { dispatchHarnessOnPod } = await import('./harness-pod-dispatch.js');
|
|
545
557
|
let output = '';
|
|
546
558
|
let runId: string | undefined;
|
|
547
|
-
const status = await dispatchHarnessOnPod({ entrance, input, podPool: pool, ...(dispatchRecorded ? { dispatchRecorded: true } : {}), ...(o.podMemory ? { podMemory: o.podMemory } : {}), ...(o.autoMerge === false ? { autoMerge: false } : {}), ...(o.base ? { base: o.base } : {}), ...(o.json ? { json: true } : {}), ...(o.source ? { source: o.source } : {}) },
|
|
559
|
+
const status = await dispatchHarnessOnPod({ entrance, input, podPool: pool, ...(dispatchRecorded ? { dispatchRecorded: true } : {}), ...(o.podMemory ? { podMemory: o.podMemory } : {}), ...(o.after ? { after: o.after } : {}), ...(o.autoMerge === false ? { autoMerge: false } : {}), ...(o.base ? { base: o.base } : {}), ...(o.json ? { json: true } : {}), ...(o.source ? { source: o.source } : {}) },
|
|
548
560
|
{ onOutput: (text) => {
|
|
549
561
|
runId ??= harnessPodRunId(output + text);
|
|
550
562
|
output = (output + text).slice(-16_000);
|
|
@@ -557,6 +569,52 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
|
|
|
557
569
|
}
|
|
558
570
|
}
|
|
559
571
|
|
|
572
|
+
const LAUNCH_BUDGET_PROVIDER: Readonly<Record<string, string>> = { 'codex-rotate': CODEX_PROVIDER, grok: GROK_PROVIDER };
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* L6 발사 관문의 예산 입력 보정 — 발사 우주의 config 에 체인이 없으면(작업 트리 = 시험 우주) 막지 않고
|
|
576
|
+
* 코드 기본 체인으로 판단한다. `--child-llm-provider` 를 명시했으면 그것이 체인이다(예산 판정 밖 provider 는 통과).
|
|
577
|
+
*/
|
|
578
|
+
export function harnessLaunchBudgetDecision(
|
|
579
|
+
inputs: BudgetInputs,
|
|
580
|
+
opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
|
|
581
|
+
): { readonly decision: BudgetDecision; readonly warning?: string } {
|
|
582
|
+
const explicit = opts.childLlmProvider?.trim();
|
|
583
|
+
if (explicit) {
|
|
584
|
+
if (explicit !== CODEX_PROVIDER && explicit !== GROK_PROVIDER) {
|
|
585
|
+
return {
|
|
586
|
+
decision: { action: 'proceed', provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}), reasons: [`${explicit}: 명시 provider — 예산 판정 밖`] },
|
|
587
|
+
warning: `budget: ${explicit} is outside the budget gate — launched as requested`,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
const chain = [{ provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}) }];
|
|
591
|
+
return { decision: decideBudget({ ...inputs, preference: { ...inputs.preference, chain } }) };
|
|
592
|
+
}
|
|
593
|
+
if (inputs.preference.chain.length > 0) return { decision: decideBudget(inputs) };
|
|
594
|
+
const chain = DEFAULT_FALLBACK_CHAIN.map((step) => ({ provider: LAUNCH_BUDGET_PROVIDER[step] ?? step }));
|
|
595
|
+
return {
|
|
596
|
+
decision: decideBudget({ ...inputs, preference: { ...inputs.preference, chain } }),
|
|
597
|
+
warning: `budget: no chain in this universe's config — judged with the code default ${DEFAULT_FALLBACK_CHAIN.join(',')}`,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async function readHarnessLaunchBudget(
|
|
602
|
+
opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
|
|
603
|
+
): Promise<BudgetDecision | 'unknown'> {
|
|
604
|
+
try {
|
|
605
|
+
const { decision, warning } = harnessLaunchBudgetDecision(await readBudgetInputsLive(), opts);
|
|
606
|
+
if (warning) {
|
|
607
|
+
console.error(`⚠️ launch gate: ${warning}`);
|
|
608
|
+
try { debug.log('execution-loop.launch-gate', 'budget-chain-defaulted', { warning, action: decision.action, provider: decision.provider }); } catch { /* observation is fail-soft */ }
|
|
609
|
+
}
|
|
610
|
+
return decision;
|
|
611
|
+
}
|
|
612
|
+
catch (error) {
|
|
613
|
+
try { debug.log('execution-loop.launch-gate', 'budget-unavailable', { reason: String(error) }); } catch { /* observation is fail-soft */ }
|
|
614
|
+
return 'unknown';
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
560
618
|
async function dispatchHarnessAskSay(
|
|
561
619
|
opts: HarnessAskSayChildLlmOptions & HarnessDryRunOpts,
|
|
562
620
|
dryRunPreview: {
|
|
@@ -566,6 +624,7 @@ async function dispatchHarnessAskSay(
|
|
|
566
624
|
readonly goalPath?: string;
|
|
567
625
|
},
|
|
568
626
|
dispatch: (resolved: ResolvedHarnessSubstrate) => Promise<void>,
|
|
627
|
+
gate: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> } = {},
|
|
569
628
|
): Promise<void> {
|
|
570
629
|
await runInjectedHarnessHandler(async () => {
|
|
571
630
|
assertHarnessChildLlmModel(opts);
|
|
@@ -574,6 +633,35 @@ async function dispatchHarnessAskSay(
|
|
|
574
633
|
printHarnessLaunchDryRun(dryRunPreview);
|
|
575
634
|
return;
|
|
576
635
|
}
|
|
636
|
+
// Without a GoalId, match the request to a live run's exact verbatim original ask; still check budget.
|
|
637
|
+
let identity = dryRunPreview.input;
|
|
638
|
+
let goalId: string | null = null;
|
|
639
|
+
if (dryRunPreview.goalPath) {
|
|
640
|
+
try {
|
|
641
|
+
identity = readFileSync(dryRunPreview.goalPath, 'utf8');
|
|
642
|
+
goalId = parseGoalId(identity);
|
|
643
|
+
} catch { /* The launch handler owns file-read errors. */ }
|
|
644
|
+
}
|
|
645
|
+
goalId ??= launchRequestId(identity);
|
|
646
|
+
// Under bun test with no injected gate deps, skip the live reads (≈5 s of codex rotation + run scans) —
|
|
647
|
+
// CLI wiring tests time out on them. Gate tests inject deps and still run the gate (0.2.11 gate 10-03).
|
|
648
|
+
if (process.env.NODE_ENV === 'test' && Object.keys(gate).length === 0) {
|
|
649
|
+
try { debug.log('execution-loop.launch-gate', 'skipped-test-env', { goalId }); } catch { /* observation is fail-soft */ }
|
|
650
|
+
await dispatch(resolved);
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
const budget = await (gate.readBudget ?? (() => readHarnessLaunchBudget(opts)))();
|
|
654
|
+
const decision = preLaunchGate({ goalId, budget, forceLaunch: opts.forceGate === true }, gate);
|
|
655
|
+
if (decision.action !== 'proceed') {
|
|
656
|
+
console.error(`❌ launch gate: ${decision.action} — ${decision.reason.split(/\r?\n/, 1)[0]}`);
|
|
657
|
+
process.exitCode = 3;
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const warnings = [
|
|
661
|
+
...(decision.sameGoalActiveRuns === 'unknown' ? ['active runs unknown'] : []),
|
|
662
|
+
...(decision.budget === 'unknown' ? ['budget unknown'] : decision.budget.action === 'next-provider' ? [decision.budget.reasons.join(' · ') || 'next-provider'] : []),
|
|
663
|
+
];
|
|
664
|
+
if (warnings.length > 0) console.error(`⚠️ launch gate: ${warnings.join(' · ').split(/\r?\n/, 1)[0]}`);
|
|
577
665
|
await dispatch(resolved);
|
|
578
666
|
});
|
|
579
667
|
}
|
|
@@ -707,6 +795,8 @@ export const HARNESS_PROCESS_LAST_ACTIVITY_SCOPE_LINE =
|
|
|
707
795
|
|
|
708
796
|
export interface HarnessProcessLedgerEntry {
|
|
709
797
|
readonly timestamp?: string;
|
|
798
|
+
readonly event?: string;
|
|
799
|
+
readonly data?: Record<string, unknown>;
|
|
710
800
|
}
|
|
711
801
|
|
|
712
802
|
export type HarnessProcessLedgerLookup = (
|
|
@@ -741,6 +831,9 @@ export interface HarnessProcessObservationDeps {
|
|
|
741
831
|
listWorktrees?: () => HarnessWorktreeListObservation | readonly string[];
|
|
742
832
|
observeLaunchdPids?: () => HarnessLaunchdPidObservation;
|
|
743
833
|
lookupLedger?: HarnessProcessLedgerLookup;
|
|
834
|
+
openProcessHandle?: (pid: number) => HarnessProcessSignalHandle;
|
|
835
|
+
readStartTime?: (pid: number) => string;
|
|
836
|
+
repositoryRoot?: string;
|
|
744
837
|
nowMs?: number;
|
|
745
838
|
thresholds?: HarnessProcessClassificationThresholds;
|
|
746
839
|
write?: (text: string) => void;
|
|
@@ -1714,6 +1807,140 @@ function installHarnessBudgetCommand(harnessCmd: Command): Command {
|
|
|
1714
1807
|
});
|
|
1715
1808
|
}
|
|
1716
1809
|
|
|
1810
|
+
export interface HarnessProcessSignalHandle {
|
|
1811
|
+
signal(signal: NodeJS.Signals): void;
|
|
1812
|
+
close(): void;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
// macOS has no pidfd: bind to the process by its microsecond start time (libproc PROC_PIDTBSDINFO) and
|
|
1816
|
+
// re-read it immediately before signalling — a reused pid within the same microsecond is not distinguishable, anything else is.
|
|
1817
|
+
function readDarwinStartMicros(pid: number): bigint | null {
|
|
1818
|
+
const libproc = dlopen('/usr/lib/libproc.dylib', {
|
|
1819
|
+
proc_pidinfo: { args: [FFIType.i32, FFIType.i32, FFIType.u64, FFIType.ptr, FFIType.i32], returns: FFIType.i32 },
|
|
1820
|
+
});
|
|
1821
|
+
try {
|
|
1822
|
+
const buf = new Uint8Array(136); // sizeof(struct proc_bsdinfo)
|
|
1823
|
+
const n = libproc.symbols.proc_pidinfo(pid, 3 /* PROC_PIDTBSDINFO */, 0n, buf, buf.length);
|
|
1824
|
+
if (n !== buf.length) return null;
|
|
1825
|
+
const view = new DataView(buf.buffer);
|
|
1826
|
+
if (view.getUint32(12, true) !== pid) return null; // pbi_pid
|
|
1827
|
+
return view.getBigUint64(120, true) * 1_000_000n + view.getBigUint64(128, true); // pbi_start_tvsec · pbi_start_tvusec
|
|
1828
|
+
} finally { libproc.close(); }
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
function openDarwinProcessHandle(pid: number): HarnessProcessSignalHandle {
|
|
1832
|
+
const start = readDarwinStartMicros(pid);
|
|
1833
|
+
if (start === null) throw new Error('proc_pidinfo failed');
|
|
1834
|
+
let closed = false;
|
|
1835
|
+
return {
|
|
1836
|
+
signal(signal) {
|
|
1837
|
+
if (closed) throw new Error('process handle already closed');
|
|
1838
|
+
if (signal !== 'SIGTERM') throw new Error('only SIGTERM is supported');
|
|
1839
|
+
if (readDarwinStartMicros(pid) !== start) throw new Error('pid no longer names the same process');
|
|
1840
|
+
process.kill(pid, 'SIGTERM');
|
|
1841
|
+
},
|
|
1842
|
+
close() { closed = true; },
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
export function openHarnessProcessHandle(pid: number): HarnessProcessSignalHandle {
|
|
1847
|
+
if (process.platform === 'darwin') return openDarwinProcessHandle(pid);
|
|
1848
|
+
if (process.platform !== 'linux' || !['x64', 'arm64'].includes(process.arch)) {
|
|
1849
|
+
throw new Error('pid-bound signaling unavailable on this platform');
|
|
1850
|
+
}
|
|
1851
|
+
const libc = dlopen('libc.so.6', {
|
|
1852
|
+
syscall: { args: [FFIType.i64, FFIType.i64, FFIType.i64, FFIType.i64, FFIType.i64], returns: FFIType.i64 },
|
|
1853
|
+
close: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
1854
|
+
});
|
|
1855
|
+
const fd = Number(libc.symbols.syscall(434, pid, 0, 0, 0)); // pidfd_open
|
|
1856
|
+
if (fd < 0) {
|
|
1857
|
+
libc.close();
|
|
1858
|
+
throw new Error('pidfd_open failed');
|
|
1859
|
+
}
|
|
1860
|
+
let closed = false;
|
|
1861
|
+
return {
|
|
1862
|
+
signal(signal) {
|
|
1863
|
+
if (closed) throw new Error('pidfd already closed');
|
|
1864
|
+
if (signal !== 'SIGTERM' || libc.symbols.syscall(424, fd, osConstants.signals.SIGTERM, 0, 0) !== 0n) {
|
|
1865
|
+
throw new Error('pidfd_send_signal failed');
|
|
1866
|
+
}
|
|
1867
|
+
},
|
|
1868
|
+
close() {
|
|
1869
|
+
if (closed) return;
|
|
1870
|
+
closed = true;
|
|
1871
|
+
libc.symbols.close(fd);
|
|
1872
|
+
libc.close();
|
|
1873
|
+
},
|
|
1874
|
+
};
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
export function killHarnessProcess(
|
|
1878
|
+
pid: number,
|
|
1879
|
+
force: boolean,
|
|
1880
|
+
deps: HarnessProcessObservationDeps = {},
|
|
1881
|
+
): { outcome: 'sent' | 'refused'; owned: boolean; runState: string; reason: string } {
|
|
1882
|
+
const refuse = (reason: string, owned = false, runState = 'unknown') => ({ outcome: 'refused' as const, owned, runState, reason });
|
|
1883
|
+
let result: ReturnType<typeof refuse> | { outcome: 'sent'; owned: true; runState: string; reason: string };
|
|
1884
|
+
let handle: HarnessProcessSignalHandle | undefined;
|
|
1885
|
+
let handleFailure: string | undefined;
|
|
1886
|
+
if (Number.isSafeInteger(pid) && pid > 1) {
|
|
1887
|
+
try { handle = (deps.openProcessHandle ?? openHarnessProcessHandle)(pid); }
|
|
1888
|
+
catch (error) { handleFailure = observationFailureReason(error); }
|
|
1889
|
+
}
|
|
1890
|
+
try {
|
|
1891
|
+
const root = deps.repositoryRoot ?? findGitDir(process.cwd())?.root;
|
|
1892
|
+
const listed = normalizeProcessListObservation(deps.listProcesses?.() ?? defaultListHarnessProcesses());
|
|
1893
|
+
const row = listed.status === 'ok' ? listed.records.find((record) => record.pid === pid) : undefined;
|
|
1894
|
+
const prefix = root ? `${resolve(root)}${sep}` : '';
|
|
1895
|
+
const entry = prefix ? `${prefix}bin/elanous.mjs` : '';
|
|
1896
|
+
const argv = row?.command ?? '';
|
|
1897
|
+
const entryIndex = entry && [
|
|
1898
|
+
`bun ${entry} `, `${process.execPath} ${entry} `,
|
|
1899
|
+
`bun bin/elanous.mjs `,
|
|
1900
|
+
].find((start) => argv.startsWith(start));
|
|
1901
|
+
const fromRepo = Boolean(entryIndex && (entryIndex !== 'bun bin/elanous.mjs ' || row?.cwd && resolve(row.cwd) === resolve(root!)));
|
|
1902
|
+
if (!Number.isSafeInteger(pid) || pid <= 1) result = refuse('invalid pid');
|
|
1903
|
+
else if (listed.status !== 'ok') result = refuse('process observation incomplete');
|
|
1904
|
+
else if (!row) result = refuse('pid not found in harness process population');
|
|
1905
|
+
else if (!fromRepo || !/\belanous\.mjs\s+(?:(?:--test|--config-dir\s+\S+)\s+)?(?:self\s+(?:orchestrate|implement)|harness\s+(?:ask|say))\b/.test(row.command)) result = refuse('not a harness process from this repository');
|
|
1906
|
+
else if (!handle) result = refuse(`pid-bound signaling unavailable: ${handleFailure ?? 'unknown failure'}`);
|
|
1907
|
+
else {
|
|
1908
|
+
let startTime: string | undefined;
|
|
1909
|
+
try {
|
|
1910
|
+
startTime = (deps.readStartTime ?? ((target) => execFileSync('ps', ['-p', String(target), '-o', 'lstart='], { encoding: 'utf8', timeout: 2_000 }).trim()))(pid);
|
|
1911
|
+
} catch { /* unavailable is not a timestamp */ }
|
|
1912
|
+
if (!startTime || !Number.isFinite(Date.parse(startTime))) result = refuse('process start time unreadable');
|
|
1913
|
+
else {
|
|
1914
|
+
const ownership = row.ownership ?? readProcessOwnership(pid);
|
|
1915
|
+
const runId = ownership.status === 'observed' ? ownership.runId : undefined;
|
|
1916
|
+
if (!runId) result = refuse('owning run unconfirmed');
|
|
1917
|
+
else {
|
|
1918
|
+
let ledger: readonly HarnessProcessLedgerEntry[] | null = null;
|
|
1919
|
+
try { ledger = (deps.lookupLedger ?? defaultLookupHarnessProcessLedger)(runId, ownership.status === 'observed' ? ownership.stateDir : undefined); }
|
|
1920
|
+
catch { /* fail closed */ }
|
|
1921
|
+
const last = [...(ledger ?? [])].reverse().find((entry) => entry.event === 'run-status');
|
|
1922
|
+
const runState = typeof last?.data?.runStatus === 'string' ? last.data.runStatus : 'unknown';
|
|
1923
|
+
if (!ledger || !last) result = refuse('owning run ledger unavailable', true, runState);
|
|
1924
|
+
else if (!['running', 'completed', 'failed', 'cancelled', 'abandoned'].includes(runState)) result = refuse('owning run status unconfirmed', true, runState);
|
|
1925
|
+
else if (runState === 'running' && !force) result = refuse('owning run is not terminal (use --force)', true, runState);
|
|
1926
|
+
else {
|
|
1927
|
+
try {
|
|
1928
|
+
const currentStart = (deps.readStartTime ?? ((target) => execFileSync('ps', ['-p', String(target), '-o', 'lstart='], { encoding: 'utf8', timeout: 2_000 }).trim()))(pid);
|
|
1929
|
+
if (currentStart !== startTime) result = refuse('pid start time changed', true, runState);
|
|
1930
|
+
else {
|
|
1931
|
+
handle.signal('SIGTERM');
|
|
1932
|
+
result = { outcome: 'sent', owned: true, runState, reason: 'SIGTERM sent' };
|
|
1933
|
+
}
|
|
1934
|
+
} catch (error) { result = refuse(`SIGTERM failed: ${observationFailureReason(error)}`, true, runState); }
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
debug.log('harness.processes', 'kill', { pid, ...result });
|
|
1940
|
+
return result;
|
|
1941
|
+
} finally { handle?.close(); }
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1717
1944
|
function installHarnessProcessObservationCommand(
|
|
1718
1945
|
harnessCmd: Command,
|
|
1719
1946
|
deps: HarnessProcessObservationDeps = {},
|
|
@@ -1721,8 +1948,18 @@ function installHarnessProcessObservationCommand(
|
|
|
1721
1948
|
const write = deps.write ?? ((text: string) => { console.log(text); });
|
|
1722
1949
|
return harnessCmd
|
|
1723
1950
|
.command('processes')
|
|
1724
|
-
.description('
|
|
1725
|
-
.
|
|
1951
|
+
.description('기본 읽기 전용 분류. --kill <pid> 는 소유 런 확인 후 단일 PID 에만 SIGTERM 한다.')
|
|
1952
|
+
.option('--kill <pid>', '소유 런을 확인한 뒤 지정한 PID 하나만 SIGTERM')
|
|
1953
|
+
.option('--force', '소유 런이 진행 중이어도 지정한 PID 하나를 종료')
|
|
1954
|
+
.action((opts: { kill?: string; force?: boolean }) => {
|
|
1955
|
+
if (opts.kill !== undefined) {
|
|
1956
|
+
const pid = Number(opts.kill);
|
|
1957
|
+
const result = killHarnessProcess(pid, opts.force === true, deps);
|
|
1958
|
+
write(`pid=${opts.kill} ${result.outcome}: ${result.reason}`);
|
|
1959
|
+
if (result.outcome === 'refused') process.exitCode = 1;
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
if (opts.force) { write('--force requires --kill <pid>'); process.exitCode = 2; return; }
|
|
1726
1963
|
const records = deps.listProcesses?.() ?? defaultListHarnessProcesses();
|
|
1727
1964
|
const worktrees = deps.listWorktrees?.() ?? defaultListHarnessWorktreePaths();
|
|
1728
1965
|
const launchd = deps.observeLaunchdPids?.() ?? observeHarnessLaunchdPids();
|
|
@@ -1749,6 +1986,7 @@ export interface HarnessCliCommandDeps {
|
|
|
1749
1986
|
say?: HarnessSayHandler;
|
|
1750
1987
|
/** Observe-only Pod host dispatch seam. */
|
|
1751
1988
|
podDispatchTask?: (input: DispatchTaskInput, deps?: DispatchTaskDeps) => ReturnType<typeof dispatchTask>;
|
|
1989
|
+
launchGate?: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> };
|
|
1752
1990
|
plan?: HarnessPlanHandler;
|
|
1753
1991
|
/** ⭐ `plan` 주입이 «없을 때» 가는 기본 분기. 시험이 이 자리로 «CLI 의 기본 배선»을 문다
|
|
1754
1992
|
* (⛔ 주입된 `plan` 이 파일을 스스로 만들면 그 시험은 배선을 «못 답한다» — 무인 리뷰 GOODHART 지적). */
|
|
@@ -1819,6 +2057,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
1819
2057
|
}
|
|
1820
2058
|
return resolved.substrate === 'pod' ? onPod(opts, 'cli-harness-ask', goalPath, resolved.pool!, deps.podDispatchTask) : ask(goalPath, normalizeHarnessAskSayOptions(opts));
|
|
1821
2059
|
},
|
|
2060
|
+
deps.launchGate,
|
|
1822
2061
|
);
|
|
1823
2062
|
});
|
|
1824
2063
|
}
|
|
@@ -1843,6 +2082,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
|
|
|
1843
2082
|
}
|
|
1844
2083
|
return resolved.substrate === 'pod' ? onPod(opts, 'cli-harness-say', sentence.join(' '), resolved.pool!, deps.podDispatchTask) : say(sentence, normalizeHarnessAskSayOptions(opts));
|
|
1845
2084
|
},
|
|
2085
|
+
deps.launchGate,
|
|
1846
2086
|
);
|
|
1847
2087
|
});
|
|
1848
2088
|
}
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* 매니페스트가 실은 런 계약(`ELANOUS_RUN_CONTRACT`)으로 자기가 Pod 인 줄 안다(graph-run-contract.ts).
|
|
8
8
|
*/
|
|
9
9
|
import { spawn } from 'node:child_process';
|
|
10
|
-
import { readFileSync, realpathSync } from 'node:fs';
|
|
11
|
-
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
10
|
+
import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
12
|
+
import { selfDevRunsDir } from '../self-dev/run-store.js';
|
|
12
13
|
import { findGitDir } from '../git-fs/locate.js';
|
|
13
14
|
import { debug } from '../debug/log.js';
|
|
14
15
|
import { ELANOUS_ENTRY_SCRIPT } from '../self-implement/seams.js';
|
|
@@ -23,6 +24,8 @@ export interface HarnessPodDispatchInput {
|
|
|
23
24
|
readonly dispatchRecorded?: boolean;
|
|
24
25
|
/** Pod 메모리 등급(standard|high) — 오케스트레이터 환경 `ELANOUS_POD_MEMORY_TIER` 로 Job 까지 간다. */
|
|
25
26
|
readonly podMemory?: string;
|
|
27
|
+
/** L7c — Pod queue predecessor (goal ID or PR) — `ELANOUS_POD_AFTER` carries it to every Pod Job admission. */
|
|
28
|
+
readonly after?: string;
|
|
26
29
|
readonly autoMerge?: boolean;
|
|
27
30
|
readonly base?: string;
|
|
28
31
|
readonly json?: boolean;
|
|
@@ -30,16 +33,9 @@ export interface HarnessPodDispatchInput {
|
|
|
30
33
|
readonly source?: string;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
export function podGoalText(input: HarnessPodDispatchInput, readFile: (path: string) => string = (p) => readFileSync(p, 'utf8')): string {
|
|
35
|
-
// 오케스트레이터에는 내용도 보내고, 저장소 안의 ask 는 별도로 Secret 을 통해 Pod 클론에 심는다.
|
|
36
|
-
const text = input.entrance === 'cli-harness-ask' ? readFile(input.input) : input.input;
|
|
37
|
-
return text.replace(/;;/gu, '; ;');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function podOrchestrateArgs(input: HarnessPodDispatchInput, goal: string): string[] {
|
|
36
|
+
export function podOrchestrateArgs(input: HarnessPodDispatchInput, goalFile: string): string[] {
|
|
41
37
|
return [
|
|
42
|
-
ELANOUS_ENTRY_SCRIPT, 'self', 'orchestrate', goal,
|
|
38
|
+
ELANOUS_ENTRY_SCRIPT, 'self', 'orchestrate', '--goal-file', goalFile,
|
|
43
39
|
'--substrate', 'pod',
|
|
44
40
|
...(input.podPool ? ['--pod-pool', input.podPool] : []),
|
|
45
41
|
// 하니스 기본(자동 병합)을 따른다 · 끄면 PR 까지 — 어느 쪽이든 Pod 가 사라져도 결과가 남는다.
|
|
@@ -66,13 +62,30 @@ export function dispatchHarnessOnPod(input: HarnessPodDispatchInput, deps: PodDi
|
|
|
66
62
|
return 2;
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
let tempDir: string | undefined;
|
|
66
|
+
let goalFile: string;
|
|
67
|
+
let goalChars: number;
|
|
68
|
+
if (input.entrance === 'cli-harness-ask') {
|
|
69
|
+
goalFile = resolve(cwd, input.input);
|
|
70
|
+
goalChars = (deps.readFile ?? ((p) => readFileSync(p, 'utf8')))(goalFile).length;
|
|
71
|
+
} else {
|
|
72
|
+
const goal = input.input;
|
|
73
|
+
const runsDir = selfDevRunsDir();
|
|
74
|
+
mkdirSync(runsDir, { recursive: true });
|
|
75
|
+
tempDir = mkdtempSync(join(runsDir, 'pod-goal-'));
|
|
76
|
+
goalFile = join(tempDir, 'goal.txt');
|
|
77
|
+
writeFileSync(goalFile, goal, { mode: 0o600 });
|
|
78
|
+
goalChars = goal.length;
|
|
79
|
+
}
|
|
80
|
+
const args = podOrchestrateArgs(input, goalFile);
|
|
81
|
+
debug.log('harness.substrate', 'goal-file', { entrance: input.entrance, mode: tempDir ? 'temp' : 'path' });
|
|
71
82
|
const env = { ...process.env };
|
|
72
83
|
delete env.ELANOUS_POD_GOAL_DOC;
|
|
73
84
|
delete env.ELANOUS_DISPATCH_RECORDED;
|
|
74
85
|
if (input.dispatchRecorded) env.ELANOUS_DISPATCH_RECORDED = '1';
|
|
75
86
|
if (input.podMemory) env.ELANOUS_POD_MEMORY_TIER = input.podMemory;
|
|
87
|
+
delete env.ELANOUS_POD_AFTER;
|
|
88
|
+
if (input.after) env.ELANOUS_POD_AFTER = input.after;
|
|
76
89
|
if (input.entrance === 'cli-harness-ask') {
|
|
77
90
|
const root = findGitDir(cwd)?.root;
|
|
78
91
|
const path = resolve(cwd, input.input);
|
|
@@ -84,8 +97,8 @@ export function dispatchHarnessOnPod(input: HarnessPodDispatchInput, deps: PodDi
|
|
|
84
97
|
}
|
|
85
98
|
}
|
|
86
99
|
debug.log('harness.substrate', 'dispatch-pod', {
|
|
87
|
-
entrance: input.entrance, podPool: input.podPool ?? null, podMemory: input.podMemory ?? null, autoMerge: input.autoMerge !== false,
|
|
88
|
-
goalChars
|
|
100
|
+
entrance: input.entrance, podPool: input.podPool ?? null, podMemory: input.podMemory ?? null, after: input.after ?? null, autoMerge: input.autoMerge !== false,
|
|
101
|
+
goalChars, ...(input.entrance === 'cli-harness-ask' ? { goalPath: input.input } : {}),
|
|
89
102
|
});
|
|
90
103
|
const run = deps.run ?? ((cmd: string, a: readonly string[], childEnv: NodeJS.ProcessEnv) => new Promise<number>((resolveStatus) => {
|
|
91
104
|
const child = (deps.spawnChild ?? spawn)(cmd, [...a], { stdio: deps.onOutput ? ['inherit', 'pipe', 'inherit'] : 'inherit', env: childEnv });
|
|
@@ -104,13 +117,20 @@ export function dispatchHarnessOnPod(input: HarnessPodDispatchInput, deps: PodDi
|
|
|
104
117
|
child.once('error', () => { cleanup(); resolveStatus(1); });
|
|
105
118
|
child.once('close', (code, signal) => { cleanup(); resolveStatus(code ?? ((signal ?? forwarded) === 'SIGINT' ? 130 : 143)); });
|
|
106
119
|
}));
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
const cleanup = () => { if (tempDir) rmSync(tempDir, { recursive: true, force: true }); };
|
|
121
|
+
try {
|
|
122
|
+
const status = run(process.execPath, args, env);
|
|
123
|
+
if (typeof status === 'number' || status === null) {
|
|
124
|
+
cleanup();
|
|
125
|
+
debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status });
|
|
126
|
+
return status ?? 1;
|
|
127
|
+
}
|
|
128
|
+
return status.then((code) => {
|
|
129
|
+
debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status: code });
|
|
130
|
+
return code;
|
|
131
|
+
}).finally(cleanup);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
cleanup();
|
|
134
|
+
throw error;
|
|
111
135
|
}
|
|
112
|
-
return status.then((code) => {
|
|
113
|
-
debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status: code });
|
|
114
|
-
return code;
|
|
115
|
-
});
|
|
116
136
|
}
|
|
@@ -23,6 +23,7 @@ import { buildReviewSeam, gateEvidenceNote, reviewResultToCritiqueLike, type Gat
|
|
|
23
23
|
import { buildExecuteProgressJudge } from './execute-progress-judge.js';
|
|
24
24
|
import type { StagedHarnessSeams } from './staged-harness.js';
|
|
25
25
|
import { debug } from '../debug/log.js';
|
|
26
|
+
import { releasePathHold, releasePathHoldComment, RELEASE_PATH_LABEL } from '../self-dev/release-path-guard.js';
|
|
26
27
|
import { setEventLoopActivity } from '../debug/event-loop-watchdog.js';
|
|
27
28
|
import { nestInfo } from '../agent/nest-depth.js';
|
|
28
29
|
import { originObservationFields } from '../agent/origin-observation.js';
|
|
@@ -721,10 +722,43 @@ export function buildHarnessSeams(deps: HarnessSeamsDeps): StagedHarnessSeams {
|
|
|
721
722
|
suppressedRiskHits: eligibility?.suppressedRiskHits.length ?? 0,
|
|
722
723
|
...(declineReasons ? { reasons: declineReasons } : {}),
|
|
723
724
|
});
|
|
724
|
-
const pr = await deps.seams.openPr({ title, body, head: branch, ...(deps.base ? { base: deps.base } : {}), draft: true,
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
725
|
+
const pr = await deps.seams.openPr({ title, body, head: branch, ...(deps.base ? { base: deps.base } : {}), draft: true, cwd });
|
|
726
|
+
let holdPath: string | undefined;
|
|
727
|
+
let inspectionError: string | undefined;
|
|
728
|
+
try {
|
|
729
|
+
if (!deps.seams.readPrFiles) throw new Error('readPrFiles seam unavailable');
|
|
730
|
+
const prFiles = await deps.seams.readPrFiles({ number: pr.number, cwd });
|
|
731
|
+
if (!Array.isArray(prFiles) || !prFiles.every((path) => typeof path === 'string')) throw new Error('invalid PR file list');
|
|
732
|
+
holdPath = releasePathHold(prFiles);
|
|
733
|
+
} catch (error) { inspectionError = String(error); }
|
|
734
|
+
if (holdPath) {
|
|
735
|
+
const protectedPath = holdPath;
|
|
736
|
+
const prCwd = cwd;
|
|
737
|
+
debug.log('self-dev.merge', 'release-path-hold', { number: pr.number, path: protectedPath, label: RELEASE_PATH_LABEL });
|
|
738
|
+
for (const [action, annotate] of [
|
|
739
|
+
['add-label', deps.seams.addPrLabel && (() => deps.seams.addPrLabel!({ number: pr.number, label: RELEASE_PATH_LABEL, cwd: prCwd }))],
|
|
740
|
+
['comment', deps.seams.postPrComment && (() => deps.seams.postPrComment!({ number: pr.number, body: releasePathHoldComment(protectedPath), cwd: prCwd }))],
|
|
741
|
+
] as const) {
|
|
742
|
+
if (!annotate) { observe('release-path-annotation-failed', { number: pr.number, action, error: 'annotation seam unavailable' }); continue; }
|
|
743
|
+
try { await annotate(); } catch (error) { observe('release-path-annotation-failed', { number: pr.number, action, error: String(error) }); }
|
|
744
|
+
}
|
|
745
|
+
observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: false, mergeReason: 'release-path-hold' });
|
|
746
|
+
} else if (inspectionError) {
|
|
747
|
+
observe('release-path-inspection-failed', { number: pr.number, error: inspectionError });
|
|
748
|
+
observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: false, mergeReason: 'release-path-inspection-failed' });
|
|
749
|
+
} else {
|
|
750
|
+
let autoReviewLabeled = false;
|
|
751
|
+
if (labels?.includes(AUTO_REVIEW_LABEL)) {
|
|
752
|
+
if (deps.seams.addPrLabel) {
|
|
753
|
+
try {
|
|
754
|
+
await deps.seams.addPrLabel({ number: pr.number, label: AUTO_REVIEW_LABEL, cwd });
|
|
755
|
+
autoReviewLabeled = true;
|
|
756
|
+
observe('auto-review-labeled', { branch, number: pr.number, label: AUTO_REVIEW_LABEL });
|
|
757
|
+
} catch (error) { observe('auto-review-label-failed', { number: pr.number, error: String(error) }); }
|
|
758
|
+
} else observe('auto-review-label-failed', { number: pr.number, error: 'addPrLabel seam unavailable' });
|
|
759
|
+
}
|
|
760
|
+
observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: autoReviewLabeled });
|
|
761
|
+
}
|
|
728
762
|
// B(대표 2026-07-21): post-PR 자율 리뷰 — 리뷰기가 PR 에 커멘트(fail-soft). 게이트가 놓친 품질 블로커 표면화.
|
|
729
763
|
await postPrReview(cwd, pr.number, objective, deps.llmReview, deps.spawnSyncFn ?? spawnSync, deps.goalDocument);
|
|
730
764
|
return { ok: true, ref: pr.url, kind: 'pr' };
|
|
@@ -14,6 +14,7 @@ import { isAbsolute, join, resolve } from 'node:path';
|
|
|
14
14
|
import { spawnSync } from 'node:child_process';
|
|
15
15
|
import { debug } from '../debug/log.js';
|
|
16
16
|
import { selfDevRunsDir } from '../self-dev/run-store.js';
|
|
17
|
+
import { launchBindingRunIds, launchRegistryDir, readLaunchBinding } from './launch-registry.js';
|
|
17
18
|
import { loadRunLedger, resolveFederatedRunLedgerDirectories, runLedgerDir } from '../self-implement/run-ledger.js';
|
|
18
19
|
|
|
19
20
|
const RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
@@ -173,6 +174,16 @@ export function readPidRecordFrom(runsDir: string, runId: string): PidRecord | n
|
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
/** The launching universe's pid.json when the binding names it, else the binding's own pid — both still pass the start-time check. */
|
|
178
|
+
export function pidRecordFromLaunchBinding(runId: string, registryDir = launchRegistryDir()): PidRecord | null {
|
|
179
|
+
const binding = readLaunchBinding(runId, registryDir);
|
|
180
|
+
if (!binding) return null;
|
|
181
|
+
const fromRunsDir = binding.runsDir ? readPidRecordFrom(binding.runsDir, runId) : null;
|
|
182
|
+
if (fromRunsDir) return fromRunsDir;
|
|
183
|
+
debug.log('harness.stop', 'pid-from-launch-binding', { runId, pid: binding.pid });
|
|
184
|
+
return { pid: binding.pid, startedAt: binding.startedAt, ...(binding.argv0 ? { argv0: binding.argv0 } : {}) };
|
|
185
|
+
}
|
|
186
|
+
|
|
176
187
|
/** macOS·Linux 공통 — `ps -o lstart=` 는 로컬 시각 문자열(초 단위)이다. */
|
|
177
188
|
export function psProcessStartMs(pid: number): number | null {
|
|
178
189
|
const r = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', timeout: 5_000 });
|
|
@@ -183,7 +194,8 @@ export function psProcessStartMs(pid: number): number | null {
|
|
|
183
194
|
return Number.isFinite(ms) ? ms : null;
|
|
184
195
|
}
|
|
185
196
|
|
|
186
|
-
export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {}): HarnessStopDeps {
|
|
197
|
+
export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {}, opts: { launchRegistryDir?: string } = {}): HarnessStopDeps {
|
|
198
|
+
const registry = opts.launchRegistryDir ?? launchRegistryDir();
|
|
187
199
|
const env = { ...process.env };
|
|
188
200
|
for (const key of ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy', 'ALL_PROXY', 'all_proxy']) delete env[key];
|
|
189
201
|
const kubectl = (args: readonly string[]) => {
|
|
@@ -191,12 +203,19 @@ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {})
|
|
|
191
203
|
return { status: r.status, stdout: r.stdout ?? '', stderr: r.stderr ?? String(r.error ?? '') };
|
|
192
204
|
};
|
|
193
205
|
return {
|
|
194
|
-
|
|
206
|
+
// This universe first; then the host-wide launch binding, so a run launched from another worktree is still found.
|
|
207
|
+
readPidRecord: (runId) => readPidRecordFrom(selfDevRunsDir(), runId) ?? pidRecordFromLaunchBinding(runId, registry),
|
|
195
208
|
runIdCandidates: (given) => {
|
|
196
209
|
const ledgerDirs = new Set([runLedgerDir(), ...resolveFederatedRunLedgerDirectories({})]);
|
|
197
|
-
|
|
210
|
+
const found = new Set(stopRunIdCandidates(given, [...ledgerDirs], selfDevRunsDir()));
|
|
211
|
+
for (const id of launchBindingRunIds(registry)) if (id.startsWith(given) && FULL_RUN_ID.test(id)) found.add(id);
|
|
212
|
+
return [...found].sort();
|
|
213
|
+
},
|
|
214
|
+
readGoalPath: (runId) => {
|
|
215
|
+
let fromLedger: string | null = null;
|
|
216
|
+
try { fromLedger = stopGoalPathFromLedger(runId); } catch { fromLedger = null; }
|
|
217
|
+
return fromLedger ?? readLaunchBinding(runId, registry)?.goalPath ?? null;
|
|
198
218
|
},
|
|
199
|
-
readGoalPath: stopGoalPathFromLedger,
|
|
200
219
|
scanProcesses: scanStopProcessTable,
|
|
201
220
|
processStartMs: psProcessStartMs,
|
|
202
221
|
kill: (pid, signal) => { process.kill(pid, signal); },
|