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
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { resolve } from 'node:path/posix';
|
|
4
|
+
import ts from 'typescript';
|
|
5
|
+
import { isTestPath } from './importer-test-index.js';
|
|
6
|
+
|
|
7
|
+
export interface RouteConsumerTestIndex {
|
|
8
|
+
readonly testsBySource: ReadonlyMap<string, readonly string[]>;
|
|
9
|
+
/** Base routes could not be inspected for these sources; an empty match is not evidence of no consumers. */
|
|
10
|
+
readonly lookupFailures: readonly { readonly source: string; readonly reason: string }[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const ROUTE_RE = /^\/(?:v\d+|api)\/[^\s]+$/;
|
|
14
|
+
|
|
15
|
+
function dynamicRoutePattern(route: string): RegExp | null {
|
|
16
|
+
const segments = route.split('/').slice(1);
|
|
17
|
+
if (!segments.some((segment) => segment.startsWith(':') || segment === '*')) return null;
|
|
18
|
+
const pattern = segments.map((segment) => {
|
|
19
|
+
if (segment === '*') return '.*';
|
|
20
|
+
if (/^:[\w]+$/.test(segment)) return '[^/?#]+';
|
|
21
|
+
return segment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
22
|
+
}).join('/');
|
|
23
|
+
return new RegExp(`^/${pattern}(?:[?#].*)?$`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function testStringValues(text: string, path: string): string[] {
|
|
27
|
+
const ast = ts.createSourceFile(path, text, ts.ScriptTarget.Latest, false);
|
|
28
|
+
const values: string[] = [];
|
|
29
|
+
const visit = (node: ts.Node): void => {
|
|
30
|
+
if (ts.isStringLiteralLike(node)) values.push(node.text);
|
|
31
|
+
ts.forEachChild(node, visit);
|
|
32
|
+
};
|
|
33
|
+
visit(ast);
|
|
34
|
+
return values;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Index paths in both the current and comparison-base server source, so removing a route still selects its consumers. */
|
|
38
|
+
export function buildRouteConsumerTestIndex(
|
|
39
|
+
cwd: string,
|
|
40
|
+
testPaths: readonly string[],
|
|
41
|
+
changedSources: readonly string[],
|
|
42
|
+
baseRef = 'HEAD',
|
|
43
|
+
readBase: (source: string) => { text: string } | { absent: true } | { lookupFailed: string } = (source) => {
|
|
44
|
+
const options = { cwd, encoding: 'utf8' as const, timeout: 20_000, maxBuffer: 8 * 1024 * 1024 };
|
|
45
|
+
const result = spawnSync('git', ['show', `${baseRef}:${source}`], options);
|
|
46
|
+
if (result.status === 0 && !result.error) return { text: result.stdout };
|
|
47
|
+
const tree = spawnSync('git', ['ls-tree', '--name-only', baseRef, '--', source], options);
|
|
48
|
+
if (tree.status === 0 && !tree.error && !tree.stdout.trim()) return { absent: true };
|
|
49
|
+
return { lookupFailed: (result.stderr || result.error?.message || tree.stderr || tree.error?.message || 'git show failed').trim() };
|
|
50
|
+
},
|
|
51
|
+
/** Lines added/removed in the diff for `source`; null = diff unavailable (then every route in the file counts). */
|
|
52
|
+
changedLines: (source: string) => string[] | null = (source) => {
|
|
53
|
+
const r = spawnSync('git', ['diff', '-U0', baseRef, '--', source], { cwd, encoding: 'utf8' as const, timeout: 20_000, maxBuffer: 8 * 1024 * 1024 });
|
|
54
|
+
if (r.status !== 0 || r.error) return null;
|
|
55
|
+
// `git diff` omits untracked files — a new, not-yet-added server file is all new lines (every route counts).
|
|
56
|
+
if (!r.stdout.trim() && spawnSync('git', ['ls-files', '--error-unmatch', '--', source], { cwd, encoding: 'utf8' as const, timeout: 20_000, maxBuffer: 8 * 1024 * 1024 }).status !== 0) return null;
|
|
57
|
+
return r.stdout.split('\n').filter((line) => /^[+-](?![+-]{2})/.test(line)).map((line) => line.slice(1));
|
|
58
|
+
},
|
|
59
|
+
): RouteConsumerTestIndex {
|
|
60
|
+
const routesBySource = new Map<string, string[]>();
|
|
61
|
+
const lookupFailures: { source: string; reason: string }[] = [];
|
|
62
|
+
for (const source of changedSources) {
|
|
63
|
+
if (!source.startsWith('src/') || isTestPath(source) || !/\.[cm]?[jt]sx?$/.test(source)) continue;
|
|
64
|
+
const routes = new Set<string>();
|
|
65
|
+
const collect = (text: string): void => {
|
|
66
|
+
const ast = ts.createSourceFile(source, text, ts.ScriptTarget.Latest, false);
|
|
67
|
+
const visit = (node: ts.Node): void => {
|
|
68
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)
|
|
69
|
+
&& /^(get|post|put|patch|delete|route|register)$/.test(node.expression.name.text)) {
|
|
70
|
+
const path = node.arguments[0];
|
|
71
|
+
if (path && ts.isStringLiteralLike(path) && ROUTE_RE.test(path.text)) routes.add(path.text);
|
|
72
|
+
}
|
|
73
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken
|
|
74
|
+
&& /(?:pathname|path)$/.test(node.left.getText(ast)) && ts.isStringLiteralLike(node.right)
|
|
75
|
+
&& ROUTE_RE.test(node.right.text)) routes.add(node.right.text);
|
|
76
|
+
if (ts.isVariableDeclaration(node) && /(?:PATH|ROUTE)$/.test(node.name.getText(ast))
|
|
77
|
+
&& node.initializer && ts.isStringLiteralLike(node.initializer)
|
|
78
|
+
&& ROUTE_RE.test(node.initializer.text)) routes.add(node.initializer.text);
|
|
79
|
+
if (ts.isCaseClause(node) && ts.isStringLiteralLike(node.expression)
|
|
80
|
+
&& ROUTE_RE.test(node.expression.text)) routes.add(node.expression.text);
|
|
81
|
+
if (ts.isPropertyAssignment(node) && /^(path|route)$/.test(node.name.getText(ast))
|
|
82
|
+
&& ts.isStringLiteralLike(node.initializer) && ROUTE_RE.test(node.initializer.text)) routes.add(node.initializer.text);
|
|
83
|
+
ts.forEachChild(node, visit);
|
|
84
|
+
};
|
|
85
|
+
visit(ast);
|
|
86
|
+
};
|
|
87
|
+
try { collect(readFileSync(resolve(cwd, source), 'utf8')); } catch { /* Deleted source: base may still contain registered routes. */ }
|
|
88
|
+
try {
|
|
89
|
+
const previous = readBase(source);
|
|
90
|
+
if ('text' in previous) collect(previous.text);
|
|
91
|
+
else if ('lookupFailed' in previous) lookupFailures.push({ source, reason: previous.lookupFailed });
|
|
92
|
+
} catch (error) {
|
|
93
|
+
lookupFailures.push({ source, reason: error instanceof Error ? error.message : String(error) });
|
|
94
|
+
}
|
|
95
|
+
// A hub server file registers every route; only routes on lines the diff touched select consumers (TC review:
|
|
96
|
+
// http-server.ts alone matched 279 tests and the cap kept the alphabetically first 30). New/deleted files keep all routes.
|
|
97
|
+
const touched = changedLines(source);
|
|
98
|
+
const selected = touched === null ? [...routes] : [...routes].filter((route) => touched.some((line) => line.includes(route)));
|
|
99
|
+
if (selected.length) routesBySource.set(source, selected);
|
|
100
|
+
}
|
|
101
|
+
const testsBySource = new Map<string, string[]>();
|
|
102
|
+
if (routesBySource.size === 0) return { testsBySource, lookupFailures };
|
|
103
|
+
for (const test of testPaths) {
|
|
104
|
+
if (!isTestPath(test)) continue;
|
|
105
|
+
let text: string;
|
|
106
|
+
try { text = readFileSync(resolve(cwd, test), 'utf8'); } catch { continue; } // deleted test
|
|
107
|
+
const literalValues = testStringValues(text, test);
|
|
108
|
+
for (const [source, routes] of routesBySource) {
|
|
109
|
+
if (routes.some((route) => {
|
|
110
|
+
const dynamic = dynamicRoutePattern(route);
|
|
111
|
+
if (dynamic) return literalValues.some((value) => dynamic.test(value));
|
|
112
|
+
let at = text.indexOf(route);
|
|
113
|
+
while (at !== -1) {
|
|
114
|
+
if (!/[\w/-]/.test(text[at + route.length] ?? '')) return true;
|
|
115
|
+
at = text.indexOf(route, at + 1);
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
})) testsBySource.set(source, [...(testsBySource.get(source) ?? []), test]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return { testsBySource, lookupFailures };
|
|
122
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RunStatus = 'completed' | 'failed' | 'cancelled';
|
|
1
|
+
export type RunStatus = 'completed' | 'failed' | 'cancelled' | 'parked';
|
|
2
2
|
/** ⭐ `crashed` — ***잡히지 않은 예외로 죽어 종결을 스스로 못 적은*** 런 (2026-08-11 · 🅣⊕🅢 어휘 합의).
|
|
3
3
|
* ⛔ `aborted`(스스로 중단을 «판정»했다)와 다른 값이다 — 이쪽은 «판정할 겨를이 없었다».
|
|
4
4
|
* 📏 왜 생겼나: 실측 미완 57 중 ≈38 이 어느 원장에도 종결이 없었고, 멈춘 자리가 전부 「노드 안」이었다. */
|
|
@@ -20,7 +20,8 @@ export type SelfImplementStage =
|
|
|
20
20
|
| 'aborted'
|
|
21
21
|
| 'timed-out'
|
|
22
22
|
| 'pr-declined'
|
|
23
|
-
| 'soft-stopped'
|
|
23
|
+
| 'soft-stopped'
|
|
24
|
+
| 'parked';
|
|
24
25
|
|
|
25
26
|
const STAGE_OUTCOMES = {
|
|
26
27
|
merged: { runStatus: 'completed' },
|
|
@@ -34,9 +35,10 @@ const STAGE_OUTCOMES = {
|
|
|
34
35
|
'timed-out': { runStatus: 'failed', failureKind: 'timed-out' },
|
|
35
36
|
'pr-declined': { runStatus: 'cancelled' },
|
|
36
37
|
'soft-stopped': { runStatus: 'cancelled' },
|
|
38
|
+
parked: { runStatus: 'parked' },
|
|
37
39
|
} satisfies Record<SelfImplementStage, MappedRunOutcome>;
|
|
38
40
|
|
|
39
|
-
const RUN_STATUSES = new Set<RunStatus>(['completed', 'failed', 'cancelled']);
|
|
41
|
+
const RUN_STATUSES = new Set<RunStatus>(['completed', 'failed', 'cancelled', 'parked']);
|
|
40
42
|
|
|
41
43
|
/** Runtime guard for the run-status payload produced by observeRunOutcome. */
|
|
42
44
|
export function isRunStatus(value: unknown): value is RunStatus {
|
|
@@ -39,6 +39,7 @@ import { writeScopedTypecheckConfig } from './scoped-typecheck-config.js';
|
|
|
39
39
|
// ⭐ 게이트 스코프 근본 수리(2026-07-26) — 풀 `bun test` 폴백 제거 + 연관 테스트 유도(순수).
|
|
40
40
|
import { resolveGateScope } from './gate-scope.js';
|
|
41
41
|
import { buildImporterTestIndex, isTestPath } from './importer-test-index.js';
|
|
42
|
+
import { buildRouteConsumerTestIndex } from './route-consumer-test-index.js';
|
|
42
43
|
import { countTestDeclarations } from './test-declarations.js';
|
|
43
44
|
import {
|
|
44
45
|
allowsBaselineOnlyFailure,
|
|
@@ -75,6 +76,7 @@ import { tscEnv, assessTypecheckExecution, classifyTypecheckErrors, diffTypechec
|
|
|
75
76
|
import { nestCapReached, childNestEnv, nestInfo } from '../agent/nest-depth.js';
|
|
76
77
|
import { harnessBoundaryEnv, harnessBoundaryRequestsEnv, harnessBoundaryResponsesEnv, harnessSpaceEnv, getHarnessSpace, normalizeSpaceId, getHarnessRunId, resolveRunIdentity } from '../harness/harness-space.js';
|
|
77
78
|
import { debug } from '../debug/log.js';
|
|
79
|
+
import { RELEASE_PATH_HOLD_MARKER, RELEASE_PATH_LABEL, releasePathHoldShouldPost, releasePathHoldCommentsArgs, releasePrFilePaths } from '../self-dev/release-path-guard.js';
|
|
78
80
|
import { emitDecision } from '../live/detail-switch.js';
|
|
79
81
|
import { gateDecision, reviewDecision, mergeDecision } from './decision-events.js';
|
|
80
82
|
import { LogStore } from '../mss/logging/log-store.js';
|
|
@@ -85,7 +87,9 @@ import { countReflectFactConflicts, type MustFixRefutation, type ReflectEvidence
|
|
|
85
87
|
import { isSupervisorDecisionSection, splitGoalSections, supervisorGoalDigest } from './goal-digest.js';
|
|
86
88
|
import type { SupervisionReworkSource } from './supervision-vocabulary.js';
|
|
87
89
|
import type { ReworkBudgetVerdict } from './run-outcome.js';
|
|
88
|
-
import { runHeadlessGoalLoopPty } from './headless-elanous-driver.js';
|
|
90
|
+
import { pickImplementRoleForGoal, runHeadlessGoalLoopPty } from './headless-elanous-driver.js';
|
|
91
|
+
import { childLlmSelectionEnv } from '../agent/run-context.js';
|
|
92
|
+
import { observeExternalEvent } from '../context-bus/external-events.js';
|
|
89
93
|
import { buildLlmHitlRelay, SIDE_EFFECT_RE } from '../harness/llm-hitl-relay.js';
|
|
90
94
|
import { dispatchAskUserQuestion } from '../ask-user-question/tool.js';
|
|
91
95
|
import { parseQuestionRequest } from '../ask-user-question/types.js';
|
|
@@ -1641,7 +1645,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1641
1645
|
if ((o.ptyAvailable ?? ptyAvailable)()) {
|
|
1642
1646
|
try {
|
|
1643
1647
|
const res = await (o.runHeadlessGoalLoopPty ?? runHeadlessGoalLoopPty)({
|
|
1644
|
-
binRoot, cwd, featurePrompt: prompt, maxWaitSec, brain,
|
|
1648
|
+
binRoot, cwd, featurePrompt: prompt, goalDocument: feature, maxWaitSec, brain,
|
|
1645
1649
|
...(activityGraceSec !== undefined ? { activityGraceSec, activityGraceSource: 'caller' as const } : {}),
|
|
1646
1650
|
autoStop: getUserConfig().tools.selfImplement.autoStop,
|
|
1647
1651
|
autoAssist: getUserConfig().tools.selfImplement.autoAssist,
|
|
@@ -1698,9 +1702,14 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1698
1702
|
// 폴백 — PTY 불가/cap 초과/에러. 기존 헤드리스 spawnSync 경로 보존(블로킹이지만 견고).
|
|
1699
1703
|
const args = [`${binRoot}/bin/elanous.mjs`, 'dev', '--implement'];
|
|
1700
1704
|
const executionId = randomUUID();
|
|
1705
|
+
const fallbackImplementRole = !childLlm && !process.env.ELANOUS_LLM_MODEL?.trim()
|
|
1706
|
+
? pickImplementRoleForGoal(feature) : undefined;
|
|
1701
1707
|
if (o.configDir) args.push('--config-dir', o.configDir);
|
|
1702
1708
|
args.push(prompt);
|
|
1703
|
-
const
|
|
1709
|
+
const fallbackSource = `elanous://harness/${encodeURIComponent(runId ?? 'unknown')}/${encodeURIComponent(executionId)}`;
|
|
1710
|
+
observeExternalEvent({ origin: 'harness-child', kind: 'started', summary: 'Harness child started (fallback)', source: fallbackSource });
|
|
1711
|
+
let r: ReturnType<typeof runSpawnSync>;
|
|
1712
|
+
try { r = runSpawnSync('bun', args, {
|
|
1704
1713
|
cwd, encoding: 'utf8', timeout: maxWaitSec * 1000, maxBuffer: 32 * 1024 * 1024,
|
|
1705
1714
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
1706
1715
|
...(executionSignal ? { signal: executionSignal } : {}), // /cancel 또는 구현 timeout → 자식 SIGTERM(고아 방지)
|
|
@@ -1716,6 +1725,9 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1716
1725
|
// ⇒ 실물: 쿼터 신호가 갱신 안 되는 우주를 봐서 전 계정 unknown ⇒ 회전이 100% 계정 선택 ⇒ 429(4회).
|
|
1717
1726
|
...(o.stateDir && o.stateDirSource ? { ELANOUS_STATE_DIR_SOURCE: o.stateDirSource } : {}),
|
|
1718
1727
|
...childNestEnv(),
|
|
1728
|
+
...childLlmSelectionEnv(childLlm ?? (fallbackImplementRole
|
|
1729
|
+
? { provider: fallbackImplementRole.provider, model: fallbackImplementRole.model, source: 'config' }
|
|
1730
|
+
: undefined)),
|
|
1719
1731
|
...((): Record<string, string> => {
|
|
1720
1732
|
const sp = getHarnessSpace() ?? { inHarness: true as const, kind: 'self-implement' as const, id: normalizeSpaceId(basename(cwd)), runId: getHarnessRunId() };
|
|
1721
1733
|
// ★ K run-identity 공백 방어 — driver 와 동일 계약(호출자 > 상속 > canonical mint). 빈 runId 는
|
|
@@ -1727,7 +1739,12 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1727
1739
|
...harnessBoundaryResponsesEnv(executionId),
|
|
1728
1740
|
...harnessPolicyEnv(),
|
|
1729
1741
|
},
|
|
1730
|
-
});
|
|
1742
|
+
}); } catch (error) {
|
|
1743
|
+
observeExternalEvent({ origin: 'harness-child', kind: 'finished', summary: 'Harness child failed (fallback)', source: fallbackSource });
|
|
1744
|
+
throw error;
|
|
1745
|
+
}
|
|
1746
|
+
observeExternalEvent({ origin: 'harness-child', kind: 'finished',
|
|
1747
|
+
summary: `Harness child finished (fallback): ${r.status ?? 'unknown'}`, source: fallbackSource });
|
|
1731
1748
|
const transcript = `${r.stdout ?? ''}${r.stderr ?? ''}`;
|
|
1732
1749
|
const errCode = (r.error as { code?: string } | undefined)?.code;
|
|
1733
1750
|
const timedOut = errCode === 'ETIMEDOUT' || r.signal === 'SIGTERM';
|
|
@@ -1807,9 +1824,11 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1807
1824
|
trackedFiles.filter(isTestPath),
|
|
1808
1825
|
[...new Set([...trackedFiles, ...changedAll, ...observationChangedFiles])].filter((file) => /\.(?:[cm]?[jt]sx?)$/.test(file)),
|
|
1809
1826
|
);
|
|
1827
|
+
const routeConsumerTestIndex = buildRouteConsumerTestIndex(cwd, trackedFiles.filter(isTestPath), changedAll, comparisonBase ?? 'HEAD');
|
|
1810
1828
|
// 워크트리에 없는 변경 경로 = 지운 파일 — 미검증으로 세지 않는다(gate-scope `isDeleted` · 2026-09-26 run-7dd4cce6).
|
|
1811
1829
|
const isDeleted = (path: string): boolean => !isFile(path);
|
|
1812
|
-
const
|
|
1830
|
+
const scopeOpts = { isDeleted, routeConsumerTestIndex: routeConsumerTestIndex ?? undefined };
|
|
1831
|
+
const scope = resolveGateScope(changedAll, isFile, importerTestIndex ?? undefined, postsync ? { ...scopeOpts, mode: 'postsync' } : scopeOpts);
|
|
1813
1832
|
const comparisonFailureReason = observationChanges.comparisonBaseStatus === 'unavailable'
|
|
1814
1833
|
? 'comparison-base-unavailable'
|
|
1815
1834
|
: observationChanges.comparisonBaseStatus === 'comparison-failed'
|
|
@@ -1817,10 +1836,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1817
1836
|
: undefined;
|
|
1818
1837
|
const unmeasuredPostsync = postsync && !comparisonFailureReason && scope.reason === 'unmeasured';
|
|
1819
1838
|
const scopeReason = comparisonFailureReason ?? scope.reason;
|
|
1820
|
-
const
|
|
1821
|
-
const observedChangedTestFiles = observationScope.reason === 'changed-tests'
|
|
1822
|
-
? (observationScope.testArgs ?? []).filter((file) => !observationScope.pulledInRelatedTests.includes(file))
|
|
1823
|
-
: [];
|
|
1839
|
+
const observedChangedTestFiles = [...new Set(observationChangedFiles.filter((file) => isTestPath(file) && isFile(file)))];
|
|
1824
1840
|
// This reads the merge-base without executing base tests. Its static declaration count is
|
|
1825
1841
|
// observational: dynamic generation and renamed helpers can make it incomplete.
|
|
1826
1842
|
const declarationDecline = testDeclarationDecline(cwd, comparisonBase, observedChangedTestFiles);
|
|
@@ -1863,6 +1879,9 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1863
1879
|
documentPaths: scope.documentPaths.slice(0, 8), documentPathCount: scope.documentPaths.length,
|
|
1864
1880
|
documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests.slice(0, 8),
|
|
1865
1881
|
documentsWithoutDerivedTestCount: scope.documentsWithoutDerivedTests.length,
|
|
1882
|
+
callerTests: scope.callerTests,
|
|
1883
|
+
callerTestsOverflow: scope.callerTestsOverflow,
|
|
1884
|
+
routeBaseLookupFailures: routeConsumerTestIndex.lookupFailures,
|
|
1866
1885
|
pulledInRelatedTests: scope.pulledInRelatedTests.slice(0, 8),
|
|
1867
1886
|
pulledInRelatedTestCount: scope.pulledInRelatedTests.length,
|
|
1868
1887
|
importerTestIndexAvailable: importerTestIndex !== null,
|
|
@@ -1871,7 +1890,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
1871
1890
|
importerTestsNotRunTruncated: scope.importerTestsNotRun?.truncated ?? null,
|
|
1872
1891
|
unresolvedRelativeImportSpecifiers: scope.importerTestsNotRun?.unresolvedRelativeSpecifiers ?? null,
|
|
1873
1892
|
// ⚠️ 커버 안 된 변경이 있으면 **테스트가 돌았어도** warn — debug 는 운영 로그에서 필터링된다(리뷰 should-fix).
|
|
1874
|
-
}, { level: scope.reason === 'no-related-tests' || scope.missingTestFiles > 0 || scope.unverified.length > 0 ? 'warn' : 'debug' });
|
|
1893
|
+
}, { level: scope.reason === 'no-related-tests' || scope.missingTestFiles > 0 || scope.unverified.length > 0 || scope.callerTestsOverflow.length > 0 || routeConsumerTestIndex.lookupFailures.length > 0 ? 'warn' : 'debug' });
|
|
1875
1894
|
try { emitDecision(gateDecision({ runId: ctx?.runId, reason: scopeReason, testStepSkipped })); } catch { /* observation must not change the gate result */ }
|
|
1876
1895
|
// `defaultSeams.gate` owns the changed-file list and runs before the test-step skip,
|
|
1877
1896
|
// so platform-only changes remain measured even when gate-scope has no Bun filters.
|
|
@@ -2174,6 +2193,12 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
2174
2193
|
+ `${scope.pulledInRelatedTests.slice(0, 8).join(', ')}`
|
|
2175
2194
|
+ `\n(편집된 테스트만 돌렸다면 이것들이 빠졌다)`
|
|
2176
2195
|
: '';
|
|
2196
|
+
const callerOverflowNote = scope.callerTestsOverflow.length > 0
|
|
2197
|
+
? `\n\n[gate-scope] ⚠️ caller test cap exceeded — not run: ${scope.callerTestsOverflow.map(({ file, reasons }) => `${file} (${reasons.join('+')})`).join(', ')}`
|
|
2198
|
+
: '';
|
|
2199
|
+
const routeLookupNote = routeConsumerTestIndex.lookupFailures.length > 0
|
|
2200
|
+
? `\n\n[gate-scope] ⚠️ caller route base lookup failed — unmeasured: ${routeConsumerTestIndex.lookupFailures.map(({ source, reason }) => `${source} (${reason})`).join(', ')}`
|
|
2201
|
+
: '';
|
|
2177
2202
|
const scopeNote = testStepSkipped
|
|
2178
2203
|
? `\n\n[gate-scope] ${scope.reason} — test 스텝을 건너뛰었다(변경파일 tsc 만 검증). `
|
|
2179
2204
|
+ (scope.reason === 'no-related-tests'
|
|
@@ -2204,7 +2229,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
2204
2229
|
: '';
|
|
2205
2230
|
return {
|
|
2206
2231
|
passed: gatePassed,
|
|
2207
|
-
log: `${baseLog}${policyFailureLog}${dependencyFailureLog}${dependencyUnmeasuredNote}${comparisonFailureLog}${baselineNote}${verifyByBreakingNote}${scopeNote}${uncoveredNote}${pulledInRelatedTestsNote}`,
|
|
2232
|
+
log: `${baseLog}${policyFailureLog}${dependencyFailureLog}${dependencyUnmeasuredNote}${comparisonFailureLog}${baselineNote}${verifyByBreakingNote}${scopeNote}${uncoveredNote}${pulledInRelatedTestsNote}${callerOverflowNote}${routeLookupNote}`,
|
|
2208
2233
|
testStepExecuted: !testStepSkipped && testStep !== undefined && !testStep.skipped,
|
|
2209
2234
|
scopeReason,
|
|
2210
2235
|
comparisonBaseStatus: observationChanges.comparisonBaseStatus,
|
|
@@ -2349,11 +2374,47 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
|
|
|
2349
2374
|
postPrComment: async ({ number, body, cwd }) => {
|
|
2350
2375
|
// Round comments go out as the GitHub App like the PR itself — a personal `gh` login made the owner a
|
|
2351
2376
|
// participant and mailed them on merge (#22089).
|
|
2377
|
+
if (body.startsWith(RELEASE_PATH_HOLD_MARKER)) {
|
|
2378
|
+
// Several merge surfaces may hold the same PR; post the release-path hold comment once.
|
|
2379
|
+
let history: unknown;
|
|
2380
|
+
try {
|
|
2381
|
+
history = JSON.parse((await execFileAsync('gh', releasePathHoldCommentsArgs(number), {
|
|
2382
|
+
cwd, encoding: 'utf8', timeout: GIT_TIMEOUT, maxBuffer: 64 * 1024 * 1024, env: ghAutomationEnv(process.env),
|
|
2383
|
+
})).stdout);
|
|
2384
|
+
} catch { history = undefined; }
|
|
2385
|
+
if (!releasePathHoldShouldPost(() => history)) return;
|
|
2386
|
+
}
|
|
2352
2387
|
await execFileAsync('gh', ['pr', 'comment', String(number), '--body', body], {
|
|
2353
2388
|
cwd, encoding: 'utf8', timeout: GIT_TIMEOUT, maxBuffer: 64 * 1024 * 1024, env: ghAutomationEnv(process.env),
|
|
2354
2389
|
});
|
|
2355
2390
|
},
|
|
2356
2391
|
|
|
2392
|
+
addPrLabel: async ({ number, label, cwd }) => {
|
|
2393
|
+
if (label === RELEASE_PATH_LABEL) {
|
|
2394
|
+
const existing = await execFileAsync('gh', ['label', 'list', '--search', label, '--json', 'name'], {
|
|
2395
|
+
cwd, encoding: 'utf8', timeout: GIT_TIMEOUT, env: ghAutomationEnv(process.env),
|
|
2396
|
+
});
|
|
2397
|
+
const names: unknown = JSON.parse(existing.stdout);
|
|
2398
|
+
if (!Array.isArray(names)) throw new Error('gh label list returned an invalid list');
|
|
2399
|
+
if (!names.some((item: unknown) => !!item && typeof item === 'object' && 'name' in item && item.name === label)) {
|
|
2400
|
+
await execFileAsync('gh', ['label', 'create', label, '--color', 'D93F0B', '--description', 'Release path requires OP approval'], {
|
|
2401
|
+
cwd, encoding: 'utf8', timeout: GIT_TIMEOUT, env: ghAutomationEnv(process.env),
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
await execFileAsync('gh', ['pr', 'edit', String(number), '--add-label', label], {
|
|
2406
|
+
cwd, encoding: 'utf8', timeout: GIT_TIMEOUT, env: ghAutomationEnv(process.env),
|
|
2407
|
+
});
|
|
2408
|
+
},
|
|
2409
|
+
readPrFiles: async ({ number, cwd }) => {
|
|
2410
|
+
// Paginate the PR file API: a single `gh pr view --json files` can omit files after the first page.
|
|
2411
|
+
const { stdout } = await execFileAsync('gh', [
|
|
2412
|
+
'api', '--paginate', '--slurp', '--method', 'GET', '-f', 'per_page=100',
|
|
2413
|
+
`repos/{owner}/{repo}/pulls/${number}/files`,
|
|
2414
|
+
], { cwd, encoding: 'utf8', timeout: GIT_TIMEOUT, maxBuffer: 64 * 1024 * 1024, env: ghAutomationEnv(process.env) });
|
|
2415
|
+
return releasePrFilePaths(JSON.parse(stdout));
|
|
2416
|
+
},
|
|
2417
|
+
|
|
2357
2418
|
...(o.approvePr ? { approvePr: o.approvePr } : {}),
|
|
2358
2419
|
|
|
2359
2420
|
// ★ 내부 리뷰(2026-07-21·review-gated merge) — worktree diff → reviewPullRequest(agent-substrate·미션/
|
|
@@ -32,6 +32,7 @@ export function seams(over: Partial<SelfImplementSeams> & { gateResults?: boolea
|
|
|
32
32
|
defaultBranchRef: () => 'origin/main',
|
|
33
33
|
mergeMain: async () => ({ status: 'up-to-date' }),
|
|
34
34
|
openPr: async ({ head }) => ({ url: `https://pr/${head}`, number: 7 }),
|
|
35
|
+
readPrFiles: async () => ['src/ordinary.ts'],
|
|
35
36
|
readPrDiff: async () => '',
|
|
36
37
|
readPrCommitShas: async () => ({ baseCommit: 'base-sha', headCommit: 'checked-head-sha' }),
|
|
37
38
|
approvePr: async () => true,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { isElanousRuntimeArtifactPath } from './gate-scope.js';
|
|
3
|
+
|
|
4
|
+
export type UncommittedWork =
|
|
5
|
+
| { status: 'clean'; trackedChanges: string[]; untrackedFiles: string[] }
|
|
6
|
+
| { status: 'changes'; trackedChanges: string[]; untrackedFiles: string[] }
|
|
7
|
+
| { status: 'unavailable'; reason: string };
|
|
8
|
+
|
|
9
|
+
/** Observe the index and working tree without staging, refreshing, or changing any files. */
|
|
10
|
+
export function detectUncommittedWork(worktree: string): UncommittedWork {
|
|
11
|
+
const gitEnv = { ...process.env };
|
|
12
|
+
for (const key of Object.keys(gitEnv)) {
|
|
13
|
+
if (key.startsWith('GIT_')) delete gitEnv[key];
|
|
14
|
+
}
|
|
15
|
+
let result: ReturnType<typeof spawnSync>;
|
|
16
|
+
try {
|
|
17
|
+
result = spawnSync('git', ['--no-optional-locks', 'status', '--porcelain=v1', '-z', '--untracked-files=all'], {
|
|
18
|
+
cwd: worktree,
|
|
19
|
+
env: gitEnv,
|
|
20
|
+
encoding: 'utf8',
|
|
21
|
+
timeout: 10_000,
|
|
22
|
+
});
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return { status: 'unavailable', reason: error instanceof Error ? error.message : String(error) };
|
|
25
|
+
}
|
|
26
|
+
if (result.error || result.status !== 0 || typeof result.stdout !== 'string') {
|
|
27
|
+
const stderr = typeof result.stderr === 'string' ? result.stderr.trim() : '';
|
|
28
|
+
return { status: 'unavailable', reason: result.error?.message || stderr || 'git status failed' };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const trackedChanges = new Set<string>();
|
|
32
|
+
const untrackedFiles = new Set<string>();
|
|
33
|
+
const entries = result.stdout.split('\0');
|
|
34
|
+
if (entries.at(-1) !== '') return { status: 'unavailable', reason: 'incomplete git status output' };
|
|
35
|
+
entries.pop();
|
|
36
|
+
for (let i = 0; i < entries.length; i += 1) {
|
|
37
|
+
const entry = entries[i]!;
|
|
38
|
+
if (entry.length < 4 || entry[2] !== ' ') return { status: 'unavailable', reason: 'invalid git status output' };
|
|
39
|
+
const kind = entry.slice(0, 2);
|
|
40
|
+
const path = entry.slice(3);
|
|
41
|
+
if (!path) return { status: 'unavailable', reason: 'invalid git status path' };
|
|
42
|
+
if (kind === '??') {
|
|
43
|
+
if (!isElanousRuntimeArtifactPath(path) && path !== '.elanous-test' && !path.startsWith('.elanous-test/')
|
|
44
|
+
&& path !== '.elanous-skill-artifacts' && !path.startsWith('.elanous-skill-artifacts/')) {
|
|
45
|
+
untrackedFiles.add(path);
|
|
46
|
+
}
|
|
47
|
+
} else if (kind !== '!!') {
|
|
48
|
+
trackedChanges.add(path);
|
|
49
|
+
if (kind.includes('R') || kind.includes('C')) {
|
|
50
|
+
const original = entries[++i];
|
|
51
|
+
if (!original) return { status: 'unavailable', reason: 'incomplete git rename/copy output' };
|
|
52
|
+
if (kind.includes('R')) trackedChanges.add(original);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return trackedChanges.size || untrackedFiles.size
|
|
57
|
+
? { status: 'changes', trackedChanges: [...trackedChanges], untrackedFiles: [...untrackedFiles] }
|
|
58
|
+
: { status: 'clean', trackedChanges: [], untrackedFiles: [] };
|
|
59
|
+
}
|
package/src/session/chat.ts
CHANGED
|
@@ -109,6 +109,8 @@ export interface RunTurnOpts {
|
|
|
109
109
|
* delegated coding agent's approval prompts back to the originating
|
|
110
110
|
* chat via `delegate_code_agent`. */
|
|
111
111
|
hitlConfirmChannel?: import('../hitl/confirm.js').ConfirmChannel;
|
|
112
|
+
/** Verified by the hosting bot from the inbound user id against its server-side owner allowlist. */
|
|
113
|
+
verifiedOwner?: { id: string };
|
|
112
114
|
/** Paired multi-option question channel (Telegram sets this). Surface
|
|
113
115
|
* runTurnImpls thread it into `delegate_code_agent` so a delegated
|
|
114
116
|
* agent's structured questions render as option buttons in the
|
package/src/session/index.ts
CHANGED
|
@@ -202,6 +202,8 @@ export interface SessionMeta {
|
|
|
202
202
|
* 아님). ~/.elanous 공유 스토어 세션은 전부 'prod'. append 는 이 값을 보존(생성자 귀속).
|
|
203
203
|
* 구 세션엔 부재(tolerant read) — 미상 = 필터 비매치. */
|
|
204
204
|
originInstance?: string;
|
|
205
|
+
/** Project association, omitted for sessions without an assigned project (including legacy records). */
|
|
206
|
+
projectId?: string;
|
|
205
207
|
/** For telegram-sourced sessions; undefined for cli. */
|
|
206
208
|
tgChatId?: number;
|
|
207
209
|
tgThreadId?: number;
|
|
@@ -383,6 +385,7 @@ export interface CreateSessionOpts {
|
|
|
383
385
|
tgBotId?: string;
|
|
384
386
|
/** Stable identity for a persona's resident conversation. */
|
|
385
387
|
personaId?: string;
|
|
388
|
+
projectId?: string;
|
|
386
389
|
title?: string;
|
|
387
390
|
/** 표면 origin(cli/pwa/tg/dc/harness) — source 유니온 밖의 세밀 라벨(PWA 챗 구분용). */
|
|
388
391
|
origin?: string;
|
|
@@ -450,6 +453,33 @@ function writeIndex(entries: SessionMeta[], root: string = sessionRoot(), remove
|
|
|
450
453
|
});
|
|
451
454
|
}
|
|
452
455
|
|
|
456
|
+
/** 세션 메타 하나를 잠금 «안에서» 디스크의 최신 목록 위에 고쳐 쓴다(IA1b).
|
|
457
|
+
* `appendMessage` 가 잠금 밖에서 읽은 목록을 통째로 쓰면, 그 사이 다른 프로세스가 바꾼
|
|
458
|
+
* 같은 세션의 `projectId`·`messageCount` 를 옛 값으로 덮었다. 없는 id 면 `null`. */
|
|
459
|
+
export function updateSessionMeta(
|
|
460
|
+
id: string,
|
|
461
|
+
mutate: (meta: SessionMeta) => void,
|
|
462
|
+
root: string = sessionRoot(),
|
|
463
|
+
opts: { bubble?: boolean } = {},
|
|
464
|
+
): SessionMeta | null {
|
|
465
|
+
ensureRoots(root);
|
|
466
|
+
const p = indexPath(root);
|
|
467
|
+
return withDirLock(join(root, '.index.lock'), INDEX_LOCK_TIMEOUT_MS, () => {
|
|
468
|
+
const idx = readIndex(root);
|
|
469
|
+
const pos = idx.findIndex((m) => m.id === id);
|
|
470
|
+
if (pos < 0) return null;
|
|
471
|
+
const meta = { ...idx[pos] };
|
|
472
|
+
mutate(meta);
|
|
473
|
+
idx.splice(pos, 1);
|
|
474
|
+
if (opts.bubble) idx.unshift(meta);
|
|
475
|
+
else idx.splice(pos, 0, meta);
|
|
476
|
+
const tmp = `${p}.${process.pid}.${randomUUID().slice(0, 8)}.tmp`;
|
|
477
|
+
writeFileSync(tmp, JSON.stringify(idx, null, 2) + '\n', 'utf-8');
|
|
478
|
+
renameSync(tmp, p);
|
|
479
|
+
return meta;
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
453
483
|
// ── Tier 1 Phase 3 — listener primitive ──────────────────────────────
|
|
454
484
|
//
|
|
455
485
|
// Channel-agnostic subscribe API the daemon-mirror module (PR 2) hooks
|
|
@@ -534,6 +564,7 @@ export function createSession(opts: CreateSessionOpts = {}, root: string = sessi
|
|
|
534
564
|
tgThreadId: opts.tgThreadId,
|
|
535
565
|
...(opts.tgBotId ? { tgBotId: opts.tgBotId } : {}),
|
|
536
566
|
...(opts.personaId ? { personaId: opts.personaId } : {}),
|
|
567
|
+
...(opts.projectId !== undefined ? { projectId: opts.projectId } : {}),
|
|
537
568
|
tgSessionKey,
|
|
538
569
|
};
|
|
539
570
|
writeFileSync(sessionFile(id, root), '', 'utf-8');
|
|
@@ -575,6 +606,7 @@ export function adoptSession(id: string, opts: CreateSessionOpts = {}, root: str
|
|
|
575
606
|
sourceKind: opts.sourceKind ?? defaultSessionSourceKind(source),
|
|
576
607
|
...(opts.forkedFromId ? { forkedFromId: opts.forkedFromId } : {}),
|
|
577
608
|
...(origin ? { origin } : {}),
|
|
609
|
+
...(opts.projectId !== undefined ? { projectId: opts.projectId } : {}),
|
|
578
610
|
originInstance: resolveInstanceName(),
|
|
579
611
|
...(opts.tgChatId != null ? { tgChatId: opts.tgChatId } : {}),
|
|
580
612
|
...(opts.tgThreadId != null ? { tgThreadId: opts.tgThreadId } : {}),
|
|
@@ -601,6 +633,7 @@ export function forkSessionFromHistory(
|
|
|
601
633
|
tgThreadId: opts.tgThreadId,
|
|
602
634
|
title: opts.title,
|
|
603
635
|
origin: opts.origin,
|
|
636
|
+
projectId: opts.projectId,
|
|
604
637
|
}, root);
|
|
605
638
|
for (const msg of opts.messages) {
|
|
606
639
|
const content = typeof msg.content === 'string' ? msg.content : '';
|
|
@@ -627,20 +660,16 @@ export function appendMessage(id: string, msg: SerializedMessage, root: string =
|
|
|
627
660
|
const line = JSON.stringify(enriched) + '\n';
|
|
628
661
|
appendFileSync(file, line, 'utf-8');
|
|
629
662
|
|
|
630
|
-
const idx = readIndex(root);
|
|
631
|
-
const pos = idx.findIndex(m => m.id === id);
|
|
632
|
-
if (pos < 0) throw new Error(`session missing from index: ${id}`);
|
|
633
|
-
const meta = idx[pos];
|
|
634
|
-
meta.updatedAt = msg.ts || new Date().toISOString();
|
|
635
|
-
meta.messageCount = meta.messageCount + 1;
|
|
636
|
-
// Auto-title on first user message.
|
|
637
|
-
if (meta.title === '(new session)' && msg.role === 'user' && msg.content) {
|
|
638
|
-
meta.title = msg.content.replace(/\s+/g, ' ').slice(0, 60).trim() || '(empty)';
|
|
639
|
-
}
|
|
640
663
|
// Bubble to front of index so listSessions returns newest-first.
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
664
|
+
const meta = updateSessionMeta(id, (m) => {
|
|
665
|
+
m.updatedAt = msg.ts || new Date().toISOString();
|
|
666
|
+
m.messageCount = m.messageCount + 1;
|
|
667
|
+
// Auto-title on first user message.
|
|
668
|
+
if (m.title === '(new session)' && msg.role === 'user' && msg.content) {
|
|
669
|
+
m.title = msg.content.replace(/\s+/g, ' ').slice(0, 60).trim() || '(empty)';
|
|
670
|
+
}
|
|
671
|
+
}, root, { bubble: true });
|
|
672
|
+
if (!meta) throw new Error(`session missing from index: ${id}`);
|
|
644
673
|
// Tier 1 Phase 3 — fire AFTER on-disk write + index update.
|
|
645
674
|
// Listeners (daemon-mirror) read the just-appended message + meta
|
|
646
675
|
// from a consistent state.
|
|
@@ -738,6 +767,8 @@ export interface ListSessionsOpts {
|
|
|
738
767
|
tgThreadId?: number;
|
|
739
768
|
/** 생성 인스턴스 정확 일치(prod · test:<repo> …). 구 세션(부재)은 비매치. */
|
|
740
769
|
originInstance?: string;
|
|
770
|
+
/** Project id exact match; sessions without the field do not match. */
|
|
771
|
+
projectId?: string;
|
|
741
772
|
/** 표면 origin 정확 일치(cli | pwa | tg | dc | harness). */
|
|
742
773
|
origin?: string;
|
|
743
774
|
/** 제외할 origin(들) — 예: ['harness'] 로 하니스 자식 세션을 사용자 대화 목록에서 숨김. */
|
|
@@ -774,6 +805,7 @@ export function listSessions(opts: ListSessionsOpts = {}, root: string = session
|
|
|
774
805
|
idx = idx.filter(m => !m.sourceKind || !opts.excludeSourceKinds!.includes(m.sourceKind));
|
|
775
806
|
}
|
|
776
807
|
if (opts.originInstance) idx = idx.filter(m => m.originInstance === opts.originInstance);
|
|
808
|
+
if (opts.projectId !== undefined) idx = idx.filter(m => m.projectId === opts.projectId);
|
|
777
809
|
if (opts.origin) idx = idx.filter(m => m.origin === opts.origin);
|
|
778
810
|
if (opts.excludeOrigins && opts.excludeOrigins.length > 0) {
|
|
779
811
|
idx = idx.filter((m) => {
|
|
@@ -210,6 +210,23 @@ export function capturedEnvAvailable(): boolean {
|
|
|
210
210
|
return captured && cached !== null;
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
/** Append login-shell PATH entries to the target without replacing its existing environment. */
|
|
214
|
+
export function mergeCapturedPath(target: NodeJS.ProcessEnv = process.env, opts: { capture?: boolean } = {}): number {
|
|
215
|
+
// capture: 아직 캡처 전이면 여기서 한 번 캡처한다(호출부가 getCapturedEnv 를 직접 부르지 않게 — identity-env 래칫).
|
|
216
|
+
const capturedPath = opts.capture || capturedEnvAvailable() ? getCapturedEnv().PATH : undefined;
|
|
217
|
+
const seen = new Set((target.PATH ?? '').split(':'));
|
|
218
|
+
const missing: string[] = [];
|
|
219
|
+
for (const entry of capturedPath?.split(':') ?? []) {
|
|
220
|
+
if (!entry || seen.has(entry)) continue;
|
|
221
|
+
missing.push(entry);
|
|
222
|
+
seen.add(entry);
|
|
223
|
+
}
|
|
224
|
+
if (missing.length) target.PATH = target.PATH ? `${target.PATH}:${missing.join(':')}` : missing.join(':');
|
|
225
|
+
const added = missing.length;
|
|
226
|
+
debug.log('shell.envbootstrap.capture', 'path-merged', { added });
|
|
227
|
+
return added;
|
|
228
|
+
}
|
|
229
|
+
|
|
213
230
|
/** Reset cache — test seam. */
|
|
214
231
|
export function resetCapturedEnvForTesting(): void {
|
|
215
232
|
cached = null;
|