elanous 0.2.9 → 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/5845-e6c003ce8d5fd36a.js +1 -0
- 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-f972fc1c00a62e88.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-adfbd2ba9598e59a.js → page-35414e0a007b4082.js} +1 -1
- 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 -0
- package/apps/pwa/out/ops/seats/index.txt +30 -0
- 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 -0
- package/apps/pwa/out/today/index.txt +33 -0
- 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/field/field-feed.yaml +2 -0
- package/graphs/implement-loop.yaml +1 -1
- package/graphs/intake/intake-daily.yaml +2 -1
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/ops/secret-exposure.yaml +24 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -1
- package/graphs/video/explainer-line.yaml +2 -2
- package/package.json +2 -1
- package/plugins/card-followup/graphs/run-step.ts +48 -13
- package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
- package/plugins/doc-draft/graphs/run-step.ts +13 -6
- 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/ci-pwa-build-gate.ts +160 -0
- 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 +54 -8
- package/scripts/coord-digest.ts +199 -0
- package/scripts/coord-post.sh +60 -3
- 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/install.ps1 +68 -9
- package/scripts/install.sh +39 -12
- package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
- package/scripts/lib/tui-regress-checks.ts +146 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/memory-lifecycle-cycle.ts +2 -2
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/ops-now-probe.ts +327 -0
- package/scripts/publish-internal-dist.ts +11 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/cut-branch.ts +84 -0
- package/scripts/release-loop/cutoff.ts +19 -8
- 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/ops-upgrade-node.ts +72 -16
- package/scripts/release-loop/release-readiness.ts +9 -0
- 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 +112 -13
- package/scripts/repo-watch-cycle.ts +1 -1
- package/scripts/retro-cycle.ts +2 -2
- package/scripts/schedule-health-report.ts +1 -1
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/storyboard/storyboard.ts +5 -161
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/test-diet/lib.ts +30 -1
- package/scripts/test-diet/node.ts +83 -8
- package/scripts/test-timeout-audit.ts +114 -0
- package/scripts/tree-sync-alert.ts +1 -1
- package/scripts/tui-regress.ts +71 -0
- package/scripts/ux/demo-rehearsal.ts +243 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
- package/scripts/waitlist-daily-digest.ts +1 -1
- 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/explainer-video/SKILL.md +4 -0
- package/skills/explainer-video/engine/reel.mjs +18 -13
- package/skills/explainer-video/engine/reel.sh +24 -5
- package/skills/explainer-video/engine/stitch.mjs +145 -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 +36 -0
- package/skills/pitch-deck/template.html +80 -0
- 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/codex-approval-adapter.ts +9 -3
- package/src/acp/core-turn-bridge.ts +117 -18
- package/src/acp/fact-question.ts +11 -0
- package/src/acp/server.ts +53 -9
- package/src/acp/tool-approval.ts +126 -0
- package/src/acp/turn-runner.ts +36 -0
- package/src/agent/monad-agent-turn.ts +8 -0
- 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/ask-user-question/pending-questions.ts +25 -10
- package/src/ask-user-question/types.ts +9 -0
- package/src/auth/setup-link-tokens.ts +16 -5
- package/src/autopilot/build/integrity-gate.ts +12 -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 +8 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/index.ts +8 -0
- package/src/boot/daemon-tools/types.ts +2 -0
- package/src/boot/daemon-tools/web-search.ts +4 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/ctrl-c-in-input.ts +14 -0
- package/src/chat/index.ts +53 -0
- package/src/chat/pickers/state.ts +6 -2
- package/src/cli/agent-cli.ts +7 -0
- package/src/cli/decisions-cli.ts +25 -3
- package/src/cli/doctor-bundle-upload.ts +68 -0
- package/src/cli/doctor-cli.ts +38 -4
- 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/ops-cli.ts +20 -0
- package/src/cli/persona-cli.ts +90 -4
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +61 -2
- package/src/cli/pr-cli.ts +82 -17
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/pwa-stop.ts +163 -13
- package/src/cli/pwa-test.ts +3 -0
- package/src/cli/release-cli.ts +80 -24
- package/src/cli/self-update.ts +14 -0
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/cli/storyboard-cli.ts +37 -0
- package/src/cli/test-state-dir-flag.ts +11 -4
- package/src/connectors/linear.ts +146 -0
- 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 +115 -0
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/dashboard/dashboard-boot-fixture.ts +23 -0
- package/src/dashboard/index.ts +63 -21
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -1
- package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
- package/src/decisions/decision-cards.ts +58 -3
- package/src/decisions/decision-ledger.ts +85 -6
- package/src/decisions/decision-linear-projection.ts +157 -0
- package/src/decisions/web-push-decision-cards.ts +50 -0
- package/src/directive/interpretation-card.ts +36 -0
- 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 +19 -2
- package/src/domains/coo-admin-tool.ts +62 -0
- package/src/domains/core-tools.ts +13 -4
- package/src/domains/elanous-card.ts +29 -0
- package/src/domains/ops-facts-tool.ts +76 -0
- package/src/domains/outbound-alert.ts +46 -13
- package/src/domains/release-tool.ts +168 -0
- package/src/domains/telegram-kind-route.ts +65 -9
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +106 -28
- package/src/exec-requests/runner.ts +123 -12
- package/src/exec-requests/store.ts +11 -2
- package/src/execution-loop/launch-gate.ts +100 -0
- package/src/field/field-media.ts +10 -7
- package/src/field/field-reel.ts +19 -5
- package/src/field-note/index.ts +201 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/git-fs/worktree.ts +45 -6
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-approval-card.ts +113 -0
- package/src/graph-runner/graph-cli.ts +189 -4
- package/src/graph-runner/graph-grow-llm.ts +37 -0
- package/src/graph-runner/graph-grow.ts +47 -0
- package/src/graph-runner/graph-notify.ts +25 -3
- package/src/graph-runner/runner.ts +453 -35
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/browser-verify.ts +25 -2
- package/src/harness/harness-cli-command.ts +478 -42
- package/src/harness/harness-incidents-writer.fixture.ts +24 -0
- package/src/harness/harness-incidents.ts +129 -0
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +75 -6
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hitl/clarification-policy.ts +3 -1
- 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 +206 -49
- package/src/intake-plane/author-goals.ts +37 -4
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/check.ts +3 -0
- package/src/intake-plane/discord-seat-work.ts +57 -2
- package/src/intake-plane/front-route-classifier.ts +33 -39
- package/src/intake-plane/persona-answer.ts +30 -0
- package/src/intake-plane/runtime-callables.ts +8 -1
- package/src/intake-plane/seat-doc-route.ts +170 -6
- package/src/intake-plane/telegram-seat-work.ts +80 -4
- package/src/intake-plane/telegram-work.ts +1 -0
- package/src/intake-plane/wish-folder.ts +67 -0
- package/src/intent-gate/gate.ts +30 -10
- package/src/live/detail-switch.ts +5 -0
- package/src/llm/difficulty.ts +57 -0
- package/src/llm/judge-layer.ts +101 -0
- package/src/llm/mission-router.ts +33 -19
- package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
- package/src/loops/contract/examples/steward.loop.yaml +50 -0
- package/src/loops/contract/loop-agent.schema.json +138 -0
- package/src/loops/contract/validate.ts +64 -0
- package/src/loops/registry.ts +20 -6
- package/src/market/signed-index.ts +4 -0
- package/src/maturity/bot-command-maturity.ts +45 -0
- package/src/maturity/cli-maturity.ts +34 -0
- package/src/maturity/feature-maturity.ts +120 -1
- package/src/maturity/tui-slash-maturity.ts +31 -0
- package/src/memory.ts +32 -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/exec-requests.ts +33 -3
- 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 +89 -1
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +32 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-api.ts +10 -1
- package/src/nexus/api/ops-seats-sources.ts +37 -7
- package/src/nexus/api/ops-seats.ts +49 -6
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/seat-requests.ts +132 -10
- package/src/nexus/api/sessions-store.ts +42 -0
- package/src/nexus/api/setup-codex-login.ts +160 -0
- 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/usage-api.ts +102 -0
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +80 -6
- package/src/nexus/index.ts +47 -4
- 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/first-run.ts +89 -0
- package/src/onboarding/lan-address.ts +45 -0
- package/src/onboarding/voice-ai.ts +3 -3
- package/src/onboarding/web-first.ts +119 -24
- package/src/onboarding.ts +4 -0
- package/src/ops-now/ops-now-refresh.ts +100 -0
- 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-store.ts +115 -0
- package/src/project/project-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +79 -5
- package/src/release-loop/feature-store.ts +159 -24
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/release-loop/release-schedule.ts +53 -0
- package/src/repl/index.ts +7 -0
- package/src/seat-dispatch/ceo-commands.ts +41 -8
- package/src/seat-dispatch/ceo-intent.ts +38 -0
- 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 +750 -0
- package/src/seat-loop/seat-report.ts +99 -0
- package/src/self-dev/decompose.ts +66 -11
- 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/run-store.ts +10 -1
- 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/execution-clarification.ts +115 -0
- package/src/self-implement/gate-baseline.ts +1 -1
- package/src/self-implement/gate-cli.ts +46 -4
- 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 +279 -12
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/run-status-mapping.ts +5 -3
- 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/chat.ts +2 -0
- package/src/session/index.ts +45 -13
- package/src/shell-env-bootstrap.ts +17 -0
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/directive.ts +51 -2
- package/src/steward/launch.ts +266 -0
- package/src/steward/outcome-notify.ts +115 -0
- package/src/steward/steward-cards.ts +25 -11
- package/src/steward/triage-plan.ts +32 -4
- package/src/steward/triage.ts +129 -13
- package/src/steward/working-backwards.ts +64 -0
- package/src/storyboard/storyboard.ts +141 -0
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-cards/card-store.ts +2 -2
- 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 +397 -0
- 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 +153 -0
- package/src/telegram-commands.ts +10 -1
- package/src/telegram-project-command.ts +71 -0
- package/src/telegram-report.ts +29 -19
- package/src/telegram-run.ts +7 -0
- package/src/telegram.ts +58 -11
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/tool-runtime/types.ts +4 -0
- package/src/tui-client/dashboard-session.ts +2 -0
- package/src/user-config.ts +216 -27
- package/src/version/packed-revision.json +1 -1
- package/src/web-push/notify-exec-request.ts +32 -0
- 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/bFI5EEwg7T6aG88ibX4Zq/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.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/2929-617f1e66a55be184.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/3441-a1dd4acfeda14488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5080-1613752891fcadb4.js +0 -10
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.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/7032-f4ef698518fba61c.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/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8630-cdfc61e82c653ffc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-e263b332208e3957.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-139040d37c79dbc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.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-fb7c2d458f32fcad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-35e2713597dd24d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-918b656f064577ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-5f30e00693527ebd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-7fbae173b3c103a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b4edcce364062ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-c5794f484c251f44.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1130d8eefcd87e76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-973996d584f008c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-016e2bda04eecb1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-b4d6d9a3b56f2940.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-ec49a466121233ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-f72db356744ceade.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-a6fd9b50d1b85378.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-8b0402a46a749a3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-037f83e2a1edc8e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-46fedff57d4bec67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-0cf318e9dcee2bbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-899b327cb8b6845c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6c1e6ba743a29dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-1a8e4807292f6b17.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-28deba6bcb834916.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-de68e2205794037d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-c71c33a573230672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0df30e0c7e50148a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4fc56790fe0d2682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-59df2aebb38a7c1e.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-4647be5dbcbd0795.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-e025892bda74b743.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a0955de73b89f078.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-369846d2921af584.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-72cbc1c8cdd0f65d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-77b28bfb0996d5ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-3220c4934f49c6c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-90670589b87abea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-7df9243ed021a4cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-4498c3853f4f688d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-35bedde6d885f08f.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-6870f30ea99f8346.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/f92f63a5df0ba229.css +0 -1
- package/src/dashboard/turn-typeahead-echo.ts +0 -23
- /package/apps/pwa/out/_next/static/{bFI5EEwg7T6aG88ibX4Zq → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
|
@@ -26,6 +26,7 @@ import { buildAutonomousToolSpecs, dispatchAutonomousTool, isAutonomousTool, del
|
|
|
26
26
|
import { isToolSearchCall, routeToolSearch } from '../skills/tools/tool-search-route.js';
|
|
27
27
|
import { financeEnabled, financeAgentSystemPrompt, marketClock } from '../domains/finance.js';
|
|
28
28
|
import { buildFinanceTools } from '../domains/finance-tools.js';
|
|
29
|
+
import { dispatchReleaseChange } from '../domains/release-tool.js';
|
|
29
30
|
import { surfaceEventsDbPath, openSurfaceEventsDb, recentSentDigest, recordInboundTurn } from '../domains/surface-events.js';
|
|
30
31
|
import { elanousSelfAccessPrompt, elanousSelfAmbientParts } from './self-ambient.js';
|
|
31
32
|
import { localRefGroundingAmbient } from './ref-grounding.js';
|
|
@@ -188,6 +189,13 @@ export function makeElanousAgentRunTurn(cfg: UserConfig, surface: SessionSource,
|
|
|
188
189
|
},
|
|
189
190
|
});
|
|
190
191
|
}
|
|
192
|
+
if (name === 'release_change') {
|
|
193
|
+
return dispatchReleaseChange(args, {
|
|
194
|
+
surface: 'chat', sessionId: opts.sessionId,
|
|
195
|
+
...(opts.verifiedOwner ? { verifiedOwner: opts.verifiedOwner } : {}),
|
|
196
|
+
...(surfaceChannels ? { confirmChannels: surfaceChannels } : {}),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
191
199
|
// Thread the turn's abort signal so a long in-flight Bash is killed by
|
|
192
200
|
// `/cancel` (dispatchBash SIGTERMs its child on abort).
|
|
193
201
|
return baseDispatch(name, args, opts.signal);
|
|
@@ -20,6 +20,8 @@ import { configuredWorktreeRoot } from '../user-config.js';
|
|
|
20
20
|
import { worktreeHasChanges, commitWorktree, changedFiles } from '../self-implement/seams.js';
|
|
21
21
|
import { streamLLM, type LLMMessage } from '../llm.js';
|
|
22
22
|
import { debug } from '../debug/log.js';
|
|
23
|
+
import { emitPtyDecision, type DecisionInput } from './pty-decision.js';
|
|
24
|
+
import { observeExternalEvent } from '../context-bus/external-events.js';
|
|
23
25
|
import { emitDecision } from '../live/detail-switch.js';
|
|
24
26
|
import { resolvePtyWebAddress } from '../cli/pty-web-address.js';
|
|
25
27
|
import { reemitPtyUsage } from '../budget/pty-usage-reemit.js';
|
|
@@ -522,6 +524,8 @@ export interface AgentMissionDeps {
|
|
|
522
524
|
createWorktree?: typeof createWorktree;
|
|
523
525
|
recordWorktreeProvenance?: typeof recordHarnessWorktreeProvenance;
|
|
524
526
|
runControlLoop?: typeof runPtyControlLoop;
|
|
527
|
+
/** Capture decisions in tests without replacing the process-wide debug logger. */
|
|
528
|
+
emitPtyDecision?: typeof emitPtyDecision;
|
|
525
529
|
/** Inject controller responses while keeping the production control loop. */
|
|
526
530
|
controlStream?: StreamLLMFn;
|
|
527
531
|
resolvePtyWebAddress?: typeof resolvePtyWebAddress;
|
|
@@ -830,6 +834,7 @@ export interface MissionControlBrainOpts {
|
|
|
830
834
|
readonly handoffEnabled?: boolean;
|
|
831
835
|
/** Screen-grounded brain summary for the next backend, never the raw PTY screen. */
|
|
832
836
|
readonly onSummary?: (summary: string) => void;
|
|
837
|
+
readonly onDecision?: (text: string, reply?: { question: string; answer: string }) => void;
|
|
833
838
|
}
|
|
834
839
|
|
|
835
840
|
/** 기존 5-action mission 판단을 canonical PTY control-loop 결정으로 축소한다. search는 이 경계에서만
|
|
@@ -855,7 +860,7 @@ export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSup
|
|
|
855
860
|
행동(action):
|
|
856
861
|
- "wait": ${backendName} 가 아직 작업 중(도구 실행/생성)이면 대기.
|
|
857
862
|
- "verify": ${backendName} 가 MISSION-COMPLETE/완료를 주장하면 증거 게이트(내가 실행)로 검증. 완료주장 시 이걸 우선.
|
|
858
|
-
- "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text).
|
|
863
|
+
- "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text). 화면의 질문에 직접 답하는 경우에만 reason 을 Answering question: <화면의 질문 원문> 으로 기록하라. 다른 send 의 reason 은 종전처럼 행동 이유를 적어라.
|
|
859
864
|
- "search": ${backendName} 가 정보/라이브러리/문법/외부자원에 막혔으면 omni-crawl 로 조사(query). ⭐외부 힌트 없이 스스로 판단.
|
|
860
865
|
${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/claude/elanous), mission(다음 지시), carry(diff/summary 선택). carry=summary 면 reason 에 화면에서 확인한 리뷰 지적을 구체적으로 요약하라(다음 backend 에 전달된다). claude 리뷰 뒤 지적은 codex 에 summary 로 되돌려라. elanous 는 증거 게이트와 PR.
|
|
861
866
|
- "ask-human": 화면에 로그인 URL/장치 코드가 보이면 reason, url/code(보이는 것만). 토큰·자격파일을 열지 마라.` : ''}${opts.provision ? `
|
|
@@ -873,6 +878,12 @@ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/c
|
|
|
873
878
|
history.push(`s${obs.step}:${decision.action}`);
|
|
874
879
|
debug.log('agent-mission', 'brain', { step: obs.step, action: decision.action,
|
|
875
880
|
...(decision.action === 'ask-human' ? {} : { reason: decision.reason.slice(0, 120) }) });
|
|
881
|
+
// A '?' on screen alone does not establish that this send answered it. Only an
|
|
882
|
+
// explicit question citation in the brain's reason can attribute the reply.
|
|
883
|
+
const citedQuestion = /^Answering question:\s*(.+\?)\s*$/i.exec(decision.reason)?.[1]?.trim();
|
|
884
|
+
const question = citedQuestion && classifierFrameLines(obs.screen).find((line) => line === citedQuestion);
|
|
885
|
+
opts.onDecision?.(`step ${obs.step}: ${decision.action}${decision.action === 'ask-human' ? '' : ` — ${decision.reason || decision.text || decision.query || ''}`}`,
|
|
886
|
+
decision.action === 'send' && decision.text?.trim() && question ? { question, answer: decision.text } : undefined);
|
|
876
887
|
if (decision.reason && decision.action !== 'ask-human') opts.onSummary?.(decision.reason.slice(0, 2000));
|
|
877
888
|
if (decision.action === 'handoff' && decision.to && decision.mission) return { action: 'handoff', to: decision.to, mission: decision.mission, ...(decision.carry ? { carry: decision.carry } : {}) };
|
|
878
889
|
if (decision.action === 'ask-human') return { action: 'ask-human', reason: decision.reason, ...(decision.url ? { url: decision.url } : {}), ...(decision.code ? { code: decision.code } : {}) };
|
|
@@ -974,6 +985,7 @@ export function makeMissionObserveStep(deps: {
|
|
|
974
985
|
bus: ChannelBus;
|
|
975
986
|
ident: { ptyId: string; instance: string; runId?: string };
|
|
976
987
|
now?: () => number;
|
|
988
|
+
onPublishedFrame?: (obs: ControlObservation) => void;
|
|
977
989
|
}): (obs: ControlObservation, decision: ControlDecision) => Promise<void> {
|
|
978
990
|
const now = deps.now ?? ((): number => Date.now());
|
|
979
991
|
let lastFrameState: FrameState | null = null;
|
|
@@ -1008,6 +1020,7 @@ export function makeMissionObserveStep(deps: {
|
|
|
1008
1020
|
...(deps.ident.runId ? { runId: deps.ident.runId } : {}),
|
|
1009
1021
|
...(pngRef ? { pngRef } : {}),
|
|
1010
1022
|
});
|
|
1023
|
+
deps.onPublishedFrame?.(obs);
|
|
1011
1024
|
// capture 는 원 semantics 유지 — 예외 전파(증거/전사 계약 불변).
|
|
1012
1025
|
await deps.capture(`s${obs.step}-${decision.action}`);
|
|
1013
1026
|
};
|
|
@@ -1574,9 +1587,19 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1574
1587
|
if (deps.isMissionAborted?.()) { offLive(); throw new Error('MISSION_ABORTED'); }
|
|
1575
1588
|
try { h = spawnPty(ptyOpts); }
|
|
1576
1589
|
catch (error) { offLive(); throw error; }
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1590
|
+
if (backend.name === 'codex') observeExternalEvent({ origin: 'codex-agent-mission', kind: 'started',
|
|
1591
|
+
summary: 'Codex agent mission started', source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
|
|
1592
|
+
let contextFinished = false;
|
|
1593
|
+
const finishContext = (ok: boolean): void => {
|
|
1594
|
+
if (contextFinished || backend.name !== 'codex') return;
|
|
1595
|
+
contextFinished = true;
|
|
1596
|
+
observeExternalEvent({ origin: 'codex-agent-mission', kind: 'finished',
|
|
1597
|
+
summary: `Codex agent mission ${ok ? 'completed' : 'failed'}`,
|
|
1598
|
+
source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
|
|
1599
|
+
};
|
|
1600
|
+
deps.onPtyStarted?.(h, () => { if (liveTimer) clearInterval(liveTimer); offLive(); finishContext(false); });
|
|
1601
|
+
if (deps.isMissionAborted?.()) { finishContext(false); return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
|
|
1602
|
+
rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' }; }
|
|
1580
1603
|
const executorRef = buildExecutorPtyRef({
|
|
1581
1604
|
ptyId: h.id,
|
|
1582
1605
|
backend: backend.name,
|
|
@@ -1589,6 +1612,12 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1589
1612
|
process.stderr.write(`[agent-mission] pty=${h.id} watch=${webAddress.webUrl ?? `(web unavailable: ${webAddress.pwaUnavailableReason ?? 'not-resolved'})`}\n`);
|
|
1590
1613
|
debug.log('agent-mission', 'pty-link', { id: h.id, webUrl: webAddress.webUrl, webUrlSource: webAddress.webUrlSource });
|
|
1591
1614
|
|
|
1615
|
+
const decisionIdentity = { missionId: runId, sessionId: runId, terminalId: h.id, agent: backend.name };
|
|
1616
|
+
const decisionEvent = (event: Omit<DecisionInput, keyof typeof decisionIdentity>): void => {
|
|
1617
|
+
try { (deps.emitPtyDecision ?? emitPtyDecision)({ ...decisionIdentity, ...event } as DecisionInput); }
|
|
1618
|
+
catch { /* Observation must not change mission control or handoff. */ }
|
|
1619
|
+
};
|
|
1620
|
+
|
|
1592
1621
|
// ⭐P2 arbiter: the child is accessMode='auto' (brain-owned), so the driver —
|
|
1593
1622
|
// the autonomous brain — must write as 'agent' or the arbiter denies it. This
|
|
1594
1623
|
// makes "protected autonomy" real: a human attaching mid-mission (read) can't
|
|
@@ -1615,6 +1644,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1615
1644
|
: 'AGENT_YIELDED: PTY 제어가 사람에게 이양됨(takeover) — 자율 미션 중단');
|
|
1616
1645
|
}
|
|
1617
1646
|
h['write'](s, 'agent');
|
|
1647
|
+
decisionEvent({ step: 'input', text: s === '\r' ? 'Sent Enter' : `Sent ${s.startsWith('\x1b') ? 'key' : 'text'}: ${s.startsWith('\x1b') ? 'navigation' : s}` });
|
|
1618
1648
|
};
|
|
1619
1649
|
|
|
1620
1650
|
let seq = 0;
|
|
@@ -1638,7 +1668,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1638
1668
|
if (liveChunks % 20 === 0) debug.log('agent-mission', 'live', { chunks: liveChunks, tail: s.slice(-80).replace(/\s+/g, ' ') });
|
|
1639
1669
|
}).catch(() => { /* noop */ });
|
|
1640
1670
|
}, 800);
|
|
1641
|
-
const stopLive = (): void => { if (liveTimer) clearInterval(liveTimer); offLive(); };
|
|
1671
|
+
const stopLive = (ok = false): void => { if (liveTimer) clearInterval(liveTimer); offLive(); if (ok) finishContext(true); };
|
|
1672
|
+
try {
|
|
1642
1673
|
|
|
1643
1674
|
// ready + trust — backend 별 신뢰/권한 프롬프트 처리(codex=1, 이후 백엔드는 자체 handler).
|
|
1644
1675
|
await (deps.awaitMission ? deps.awaitMission(waitForQuiet(h, 1500, 20000)) : waitForQuiet(h, 1500, 20000));
|
|
@@ -1648,7 +1679,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1648
1679
|
// A trust menu can need more than one key (claude: ↓ to «Yes», then Enter) — answer until it is gone, at most 3 times.
|
|
1649
1680
|
// 🩸 09-29: one pass sent only ↓, the mission text went into the menu and its Enter confirmed «Yes» instead of
|
|
1650
1681
|
// submitting the mission, which then sat unsent in the input box.
|
|
1651
|
-
for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) =>
|
|
1682
|
+
for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) => {
|
|
1683
|
+
drive(s);
|
|
1684
|
+
// Moving the selection is only input; the trust question is answered when the choice is confirmed.
|
|
1685
|
+
if (s === '\r') decisionEvent({ step: 'answer', text: 'Answered folder trust prompt', detail: { question: 'Trust this folder?', answer: 'Confirm selected choice' } });
|
|
1686
|
+
}); pass++) {
|
|
1652
1687
|
debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled', pass });
|
|
1653
1688
|
const trusted = (async () => { await waitForQuiet(h, 1500, 15000); return capture('trusted'); })();
|
|
1654
1689
|
screen = await (deps.awaitMission ? deps.awaitMission(trusted) : trusted);
|
|
@@ -1761,6 +1796,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1761
1796
|
let controllerSummary = deps.previousSummary ?? '';
|
|
1762
1797
|
let reviewSummary = '';
|
|
1763
1798
|
let coverageRetries = enhanceActive && checklist.length ? 2 : 0;
|
|
1799
|
+
let pendingAnswer: { text: string; question: string; answer: string } | undefined;
|
|
1764
1800
|
const search = createMissionSearch({ worktree: wt.path, omniPath });
|
|
1765
1801
|
const brain = createMissionControlBrain({
|
|
1766
1802
|
mission: spec.mission,
|
|
@@ -1768,6 +1804,10 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1768
1804
|
stream: deps.controlStream,
|
|
1769
1805
|
handoffEnabled: true,
|
|
1770
1806
|
onSummary: (summary) => { controllerSummary = summary; },
|
|
1807
|
+
onDecision: (text, reply) => {
|
|
1808
|
+
pendingAnswer = reply ? { text: `${reply.answer || 'continue'}\r`, ...reply } : undefined;
|
|
1809
|
+
decisionEvent({ step: 'judge', text });
|
|
1810
|
+
},
|
|
1771
1811
|
evidenceReady: () => spec.chain && spec.chain.length > 1 ? true : verifyEvidence(wt.path, spec.evidence).ok,
|
|
1772
1812
|
search: async (query, step) => {
|
|
1773
1813
|
usedOmni = true;
|
|
@@ -1784,9 +1824,13 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1784
1824
|
// before asking the LLM — otherwise the mission text is typed into the prompt and the run stalls.
|
|
1785
1825
|
const trustAwareBrain: RunSupervisor = {
|
|
1786
1826
|
decide: (obs, signal) => {
|
|
1827
|
+
pendingAnswer = undefined;
|
|
1787
1828
|
let answer: string | undefined;
|
|
1788
1829
|
if (backend.handleTrust?.(obs.screen, (bytes) => { answer = bytes; }) && answer !== undefined) {
|
|
1789
1830
|
debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled-in-loop', step: obs.step });
|
|
1831
|
+
decisionEvent({ step: 'judge', text: `step ${obs.step}: trust prompt` });
|
|
1832
|
+
// Only the confirming Enter answers the trust question; a navigation key stays an input event.
|
|
1833
|
+
if (answer === '\r') pendingAnswer = { text: answer, question: 'Trust this folder?', answer: 'Confirm selected choice' };
|
|
1790
1834
|
emitDecision({ kind: 'ROUTE', what: `${backend.name} 폴더 신뢰 화면 → 계속`, reason: '시작 뒤 늦게 뜬 신뢰 확인', purpose: '미션을 이어 간다', target: backend.name, phase: 'implement' });
|
|
1791
1835
|
return { action: 'input', text: answer };
|
|
1792
1836
|
}
|
|
@@ -1872,6 +1916,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1872
1916
|
renderPng: () => h.renderScreenPng(),
|
|
1873
1917
|
bus,
|
|
1874
1918
|
ident: { ptyId: h.id, instance: resolveInstanceName(), runId },
|
|
1919
|
+
onPublishedFrame: (obs) => decisionEvent({ step: 'read', text: `step ${obs.step} (${obs.state}): ${classifierFrameLines(obs.screen).at(-1) ?? 'empty screen'}` }),
|
|
1875
1920
|
});
|
|
1876
1921
|
debug.log('agent-mission', 'takeover-wait', { id: h.id, maxWaitMs: AGENT_MISSION_TAKEOVER_WAIT_MS });
|
|
1877
1922
|
const controlRun = runWithControlObserve(
|
|
@@ -1879,9 +1924,24 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1879
1924
|
(d) => debug.log('agent-mission.observe', 'progress', { surfaceId: d.surfaceId, state: d.state, summary: d.summary, unknownInput: d.unknownInput, frame: d.frameCount, runId: d.runId }),
|
|
1880
1925
|
() => {
|
|
1881
1926
|
const handleDeps = controlDepsForHandle(h);
|
|
1927
|
+
const inject = backend.name === 'claude' ? submitSeparately(handleDeps.inject) : handleDeps.inject;
|
|
1882
1928
|
const pending = (deps.runControlLoop ?? runPtyControlLoop)(trustAwareBrain, {
|
|
1883
1929
|
...handleDeps,
|
|
1884
|
-
|
|
1930
|
+
inject: (text) => {
|
|
1931
|
+
const reply = pendingAnswer?.text === text ? pendingAnswer : undefined;
|
|
1932
|
+
pendingAnswer = undefined;
|
|
1933
|
+
const accepted = inject(text);
|
|
1934
|
+
if (accepted) {
|
|
1935
|
+
decisionEvent({ step: 'input', text: `Sent ${text.startsWith('\x1b') ? 'key' : 'text'}: ${text.startsWith('\x1b') ? 'navigation' : text}` });
|
|
1936
|
+
if (reply) decisionEvent({ step: 'answer', text: 'Answered agent question', detail: { question: reply.question, answer: reply.answer } });
|
|
1937
|
+
}
|
|
1938
|
+
return accepted;
|
|
1939
|
+
},
|
|
1940
|
+
injectKey: handleDeps.injectKey && ((name, repeat) => {
|
|
1941
|
+
const accepted = handleDeps.injectKey!(name, repeat);
|
|
1942
|
+
if (accepted) decisionEvent({ step: 'input', text: `Pressed ${name}${repeat ? ` ×${repeat}` : ''}`, detail: { keys: name } });
|
|
1943
|
+
return accepted;
|
|
1944
|
+
}),
|
|
1885
1945
|
...(deps.isMissionAborted ? {
|
|
1886
1946
|
controlStance: () => deps.isMissionAborted!() ? 'unknown' as const : probeControlStance(h, 'agent', (e) =>
|
|
1887
1947
|
debug.log('agent-mission', 'hascontrol-error', { id: h.id, error: (e as Error)?.message ?? String(e) })),
|
|
@@ -1903,7 +1963,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1903
1963
|
}
|
|
1904
1964
|
}
|
|
1905
1965
|
},
|
|
1906
|
-
verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) :
|
|
1966
|
+
verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : async (obs) => {
|
|
1967
|
+
const verdict = await verifyDone(obs);
|
|
1968
|
+
if (!verdict.ok) decisionEvent({ step: 'recover', text: 'Evidence check requires another attempt', detail: { blocked: verdict.retry, action: 'Retry after fixing evidence' } });
|
|
1969
|
+
return verdict;
|
|
1970
|
+
},
|
|
1907
1971
|
handoff: async (decision, obs) => {
|
|
1908
1972
|
try {
|
|
1909
1973
|
if (spec.chain && decision.to !== spec.chain[1]) throw new Error(`chain order violation: expected ${spec.chain[1] ?? 'completion'}, got ${decision.to}`);
|
|
@@ -1916,6 +1980,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1916
1980
|
askHuman: async (decision) => {
|
|
1917
1981
|
try {
|
|
1918
1982
|
await waitForHumanLogin(decision, handoffOps);
|
|
1983
|
+
decisionEvent({ step: 'answer', text: 'Human login question resolved', detail: { question: decision.reason, answer: 'Login completed' } });
|
|
1919
1984
|
} catch (error) {
|
|
1920
1985
|
transitionFailure = error instanceof Error ? error.message : String(error);
|
|
1921
1986
|
throw error;
|
|
@@ -1954,7 +2019,9 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1954
2019
|
}
|
|
1955
2020
|
// A gate/PR handoff only counts as success when the control loop itself did not end in error.
|
|
1956
2021
|
if (gatedHandoff && control.termination.kind !== 'error') {
|
|
1957
|
-
|
|
2022
|
+
// The gate hands off a branch, not a file: record what is known instead of mislabeling the worktree directory.
|
|
2023
|
+
decisionEvent({ step: 'done', text: 'Mission handoff gate completed', detail: { result: { kind: 'text', ref: `branch ${wt.branch}` } } });
|
|
2024
|
+
stopLive(true);
|
|
1958
2025
|
try { h.kill(); } catch { /* noop */ }
|
|
1959
2026
|
return { ok: true, worktree: wt.path, branch: wt.branch, rounds: control.steps, evidencePath: wt.path, committed: true, usedOmniCrawl: usedOmni,
|
|
1960
2027
|
...(handoffPrSkipped ? { pr: 'skipped' as const, reason: 'origin-not-github' as const } : {}),
|
|
@@ -1985,6 +2052,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1985
2052
|
maxFallbackDescents: runtimeFallback.maxDescents,
|
|
1986
2053
|
});
|
|
1987
2054
|
if (nextBackend && !deps.isMissionAborted?.()) {
|
|
2055
|
+
decisionEvent({ step: 'recover', text: `Switching ${backend.name} to ${nextBackend.name}`, detail: { blocked: control.termination.message, action: `Retry with ${nextBackend.name}` } });
|
|
1988
2056
|
const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : 'codex-rotate';
|
|
1989
2057
|
stopLive();
|
|
1990
2058
|
if (h.pid) await (deps.terminateProcessTree ?? terminateMissionProcessTree)(h.pid);
|
|
@@ -2019,7 +2087,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
2019
2087
|
debug.log('agent-mission', 'commit', { ok: c.ok, out: c.out.slice(0, 120) });
|
|
2020
2088
|
}
|
|
2021
2089
|
debug.log('agent-mission', 'result', { ok: finalEv.ok, rounds: round, evidencePath, committed, usedOmni });
|
|
2022
|
-
|
|
2090
|
+
decisionEvent({ step: 'done', text: finalEv.ok ? 'Mission evidence accepted' : 'Mission ended without sufficient evidence', detail: { result: { kind: evidencePath ? 'file' : 'text', ref: evidencePath ?? (control.termination.kind === 'error' ? control.termination.message : 'evidence unavailable') } } });
|
|
2091
|
+
stopLive(finalEv.ok);
|
|
2023
2092
|
if (h.pid) await terminateMissionProcessTree(h.pid);
|
|
2024
2093
|
try { h.kill(); } catch { /* noop */ }
|
|
2025
2094
|
|
|
@@ -2029,6 +2098,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
2029
2098
|
ptyId: h.id, webUrl: webAddress.webUrl,
|
|
2030
2099
|
detail: done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
|
|
2031
2100
|
};
|
|
2101
|
+
} finally { stopLive(); finishContext(false); }
|
|
2032
2102
|
}
|
|
2033
2103
|
|
|
2034
2104
|
/** @deprecated codex 특정 이름 — runAgentMission 을 쓰라(codex 는 기본 backend). */
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
|
|
3
|
+
type Identity = {
|
|
4
|
+
ts: string;
|
|
5
|
+
missionId: string;
|
|
6
|
+
seq: number;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
terminalId: string;
|
|
9
|
+
agent: string;
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
type Detail = { keys?: string; row?: number };
|
|
13
|
+
|
|
14
|
+
export type PtyDecision = Identity & (
|
|
15
|
+
| { step: 'read' | 'judge' | 'input'; detail?: Detail }
|
|
16
|
+
| { step: 'answer'; detail: Detail & { question: string; answer: string } }
|
|
17
|
+
| { step: 'recover'; detail: Detail & { blocked: string; action: string } }
|
|
18
|
+
| { step: 'done'; detail: Detail & { result: { kind: 'pr' | 'file' | 'text'; ref: string } } }
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type DecisionInput = Omit<Identity, 'ts' | 'seq'> & (
|
|
22
|
+
| { step: 'read' | 'judge' | 'input'; detail?: Detail }
|
|
23
|
+
| { step: 'answer'; detail: Detail & { question: string; answer: string } }
|
|
24
|
+
| { step: 'recover'; detail: Detail & { blocked: string; action: string } }
|
|
25
|
+
| { step: 'done'; detail: Detail & { result: { kind: 'pr' | 'file' | 'text'; ref: string } } }
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const missionStreams = new Map<string, { alias: string; seq: number }>();
|
|
29
|
+
export const PTY_DECISION_TEXT_MAX = 240;
|
|
30
|
+
|
|
31
|
+
function safe(value: string): string {
|
|
32
|
+
const masked = value
|
|
33
|
+
.replace(/\bBearer\s+(?:"[^"]*"|'[^']*'|[^\s"'<>]+)/gi, 'Bearer [redacted]')
|
|
34
|
+
.replace(/\b([a-z0-9_]*(?:token|key(?:[_-]?id)?|secret|password|authorization)\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s"'<>]+)/gi, '$1[redacted]')
|
|
35
|
+
.replace(/\b(?:sk-[a-z0-9_-]+|gh[pousr]_[a-z0-9_]+|github_pat_[a-z0-9_]+|AIza[a-z0-9_-]+|xox[baprs]-[a-z0-9-]+)\b/gi, '[redacted]')
|
|
36
|
+
.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '[redacted]')
|
|
37
|
+
.replace(/[\x00-\x1f\x7f-\x9f]/g, ' ')
|
|
38
|
+
.trim();
|
|
39
|
+
const clipped = masked.slice(0, PTY_DECISION_TEXT_MAX);
|
|
40
|
+
return clipped.replace(/[\uD800-\uDBFF]$/, '') || '[redacted]';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The only emission point for the inside-PTY decision stream. Never log unsanitized input. */
|
|
44
|
+
export function emitPtyDecision(input: DecisionInput, log: typeof debug.log = debug.log): PtyDecision {
|
|
45
|
+
let stream = missionStreams.get(input.missionId);
|
|
46
|
+
if (!stream) {
|
|
47
|
+
stream = { alias: `mission-${missionStreams.size + 1}`, seq: -1 };
|
|
48
|
+
missionStreams.set(input.missionId, stream);
|
|
49
|
+
}
|
|
50
|
+
stream.seq += 1;
|
|
51
|
+
const base = {
|
|
52
|
+
ts: new Date().toISOString(),
|
|
53
|
+
missionId: stream.alias,
|
|
54
|
+
seq: stream.seq,
|
|
55
|
+
sessionId: safe(input.sessionId),
|
|
56
|
+
terminalId: safe(input.terminalId),
|
|
57
|
+
agent: safe(input.agent),
|
|
58
|
+
text: safe(input.text),
|
|
59
|
+
};
|
|
60
|
+
const common = input.detail ? {
|
|
61
|
+
...(input.detail.keys !== undefined ? { keys: safe(input.detail.keys) } : {}),
|
|
62
|
+
...(input.detail.row !== undefined ? { row: input.detail.row } : {}),
|
|
63
|
+
} : {};
|
|
64
|
+
let decision: PtyDecision;
|
|
65
|
+
if (input.step === 'answer') decision = { ...base, step: input.step, detail: { ...common, question: safe(input.detail.question), answer: safe(input.detail.answer) } };
|
|
66
|
+
else if (input.step === 'recover') decision = { ...base, step: input.step, detail: { ...common, blocked: safe(input.detail.blocked), action: safe(input.detail.action) } };
|
|
67
|
+
else if (input.step === 'done') decision = { ...base, step: input.step, detail: { ...common, result: { kind: input.detail.result.kind, ref: safe(input.detail.result.ref) } } };
|
|
68
|
+
else decision = { ...base, step: input.step, ...(input.detail ? { detail: common } : {}) };
|
|
69
|
+
log('pty.decision', decision.step, decision);
|
|
70
|
+
return decision;
|
|
71
|
+
}
|
|
@@ -11,6 +11,7 @@ import { runGitCommand } from '../git-fs/runner.js';
|
|
|
11
11
|
import * as llm from '../llm.js';
|
|
12
12
|
import type { LLMMessage } from '../llm.js';
|
|
13
13
|
import { debug } from '../debug/log.js';
|
|
14
|
+
import { releasePathHold, releasePathHoldShouldPost, releasePathHoldComment, releasePathHoldCommentsArgs, releasePrFilePaths, RELEASE_PATH_LABEL } from '../self-dev/release-path-guard.js';
|
|
14
15
|
import { runAgentMission, resolveBackend, type AgentMissionResult, type EvidenceMode } from './driver.js';
|
|
15
16
|
import { judgeWithAcp, prepareJudgeDiff } from './acp-judge.js';
|
|
16
17
|
import { verifyMergeAndMaybeRevert } from './merge-safety.js';
|
|
@@ -114,6 +115,31 @@ function gh(args: string[]): string {
|
|
|
114
115
|
return execFileSync('gh', args, { encoding: 'utf8', timeout: 60000, maxBuffer: 20 * 1024 * 1024, env: process.env });
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
/** Check every page of the PR file list immediately before an unattended review-loop merge. */
|
|
119
|
+
function holdReleasePathBeforeReviewMerge(pr: string, runGh: (args: string[]) => string): boolean {
|
|
120
|
+
let paths: string[];
|
|
121
|
+
try {
|
|
122
|
+
paths = releasePrFilePaths(JSON.parse(runGh(['api', '--paginate', '--slurp', '--method', 'GET', '-f', 'per_page=100', `repos/{owner}/{repo}/pulls/${pr}/files`])));
|
|
123
|
+
} catch (error) {
|
|
124
|
+
debug.log('self-dev.merge', 'release-path-inspection-failed', { pr, error: String(error) });
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
const path = releasePathHold(paths);
|
|
128
|
+
if (!path) return false;
|
|
129
|
+
debug.log('self-dev.merge', 'release-path-hold', { pr, path, label: RELEASE_PATH_LABEL, surface: 'review-loop' });
|
|
130
|
+
try {
|
|
131
|
+
const names: unknown = JSON.parse(runGh(['label', 'list', '--search', RELEASE_PATH_LABEL, '--json', 'name']));
|
|
132
|
+
if (!Array.isArray(names)) throw new Error('invalid label list');
|
|
133
|
+
if (!names.some((item: unknown) => !!item && typeof item === 'object' && 'name' in item && item.name === RELEASE_PATH_LABEL)) {
|
|
134
|
+
runGh(['label', 'create', RELEASE_PATH_LABEL, '--color', 'D93F0B', '--description', 'Release path requires OP approval']);
|
|
135
|
+
}
|
|
136
|
+
runGh(['pr', 'edit', pr, '--add-label', RELEASE_PATH_LABEL]);
|
|
137
|
+
} catch (error) { debug.log('self-dev.merge', 'release-path-annotation-failed', { pr, action: 'label', error: String(error) }); }
|
|
138
|
+
try { if (releasePathHoldShouldPost(() => JSON.parse(runGh(releasePathHoldCommentsArgs(pr))))) runGh(['pr', 'comment', pr, '--body', releasePathHoldComment(path)]); }
|
|
139
|
+
catch (error) { debug.log('self-dev.merge', 'release-path-annotation-failed', { pr, action: 'comment', error: String(error) }); }
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
117
143
|
/** ★ G10 안전봉투 — 자율머지 직후 회귀검증(verifyMerge 시). 회귀면 revert PR 이 이미 생성됨(알림 포함) →
|
|
118
144
|
* 원 PR 에 링크 코멘트만. fail-open(검증 오류는 머지를 막지 않음). */
|
|
119
145
|
async function runMergeSafety(pr: string, opts: ReviewLoopOpts, depth: ReviewDepth): Promise<void> {
|
|
@@ -233,6 +259,7 @@ export async function judgeAndFinalize(
|
|
|
233
259
|
|
|
234
260
|
if (j.verdict === 'merge') {
|
|
235
261
|
if (opts.autoMerge) {
|
|
262
|
+
if (holdReleasePathBeforeReviewMerge(pr, runGh)) return { pr, branch, verdict: 'reinforce', asks, action: 'parked', reworkOk: true, pushed: lastPushed, rounds: round, detail: 'OP approval required: release-path hold or PR file inspection unavailable' };
|
|
236
263
|
const approve = opts.approve ?? approvePr;
|
|
237
264
|
const recordReviewOutcome = opts.recordReviewOutcome ?? recordOutcome;
|
|
238
265
|
approve(pr, `2차 ACP 최종심판 MERGE (round ${round})`);
|
|
@@ -480,6 +507,9 @@ export async function runReviewLoop(pr: string, opts: ReviewLoopOpts = {}): Prom
|
|
|
480
507
|
if (cls.verdict === 'ok') {
|
|
481
508
|
// light: 1차 clean 으로 충분 → approve + 머지. heavy: 1차 ok 여도 2차 심판 머스트.
|
|
482
509
|
if (!effectiveFinalJudge) {
|
|
510
|
+
if ((opts.autoMergeOnOk || opts.autoMerge) && holdReleasePathBeforeReviewMerge(pr, runGh)) {
|
|
511
|
+
return { pr, branch, verdict: 'ok', asks: [], action: 'parked', detail: 'OP approval required: release-path hold or PR file inspection unavailable' };
|
|
512
|
+
}
|
|
483
513
|
approve(pr, `소작업(light)·1차 리뷰 clean`);
|
|
484
514
|
let merged = false;
|
|
485
515
|
if (opts.autoMergeOnOk || opts.autoMerge) {
|
|
@@ -3,16 +3,13 @@ import { join } from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
5
5
|
import { ASK_USER_QUESTION_DELIVERY_VALUES } from './types.js';
|
|
6
|
-
import type { AskUserQuestionRequest, AskUserQuestionResult, HitlDelivery, QuestionOption } from './types.js';
|
|
6
|
+
import type { AskUserQuestionRequest, AskUserQuestionResult, HitlDelivery, Question, QuestionOption } from './types.js';
|
|
7
7
|
|
|
8
|
-
interface PendingQuestion {
|
|
8
|
+
export interface PendingQuestion {
|
|
9
9
|
id: string;
|
|
10
10
|
sessionId?: string;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
question: string;
|
|
14
|
-
options: QuestionOption[];
|
|
15
|
-
}>;
|
|
11
|
+
runId?: string;
|
|
12
|
+
questions: Array<Pick<Question, 'id' | 'question' | 'options' | 'impact' | 'recommendedIndex'>>;
|
|
16
13
|
startedAt: string;
|
|
17
14
|
expiresAt?: string;
|
|
18
15
|
surface: 'tui' | 'file';
|
|
@@ -86,6 +83,7 @@ function isPendingQuestion(value: unknown): value is PendingQuestion {
|
|
|
86
83
|
const pending = value as Record<string, unknown>;
|
|
87
84
|
return typeof pending.id === 'string'
|
|
88
85
|
&& (pending.sessionId === undefined || typeof pending.sessionId === 'string')
|
|
86
|
+
&& (pending.runId === undefined || typeof pending.runId === 'string')
|
|
89
87
|
&& Array.isArray(pending.questions)
|
|
90
88
|
&& pending.questions.every((question) => {
|
|
91
89
|
if (question === null || typeof question !== 'object' || Array.isArray(question)) return false;
|
|
@@ -93,7 +91,10 @@ function isPendingQuestion(value: unknown): value is PendingQuestion {
|
|
|
93
91
|
return typeof record.id === 'string'
|
|
94
92
|
&& typeof record.question === 'string'
|
|
95
93
|
&& Array.isArray(record.options)
|
|
96
|
-
&& record.options.every(isQuestionOption)
|
|
94
|
+
&& record.options.every(isQuestionOption)
|
|
95
|
+
&& (record.impact === undefined || record.impact === 'low' || record.impact === 'medium' || record.impact === 'high' || record.impact === 'critical')
|
|
96
|
+
&& (record.recommendedIndex === undefined || (typeof record.recommendedIndex === 'number'
|
|
97
|
+
&& Number.isInteger(record.recommendedIndex)));
|
|
97
98
|
})
|
|
98
99
|
&& isIsoTimestamp(pending.startedAt)
|
|
99
100
|
&& (pending.surface === 'tui' || pending.surface === 'file')
|
|
@@ -111,7 +112,15 @@ function isPendingQuestion(value: unknown): value is PendingQuestion {
|
|
|
111
112
|
function parsePendingQuestion(contents: string, file: string): PendingQuestion {
|
|
112
113
|
const value: unknown = JSON.parse(contents);
|
|
113
114
|
if (!isPendingQuestion(value)) throw new Error(`Invalid pending question record: ${file}`);
|
|
114
|
-
return
|
|
115
|
+
return {
|
|
116
|
+
...value,
|
|
117
|
+
questions: value.questions.map((question) => ({
|
|
118
|
+
...question,
|
|
119
|
+
...(question.recommendedIndex !== undefined
|
|
120
|
+
&& (question.recommendedIndex < 0 || question.recommendedIndex >= question.options.length)
|
|
121
|
+
? { recommendedIndex: undefined } : {}),
|
|
122
|
+
})),
|
|
123
|
+
};
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
export function isAskUserQuestionResult(value: unknown): value is AskUserQuestionResult {
|
|
@@ -176,7 +185,13 @@ export function createPendingQuestion(
|
|
|
176
185
|
return {
|
|
177
186
|
id,
|
|
178
187
|
...(sessionId === undefined ? {} : { sessionId }),
|
|
179
|
-
|
|
188
|
+
...(request.runId === undefined ? {} : { runId: request.runId }),
|
|
189
|
+
questions: request.questions.map(({ id, question, options, impact, recommendedIndex }) => ({
|
|
190
|
+
id, question, options,
|
|
191
|
+
...(impact === undefined ? {} : { impact }),
|
|
192
|
+
...(recommendedIndex !== undefined && Number.isInteger(recommendedIndex) && recommendedIndex >= 0 && recommendedIndex < options.length
|
|
193
|
+
? { recommendedIndex } : {}),
|
|
194
|
+
})),
|
|
180
195
|
startedAt: (deps.now ?? (() => new Date()))().toISOString(),
|
|
181
196
|
...(presentation.expiresAt === undefined ? {} : { expiresAt: presentation.expiresAt }),
|
|
182
197
|
surface: presentation.surface,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// behaviour exactly.
|
|
14
14
|
|
|
15
15
|
import type { HitlDelivery } from '../hitl/types.js';
|
|
16
|
+
import type { ClarificationImpact } from '../hitl/clarification-policy.js';
|
|
16
17
|
export type { HitlDelivery };
|
|
17
18
|
|
|
18
19
|
export interface QuestionOption {
|
|
@@ -37,6 +38,9 @@ export interface Question {
|
|
|
37
38
|
question: string;
|
|
38
39
|
/** 2–4 pre-defined choices. */
|
|
39
40
|
options: QuestionOption[];
|
|
41
|
+
impact?: ClarificationImpact;
|
|
42
|
+
/** Zero-based position in options; an out-of-range value is ignored. */
|
|
43
|
+
recommendedIndex?: number;
|
|
40
44
|
/** When true, user can pick more than one option; Space toggles,
|
|
41
45
|
* Enter submits. Default false. */
|
|
42
46
|
multiSelect?: boolean;
|
|
@@ -49,6 +53,7 @@ export interface Question {
|
|
|
49
53
|
|
|
50
54
|
export interface AskUserQuestionRequest {
|
|
51
55
|
questions: Question[]; // 1–3
|
|
56
|
+
runId?: string;
|
|
52
57
|
/** AXON F4 — optional routing hint. When set, callers with HITL
|
|
53
58
|
* resolvers can fan the prompt out to Telegram/Discord/etc;
|
|
54
59
|
* omitted (or `'modal'` / `'terminal'`) keeps the existing TUI
|
|
@@ -165,6 +170,9 @@ export function parseQuestionRequest(
|
|
|
165
170
|
header,
|
|
166
171
|
question,
|
|
167
172
|
options,
|
|
173
|
+
...(item.impact === 'low' || item.impact === 'medium' || item.impact === 'high' || item.impact === 'critical' ? { impact: item.impact } : {}),
|
|
174
|
+
...(typeof item.recommendedIndex === 'number' && Number.isInteger(item.recommendedIndex)
|
|
175
|
+
&& item.recommendedIndex >= 0 && item.recommendedIndex < options.length ? { recommendedIndex: item.recommendedIndex } : {}),
|
|
168
176
|
multiSelect: item.multiSelect === true,
|
|
169
177
|
includeOther: item.includeOther !== false, // default true
|
|
170
178
|
});
|
|
@@ -186,5 +194,6 @@ export function parseQuestionRequest(
|
|
|
186
194
|
|
|
187
195
|
const req: AskUserQuestionRequest = { questions: parsed };
|
|
188
196
|
if (delivery !== undefined) req.delivery = delivery;
|
|
197
|
+
if (typeof raw.runId === 'string') req.runId = raw.runId;
|
|
189
198
|
return { ok: true, req };
|
|
190
199
|
}
|
|
@@ -74,15 +74,26 @@ function writeStore(dir: string, tokens: SetupLinkEntry[]): void {
|
|
|
74
74
|
|
|
75
75
|
// A persistent inode and an OS advisory lock avoid stale owner files after an abrupt process exit.
|
|
76
76
|
// Never unlink this file: a replacement inode would let two processes hold different locks.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
// Loaded on first use, not at import: libc.so.6 does not exist on Windows and this module sits on the CLI start path (WIN2 10-02).
|
|
78
|
+
type Flock = (fd: number, op: number) => number;
|
|
79
|
+
let flockFn: Flock | null | undefined;
|
|
80
|
+
function osFlock(): Flock | null {
|
|
81
|
+
if (flockFn !== undefined) return flockFn;
|
|
82
|
+
if (process.platform === 'win32') return (flockFn = null);
|
|
83
|
+
const lib = dlopen(process.platform === 'darwin' ? '/usr/lib/libSystem.B.dylib' : 'libc.so.6', {
|
|
84
|
+
flock: { args: [FFIType.i32, FFIType.i32], returns: FFIType.i32 },
|
|
85
|
+
});
|
|
86
|
+
return (flockFn = lib.symbols.flock as Flock);
|
|
87
|
+
}
|
|
80
88
|
const LOCK_EX = 2;
|
|
81
89
|
const LOCK_NB = 4;
|
|
82
90
|
const LOCK_UN = 8;
|
|
83
91
|
|
|
84
92
|
function withLock<T>(dir: string, fn: () => T): T {
|
|
85
93
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
94
|
+
const flock = osFlock();
|
|
95
|
+
// Windows: no advisory flock and no POSIX modes — the store still writes by atomic rename.
|
|
96
|
+
if (!flock) return fn();
|
|
86
97
|
const lock = `${storePath(dir)}.lock`;
|
|
87
98
|
const fd = openSync(lock, constants.O_CREAT | constants.O_RDWR | constants.O_NOFOLLOW, 0o600);
|
|
88
99
|
try {
|
|
@@ -92,7 +103,7 @@ function withLock<T>(dir: string, fn: () => T): T {
|
|
|
92
103
|
throw new Error('setup link lock must be a private regular file (0600)');
|
|
93
104
|
}
|
|
94
105
|
const until = Date.now() + 3000;
|
|
95
|
-
while (
|
|
106
|
+
while (flock(fd, LOCK_EX | LOCK_NB) !== 0) {
|
|
96
107
|
if (Date.now() > until) throw new Error('setup link store is locked — try again');
|
|
97
108
|
Bun.sleepSync(20);
|
|
98
109
|
}
|
|
@@ -101,7 +112,7 @@ function withLock<T>(dir: string, fn: () => T): T {
|
|
|
101
112
|
if (stat.ino !== locked.ino || stat.dev !== locked.dev) throw new Error('setup link lock changed');
|
|
102
113
|
return fn();
|
|
103
114
|
} finally {
|
|
104
|
-
|
|
115
|
+
flock(fd, LOCK_UN);
|
|
105
116
|
}
|
|
106
117
|
} finally {
|
|
107
118
|
closeSync(fd);
|
|
@@ -255,6 +255,7 @@ const STEP_CMDS: Record<GateStepName, { cmd: string; args: string[]; timeoutMs:
|
|
|
255
255
|
'cli-smoke': { cmd: 'bun', args: ['bin/elanous.mjs', '--help'], timeoutMs: 60_000 },
|
|
256
256
|
};
|
|
257
257
|
|
|
258
|
+
const DEPENDENCY_INSTALL_TIMEOUT_MS = 300_000;
|
|
258
259
|
const MAX_LOGGED_TEST_FILTERS = 6;
|
|
259
260
|
|
|
260
261
|
/** Platform runners own Kotlin/Swift execution; Bun must never receive their paths as test filters. */
|
|
@@ -289,6 +290,17 @@ export async function runIntegrityGate(
|
|
|
289
290
|
const runCmd = opts.runCmd ?? createRunCmd();
|
|
290
291
|
const results: GateStep[] = [];
|
|
291
292
|
const logs: string[] = [];
|
|
293
|
+
// A Pod worktree has no node_modules unless the child happened to install them (the Pod clone has none to link), and Bun
|
|
294
|
+
// then auto-installs at import time — «Unexpected while resolving package 'commander'» failed cli-smoke as an
|
|
295
|
+
// «environment deficiency» three times on 10-02 (#22849 · #22919). Install from the lockfile before measuring instead.
|
|
296
|
+
if (steps.length > 0 && existsSync(join(cwd, 'bin', 'elanous.mjs')) && existsSync(join(cwd, 'bun.lock'))
|
|
297
|
+
&& !existsSync(join(cwd, 'node_modules', 'commander', 'package.json'))) {
|
|
298
|
+
const install = await runCmd('bun', ['install', '--frozen-lockfile'], cwd, DEPENDENCY_INSTALL_TIMEOUT_MS);
|
|
299
|
+
const installed = install.code === 0 && !install.timedOut;
|
|
300
|
+
debug.log('gate.deps', 'install', { installed, code: install.code, timedOut: install.timedOut });
|
|
301
|
+
const tail = (install.stderr || install.stdout).split('\n').filter(Boolean).slice(-2).join(' | ').slice(0, 200);
|
|
302
|
+
logs.push(`[deps] ${installed ? 'INSTALLED' : 'FAIL'} bun install --frozen-lockfile — node_modules/commander was missing${installed ? '' : `: ${tail}`}`);
|
|
303
|
+
}
|
|
292
304
|
let passed = true;
|
|
293
305
|
let testPassCount: number | undefined;
|
|
294
306
|
let sawPassCountRegression = false;
|
|
@@ -9,6 +9,17 @@ import { join } from 'node:path';
|
|
|
9
9
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
10
10
|
import { runGitCommand } from '../../git-fs/runner.js';
|
|
11
11
|
import { countTestDeclarations } from '../../self-implement/test-declarations.js';
|
|
12
|
+
import { NEXT_MD_PATH, resolveNextMdConflict } from '../../release-loop/next-md-merge.js';
|
|
13
|
+
|
|
14
|
+
function deterministicNextMd(git: MergeGitSeam, worktreePath: string, file: string): string | null {
|
|
15
|
+
try {
|
|
16
|
+
const resolved = resolveNextMdConflict(git.readIndexStage(worktreePath, 1, file), git.readIndexStage(worktreePath, 2, file), git.readIndexStage(worktreePath, 3, file));
|
|
17
|
+
void import('../../debug/log.js').then(({ debug }) => debug.log('self-dev.merge', 'next-md-deterministic', { resolved: resolved !== null })).catch(() => {});
|
|
18
|
+
return resolved;
|
|
19
|
+
} catch {
|
|
20
|
+
return null; // a stage is missing (added/deleted on one side) — the usual resolver decides
|
|
21
|
+
}
|
|
22
|
+
}
|
|
12
23
|
|
|
13
24
|
/** 충돌 마커가 남아있나(LLM 이 해결 못 함 판별). ours/base/theirs 3-way 마커 모두. 순수. */
|
|
14
25
|
export function hasConflictMarkers(s: string): boolean {
|
|
@@ -130,8 +141,8 @@ export interface MergeGitSeam {
|
|
|
130
141
|
merge: (wt: string, mergeTarget: string) => { ok: boolean; conflict: boolean; stdout: string; errorDetail?: string };
|
|
131
142
|
/** 충돌(unmerged) 파일 목록(worktree 상대 경로). */
|
|
132
143
|
conflictedFiles: (wt: string) => string[];
|
|
133
|
-
/** Reads an unmerged index stage (2=ours, 3=theirs) for a conflicted file. */
|
|
134
|
-
readIndexStage: (wt: string, stage: 2 | 3, file: string) => string;
|
|
144
|
+
/** Reads an unmerged index stage (1=base, 2=ours, 3=theirs) for a conflicted file. */
|
|
145
|
+
readIndexStage: (wt: string, stage: 1 | 2 | 3, file: string) => string;
|
|
135
146
|
readFile: (absPath: string) => string;
|
|
136
147
|
writeFile: (absPath: string, content: string) => void;
|
|
137
148
|
/** 해결된 파일 스테이징. */
|
|
@@ -193,7 +204,9 @@ export async function mergeMainWithLlmResolve(
|
|
|
193
204
|
let merged: string;
|
|
194
205
|
try {
|
|
195
206
|
conflicted = git.readFile(abs);
|
|
196
|
-
|
|
207
|
+
// release/next.md: concurrent landings each append a line — keep both without asking the LLM (REL7c).
|
|
208
|
+
const deterministic = f === NEXT_MD_PATH ? deterministicNextMd(git, worktreePath, f) : null;
|
|
209
|
+
merged = deterministic ?? await resolve(f, conflicted);
|
|
197
210
|
} catch {
|
|
198
211
|
git.abort(worktreePath); // LLM 예외 → base 유지
|
|
199
212
|
return measuredOutcome({ status: 'conflict-unresolved', resolvedFiles });
|