@iowarp/clio-coder 0.3.0 → 0.3.2
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/CHANGELOG.md +123 -2
- package/CONTRIBUTING.md +23 -23
- package/README.md +295 -627
- package/dist/acp-BIYHVZIM.js +128 -0
- package/dist/{agents-Q4MYPMUW.js → agents-YT6SSRIT.js} +52 -27
- package/dist/assets/codewiki.json +1 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
- package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
- package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter.wasm +0 -0
- package/dist/{auth-O6HYIJ6J.js → auth-5TWEIYDN.js} +30 -15
- package/dist/chunk-2EHAIA3X.js +481 -0
- package/dist/{chunk-ME6DNWIU.js → chunk-2IR2NMPA.js} +12 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-3I7MS7N2.js +40 -0
- package/dist/chunk-3R73A4XB.js +69 -0
- package/dist/{chunk-JPOWPFCU.js → chunk-3ZXDFGR5.js} +52 -23
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-26BZQOAD.js → chunk-4BPJXDWC.js} +161 -260
- package/dist/chunk-4KLWL3UC.js +18 -0
- package/dist/{chunk-5LDRNKX2.js → chunk-4VP4KH3K.js} +161 -262
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/chunk-5TSRNF4G.js +510 -0
- package/dist/{chunk-WD6AJM35.js → chunk-5UUP6MWO.js} +48 -69
- package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6EJV5X2W.js +16405 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/{chunk-XNISANGE.js → chunk-77VKQEHF.js} +171 -74
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/{chunk-UWIJNAOB.js → chunk-7EYHLWU7.js} +907 -638
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-JWHCJDCI.js → chunk-A3CYT5EX.js} +257 -79
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/chunk-AO4RKG4M.js +277 -0
- package/dist/chunk-APJ265NV.js +7410 -0
- package/dist/chunk-ARBGF5F7.js +174 -0
- package/dist/{chunk-TFSSEXL6.js → chunk-BMEMKKIT.js} +14 -4
- package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/{chunk-67MTHP2E.js → chunk-ED4KHGC3.js} +13 -5
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/{chunk-O4EJEDHO.js → chunk-EPVUXGXG.js} +50 -35
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G2DE3C7R.js +644 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-7BHLZB3A.js → chunk-GGXXDWE4.js} +190 -1218
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-E3NYWENM.js → chunk-HFSBBKSQ.js} +55 -61
- package/dist/chunk-HKIYEGME.js +30 -0
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IGLFWIYI.js +161 -0
- package/dist/chunk-IHXBNWMM.js +137 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
- package/dist/{chunk-VOO7NYPP.js → chunk-J5HN4RYU.js} +27 -9
- package/dist/{chunk-4UQA7NCT.js → chunk-J5Q24KAG.js} +7 -2
- package/dist/{chunk-KBR4MZZR.js → chunk-JVCV3ICN.js} +7 -1
- package/dist/chunk-KJ5LWLOE.js +1077 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-3DANZDGR.js → chunk-LBNRH5WM.js} +100 -161
- package/dist/{chunk-TKHQ4DGZ.js → chunk-LZSJBIVT.js} +7358 -7414
- package/dist/{chunk-UGYAX5YI.js → chunk-M6SHUN7Q.js} +13 -8
- package/dist/chunk-MAW544W2.js +1882 -0
- package/dist/chunk-MBS4V7ZP.js +217 -0
- package/dist/{chunk-2J63S4SF.js → chunk-MFFY33HR.js} +167 -140
- package/dist/chunk-MNA4JGU4.js +255 -0
- package/dist/chunk-MQSRRFWA.js +3428 -0
- package/dist/{chunk-RQDWMVRB.js → chunk-MVVUPGPW.js} +138 -137
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/chunk-OHHN2SO4.js +5135 -0
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-BBUH4VAA.js → chunk-OOJYHWRB.js} +60 -361
- package/dist/{chunk-D5YD55AR.js → chunk-OQ33BKR3.js} +12 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-AMFR5YA3.js → chunk-ORBHGJC5.js} +26 -12
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/{chunk-7RBKDI66.js → chunk-QTYWRVRA.js} +104 -12
- package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
- package/dist/chunk-SRF2PJNW.js +184 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/{chunk-XV4ZJ6ZM.js → chunk-STBPMHSX.js} +473 -1194
- package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TXOTCRLG.js +15 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-527KG6XR.js → chunk-V4RXGQ5Q.js} +72 -185
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
- package/dist/chunk-WMSVI4G2.js +2095 -0
- package/dist/chunk-WVO7V2QY.js +797 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/chunk-X75S7HFS.js +374 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
- package/dist/{chunk-PIDUD6M2.js → chunk-YCWGATWI.js} +12 -5
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-UHTSULZS.js → chunk-ZDOOVTXZ.js} +38 -73
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-CLJ5HLUD.js → chunk-ZWLZP4ZT.js} +25 -6
- package/dist/cli/index.js +70 -56
- package/dist/clio-4LY5K2AC.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-JVHMUBEB.js → components-KELWS457.js} +31 -9
- package/dist/{config-ZFCDBMDC.js → config-GTLUW2PR.js} +104 -56
- package/dist/configure-R6A64DHX.js +42 -0
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-CDXTP2MP.js → context-JFZEJ7W5.js} +21 -13
- package/dist/{context-E3KIFVXI.js → context-RW5HC47S.js} +77 -36
- package/dist/{context-clear-3F4PLXOS.js → context-clear-6ZHBAZZT.js} +64 -30
- package/dist/{context-index-Q7YSYTR3.js → context-index-BZ4UYMTC.js} +36 -24
- package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
- package/dist/{docs-YIETIWZI.js → docs-2C2LTVT2.js} +32 -13
- package/dist/doctor-KI767GSN.js +87 -0
- package/dist/{eval-B3KZZESM.js → eval-XSSNATB4.js} +93 -27
- package/dist/{evidence-V67CHM35.js → evidence-UA6AWDQQ.js} +55 -27
- package/dist/{evolve-YDZSUQYA.js → evolve-QNTFGV6Z.js} +59 -26
- package/dist/{extensions-SRG7XCAH.js → extensions-QVDOHDGJ.js} +23 -8
- package/dist/{fleet-CA2CRTVG.js → fleet-Q7UOMUSG.js} +173 -56
- package/dist/fleet-preflight-DDN536IT.js +26 -0
- package/dist/{init-2OZDJE2D.js → init-WBB65ZHQ.js} +79 -34
- package/dist/{memory-3PIQQAKX.js → memory-MD3O64RI.js} +57 -28
- package/dist/{models-DY35XI7Y.js → models-BZU34YWD.js} +49 -24
- package/dist/monitor-MEQA5C3I.js +661 -0
- package/dist/{chunk-PS4PFJQP.js → orchestrator-CGFKEP27.js} +22837 -18564
- package/dist/{paths-5OMXW7Z4.js → paths-UXLN5YYZ.js} +17 -6
- package/dist/preload-P6DGH2PZ.js +13 -0
- package/dist/{reset-PIFYNOS3.js → reset-L2FQEE3E.js} +25 -13
- package/dist/{run-3VSPP24F.js → run-IV4Q6RLN.js} +115 -63
- package/dist/{share-D36RQCXM.js → share-S5BZQC5I.js} +23 -10
- package/dist/{skills-F2MRLELY.js → skills-LQEKRDTN.js} +42 -15
- package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-3DC4HEWS.js} +90 -45
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-DZMEZAH4.js → targets-C4SSGQOB.js} +78 -60
- package/dist/terminal-lease-IT5JW2NR.js +395 -0
- package/dist/{trace-7NYCUI2J.js → trace-PNCASAXC.js} +48 -17
- package/dist/tree-sitter-HGKH6LG4.js +4673 -0
- package/dist/{uninstall-AD3JWHBB.js → uninstall-FZCQCDKC.js} +19 -8
- package/dist/{upgrade-WYYBKGDY.js → upgrade-7TT7SQ3G.js} +66 -24
- package/dist/{usage-ULIDAGFF.js → usage-GV4PKT3M.js} +71 -32
- package/dist/verify-G6V4D2G7.js +716 -0
- package/dist/version-KGEG7EPO.js +21 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-DQF6Z66B.js} +98 -48
- package/dist/worker/entry.js +297 -54
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +29 -21
- package/docs/acp.md +191 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +157 -7
- package/docs/artifact-placement.md +101 -0
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +4 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +224 -97
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +236 -38
- package/docs/context-engine.md +34 -7
- package/docs/development-pipeline.md +102 -0
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +3 -3
- package/docs/environment-variables.md +15 -6
- package/docs/eval-runner.md +3 -3
- package/docs/evals-internal.md +2 -2
- package/docs/evidence-and-memory.md +10 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +25 -18
- package/docs/fleet-demo-runbook.md +22 -23
- package/docs/fleet-dispatch.md +117 -16
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +107 -15
- package/docs/installation-and-lifecycle.md +75 -17
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +46 -15
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +14 -14
- package/docs/prompt-envelope-and-tools.md +25 -4
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -111
- package/docs/safety-model.md +28 -8
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +101 -0
- package/docs/tool-usage.md +6 -5
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +121 -28
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +33 -36
- package/skills/README.md +5 -6
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/git/file-ticket/SKILL.md +107 -0
- package/skills/git/file-ticket/evals.md +54 -0
- package/skills/git/fix-issue/SKILL.md +106 -0
- package/skills/git/fix-issue/evals.md +71 -0
- package/skills/git/ship/SKILL.md +92 -0
- package/skills/git/ship/evals.md +72 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/skill-marketplace.json +12 -20
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +115 -0
- package/src/cli/agents.ts +60 -0
- package/src/cli/args.ts +280 -0
- package/src/cli/argv.ts +170 -0
- package/src/cli/ask.ts +34 -0
- package/src/cli/auth.ts +468 -0
- package/src/cli/bootstrap-generate.ts +498 -0
- package/src/cli/clio.ts +96 -0
- package/src/cli/components.ts +195 -0
- package/src/cli/config-inspect.ts +336 -0
- package/src/cli/config.ts +72 -0
- package/src/cli/configure-interop.ts +67 -0
- package/src/cli/configure-layout.ts +172 -0
- package/src/cli/configure.ts +1525 -0
- package/src/cli/context-clear.ts +76 -0
- package/src/cli/context-index.ts +100 -0
- package/src/cli/context.ts +321 -0
- package/src/cli/default-target.ts +55 -0
- package/src/cli/docs.ts +346 -0
- package/src/cli/doctor.ts +54 -0
- package/src/cli/eval.ts +315 -0
- package/src/cli/evidence.ts +225 -0
- package/src/cli/evolve.ts +219 -0
- package/src/cli/extensions.ts +214 -0
- package/src/cli/fleet.ts +868 -0
- package/src/cli/index.ts +338 -0
- package/src/cli/init.ts +219 -0
- package/src/cli/initial-message.ts +47 -0
- package/src/cli/internal-dispatch.ts +55 -0
- package/src/cli/memory.ts +182 -0
- package/src/cli/models.ts +257 -0
- package/src/cli/modes/json-stream.ts +121 -0
- package/src/cli/modes/jsonl.ts +9 -0
- package/src/cli/modes/print.ts +604 -0
- package/src/cli/oauth-manual-input.ts +72 -0
- package/src/cli/oauth-select.ts +36 -0
- package/src/cli/output-guard.ts +48 -0
- package/src/cli/paths.ts +44 -0
- package/src/cli/provider-target.ts +113 -0
- package/src/cli/removal.ts +72 -0
- package/src/cli/reset.ts +253 -0
- package/src/cli/run.ts +497 -0
- package/src/cli/share.ts +243 -0
- package/src/cli/shared.ts +60 -0
- package/src/cli/skills-eval.ts +1240 -0
- package/src/cli/skills.ts +485 -0
- package/src/cli/steer-channel.ts +86 -0
- package/src/cli/targets.ts +1154 -0
- package/src/cli/text-layout.ts +112 -0
- package/src/cli/trace.ts +322 -0
- package/src/cli/uninstall.ts +405 -0
- package/src/cli/upgrade.ts +286 -0
- package/src/cli/usage.ts +876 -0
- package/src/cli/validate-model.ts +28 -0
- package/src/cli/version.ts +7 -0
- package/src/cli/wiki-generate.ts +510 -0
- package/src/core/agent-environment.ts +7 -0
- package/src/core/artifact-paths.ts +43 -0
- package/src/core/bash-exec.ts +313 -0
- package/src/core/boot-trace.ts +42 -0
- package/src/core/bus-events.ts +744 -0
- package/src/core/bus-trace.ts +53 -0
- package/src/core/c-header-language.ts +265 -0
- package/src/core/clio-repo.ts +78 -0
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +1722 -0
- package/src/core/context-floor.ts +33 -0
- package/src/core/defaults.ts +659 -0
- package/src/core/domain-loader.ts +177 -0
- package/src/core/event-bus.ts +94 -0
- package/src/core/file-references.ts +282 -0
- package/src/core/git-commit-attribution.ts +362 -0
- package/src/core/guardrails.ts +185 -0
- package/src/core/headless-permission.ts +21 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/init.ts +223 -0
- package/src/core/json-payload.ts +58 -0
- package/src/core/package-root.ts +54 -0
- package/src/core/path-canonical.ts +37 -0
- package/src/core/process-identity.ts +41 -0
- package/src/core/recent-models.ts +91 -0
- package/src/core/residency-protection.ts +56 -0
- package/src/core/resolve-config-value.ts +88 -0
- package/src/core/response-schema.ts +279 -0
- package/src/core/run-overrides.ts +77 -0
- package/src/core/safe-exec.ts +205 -0
- package/src/core/safe-id.ts +37 -0
- package/src/core/safe-resource-write.ts +162 -0
- package/src/core/session-routing.ts +339 -0
- package/src/core/settings-layers.ts +354 -0
- package/src/core/shared-bus.ts +8 -0
- package/src/core/shell-quote.ts +26 -0
- package/src/core/skill-activation.ts +190 -0
- package/src/core/startup-timer.ts +37 -0
- package/src/core/state-file-lock.ts +219 -0
- package/src/core/termination.ts +275 -0
- package/src/core/timers.ts +38 -0
- package/src/core/tool-names.ts +65 -0
- package/src/core/verification-scripts.ts +13 -0
- package/src/core/workspace-files.ts +492 -0
- package/src/core/xdg.ts +177 -0
- package/src/domains/agents/builtins/architect.md +4 -4
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +3 -3
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +1 -1
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/catalog.ts +172 -0
- package/src/domains/agents/contract.ts +16 -0
- package/src/domains/agents/extension.ts +110 -0
- package/src/domains/agents/fleet-commands.ts +154 -0
- package/src/domains/agents/fleet-contract.ts +797 -0
- package/src/domains/agents/frontmatter.ts +40 -0
- package/src/domains/agents/index.ts +102 -0
- package/src/domains/agents/manifest.ts +6 -0
- package/src/domains/agents/recipe-schema.ts +202 -0
- package/src/domains/agents/recipe.ts +125 -0
- package/src/domains/agents/registry.ts +111 -0
- package/src/domains/agents/result-contract.ts +1265 -0
- package/src/domains/agents/spec.ts +371 -0
- package/src/domains/agents/write-boundary.ts +109 -0
- package/src/domains/components/diff.ts +99 -0
- package/src/domains/components/hash.ts +21 -0
- package/src/domains/components/index.ts +3 -0
- package/src/domains/components/scan.ts +304 -0
- package/src/domains/components/snapshot.ts +108 -0
- package/src/domains/components/types.ts +82 -0
- package/src/domains/config/agent-namespace.ts +13 -0
- package/src/domains/config/classify.ts +106 -0
- package/src/domains/config/contract.ts +22 -0
- package/src/domains/config/extension.ts +142 -0
- package/src/domains/config/index.ts +23 -0
- package/src/domains/config/keybindings.ts +200 -0
- package/src/domains/config/manifest.ts +6 -0
- package/src/domains/config/watcher.ts +41 -0
- package/src/domains/context/adoption.ts +880 -0
- package/src/domains/context/bootstrap-prompt.ts +273 -0
- package/src/domains/context/bootstrap.ts +1502 -0
- package/src/domains/context/clear.ts +91 -0
- package/src/domains/context/clio-md.ts +429 -0
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/cmake.ts +356 -0
- package/src/domains/context/codewiki/cooperative.ts +46 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/digest.ts +135 -0
- package/src/domains/context/codewiki/grammar-assets.ts +33 -0
- package/src/domains/context/codewiki/indexer.ts +1529 -0
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +771 -0
- package/src/domains/context/contract.ts +68 -0
- package/src/domains/context/excluded-dirs.ts +1 -0
- package/src/domains/context/extension.ts +358 -0
- package/src/domains/context/fingerprint.ts +198 -0
- package/src/domains/context/index.ts +154 -0
- package/src/domains/context/init-options.ts +69 -0
- package/src/domains/context/manifest.ts +6 -0
- package/src/domains/context/operator-profile.ts +157 -0
- package/src/domains/context/project-metadata.ts +529 -0
- package/src/domains/context/project-rules.ts +227 -0
- package/src/domains/context/prompt-context.ts +61 -0
- package/src/domains/context/refresh.ts +178 -0
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/sibling-files.ts +10 -0
- package/src/domains/context/state.ts +237 -0
- package/src/domains/context/wiki/assemble.ts +303 -0
- package/src/domains/context/wiki/frontmatter.ts +210 -0
- package/src/domains/context/wiki/generate.ts +595 -0
- package/src/domains/context/wiki/layout.ts +111 -0
- package/src/domains/context/wiki/meta.ts +221 -0
- package/src/domains/context/wiki/plan-store.ts +217 -0
- package/src/domains/context/wiki/plan.ts +250 -0
- package/src/domains/context/wiki/prompts.ts +283 -0
- package/src/domains/context/wiki/staleness.ts +198 -0
- package/src/domains/dispatch/active-route-planner.ts +168 -0
- package/src/domains/dispatch/admission-queue.ts +150 -0
- package/src/domains/dispatch/admission.ts +334 -0
- package/src/domains/dispatch/agent-candidates.ts +307 -0
- package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
- package/src/domains/dispatch/agent-ledger-store.ts +257 -0
- package/src/domains/dispatch/agent-ledger.ts +212 -0
- package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
- package/src/domains/dispatch/assignment-events.ts +132 -0
- package/src/domains/dispatch/assignment-reconcile.ts +76 -0
- package/src/domains/dispatch/assignment-store.ts +162 -0
- package/src/domains/dispatch/assignment.ts +278 -0
- package/src/domains/dispatch/backoff.ts +59 -0
- package/src/domains/dispatch/batch-store.ts +134 -0
- package/src/domains/dispatch/batch-tracker.ts +66 -0
- package/src/domains/dispatch/capability-match.ts +155 -0
- package/src/domains/dispatch/capacity-lease.ts +413 -0
- package/src/domains/dispatch/code-step-store.ts +52 -0
- package/src/domains/dispatch/code-step.ts +387 -0
- package/src/domains/dispatch/contract.ts +278 -0
- package/src/domains/dispatch/dedup.ts +133 -0
- package/src/domains/dispatch/event-pump.ts +251 -0
- package/src/domains/dispatch/execution-handoff.ts +29 -0
- package/src/domains/dispatch/execution-plan.ts +328 -0
- package/src/domains/dispatch/execution-role.ts +277 -0
- package/src/domains/dispatch/execution-scheduler.ts +583 -0
- package/src/domains/dispatch/extension.ts +6006 -0
- package/src/domains/dispatch/failure-classification.ts +147 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/fleet-plan.ts +225 -0
- package/src/domains/dispatch/fleet-preflight.ts +394 -0
- package/src/domains/dispatch/gate-decisions.ts +1040 -0
- package/src/domains/dispatch/gate-role-prompts.ts +58 -0
- package/src/domains/dispatch/heartbeat.ts +27 -0
- package/src/domains/dispatch/index.ts +137 -0
- package/src/domains/dispatch/joint-route-adapter.ts +114 -0
- package/src/domains/dispatch/joint-route-resolver.ts +283 -0
- package/src/domains/dispatch/manifest.ts +6 -0
- package/src/domains/dispatch/orphan-recovery.ts +266 -0
- package/src/domains/dispatch/outcome.ts +109 -0
- package/src/domains/dispatch/phase-timing.ts +47 -0
- package/src/domains/dispatch/placement.ts +202 -0
- package/src/domains/dispatch/receipt-findings.ts +255 -0
- package/src/domains/dispatch/receipt-integrity.ts +383 -0
- package/src/domains/dispatch/recovery-candidates.ts +74 -0
- package/src/domains/dispatch/reproducibility.ts +48 -0
- package/src/domains/dispatch/reservation-store.ts +501 -0
- package/src/domains/dispatch/route-approval.ts +177 -0
- package/src/domains/dispatch/route-candidates.ts +57 -0
- package/src/domains/dispatch/route-decision.ts +1079 -0
- package/src/domains/dispatch/route-facts.ts +187 -0
- package/src/domains/dispatch/route-history.ts +238 -0
- package/src/domains/dispatch/route-observer.ts +488 -0
- package/src/domains/dispatch/route-policy.ts +327 -0
- package/src/domains/dispatch/route-quality.ts +256 -0
- package/src/domains/dispatch/route-readiness.ts +120 -0
- package/src/domains/dispatch/routing-intent.ts +287 -0
- package/src/domains/dispatch/run-identity.ts +56 -0
- package/src/domains/dispatch/scout-transition.ts +130 -0
- package/src/domains/dispatch/state.ts +302 -0
- package/src/domains/dispatch/tool-stats.ts +132 -0
- package/src/domains/dispatch/transport.ts +210 -0
- package/src/domains/dispatch/types.ts +799 -0
- package/src/domains/dispatch/validation-grounding.ts +154 -0
- package/src/domains/dispatch/validation.ts +721 -0
- package/src/domains/dispatch/worker-protocol.ts +275 -0
- package/src/domains/dispatch/worker-spawn.ts +585 -0
- package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
- package/src/domains/dispatch/write-boundary.ts +426 -0
- package/src/domains/eval/artifacts/redact.ts +42 -0
- package/src/domains/eval/artifacts/store.ts +173 -0
- package/src/domains/eval/compare/compare.ts +33 -0
- package/src/domains/eval/compare/gates.ts +66 -0
- package/src/domains/eval/compare/thresholds.ts +92 -0
- package/src/domains/eval/harness-metrics.ts +62 -0
- package/src/domains/eval/index.ts +66 -0
- package/src/domains/eval/metrics/chaos-stream.ts +93 -0
- package/src/domains/eval/metrics/context.ts +34 -0
- package/src/domains/eval/metrics/coverage.ts +21 -0
- package/src/domains/eval/metrics/evidence.ts +182 -0
- package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
- package/src/domains/eval/metrics/invariants.ts +736 -0
- package/src/domains/eval/metrics/latency.ts +4 -0
- package/src/domains/eval/metrics/token-stream.ts +139 -0
- package/src/domains/eval/metrics/tokens.ts +51 -0
- package/src/domains/eval/metrics/tool-calls.ts +7 -0
- package/src/domains/eval/proactive-memory.ts +279 -0
- package/src/domains/eval/provenance.ts +35 -0
- package/src/domains/eval/report.ts +234 -0
- package/src/domains/eval/reports/json.ts +5 -0
- package/src/domains/eval/reports/junit.ts +23 -0
- package/src/domains/eval/reports/markdown.ts +20 -0
- package/src/domains/eval/reports/swe-jsonl.ts +16 -0
- package/src/domains/eval/reports/text.ts +25 -0
- package/src/domains/eval/run-compare.ts +274 -0
- package/src/domains/eval/runner.ts +244 -0
- package/src/domains/eval/runners/clio-run.ts +148 -0
- package/src/domains/eval/runners/context-index.ts +56 -0
- package/src/domains/eval/runners/context-init.ts +203 -0
- package/src/domains/eval/runners/external-command.ts +350 -0
- package/src/domains/eval/runtime-paths.ts +171 -0
- package/src/domains/eval/schema/artifact.ts +75 -0
- package/src/domains/eval/schema/suite.ts +235 -0
- package/src/domains/eval/schema/validate.ts +339 -0
- package/src/domains/eval/store.ts +392 -0
- package/src/domains/eval/suites/load.ts +74 -0
- package/src/domains/eval/suites/matrix.ts +19 -0
- package/src/domains/eval/suites/resolve.ts +44 -0
- package/src/domains/eval/suites/run.ts +325 -0
- package/src/domains/eval/task-file.ts +186 -0
- package/src/domains/eval/types.ts +140 -0
- package/src/domains/eval/verifiers/command.ts +27 -0
- package/src/domains/eval/verifiers/file-exists.ts +6 -0
- package/src/domains/eval/verifiers/patch.ts +22 -0
- package/src/domains/eval/workspaces/git.ts +41 -0
- package/src/domains/eval/workspaces/local.ts +17 -0
- package/src/domains/eval/workspaces/temp-copy.ts +29 -0
- package/src/domains/evidence/build.ts +1754 -0
- package/src/domains/evidence/eval.ts +605 -0
- package/src/domains/evidence/failure-attribution.ts +54 -0
- package/src/domains/evidence/finish-contract-map.ts +42 -0
- package/src/domains/evidence/index.ts +55 -0
- package/src/domains/evidence/provenance.ts +200 -0
- package/src/domains/evidence/redact.ts +81 -0
- package/src/domains/evidence/store.ts +291 -0
- package/src/domains/evidence/types.ts +325 -0
- package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
- package/src/domains/evolution/index.ts +26 -0
- package/src/domains/evolution/manifest.ts +154 -0
- package/src/domains/evolution/validate.ts +304 -0
- package/src/domains/extensions/contract.ts +22 -0
- package/src/domains/extensions/discovery.ts +193 -0
- package/src/domains/extensions/extension.ts +46 -0
- package/src/domains/extensions/index.ts +34 -0
- package/src/domains/extensions/manager.ts +30 -0
- package/src/domains/extensions/manifest.ts +6 -0
- package/src/domains/extensions/resources.ts +38 -0
- package/src/domains/extensions/state.ts +224 -0
- package/src/domains/extensions/types.ts +83 -0
- package/src/domains/interop/consent.ts +185 -0
- package/src/domains/interop/contract.ts +29 -0
- package/src/domains/interop/detect.ts +173 -0
- package/src/domains/interop/extension.ts +59 -0
- package/src/domains/interop/index.ts +34 -0
- package/src/domains/interop/manifest.ts +6 -0
- package/src/domains/interop/registry.ts +139 -0
- package/src/domains/interop/state.ts +92 -0
- package/src/domains/interop/types.ts +109 -0
- package/src/domains/lifecycle/contract.ts +11 -0
- package/src/domains/lifecycle/doctor.ts +536 -0
- package/src/domains/lifecycle/extension.ts +23 -0
- package/src/domains/lifecycle/index.ts +21 -0
- package/src/domains/lifecycle/install-method.ts +51 -0
- package/src/domains/lifecycle/manifest.ts +6 -0
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +114 -0
- package/src/domains/lifecycle/state.ts +93 -0
- package/src/domains/lifecycle/upgrade-notice.ts +35 -0
- package/src/domains/lifecycle/version.ts +35 -0
- package/src/domains/memory/index.ts +128 -0
- package/src/domains/memory/operations.ts +143 -0
- package/src/domains/memory/prompt-section.ts +86 -0
- package/src/domains/memory/proposal.ts +180 -0
- package/src/domains/memory/store.ts +163 -0
- package/src/domains/memory/task-bank.ts +229 -0
- package/src/domains/memory/task-memory-handoff.ts +222 -0
- package/src/domains/memory/task-memory-policy.ts +602 -0
- package/src/domains/memory/task-memory-status.ts +58 -0
- package/src/domains/memory/task-memory-telemetry.ts +346 -0
- package/src/domains/memory/task-memory-trace.ts +89 -0
- package/src/domains/memory/types.ts +74 -0
- package/src/domains/memory/validate.ts +297 -0
- package/src/domains/middleware/budget.ts +216 -0
- package/src/domains/middleware/contract.ts +35 -0
- package/src/domains/middleware/dispatch-nudge.ts +469 -0
- package/src/domains/middleware/extension.ts +129 -0
- package/src/domains/middleware/hook-receipts.ts +70 -0
- package/src/domains/middleware/hooks-io.ts +186 -0
- package/src/domains/middleware/hooks.ts +432 -0
- package/src/domains/middleware/index.ts +154 -0
- package/src/domains/middleware/manifest.ts +6 -0
- package/src/domains/middleware/memory-intervention.ts +701 -0
- package/src/domains/middleware/rules.ts +42 -0
- package/src/domains/middleware/runtime.ts +333 -0
- package/src/domains/middleware/skills-reminder.ts +202 -0
- package/src/domains/middleware/snapshot.ts +71 -0
- package/src/domains/middleware/stalled-turn.ts +71 -0
- package/src/domains/middleware/task-board-reminder.ts +87 -0
- package/src/domains/middleware/task-nudge.ts +77 -0
- package/src/domains/middleware/tool-choice-control.ts +42 -0
- package/src/domains/middleware/types.ts +131 -0
- package/src/domains/middleware/validate.ts +329 -0
- package/src/domains/observability/accountability.ts +67 -0
- package/src/domains/observability/contract.ts +168 -0
- package/src/domains/observability/cost.ts +206 -0
- package/src/domains/observability/evidence-index.ts +123 -0
- package/src/domains/observability/extension.ts +281 -0
- package/src/domains/observability/index.ts +78 -0
- package/src/domains/observability/manifest.ts +10 -0
- package/src/domains/observability/metrics.ts +37 -0
- package/src/domains/observability/projection.ts +477 -0
- package/src/domains/observability/telemetry.ts +89 -0
- package/src/domains/observability/trace-store.ts +1454 -0
- package/src/domains/prompts/compiler.ts +614 -0
- package/src/domains/prompts/contract.ts +46 -0
- package/src/domains/prompts/extension.ts +336 -0
- package/src/domains/prompts/fragment-loader.ts +138 -0
- package/src/domains/prompts/fragments/identity/clio.md +5 -6
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +19 -0
- package/src/domains/prompts/fragments/operating/contract.md +4 -41
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/hash.ts +73 -0
- package/src/domains/prompts/index.ts +32 -0
- package/src/domains/prompts/manifest.ts +8 -0
- package/src/domains/prompts/memory-intervention.ts +57 -0
- package/src/domains/prompts/preload.ts +82 -0
- package/src/domains/providers/auth/api-key.ts +47 -0
- package/src/domains/providers/auth/backend-file.ts +79 -0
- package/src/domains/providers/auth/backend-memory.ts +72 -0
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/index.ts +37 -0
- package/src/domains/providers/auth/oauth.ts +37 -0
- package/src/domains/providers/auth/storage.ts +726 -0
- package/src/domains/providers/capabilities.ts +58 -0
- package/src/domains/providers/catalog.ts +162 -0
- package/src/domains/providers/contract.ts +162 -0
- package/src/domains/providers/credentials.ts +20 -0
- package/src/domains/providers/eligibility.ts +24 -0
- package/src/domains/providers/errors.ts +64 -0
- package/src/domains/providers/extension.ts +548 -0
- package/src/domains/providers/index.ts +142 -0
- package/src/domains/providers/knowledge-base-path.ts +102 -0
- package/src/domains/providers/manifest.ts +6 -0
- package/src/domains/providers/model-capabilities.ts +136 -0
- package/src/domains/providers/model-discovery.ts +144 -0
- package/src/domains/providers/model-family.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +723 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +120 -37
- package/src/domains/providers/plugins.ts +61 -0
- package/src/domains/providers/probe/fingerprint.ts +64 -0
- package/src/domains/providers/probe/http.ts +114 -0
- package/src/domains/providers/probe/reasoning.ts +111 -0
- package/src/domains/providers/registry.ts +187 -0
- package/src/domains/providers/resolver.ts +156 -0
- package/src/domains/providers/runtime-resolution.ts +720 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +78 -0
- package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
- package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
- package/src/domains/providers/runtimes/claude/common.ts +55 -0
- package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
- package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
- package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
- package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
- package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
- package/src/domains/providers/runtimes/cloud/google.ts +41 -0
- package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
- package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
- package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +164 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
- package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
- package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
- package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
- package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
- package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
- package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
- package/src/domains/providers/runtimes/protocol/google.ts +27 -0
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
- package/src/domains/providers/support.ts +241 -0
- package/src/domains/providers/thinking-control-policy.ts +85 -0
- package/src/domains/providers/types/capability-flags.ts +114 -0
- package/src/domains/providers/types/cost-provenance.ts +7 -0
- package/src/domains/providers/types/inference.ts +41 -0
- package/src/domains/providers/types/knowledge-base.ts +156 -0
- package/src/domains/providers/types/local-model-quirks.ts +216 -0
- package/src/domains/providers/types/runtime-descriptor.ts +181 -0
- package/src/domains/providers/types/target-descriptor.ts +60 -0
- package/src/domains/resources/collision.ts +92 -0
- package/src/domains/resources/common-loader.ts +140 -0
- package/src/domains/resources/contract.ts +24 -0
- package/src/domains/resources/extension.ts +59 -0
- package/src/domains/resources/index.ts +74 -0
- package/src/domains/resources/loader.ts +85 -0
- package/src/domains/resources/manifest.ts +6 -0
- package/src/domains/resources/prompts/loader.ts +246 -0
- package/src/domains/resources/prompts/substitute.ts +1 -0
- package/src/domains/resources/skills/content-hash.ts +107 -0
- package/src/domains/resources/skills/evals.ts +175 -0
- package/src/domains/resources/skills/install.ts +427 -0
- package/src/domains/resources/skills/loader.ts +985 -0
- package/src/domains/resources/skills/marketplace.ts +301 -0
- package/src/domains/resources/skills/provenance-pin.ts +115 -0
- package/src/domains/safety/action-classifier.ts +270 -0
- package/src/domains/safety/approval-axis.ts +23 -0
- package/src/domains/safety/audit.ts +493 -0
- package/src/domains/safety/autonomy.ts +174 -0
- package/src/domains/safety/call-target.ts +59 -0
- package/src/domains/safety/contract.ts +65 -0
- package/src/domains/safety/damage-control.ts +44 -0
- package/src/domains/safety/default-path-policy.ts +117 -0
- package/src/domains/safety/extension.ts +383 -0
- package/src/domains/safety/finish-contract-registration.ts +128 -0
- package/src/domains/safety/finish-contract.ts +554 -0
- package/src/domains/safety/index.ts +44 -0
- package/src/domains/safety/loop-detector.ts +143 -0
- package/src/domains/safety/manifest.ts +6 -0
- package/src/domains/safety/path-policy.ts +164 -0
- package/src/domains/safety/policy-engine.ts +994 -0
- package/src/domains/safety/project-policy.ts +391 -0
- package/src/domains/safety/protected-artifacts-registration.ts +189 -0
- package/src/domains/safety/protected-artifacts.ts +993 -0
- package/src/domains/safety/rejection-feedback.ts +102 -0
- package/src/domains/safety/rigor.ts +72 -0
- package/src/domains/safety/rule-compiler.ts +48 -0
- package/src/domains/safety/rule-pack-loader.ts +92 -0
- package/src/domains/safety/run-effects.ts +197 -0
- package/src/domains/safety/scope.ts +61 -0
- package/src/domains/scheduling/budget.ts +35 -0
- package/src/domains/scheduling/cluster.ts +175 -0
- package/src/domains/scheduling/contract.ts +30 -0
- package/src/domains/scheduling/extension.ts +91 -0
- package/src/domains/scheduling/index.ts +12 -0
- package/src/domains/scheduling/manifest.ts +6 -0
- package/src/domains/session/archive-readers.ts +208 -0
- package/src/domains/session/checkpoint.ts +38 -0
- package/src/domains/session/compaction/auto.ts +89 -0
- package/src/domains/session/compaction/branch-summary.ts +187 -0
- package/src/domains/session/compaction/compact.ts +493 -0
- package/src/domains/session/compaction/cut-point.ts +172 -0
- package/src/domains/session/compaction/defaults.ts +34 -0
- package/src/domains/session/compaction/mask-observations.ts +265 -0
- package/src/domains/session/compaction/session-entries.ts +18 -0
- package/src/domains/session/compaction/tokens.ts +148 -0
- package/src/domains/session/context-accounting.ts +583 -0
- package/src/domains/session/context-ledger.ts +362 -0
- package/src/domains/session/contract.ts +159 -0
- package/src/domains/session/cwd-fallback.ts +65 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +572 -0
- package/src/domains/session/extension.ts +403 -0
- package/src/domains/session/history.ts +172 -0
- package/src/domains/session/index.ts +84 -0
- package/src/domains/session/manager.ts +128 -0
- package/src/domains/session/manifest.ts +6 -0
- package/src/domains/session/migrations/index.ts +27 -0
- package/src/domains/session/prompt-manifest.ts +173 -0
- package/src/domains/session/protected-artifact-journal.ts +241 -0
- package/src/domains/session/protected-artifacts.ts +90 -0
- package/src/domains/session/retry.ts +230 -0
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +569 -0
- package/src/domains/session/tree/active-path.ts +137 -0
- package/src/domains/session/tree/fork.ts +159 -0
- package/src/domains/session/tree/manager.ts +128 -0
- package/src/domains/session/tree/navigator.ts +177 -0
- package/src/domains/session/tree/preview.ts +259 -0
- package/src/domains/session/usage.ts +148 -0
- package/src/domains/session/workspace/git-probe.ts +167 -0
- package/src/domains/session/workspace/index.ts +4 -0
- package/src/domains/session/workspace/project-type.ts +217 -0
- package/src/domains/session/workspace/snapshot.ts +74 -0
- package/src/domains/share/archive.ts +684 -0
- package/src/domains/share/contract.ts +9 -0
- package/src/domains/share/extension.ts +26 -0
- package/src/domains/share/index.ts +28 -0
- package/src/domains/share/manifest.ts +6 -0
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/adapter.ts +397 -0
- package/src/engine/acp/errors.ts +128 -0
- package/src/engine/acp/event-mapper.ts +154 -0
- package/src/engine/acp/server.ts +2238 -0
- package/src/engine/acp/tool-mediator.ts +686 -0
- package/src/engine/acp/transport.ts +775 -0
- package/src/engine/acp/types.ts +196 -0
- package/src/engine/agent.ts +29 -0
- package/src/engine/ai.ts +207 -0
- package/src/engine/alcf-oauth.ts +205 -0
- package/src/engine/antigravity/subprocess-runtime.ts +205 -0
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/degraded-inference.ts +95 -0
- package/src/engine/apis/index.ts +16 -0
- package/src/engine/apis/llamacpp-residency.ts +292 -0
- package/src/engine/apis/lmstudio-residency.ts +76 -0
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +528 -0
- package/src/engine/apis/openai-completions.ts +795 -0
- package/src/engine/apis/output-budget.ts +99 -0
- package/src/engine/apis/residency-lock.ts +29 -0
- package/src/engine/apis/residency.ts +776 -0
- package/src/engine/apis/resident-models.ts +42 -0
- package/src/engine/apis/sampling-overrides.ts +38 -0
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/claude/sdk-runtime.ts +685 -0
- package/src/engine/claude/session-id.ts +5 -0
- package/src/engine/claude/subprocess-runtime.ts +316 -0
- package/src/engine/claude/tool-safety.ts +400 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/external-subprocess.ts +23 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/harmony-response.ts +165 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/loop-guard.ts +1127 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +196 -0
- package/src/engine/pi-mono-names.ts +13 -0
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +272 -0
- package/src/engine/select-list.ts +53 -0
- package/src/engine/session.ts +834 -0
- package/src/engine/strip-tokenizer-sentinels.ts +125 -0
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +111 -0
- package/src/engine/types.ts +63 -0
- package/src/engine/worker-events.ts +100 -0
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1022 -0
- package/src/engine/worker-tools.ts +208 -0
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +2011 -0
- package/src/interactive/application-controller.ts +433 -0
- package/src/interactive/bus-notices.ts +265 -0
- package/src/interactive/chat-loop-messages.ts +626 -0
- package/src/interactive/chat-loop-policy.ts +18 -0
- package/src/interactive/chat-loop.ts +1090 -0
- package/src/interactive/chat-panel.ts +1820 -0
- package/src/interactive/chat-renderer.ts +1228 -0
- package/src/interactive/clio-editor.ts +161 -0
- package/src/interactive/command-fallbacks.ts +23 -0
- package/src/interactive/command-output.ts +85 -0
- package/src/interactive/context-activity.ts +203 -0
- package/src/interactive/context-meter.ts +223 -0
- package/src/interactive/context-overlay.ts +246 -0
- package/src/interactive/cost-overlay.ts +279 -0
- package/src/interactive/dispatch-board.ts +1319 -0
- package/src/interactive/dispatch-steering.ts +86 -0
- package/src/interactive/editor-bash.ts +46 -0
- package/src/interactive/editor-steer.ts +51 -0
- package/src/interactive/editor-submit.ts +507 -0
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/external-editor.ts +67 -0
- package/src/interactive/follow-up-queue-panel.ts +75 -0
- package/src/interactive/footer/dashboard.ts +538 -0
- package/src/interactive/footer/notifications.ts +275 -0
- package/src/interactive/footer/widgets.ts +1264 -0
- package/src/interactive/footer-panel.ts +187 -0
- package/src/interactive/format-time.ts +97 -0
- package/src/interactive/index.ts +11 -0
- package/src/interactive/interactive-application.ts +939 -0
- package/src/interactive/interactive-event-projection.ts +385 -0
- package/src/interactive/interactive-input-runtime.ts +307 -0
- package/src/interactive/interactive-presentation.ts +584 -0
- package/src/interactive/interactive-shell.ts +388 -0
- package/src/interactive/interactive-slash-runtime.ts +554 -0
- package/src/interactive/interactive-subscriptions.ts +111 -0
- package/src/interactive/interactive-tickers.ts +183 -0
- package/src/interactive/keybinding-manager.ts +496 -0
- package/src/interactive/layout.ts +57 -0
- package/src/interactive/leader-key.ts +143 -0
- package/src/interactive/loop-guard-interrupt.ts +101 -0
- package/src/interactive/memory-overlay.ts +280 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
- package/src/interactive/overlay-auth-lifecycle.ts +308 -0
- package/src/interactive/overlay-frame.ts +502 -0
- package/src/interactive/overlay-general-openers.ts +274 -0
- package/src/interactive/overlay-key-routing.ts +216 -0
- package/src/interactive/overlay-lifecycle.ts +426 -0
- package/src/interactive/overlay-model-selectors.ts +127 -0
- package/src/interactive/overlay-permission-lifecycle.ts +345 -0
- package/src/interactive/overlay-resource-openers.ts +112 -0
- package/src/interactive/overlay-session-lifecycle.ts +327 -0
- package/src/interactive/overlay-transitions.ts +57 -0
- package/src/interactive/overlays/agents.ts +69 -0
- package/src/interactive/overlays/ask-user.ts +921 -0
- package/src/interactive/overlays/auth-dialog.ts +221 -0
- package/src/interactive/overlays/context-reset.ts +108 -0
- package/src/interactive/overlays/cwd-fallback.ts +141 -0
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/extensions.ts +54 -0
- package/src/interactive/overlays/help-reference.ts +145 -0
- package/src/interactive/overlays/interop.ts +139 -0
- package/src/interactive/overlays/keybinding-detail.ts +90 -0
- package/src/interactive/overlays/list-overlay.ts +606 -0
- package/src/interactive/overlays/message-picker.ts +155 -0
- package/src/interactive/overlays/model-selector.ts +1109 -0
- package/src/interactive/overlays/prompts.ts +72 -0
- package/src/interactive/overlays/session-selector-search.ts +31 -0
- package/src/interactive/overlays/session-selector.ts +284 -0
- package/src/interactive/overlays/settings.ts +3451 -0
- package/src/interactive/overlays/skills-hub.ts +237 -0
- package/src/interactive/overlays/tree-selector.ts +422 -0
- package/src/interactive/permission-overlay.ts +170 -0
- package/src/interactive/render-trace.ts +534 -0
- package/src/interactive/renderers/branch-summary.ts +86 -0
- package/src/interactive/renderers/code-ink.ts +420 -0
- package/src/interactive/renderers/compaction-summary.ts +112 -0
- package/src/interactive/renderers/diff.ts +137 -0
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/notice.ts +28 -0
- package/src/interactive/renderers/retry-status.ts +31 -0
- package/src/interactive/renderers/structured.ts +89 -0
- package/src/interactive/renderers/tool-execution.ts +1357 -0
- package/src/interactive/renderers/worker-entry.ts +280 -0
- package/src/interactive/session-last-turn.ts +186 -0
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/session-transcript.ts +105 -0
- package/src/interactive/session-usage-reseed.ts +74 -0
- package/src/interactive/slash-autocomplete.ts +256 -0
- package/src/interactive/slash-commands.ts +1407 -0
- package/src/interactive/slash-spec.ts +424 -0
- package/src/interactive/status/controller.ts +260 -0
- package/src/interactive/status/index.ts +23 -0
- package/src/interactive/status/state-machine.ts +530 -0
- package/src/interactive/status/summary.ts +170 -0
- package/src/interactive/status/types.ts +121 -0
- package/src/interactive/status/verbs.ts +163 -0
- package/src/interactive/status/watchdog.ts +24 -0
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +540 -0
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/components.ts +55 -0
- package/src/interactive/theme/glyphs.ts +70 -0
- package/src/interactive/theme/index.ts +15 -0
- package/src/interactive/theme/labels.ts +88 -0
- package/src/interactive/theme/rules.ts +138 -0
- package/src/interactive/theme/segments.ts +88 -0
- package/src/interactive/theme/tokens.ts +121 -0
- package/src/interactive/thinking-level-policy.ts +6 -0
- package/src/interactive/tool-prose-loop.ts +122 -0
- package/src/interactive/tool-prose-registration.ts +48 -0
- package/src/interactive/turn-context.ts +855 -0
- package/src/interactive/turn-middleware.ts +283 -0
- package/src/interactive/turn-persistence.ts +458 -0
- package/src/interactive/turn-queues.ts +181 -0
- package/src/interactive/turn-recovery.ts +323 -0
- package/src/interactive/turn-runtime.ts +869 -0
- package/src/interactive/turn-state.ts +133 -0
- package/src/interactive/view/artifacts.ts +1452 -0
- package/src/interactive/view/view-overlay.ts +735 -0
- package/src/interactive/welcome-dashboard.ts +537 -0
- package/src/interactive/worker-receipts.ts +143 -0
- package/src/interactive/worker-replay.ts +111 -0
- package/src/interactive/worker-share.ts +100 -0
- package/src/interactive/worker-stream.ts +446 -0
- package/src/interactive/workspace-facts.ts +141 -0
- package/src/tools/agent-tools.ts +402 -0
- package/src/tools/artifact.ts +103 -0
- package/src/tools/ask-user.ts +666 -0
- package/src/tools/bash.ts +204 -0
- package/src/tools/bootstrap.ts +77 -0
- package/src/tools/builtin-tool-catalog.ts +265 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +549 -0
- package/src/tools/codewiki/shared.ts +118 -0
- package/src/tools/compete-worktrees.ts +898 -0
- package/src/tools/context/docs-engine.ts +630 -0
- package/src/tools/context/index.ts +514 -0
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +151 -0
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-arguments.ts +228 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +746 -0
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-scout.ts +461 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +244 -0
- package/src/tools/edit-diff.ts +534 -0
- package/src/tools/edit.ts +128 -0
- package/src/tools/executables.ts +22 -0
- package/src/tools/file-mutation-queue.ts +35 -0
- package/src/tools/find.ts +294 -0
- package/src/tools/grep.ts +495 -0
- package/src/tools/ignore-policy.ts +169 -0
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +206 -0
- package/src/tools/ls.ts +110 -0
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +767 -0
- package/src/tools/network-policy.ts +29 -0
- package/src/tools/observation.ts +421 -0
- package/src/tools/observers.ts +99 -0
- package/src/tools/path-utils.ts +79 -0
- package/src/tools/policy.ts +154 -0
- package/src/tools/profiles.ts +108 -0
- package/src/tools/read.ts +173 -0
- package/src/tools/registry.ts +1169 -0
- package/src/tools/result-shaping.ts +204 -0
- package/src/tools/safe-exec.ts +128 -0
- package/src/tools/spawn-hygiene.ts +182 -0
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +77 -0
- package/src/tools/tasks.ts +265 -0
- package/src/tools/truncate-utf8.ts +17 -0
- package/src/tools/truncate.ts +43 -0
- package/src/tools/verify/frontend.ts +687 -0
- package/src/tools/verify/index.ts +31 -0
- package/src/tools/verify/scripts.ts +108 -0
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +759 -0
- package/src/tools/worker-evidence.ts +215 -0
- package/src/tools/write.ts +57 -0
- package/src/utils/exif-orientation.ts +192 -0
- package/src/utils/git.ts +24 -0
- package/src/utils/image-resize.ts +148 -0
- package/src/utils/photon.ts +103 -0
- package/src/worker/control-lane.ts +22 -0
- package/src/worker/entry.ts +294 -0
- package/src/worker/event-projection.ts +56 -0
- package/src/worker/heartbeat.ts +24 -0
- package/src/worker/ledger-mirror.ts +95 -0
- package/src/worker/ndjson.ts +40 -0
- package/src/worker/protocol.ts +529 -0
- package/src/worker/resource-facts.ts +79 -0
- package/src/worker/runtime-registry.ts +12 -0
- package/src/worker/spec-contract.ts +675 -0
- package/src/worker/stdin-demux.ts +316 -0
- package/dist/acp-UMLFVA3F.js +0 -92
- package/dist/chunk-262G75JS.js +0 -35
- package/dist/chunk-6CWDTGUC.js +0 -20
- package/dist/chunk-BYEU76JP.js +0 -899
- package/dist/chunk-GNGDQYDU.js +0 -34688
- package/dist/chunk-GOTUR54M.js +0 -9
- package/dist/chunk-NI4DEJMC.js +0 -88
- package/dist/chunk-TPOCL34A.js +0 -2876
- package/dist/chunk-UU3R62TT.js +0 -128
- package/dist/clio-KIQ5SNDS.js +0 -53
- package/dist/configure-G4E3A2PG.js +0 -27
- package/dist/doctor-M5HJJZOL.js +0 -61
- package/dist/domains/agents/builtins/architect.md +0 -33
- package/dist/domains/agents/builtins/coder.md +0 -31
- package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
- package/dist/domains/agents/builtins/debugger.md +0 -30
- package/dist/domains/agents/builtins/documenter.md +0 -31
- package/dist/domains/agents/builtins/git-master.md +0 -30
- package/dist/domains/agents/builtins/provenance.md +0 -30
- package/dist/domains/agents/builtins/researcher.md +0 -71
- package/dist/domains/agents/builtins/scout.md +0 -42
- package/dist/domains/agents/builtins/tester.md +0 -31
- package/dist/domains/agents/builtins/verifier.md +0 -30
- package/dist/domains/agents/builtins/wiki-writer.md +0 -41
- package/dist/fleet-preflight-CLIAX7YR.js +0 -21
- package/dist/preload-KZVHET2B.js +0 -11
- package/dist/version-ROZ6CZKH.js +0 -16
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -794
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -314
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/skills/git/commit-crafting/SKILL.md +0 -79
- package/skills/git/commit-crafting/evals.md +0 -92
- package/skills/git/create-pr/SKILL.md +0 -116
- package/skills/git/create-pr/evals.md +0 -114
- package/skills/git/investigate-issue/SKILL.md +0 -139
- package/skills/git/investigate-issue/evals.md +0 -94
- package/skills/git/review-changes/SKILL.md +0 -103
- package/skills/git/review-changes/evals.md +0 -85
|
@@ -0,0 +1,1502 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, parse } from "node:path";
|
|
4
|
+
import type { ContextActivityPayload } from "../../core/bus-events.js";
|
|
5
|
+
import { classifyProjectPreload, type ProjectPreloadClass } from "../prompts/preload.js";
|
|
6
|
+
import { detectProjectType, type ProjectType } from "../session/workspace/project-type.js";
|
|
7
|
+
import {
|
|
8
|
+
type AdoptionScanResult,
|
|
9
|
+
adoptionSnapshotsHash,
|
|
10
|
+
RULE_KEYWORDS,
|
|
11
|
+
renderImportedAgentContext,
|
|
12
|
+
scanAgentConfigs,
|
|
13
|
+
} from "./adoption.js";
|
|
14
|
+
import { type ClioMdSection, type ParsedClioMd, parseClioMd, serializeClioMd, tryReadClioMd } from "./clio-md.js";
|
|
15
|
+
import { buildCodewikiCandidate, coordinateCodewikiWrite } from "./codewiki/coordinator.js";
|
|
16
|
+
import type { Codewiki } from "./codewiki/schema.js";
|
|
17
|
+
import type { Fingerprint } from "./fingerprint.js";
|
|
18
|
+
import { hasTomlTable, type ProjectMetadata, readProjectMetadata } from "./project-metadata.js";
|
|
19
|
+
import { renderPromptContext } from "./prompt-context.js";
|
|
20
|
+
import type { SiblingContextFile } from "./sibling-files.js";
|
|
21
|
+
import {
|
|
22
|
+
type BootstrapGenerationMode,
|
|
23
|
+
type BootstrapGenerationState,
|
|
24
|
+
type BootstrapParserOutcome,
|
|
25
|
+
readClioState,
|
|
26
|
+
statePath as resolveStatePath,
|
|
27
|
+
writeClioState,
|
|
28
|
+
} from "./state.js";
|
|
29
|
+
|
|
30
|
+
export interface BootstrapStructuredOutput {
|
|
31
|
+
projectName: string;
|
|
32
|
+
identity: string;
|
|
33
|
+
conventions: string[];
|
|
34
|
+
invariants: string[];
|
|
35
|
+
sections?: ClioMdSection[];
|
|
36
|
+
importedAgentContext?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface BootstrapIo {
|
|
40
|
+
stdout: (s: string) => void;
|
|
41
|
+
stderr: (s: string) => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Input handed to a CLIO-CODER.md generator. Carries the adoption scan plus the freshly
|
|
46
|
+
* built codewiki so generators can ground their output in the real repository
|
|
47
|
+
* structure (entry points, key modules) instead of guessing from prose alone.
|
|
48
|
+
*/
|
|
49
|
+
export interface BootstrapGenerateInput {
|
|
50
|
+
cwd: string;
|
|
51
|
+
expectedProjectName?: string;
|
|
52
|
+
projectType: ProjectType;
|
|
53
|
+
siblingFiles: ReadonlyArray<SiblingContextFile>;
|
|
54
|
+
adoption: AdoptionScanResult;
|
|
55
|
+
codewiki: Codewiki;
|
|
56
|
+
existingClioMd?: ParsedClioMd;
|
|
57
|
+
existingClioMdText?: string;
|
|
58
|
+
progress?: BootstrapProgressSink;
|
|
59
|
+
reportGeneration?: BootstrapGenerationSink;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type BootstrapGenerate = (
|
|
63
|
+
input: BootstrapGenerateInput,
|
|
64
|
+
) => BootstrapStructuredOutput | Promise<BootstrapStructuredOutput>;
|
|
65
|
+
|
|
66
|
+
export type BootstrapProgressEvent = Omit<ContextActivityPayload, "kind" | "at">;
|
|
67
|
+
export type BootstrapProgressSink = (event: BootstrapProgressEvent) => void;
|
|
68
|
+
|
|
69
|
+
export interface BootstrapRunTelemetry {
|
|
70
|
+
structuredOutputMode: "native-schema" | "prompt-parser";
|
|
71
|
+
runId?: string;
|
|
72
|
+
targetId?: string;
|
|
73
|
+
wireModelId?: string;
|
|
74
|
+
runtimeId?: string;
|
|
75
|
+
runtimeKind?: string;
|
|
76
|
+
thinkingLevel?: string;
|
|
77
|
+
tokens?: {
|
|
78
|
+
total: number;
|
|
79
|
+
input?: number;
|
|
80
|
+
output?: number;
|
|
81
|
+
cacheRead?: number;
|
|
82
|
+
cacheWrite?: number;
|
|
83
|
+
reasoning?: number;
|
|
84
|
+
};
|
|
85
|
+
toolCalls?: number;
|
|
86
|
+
toolFailures?: number;
|
|
87
|
+
toolBlocked?: number;
|
|
88
|
+
durationMs?: number;
|
|
89
|
+
promptBytes: number;
|
|
90
|
+
outputBytes: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface BootstrapGenerationTelemetry {
|
|
94
|
+
mode: BootstrapGenerationMode;
|
|
95
|
+
parserOutcome: BootstrapParserOutcome;
|
|
96
|
+
fallbackReason?: string;
|
|
97
|
+
run?: BootstrapRunTelemetry;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type BootstrapGenerationSink = (telemetry: BootstrapGenerationTelemetry) => void;
|
|
101
|
+
|
|
102
|
+
export type BootstrapFallbackMode = "existing" | "heuristic";
|
|
103
|
+
|
|
104
|
+
export interface BootstrapFallbackResult {
|
|
105
|
+
mode: BootstrapFallbackMode;
|
|
106
|
+
output: BootstrapStructuredOutput;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface RunBootstrapInput {
|
|
110
|
+
cwd?: string;
|
|
111
|
+
io?: BootstrapIo;
|
|
112
|
+
modelId?: string;
|
|
113
|
+
now?: () => Date;
|
|
114
|
+
confirmGitignore?: () => boolean | Promise<boolean>;
|
|
115
|
+
preview?: boolean;
|
|
116
|
+
adopt?: boolean;
|
|
117
|
+
applyClioMd?: boolean;
|
|
118
|
+
rewriteClioMd?: boolean;
|
|
119
|
+
proposeClioMd?: boolean;
|
|
120
|
+
includeGlobalImports?: boolean;
|
|
121
|
+
homeDir?: string;
|
|
122
|
+
generate?: BootstrapGenerate;
|
|
123
|
+
onProgress?: BootstrapProgressSink;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface RunBootstrapResult {
|
|
127
|
+
clioMdPath: string;
|
|
128
|
+
statePath: string;
|
|
129
|
+
siblingFiles: ReadonlyArray<SiblingContextFile>;
|
|
130
|
+
output: BootstrapStructuredOutput;
|
|
131
|
+
projectType: ProjectType;
|
|
132
|
+
summary: RunBootstrapSummary;
|
|
133
|
+
adoption: AdoptionScanResult;
|
|
134
|
+
telemetry: {
|
|
135
|
+
generation: BootstrapGenerationTelemetry;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* How the session compiler will preload the project context that exists
|
|
139
|
+
* on disk after this run: full, synopsis (with the limit that forced it),
|
|
140
|
+
* or none. In preview mode this reflects the current on-disk state, since
|
|
141
|
+
* preview writes nothing.
|
|
142
|
+
*/
|
|
143
|
+
preload: ProjectPreloadClass;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface RunBootstrapSummary {
|
|
147
|
+
action: "wrote" | "refreshed" | "preserved" | "proposed" | "previewed";
|
|
148
|
+
contextFileCount: number;
|
|
149
|
+
contextFileNames: string[];
|
|
150
|
+
codewikiEntries: number;
|
|
151
|
+
dirtyFiles: number;
|
|
152
|
+
adoption: RunBootstrapAdoptionSummary;
|
|
153
|
+
proposalPath?: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface RunBootstrapAdoptionSummary {
|
|
157
|
+
mode: "scan" | "adopt" | "preview";
|
|
158
|
+
sourceCount: number;
|
|
159
|
+
projectSourceCount: number;
|
|
160
|
+
globalSourceCount: number;
|
|
161
|
+
importedRuleCount: number;
|
|
162
|
+
conflictCount: number;
|
|
163
|
+
rejectedCount: number;
|
|
164
|
+
includeGlobal: boolean;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function out(io: BootstrapIo | undefined, message: string): void {
|
|
168
|
+
io?.stdout(message);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function warn(io: BootstrapIo | undefined, message: string): void {
|
|
172
|
+
io?.stderr(message);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function progress(input: RunBootstrapInput, event: BootstrapProgressEvent): void {
|
|
176
|
+
input.onProgress?.(event);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function readJsonFile(filePath: string): unknown {
|
|
180
|
+
try {
|
|
181
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
182
|
+
} catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function stringField(value: unknown, key: string): string | null {
|
|
188
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
189
|
+
const field = (value as Record<string, unknown>)[key];
|
|
190
|
+
return typeof field === "string" && field.trim().length > 0 ? field.trim() : null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function titleFromPackageName(raw: string): string {
|
|
194
|
+
const base = raw.includes("/") ? (raw.split("/").pop() ?? raw) : raw;
|
|
195
|
+
return base
|
|
196
|
+
.split(/[-_]+/)
|
|
197
|
+
.filter(Boolean)
|
|
198
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
199
|
+
.join(" ");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* A name a manifest chose is already the project's own spelling; a name read
|
|
204
|
+
* off a package identifier or a directory is a slug that has to be titled.
|
|
205
|
+
*/
|
|
206
|
+
function projectNameFrom(metadata: ProjectMetadata, cwd: string): string {
|
|
207
|
+
const declared = metadata.name;
|
|
208
|
+
if (declared) {
|
|
209
|
+
return metadata.nameSource === "package.json" ? titleFromPackageName(declared) : declared.slice(0, 80);
|
|
210
|
+
}
|
|
211
|
+
return titleFromPackageName(parse(cwd).base || "Project");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function projectName(cwd: string): string {
|
|
215
|
+
return projectNameFrom(readProjectMetadata(cwd), cwd);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function projectTypeLabel(projectType: ProjectType): string {
|
|
219
|
+
switch (projectType) {
|
|
220
|
+
case "typescript":
|
|
221
|
+
return "TypeScript/Node.js";
|
|
222
|
+
case "javascript":
|
|
223
|
+
return "JavaScript/Node.js";
|
|
224
|
+
case "python":
|
|
225
|
+
return "Python";
|
|
226
|
+
case "rust":
|
|
227
|
+
return "Rust";
|
|
228
|
+
case "go":
|
|
229
|
+
return "Go";
|
|
230
|
+
case "c":
|
|
231
|
+
return "C";
|
|
232
|
+
case "c++":
|
|
233
|
+
return "C++";
|
|
234
|
+
case "java":
|
|
235
|
+
return "Java";
|
|
236
|
+
case "ruby":
|
|
237
|
+
return "Ruby";
|
|
238
|
+
case "c#":
|
|
239
|
+
return "C#";
|
|
240
|
+
case "polyglot":
|
|
241
|
+
return "polyglot";
|
|
242
|
+
case "dotfiles":
|
|
243
|
+
return "dotfiles";
|
|
244
|
+
case "unknown":
|
|
245
|
+
return "software";
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function allContextText(files: ReadonlyArray<SiblingContextFile>): string {
|
|
250
|
+
return files.map((file) => file.content).join("\n\n");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
interface DeterministicIdentity {
|
|
254
|
+
/** The identity sentence the deterministic path produces. */
|
|
255
|
+
text: string;
|
|
256
|
+
/**
|
|
257
|
+
* True when nothing but the project name and the stack label reached the
|
|
258
|
+
* sentence, so `text` is the bare `<name> is a <stack> project.` template.
|
|
259
|
+
* That happens only when no manifest, no research metadata, and no README
|
|
260
|
+
* variant in this repository describes it at all. The flag is what decides
|
|
261
|
+
* whether a model-authored identity is allowed to win, so the caller never
|
|
262
|
+
* has to pattern-match the rendering.
|
|
263
|
+
*/
|
|
264
|
+
bare: boolean;
|
|
265
|
+
/** Repo-relative file the description came from, or null when bare. */
|
|
266
|
+
descriptionSource: string | null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function resolveDefaultIdentity(
|
|
270
|
+
cwd: string,
|
|
271
|
+
projectType: ProjectType,
|
|
272
|
+
files: ReadonlyArray<SiblingContextFile>,
|
|
273
|
+
): DeterministicIdentity {
|
|
274
|
+
const metadata = readProjectMetadata(cwd);
|
|
275
|
+
const name = projectNameFrom(metadata, cwd);
|
|
276
|
+
const context = allContextText(files);
|
|
277
|
+
if (/Clio owns the agent loop/i.test(context) && /pi-(?:ai|SDK)/i.test(context)) {
|
|
278
|
+
return {
|
|
279
|
+
text: [
|
|
280
|
+
"Clio Coder is IOWarp's orchestrator coding agent, named for the Greek muse of history and developed by the Gnosis Research Center at Illinois Tech (github.com/grc-iit, @grc-iit) and the IOWarp team. CLIO stands for Context Layer for Input/Output.",
|
|
281
|
+
"pi-ai is accessed through the engine boundary.",
|
|
282
|
+
"Clio owns the agent loop, TUI, session format, tool registry, and identity.",
|
|
283
|
+
].join(" "),
|
|
284
|
+
bare: false,
|
|
285
|
+
descriptionSource: null,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const stack = projectTypeLabel(projectType);
|
|
289
|
+
const head = `${name} is a ${stack} project.`;
|
|
290
|
+
const description = metadata.description;
|
|
291
|
+
if (!description) return { text: head.slice(0, 600), bare: true, descriptionSource: null };
|
|
292
|
+
const cleaned = description.replace(/\.$/, "").trim();
|
|
293
|
+
const role = /^[a-z]/.test(cleaned) ? `It is ${cleaned}.` : `${cleaned}.`;
|
|
294
|
+
return { text: `${head} ${role}`.slice(0, 600), bare: false, descriptionSource: metadata.descriptionSource };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Identity precedence for a stabilized handbook, below an existing `CLIO-CODER.md`
|
|
299
|
+
* identity, which always wins. The deterministic sentence is evidence read off
|
|
300
|
+
* the repository, so it outranks anything the model wrote. The single exception
|
|
301
|
+
* is the bare case: with no `package.json` description and no `README.md`
|
|
302
|
+
* summary the deterministic path can only say `<name> is a <stack> project.`,
|
|
303
|
+
* which tells a reader nothing the directory name did not. A model sentence is
|
|
304
|
+
* strictly better than that, and only than that.
|
|
305
|
+
*/
|
|
306
|
+
function stabilizedIdentity(input: BootstrapGenerateInput, modelIdentity: unknown): string {
|
|
307
|
+
const deterministic = resolveDefaultIdentity(input.cwd, input.projectType, input.siblingFiles);
|
|
308
|
+
const model = typeof modelIdentity === "string" ? modelIdentity.trim() : "";
|
|
309
|
+
if (deterministic.bare && model.length > 0) return model;
|
|
310
|
+
return deterministic.text;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function pushUnique(target: string[], value: string): void {
|
|
314
|
+
if (target.includes(value)) return;
|
|
315
|
+
target.push(value);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const SKIP_BULLET_PATTERNS = [/^marker\s*[:=]/i, /marker[-_:]\s*\w+-\w+/i, /^todo\b/i, /^note\b/i, /^example\b/i];
|
|
319
|
+
|
|
320
|
+
function harvestSiblingBullets(files: ReadonlyArray<SiblingContextFile>): string[] {
|
|
321
|
+
const out: string[] = [];
|
|
322
|
+
for (const file of files) {
|
|
323
|
+
for (const rawLine of file.content.split("\n")) {
|
|
324
|
+
const match = /^[\s>]*[-*]\s+(.+?)\s*$/.exec(rawLine);
|
|
325
|
+
if (!match) continue;
|
|
326
|
+
const bullet = match[1]?.trim();
|
|
327
|
+
if (!bullet || bullet.length < 5) continue;
|
|
328
|
+
if (bullet.length > 200) continue;
|
|
329
|
+
if (SKIP_BULLET_PATTERNS.some((re) => re.test(bullet))) continue;
|
|
330
|
+
if (!RULE_KEYWORDS.test(bullet)) continue;
|
|
331
|
+
out.push(bullet);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* The extension local imports actually carry, measured from the specifiers the
|
|
339
|
+
* indexer already extracted. Reported only on a clear majority so a repository
|
|
340
|
+
* mid-migration is described as having no rule rather than the wrong one.
|
|
341
|
+
*/
|
|
342
|
+
function localImportExtension(codewiki: Codewiki): string | null {
|
|
343
|
+
const counts = new Map<string, number>();
|
|
344
|
+
let total = 0;
|
|
345
|
+
for (const file of codewiki.files) {
|
|
346
|
+
for (const specifier of file.imports) {
|
|
347
|
+
if (!specifier.startsWith(".")) continue;
|
|
348
|
+
total += 1;
|
|
349
|
+
const extension = /\.([A-Za-z0-9]+)$/.exec(specifier)?.[1];
|
|
350
|
+
const key = extension === undefined ? "" : `.${extension}`;
|
|
351
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (total < 4) return null;
|
|
355
|
+
for (const [extension, count] of counts) {
|
|
356
|
+
if (extension.length > 0 && count / total >= 0.8) return extension;
|
|
357
|
+
}
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function inferConventions(cwd: string, files: ReadonlyArray<SiblingContextFile>, codewiki: Codewiki): string[] {
|
|
362
|
+
const conventions: string[] = [];
|
|
363
|
+
const context = allContextText(files);
|
|
364
|
+
const pkg = readJsonFile(join(cwd, "package.json"));
|
|
365
|
+
const packageText = typeof pkg === "object" && pkg !== null ? JSON.stringify(pkg) : "";
|
|
366
|
+
// A convention here is read as fact on every turn, so it is measured or it
|
|
367
|
+
// is not stated. The stack alone decides nothing: a repository that imports
|
|
368
|
+
// `./money.ts` under allowImportingTsExtensions is told to break its own
|
|
369
|
+
// build by a rule inferred from the presence of a tsconfig.
|
|
370
|
+
const declaredJs = /Local imports end in `?\.js`?/i.test(context);
|
|
371
|
+
const importExtension = declaredJs ? ".js" : localImportExtension(codewiki);
|
|
372
|
+
if (importExtension !== null) {
|
|
373
|
+
pushUnique(conventions, `Local imports end in \`${importExtension}\`.`);
|
|
374
|
+
}
|
|
375
|
+
if (/node:test/i.test(context) || /node --import tsx --test|node --test/.test(packageText)) {
|
|
376
|
+
pushUnique(conventions, "Tests use `node:test`.");
|
|
377
|
+
}
|
|
378
|
+
if (/No em-dash|em-dash/i.test(context)) {
|
|
379
|
+
pushUnique(
|
|
380
|
+
conventions,
|
|
381
|
+
"No em-dash clause separators in code, comments, commits, or responses. Write full sentences.",
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
if (/Commit subjects|conventional commit|Imperative, lowercase|lowercase-typed subjects/i.test(context)) {
|
|
385
|
+
pushUnique(
|
|
386
|
+
conventions,
|
|
387
|
+
"Commit subjects are imperative, lowercase, conventional, at most 72 characters, and end without a period.",
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
for (const bullet of harvestSiblingBullets(files)) pushUnique(conventions, bullet);
|
|
391
|
+
return conventions.slice(0, 6);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function inferInvariants(files: ReadonlyArray<SiblingContextFile>): string[] {
|
|
395
|
+
const context = allContextText(files);
|
|
396
|
+
const invariants: string[] = [];
|
|
397
|
+
if (/Engine boundary/i.test(context)) {
|
|
398
|
+
pushUnique(invariants, "Engine boundary. Only `src/engine/**` may value-import `@earendil-works/pi-*`.");
|
|
399
|
+
}
|
|
400
|
+
if (/Worker isolation/i.test(context)) {
|
|
401
|
+
pushUnique(
|
|
402
|
+
invariants,
|
|
403
|
+
"Worker isolation. `src/worker/**` never imports `src/domains/**` except `src/domains/providers`.",
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
if (/Domain independence/i.test(context)) {
|
|
407
|
+
pushUnique(
|
|
408
|
+
invariants,
|
|
409
|
+
"Domain independence. `src/domains/<x>/**` never imports `src/domains/<y>/extension.ts` for `y != x`.",
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
return invariants.slice(0, 3);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function indexedSourceFileCount(codewiki: Codewiki): number {
|
|
416
|
+
return codewiki.files.filter((file) => file.lang !== "config").length;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/** Measure how the session compiler will preload the on-disk project context. */
|
|
420
|
+
function measureProjectPreload(cwd: string): ProjectPreloadClass {
|
|
421
|
+
const promptContext = renderPromptContext(cwd);
|
|
422
|
+
return classifyProjectPreload({ hasClioMd: promptContext.clioMd !== null, text: promptContext.text });
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function packageScripts(cwd: string): Record<string, string> {
|
|
426
|
+
const pkg = readJsonFile(join(cwd, "package.json"));
|
|
427
|
+
if (typeof pkg !== "object" || pkg === null || Array.isArray(pkg)) return {};
|
|
428
|
+
const scripts = (pkg as Record<string, unknown>).scripts;
|
|
429
|
+
if (typeof scripts !== "object" || scripts === null || Array.isArray(scripts)) return {};
|
|
430
|
+
const out: Record<string, string> = {};
|
|
431
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
432
|
+
if (typeof command === "string" && command.trim().length > 0) out[name] = command.trim();
|
|
433
|
+
}
|
|
434
|
+
return out;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* The command prefix an agent must actually type in this repository. The
|
|
441
|
+
* handbook used to hardcode `npm run`, which is simply wrong in a pnpm, yarn, or
|
|
442
|
+
* bun workspace. A handbook that names a command the repository cannot run is
|
|
443
|
+
* worse than one that names no command at all: the agent runs it, it fails, and
|
|
444
|
+
* the failure looks like the agent's own mistake.
|
|
445
|
+
*/
|
|
446
|
+
export function packageManager(cwd: string): PackageManager {
|
|
447
|
+
const declared = stringField(readJsonFile(join(cwd, "package.json")), "packageManager")?.split("@")[0];
|
|
448
|
+
if (declared === "pnpm" || declared === "yarn" || declared === "bun" || declared === "npm") return declared;
|
|
449
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
450
|
+
if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
|
|
451
|
+
if (existsSync(join(cwd, "bun.lock")) || existsSync(join(cwd, "bun.lockb"))) return "bun";
|
|
452
|
+
return "npm";
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/** A script whose command rewrites the tree cannot serve as a verification gate. */
|
|
456
|
+
const MUTATING_SCRIPT_RE = /(?:^|\s)--(?:fix|write)(?:\s|$)/;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* First preset a human could actually invoke: named and not hidden. Hidden
|
|
460
|
+
* presets exist only to be inherited from, so naming one in the handbook would
|
|
461
|
+
* hand the agent a command CMake refuses to run.
|
|
462
|
+
*/
|
|
463
|
+
function cmakePresetName(presets: unknown, key: string): string | null {
|
|
464
|
+
if (typeof presets !== "object" || presets === null || Array.isArray(presets)) return null;
|
|
465
|
+
const list = (presets as Record<string, unknown>)[key];
|
|
466
|
+
if (!Array.isArray(list)) return null;
|
|
467
|
+
for (const entry of list) {
|
|
468
|
+
if ((entry as Record<string, unknown> | null)?.hidden === true) continue;
|
|
469
|
+
const name = stringField(entry, "name");
|
|
470
|
+
if (name !== null) return name;
|
|
471
|
+
}
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* CMake presets are the project's own declared configure/build/test recipes,
|
|
477
|
+
* the same authority package.json scripts carry for Node. A CMake tree without
|
|
478
|
+
* presets stays silent: nothing there declares a runnable command, and a
|
|
479
|
+
* guessed `cmake -B build` fails on exactly the toolchain-file and MPI-wrapper
|
|
480
|
+
* projects this tool targets. Configure, build, and test are each named
|
|
481
|
+
* independently: a project can declare a visible build preset without a
|
|
482
|
+
* visible configure preset (e.g. the configure preset is the hidden base
|
|
483
|
+
* every build preset inherits from), and that build command is still one the
|
|
484
|
+
* agent can run.
|
|
485
|
+
*/
|
|
486
|
+
function cmakeVerificationLines(cwd: string): string[] {
|
|
487
|
+
const presets = readJsonFile(join(cwd, "CMakePresets.json"));
|
|
488
|
+
if (presets === null) return [];
|
|
489
|
+
const configure = cmakePresetName(presets, "configurePresets");
|
|
490
|
+
const build = cmakePresetName(presets, "buildPresets");
|
|
491
|
+
const test = cmakePresetName(presets, "testPresets");
|
|
492
|
+
const lines: string[] = [];
|
|
493
|
+
if (configure !== null) lines.push(`Configure with \`cmake --preset ${configure}\`.`);
|
|
494
|
+
if (build !== null) lines.push(`Build with \`cmake --build --preset ${build}\`.`);
|
|
495
|
+
if (test !== null) lines.push(`Run tests with \`ctest --preset ${test}\`.`);
|
|
496
|
+
return lines;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Python has no single scripts manifest, so this names a runner only where the
|
|
501
|
+
* project declares one: a tox configuration declares `tox`, and a declared
|
|
502
|
+
* pytest configuration declares `pytest`. An undeclared layout stays silent
|
|
503
|
+
* rather than guessing `python -m unittest` at a repository that tests some
|
|
504
|
+
* other way. Tox wins when both are declared because it typically wraps the
|
|
505
|
+
* pytest run.
|
|
506
|
+
*/
|
|
507
|
+
function pythonVerificationLines(cwd: string): string[] {
|
|
508
|
+
let pyproject = "";
|
|
509
|
+
try {
|
|
510
|
+
pyproject = readFileSync(join(cwd, "pyproject.toml"), "utf8");
|
|
511
|
+
} catch {
|
|
512
|
+
pyproject = "";
|
|
513
|
+
}
|
|
514
|
+
if (existsSync(join(cwd, "tox.ini")) || hasTomlTable(pyproject, "tool.tox")) {
|
|
515
|
+
return ["Run `tox` before handoff."];
|
|
516
|
+
}
|
|
517
|
+
if (existsSync(join(cwd, "pytest.ini")) || hasTomlTable(pyproject, "tool.pytest.ini_options")) {
|
|
518
|
+
return ["Run `pytest` before handoff."];
|
|
519
|
+
}
|
|
520
|
+
return [];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function verificationSection(cwd: string): ClioMdSection | null {
|
|
524
|
+
const scripts = packageScripts(cwd);
|
|
525
|
+
const pm = packageManager(cwd);
|
|
526
|
+
const hasScript = (name: string) => typeof scripts[name] === "string";
|
|
527
|
+
const command = (name: string) => `\`${pm} run ${name}\``;
|
|
528
|
+
// Prefer a non-mutating `:check` variant. Naming an autofixer as the gate
|
|
529
|
+
// tells the agent to rewrite the working tree instead of judging it, which
|
|
530
|
+
// turns a verification step into an unreviewed diff.
|
|
531
|
+
const gate = (name: string): string | null => {
|
|
532
|
+
if (hasScript(`${name}:check`)) return `${name}:check`;
|
|
533
|
+
return hasScript(name) && !MUTATING_SCRIPT_RE.test(scripts[name] ?? "") ? name : null;
|
|
534
|
+
};
|
|
535
|
+
const lines: string[] = [];
|
|
536
|
+
const baseline = ["typecheck", "lint", "format"]
|
|
537
|
+
.map(gate)
|
|
538
|
+
.filter((name): name is string => name !== null)
|
|
539
|
+
.map(command);
|
|
540
|
+
if (baseline.length > 0) {
|
|
541
|
+
lines.push(`Before handoff, run ${baseline.join(", ")}.`);
|
|
542
|
+
}
|
|
543
|
+
if (hasScript("build")) {
|
|
544
|
+
lines.push(`Run ${command("build")} after CLI, worker, packaging, or generated-dist changes.`);
|
|
545
|
+
}
|
|
546
|
+
const targeted = ["test:contracts", "test:smoke", "check:boundaries"].filter(hasScript).map(command);
|
|
547
|
+
if (targeted.length > 0) {
|
|
548
|
+
lines.push(`Use targeted checks for narrower risk: ${targeted.join(", ")}.`);
|
|
549
|
+
}
|
|
550
|
+
if (hasScript("test")) {
|
|
551
|
+
lines.push(`Run ${command("test")} when behavior crosses domains, tool contracts, smoke flows, or boundaries.`);
|
|
552
|
+
}
|
|
553
|
+
if (hasScript("ci")) {
|
|
554
|
+
lines.push(`Use ${command("ci")} for the full local gate before committing broad or shared behavior changes.`);
|
|
555
|
+
}
|
|
556
|
+
lines.push(...cmakeVerificationLines(cwd));
|
|
557
|
+
// Cargo's commands are defined by the toolchain, not by each project, so
|
|
558
|
+
// naming them for any Cargo workspace carries the same confidence as a
|
|
559
|
+
// declared package script.
|
|
560
|
+
if (existsSync(join(cwd, "Cargo.toml"))) {
|
|
561
|
+
lines.push("Run `cargo build` and `cargo test` before handoff.");
|
|
562
|
+
}
|
|
563
|
+
// Go's commands are defined by the toolchain, not by each project, so
|
|
564
|
+
// naming them for any module carries the same confidence as a declared
|
|
565
|
+
// package script.
|
|
566
|
+
if (existsSync(join(cwd, "go.mod"))) {
|
|
567
|
+
lines.push("Run `go build ./...` and `go test ./...` before handoff.");
|
|
568
|
+
}
|
|
569
|
+
lines.push(...pythonVerificationLines(cwd));
|
|
570
|
+
if (lines.length === 0) return null;
|
|
571
|
+
return { title: "Verification expectations", body: lines.join(" ") };
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const VERIFICATION_SECTION_RE = /\bverification\b/i;
|
|
575
|
+
|
|
576
|
+
interface ModelGroundingCorpus {
|
|
577
|
+
lower: string;
|
|
578
|
+
indexedPaths: ReadonlySet<string>;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Everything Scout is allowed to cite: sibling agent-context prose, the existing
|
|
583
|
+
* handbook, every indexed path, every indexed symbol, and every runnable package
|
|
584
|
+
* script rendered the way this repository would type it.
|
|
585
|
+
*/
|
|
586
|
+
function createModelGroundingCorpus(input: BootstrapGenerateInput): ModelGroundingCorpus {
|
|
587
|
+
let siblingBudget = 64_000;
|
|
588
|
+
const siblingEvidence: string[] = [];
|
|
589
|
+
for (const file of input.siblingFiles) {
|
|
590
|
+
if (siblingBudget <= 0) break;
|
|
591
|
+
const chunk = file.content.slice(0, siblingBudget);
|
|
592
|
+
siblingEvidence.push(chunk);
|
|
593
|
+
siblingBudget -= chunk.length;
|
|
594
|
+
}
|
|
595
|
+
const indexedPaths = new Set(input.codewiki.files.map((file) => file.path));
|
|
596
|
+
const pm = packageManager(input.cwd);
|
|
597
|
+
const scripts = packageScripts(input.cwd);
|
|
598
|
+
const evidence = [
|
|
599
|
+
...siblingEvidence,
|
|
600
|
+
(input.existingClioMdText ?? "").slice(0, 8000),
|
|
601
|
+
input.expectedProjectName ?? "",
|
|
602
|
+
input.projectType,
|
|
603
|
+
[...indexedPaths].join("\n").slice(0, 64_000),
|
|
604
|
+
...Object.entries(scripts).flatMap(([name, command]) => [`${pm} run ${name}`, `${pm} ${name}`, command]),
|
|
605
|
+
input.codewiki.symbols
|
|
606
|
+
.map((symbol) => symbol.name)
|
|
607
|
+
.join("\n")
|
|
608
|
+
.slice(0, 128_000),
|
|
609
|
+
].join("\n");
|
|
610
|
+
return { lower: evidence.toLowerCase(), indexedPaths };
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const CODE_TOKEN_RE = /`([^`\n]+)`/g;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* A citation anchored to a location: `src/cart.ts:26`, `src/cart.ts:40-42`, or
|
|
617
|
+
* `src/cart.ts:26:8`. The codewiki digest handed to the model prints its key
|
|
618
|
+
* symbols in exactly this form, so this is the shape a model that read the
|
|
619
|
+
* evidence writes back.
|
|
620
|
+
*/
|
|
621
|
+
const CITED_LOCATION_RE = /^(.*[^:]):(\d+)(?:[-:]\d+)?$/;
|
|
622
|
+
|
|
623
|
+
/** A symbol written as a call: `priceCart()`. */
|
|
624
|
+
const CITED_CALL_RE = /^(.+?)\(\s*\)$/;
|
|
625
|
+
|
|
626
|
+
function groundedName(token: string, evidence: ModelGroundingCorpus): boolean {
|
|
627
|
+
return evidence.lower.includes(token.toLowerCase()) || evidence.indexedPaths.has(token.replace(/^\.\//, ""));
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* The names a citation carries under its decoration. The corpus holds paths,
|
|
632
|
+
* symbol names, and scripts, so a token that adds a file offset or call parens
|
|
633
|
+
* to one of them cannot match it whole, and requiring the whole token to match
|
|
634
|
+
* deleted precisely the lines that had done the most reading. A Gotchas section
|
|
635
|
+
* whose five bullets each named a real file and line lost all five and
|
|
636
|
+
* vanished; the run after that lost every line that wrote `priceCart()` for the
|
|
637
|
+
* symbol `priceCart`. Peeling the decoration cannot loosen the rule, because
|
|
638
|
+
* the bare name still has to ground on its own.
|
|
639
|
+
*/
|
|
640
|
+
function citedNames(token: string): string[] {
|
|
641
|
+
const names: string[] = [];
|
|
642
|
+
let current = token;
|
|
643
|
+
for (let round = 0; round < 2; round += 1) {
|
|
644
|
+
const next = (CITED_CALL_RE.exec(current)?.[1] ?? CITED_LOCATION_RE.exec(current)?.[1])?.trim();
|
|
645
|
+
if (next === undefined || next.length === 0 || next === current) break;
|
|
646
|
+
names.push(next);
|
|
647
|
+
current = next;
|
|
648
|
+
}
|
|
649
|
+
return names;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function groundedToken(token: string, evidence: ModelGroundingCorpus): boolean {
|
|
653
|
+
return groundedName(token, evidence) || citedNames(token).some((name) => groundedName(name, evidence));
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Keep a Scout line only when it cites the repository and every citation is real.
|
|
658
|
+
*
|
|
659
|
+
* This used to require the line to be a verbatim member of the sibling-file
|
|
660
|
+
* corpus, which made Scout a copier rather than a reader: in a repository with no
|
|
661
|
+
* sibling agent-context files, and that is exactly the repository `context init`
|
|
662
|
+
* exists for, the corpus held only paths and symbol names, so no sentence could
|
|
663
|
+
* ever match and the model's entire contribution was deleted by construction.
|
|
664
|
+
*
|
|
665
|
+
* The replacement rule is one sentence and strictly more general than the term
|
|
666
|
+
* blacklist it also replaces: a line must contain at least one backticked token,
|
|
667
|
+
* and every backticked token must name a real indexed path, symbol, script, or
|
|
668
|
+
* a string that occurs in the supplied evidence. "A dedicated team owns every
|
|
669
|
+
* change" cites nothing and is dropped. "`src/commands.ts` owns argv parsing and
|
|
670
|
+
* the help text" names a file that exists and survives. An invented command like
|
|
671
|
+
* `npm publish` in a repository with no publish script is dropped even though the
|
|
672
|
+
* rest of the sentence is unremarkable, which was the real failure mode.
|
|
673
|
+
*/
|
|
674
|
+
function groundedModelBody(body: string, evidence: ModelGroundingCorpus): string {
|
|
675
|
+
const kept: string[] = [];
|
|
676
|
+
let inFence = false;
|
|
677
|
+
for (const rawLine of body.split(/\r?\n/)) {
|
|
678
|
+
const trimmed = rawLine.trim();
|
|
679
|
+
if (trimmed.startsWith("```")) {
|
|
680
|
+
inFence = !inFence;
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
if (trimmed.length === 0 || /^#{1,6}\s|^---+$/.test(trimmed)) continue;
|
|
684
|
+
// A fenced command block is the single highest-value thing Scout can return,
|
|
685
|
+
// and dropping the fence used to drop the commands with it. Inline the line
|
|
686
|
+
// instead, so it faces the same citation rule as any other line.
|
|
687
|
+
const line = inFence ? `\`${trimmed.replace(/`/g, "")}\`` : trimmed;
|
|
688
|
+
const codeTokens = [...line.matchAll(CODE_TOKEN_RE)]
|
|
689
|
+
.map((match) => match[1]?.trim())
|
|
690
|
+
.filter((token): token is string => token !== undefined && token.length > 0);
|
|
691
|
+
if (codeTokens.length === 0) continue;
|
|
692
|
+
if (!codeTokens.every((token) => groundedToken(token, evidence))) continue;
|
|
693
|
+
if (line.replace(CODE_TOKEN_RE, "").trim().length === 0 && !inFence) continue;
|
|
694
|
+
kept.push(line);
|
|
695
|
+
}
|
|
696
|
+
const bounded: string[] = [];
|
|
697
|
+
let length = 0;
|
|
698
|
+
for (const line of kept) {
|
|
699
|
+
const nextLength = length + (bounded.length > 0 ? 1 : 0) + line.length;
|
|
700
|
+
if (nextLength > 1200) break;
|
|
701
|
+
bounded.push(line);
|
|
702
|
+
length = nextLength;
|
|
703
|
+
}
|
|
704
|
+
return bounded.join("\n").trim();
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function sanitizeModelSection(section: ClioMdSection, evidence: ModelGroundingCorpus): ClioMdSection | null {
|
|
708
|
+
const body = groundedModelBody(section.body, evidence);
|
|
709
|
+
if (body.length < 40) return null;
|
|
710
|
+
const title = section.title.replace(/\s+/g, " ").trim();
|
|
711
|
+
return title.length > 0 ? { title, body } : null;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function stabilizeGeneratedOutput(
|
|
715
|
+
input: BootstrapGenerateInput,
|
|
716
|
+
base: BootstrapStructuredOutput,
|
|
717
|
+
onModelSectionRetained?: () => void,
|
|
718
|
+
groundModelOutput = false,
|
|
719
|
+
): BootstrapStructuredOutput {
|
|
720
|
+
const existing = input.existingClioMd;
|
|
721
|
+
const conventions: string[] = [];
|
|
722
|
+
for (const convention of existing?.conventions ?? []) pushUnique(conventions, convention);
|
|
723
|
+
for (const convention of inferConventions(input.cwd, input.siblingFiles, input.codewiki)) {
|
|
724
|
+
pushUnique(conventions, convention);
|
|
725
|
+
}
|
|
726
|
+
const invariants: string[] = [];
|
|
727
|
+
for (const invariant of existing?.invariants ?? []) pushUnique(invariants, invariant);
|
|
728
|
+
for (const invariant of inferInvariants(input.siblingFiles)) pushUnique(invariants, invariant);
|
|
729
|
+
|
|
730
|
+
const verification = verificationSection(input.cwd);
|
|
731
|
+
const inferredSections = inferHeuristicSections(input);
|
|
732
|
+
const existingSections = existing?.sections ?? [];
|
|
733
|
+
const ordinarySections: ClioMdSection[] = [];
|
|
734
|
+
const modelSections = new Set<ClioMdSection>();
|
|
735
|
+
const seenSectionTitles = new Set<string>();
|
|
736
|
+
const addSection = (section: ClioMdSection): boolean => {
|
|
737
|
+
if (VERIFICATION_SECTION_RE.test(section.title)) return false;
|
|
738
|
+
const titleKey = section.title.replace(/\s+/g, " ").trim().toLowerCase();
|
|
739
|
+
if (seenSectionTitles.has(titleKey)) return false;
|
|
740
|
+
seenSectionTitles.add(titleKey);
|
|
741
|
+
ordinarySections.push(section);
|
|
742
|
+
return true;
|
|
743
|
+
};
|
|
744
|
+
for (const section of existing ? [...existingSections, ...inferredSections] : inferredSections) addSection(section);
|
|
745
|
+
const groundingCorpus = groundModelOutput ? createModelGroundingCorpus(input) : null;
|
|
746
|
+
for (const section of base.sections ?? []) {
|
|
747
|
+
const sanitized = groundingCorpus ? sanitizeModelSection(section, groundingCorpus) : section;
|
|
748
|
+
if (sanitized && addSection(sanitized)) modelSections.add(sanitized);
|
|
749
|
+
}
|
|
750
|
+
const ordinaryLimit = verification ? 6 : 7;
|
|
751
|
+
const retainedOrdinarySections = ordinarySections.slice(0, ordinaryLimit);
|
|
752
|
+
for (const section of retainedOrdinarySections) {
|
|
753
|
+
if (modelSections.has(section)) onModelSectionRetained?.();
|
|
754
|
+
}
|
|
755
|
+
return {
|
|
756
|
+
...base,
|
|
757
|
+
projectName: existing?.projectName ?? projectName(input.cwd),
|
|
758
|
+
identity: existing?.identity ?? stabilizedIdentity(input, base.identity),
|
|
759
|
+
conventions: conventions.slice(0, 6),
|
|
760
|
+
invariants: invariants.slice(0, 3),
|
|
761
|
+
sections: [...retainedOrdinarySections, ...(verification ? [verification] : [])],
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* The handbook sections whose every fact is read straight off the codewiki index:
|
|
767
|
+
* which modules anchor it and where the mass sits. They are the only sections
|
|
768
|
+
* nothing but the index can author, and equally the only ones that are wrong the
|
|
769
|
+
* moment the tree moves, so `context refresh` re-derives them in place and leaves
|
|
770
|
+
* every other section to its human or model author. An exact file count stays
|
|
771
|
+
* out: the handbook persists between refreshes while the tree keeps moving, so a
|
|
772
|
+
* precise number is falsified by any single added file and carries no
|
|
773
|
+
* navigational value the entry-point list does not.
|
|
774
|
+
*/
|
|
775
|
+
export function codewikiSections(codewiki: Codewiki): ClioMdSection[] {
|
|
776
|
+
const sections: ClioMdSection[] = [];
|
|
777
|
+
const entryPoints = codewikiEntryPoints(codewiki, 8);
|
|
778
|
+
if (entryPoints.length > 0) {
|
|
779
|
+
sections.push({
|
|
780
|
+
title: "Context retrieval",
|
|
781
|
+
body: [
|
|
782
|
+
`Start orientation with these indexed entry points: ${entryPoints.map((entry) => `\`${entry}\``).join(", ")}.`,
|
|
783
|
+
"Use `code_nav` (modes: symbol, path, entries, outline, deps, dependents, wiki) before broad reads when the task is navigational.",
|
|
784
|
+
].join(" "),
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
return sections;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
function inferHeuristicSections(input: BootstrapGenerateInput): ClioMdSection[] {
|
|
791
|
+
const sections: ClioMdSection[] = [...codewikiSections(input.codewiki)];
|
|
792
|
+
const invariants = inferInvariants(input.siblingFiles);
|
|
793
|
+
if (invariants.length > 0) {
|
|
794
|
+
sections.push({
|
|
795
|
+
title: "Architecture boundaries",
|
|
796
|
+
body: invariants.map((item) => `- ${item}`).join("\n"),
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
if (input.adoption.sources.length > 0) {
|
|
800
|
+
const sourceNames = input.adoption.sources
|
|
801
|
+
.map((source) => `\`${source.displayPath}\``)
|
|
802
|
+
.slice(0, 8)
|
|
803
|
+
.join(", ");
|
|
804
|
+
sections.push({
|
|
805
|
+
title: "Agent context interop",
|
|
806
|
+
body: [
|
|
807
|
+
`Bootstrap scanned ${input.adoption.sources.length} sibling context source${input.adoption.sources.length === 1 ? "" : "s"}: ${sourceNames}${input.adoption.sources.length > 8 ? ", ..." : ""}.`,
|
|
808
|
+
"Run `clio-coder context init --adopt` to refresh the managed provenance section when those sources change.",
|
|
809
|
+
].join(" "),
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
return sections.slice(0, 6);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Deterministic CLIO-CODER.md generator. Distills identity, conventions, and invariants
|
|
817
|
+
* from sibling agent-context files and package metadata without a model. Used as
|
|
818
|
+
* the offline path and as the fallback when model-driven generation is
|
|
819
|
+
* unavailable or fails.
|
|
820
|
+
*/
|
|
821
|
+
function heuristicBootstrapOutputSync(input: BootstrapGenerateInput): BootstrapStructuredOutput {
|
|
822
|
+
return stabilizeGeneratedOutput(input, {
|
|
823
|
+
projectName: projectName(input.cwd),
|
|
824
|
+
identity: resolveDefaultIdentity(input.cwd, input.projectType, input.siblingFiles).text,
|
|
825
|
+
conventions: inferConventions(input.cwd, input.siblingFiles, input.codewiki),
|
|
826
|
+
invariants: inferInvariants(input.siblingFiles),
|
|
827
|
+
sections: inferHeuristicSections(input),
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
export const heuristicBootstrapOutput: BootstrapGenerate = heuristicBootstrapOutputSync;
|
|
832
|
+
|
|
833
|
+
function bootstrapOutputFromParsed(parsed: ParsedClioMd): BootstrapStructuredOutput {
|
|
834
|
+
const out: BootstrapStructuredOutput = {
|
|
835
|
+
projectName: parsed.projectName,
|
|
836
|
+
identity: parsed.identity,
|
|
837
|
+
conventions: [...parsed.conventions],
|
|
838
|
+
invariants: [...parsed.invariants],
|
|
839
|
+
};
|
|
840
|
+
if (parsed.sections.length > 0) {
|
|
841
|
+
out.sections = parsed.sections.map((section) => ({ title: section.title, body: section.body }));
|
|
842
|
+
}
|
|
843
|
+
if (parsed.importedAgentContext) out.importedAgentContext = parsed.importedAgentContext;
|
|
844
|
+
return out;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
function existingClioMdBootstrapOutput(cwd: string): BootstrapStructuredOutput | null {
|
|
848
|
+
const parsed = tryReadClioMd(cwd);
|
|
849
|
+
if (!parsed?.ok) return null;
|
|
850
|
+
return bootstrapOutputFromParsed(parsed.value);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
export function fallbackBootstrapOutput(input: BootstrapGenerateInput): BootstrapFallbackResult {
|
|
854
|
+
const existing = input.existingClioMd
|
|
855
|
+
? bootstrapOutputFromParsed(input.existingClioMd)
|
|
856
|
+
: existingClioMdBootstrapOutput(input.cwd);
|
|
857
|
+
if (existing) return { mode: "existing", output: existing };
|
|
858
|
+
return { mode: "heuristic", output: heuristicBootstrapOutputSync(input) };
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function readExistingClioMdText(cwd: string): string | null {
|
|
862
|
+
try {
|
|
863
|
+
return readFileSync(join(cwd, "CLIO-CODER.md"), "utf8");
|
|
864
|
+
} catch {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
function replaceImportedAgentContext(
|
|
870
|
+
output: BootstrapStructuredOutput,
|
|
871
|
+
importedAgentContext: string,
|
|
872
|
+
): BootstrapStructuredOutput {
|
|
873
|
+
const { importedAgentContext: _old, ...rest } = output;
|
|
874
|
+
if (importedAgentContext.length === 0) return rest;
|
|
875
|
+
return { ...rest, importedAgentContext };
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function loadBootstrapSiblingFiles(adoption: AdoptionScanResult): SiblingContextFile[] {
|
|
879
|
+
return adoption.sources.map((source) => ({
|
|
880
|
+
source: source.scope,
|
|
881
|
+
path: source.path,
|
|
882
|
+
content: source.content,
|
|
883
|
+
}));
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
function gitStatus(cwd: string): string {
|
|
887
|
+
try {
|
|
888
|
+
return execFileSync("git", ["status", "--short"], {
|
|
889
|
+
cwd,
|
|
890
|
+
encoding: "utf8",
|
|
891
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
892
|
+
});
|
|
893
|
+
} catch {
|
|
894
|
+
return "";
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function countStatusLines(status: string): number {
|
|
899
|
+
return status
|
|
900
|
+
.split("\n")
|
|
901
|
+
.map((line) => line.trim())
|
|
902
|
+
.filter(Boolean).length;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
function basenameList(paths: ReadonlyArray<string>): string {
|
|
906
|
+
const names = paths.map((path) => parse(path).base).sort((a, b) => a.localeCompare(b));
|
|
907
|
+
if (names.length === 0) return "";
|
|
908
|
+
if (names.length <= 3) return names.join(", ");
|
|
909
|
+
return `${names.slice(0, 3).join(", ")} +${names.length - 3}`;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
function formatAdoptionLine(summary: RunBootstrapSummary): string | null {
|
|
913
|
+
const adoption = summary.adoption;
|
|
914
|
+
const shouldRender =
|
|
915
|
+
summary.action === "previewed" ||
|
|
916
|
+
adoption.mode === "adopt" ||
|
|
917
|
+
adoption.globalSourceCount > 0 ||
|
|
918
|
+
adoption.conflictCount > 0 ||
|
|
919
|
+
adoption.rejectedCount > 0;
|
|
920
|
+
if (!shouldRender) return null;
|
|
921
|
+
const global = adoption.includeGlobal ? `${adoption.globalSourceCount} global` : "global off";
|
|
922
|
+
const verb = adoption.mode === "adopt" ? "imported" : "scanned";
|
|
923
|
+
return ` adoption ${verb} ${adoption.sourceCount} source${adoption.sourceCount === 1 ? "" : "s"} (${adoption.projectSourceCount} project, ${global}); ${adoption.importedRuleCount} candidate rule${adoption.importedRuleCount === 1 ? "" : "s"}; ${adoption.conflictCount} conflict${adoption.conflictCount === 1 ? "" : "s"}; ${adoption.rejectedCount} rejected`;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
function formatBootstrapSummary(summary: RunBootstrapSummary): string {
|
|
927
|
+
const contextLine =
|
|
928
|
+
summary.contextFileCount > 0
|
|
929
|
+
? `folded ${summary.contextFileCount} context file${summary.contextFileCount === 1 ? "" : "s"} (${basenameList(summary.contextFileNames)})`
|
|
930
|
+
: "no sibling context files found";
|
|
931
|
+
const dirtyLine =
|
|
932
|
+
summary.dirtyFiles === 0
|
|
933
|
+
? "workspace clean"
|
|
934
|
+
: `workspace has ${summary.dirtyFiles} dirty file${summary.dirtyFiles === 1 ? "" : "s"}`;
|
|
935
|
+
if (summary.action === "previewed") {
|
|
936
|
+
const adoptionLine = formatAdoptionLine(summary);
|
|
937
|
+
return [
|
|
938
|
+
"clio-coder context init preview",
|
|
939
|
+
` ${contextLine}; codewiki would index ${summary.codewikiEntries} entr${summary.codewikiEntries === 1 ? "y" : "ies"}; ${dirtyLine}; no files written`,
|
|
940
|
+
...(adoptionLine ? [adoptionLine] : []),
|
|
941
|
+
"",
|
|
942
|
+
].join("\n");
|
|
943
|
+
}
|
|
944
|
+
const adoptionLine = formatAdoptionLine(summary);
|
|
945
|
+
const proposalLine = summary.proposalPath ? ` proposal written ${summary.proposalPath}` : null;
|
|
946
|
+
if (summary.action === "preserved") {
|
|
947
|
+
return [
|
|
948
|
+
"clio-coder context init preserved CLIO-CODER.md",
|
|
949
|
+
` ${contextLine}; codewiki rebuilt ${summary.codewikiEntries} entr${summary.codewikiEntries === 1 ? "y" : "ies"}; state refreshed; ${dirtyLine}`,
|
|
950
|
+
" CLIO-CODER.md is treated as human-owned. Use --apply to replace it with a generated draft, --propose to write an ignored proposal, or --adopt to refresh only imported agent context.",
|
|
951
|
+
...(adoptionLine ? [adoptionLine] : []),
|
|
952
|
+
"",
|
|
953
|
+
].join("\n");
|
|
954
|
+
}
|
|
955
|
+
if (summary.action === "proposed") {
|
|
956
|
+
return [
|
|
957
|
+
"clio-coder context init proposed CLIO-CODER.md",
|
|
958
|
+
` ${contextLine}; codewiki rebuilt ${summary.codewikiEntries} entr${summary.codewikiEntries === 1 ? "y" : "ies"}; state refreshed; ${dirtyLine}`,
|
|
959
|
+
...(proposalLine ? [proposalLine] : []),
|
|
960
|
+
" CLIO-CODER.md was not changed. Re-run with --apply only after reviewing the proposal.",
|
|
961
|
+
...(adoptionLine ? [adoptionLine] : []),
|
|
962
|
+
"",
|
|
963
|
+
].join("\n");
|
|
964
|
+
}
|
|
965
|
+
return [
|
|
966
|
+
`clio-coder context init ${summary.action} CLIO-CODER.md`,
|
|
967
|
+
` ${contextLine}; codewiki rebuilt ${summary.codewikiEntries} entr${summary.codewikiEntries === 1 ? "y" : "ies"}; state refreshed; ${dirtyLine}`,
|
|
968
|
+
" git policy: .clio-coder/ stays ignored by default; CLIO-CODER.md stays versioned and human-owned. Force-add .clio-coder assets only when you explicitly intend to share them.",
|
|
969
|
+
...(proposalLine ? [proposalLine] : []),
|
|
970
|
+
...(adoptionLine ? [adoptionLine] : []),
|
|
971
|
+
"",
|
|
972
|
+
].join("\n");
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
const CLIO_GITIGNORE_LINE = ".clio-coder/";
|
|
976
|
+
const CLIO_GITIGNORE_DYNAMIC_LINES = new Set<string>([
|
|
977
|
+
".clio-coder/codewiki.json",
|
|
978
|
+
".clio-coder/state.json",
|
|
979
|
+
".clio-coder/handoffs/",
|
|
980
|
+
]);
|
|
981
|
+
|
|
982
|
+
function normalizedGitignoreLines(content: string): string[] {
|
|
983
|
+
return content.split(/\r?\n/).map((line) => line.trim());
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
function hasBlanketClioIgnore(content: string): boolean {
|
|
987
|
+
return normalizedGitignoreLines(content).some(isBlanketClioIgnoreLine);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
function isBlanketClioIgnoreLine(line: string): boolean {
|
|
991
|
+
if (line.length === 0 || line.startsWith("#") || line.startsWith("!")) return false;
|
|
992
|
+
return /^(?:\/|\*\*\/)?\.clio-coder(?:\/|\/\*|\/\*\*)?$/.test(line);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
function hasDynamicOnlyClioIgnore(content: string): boolean {
|
|
996
|
+
const lines = new Set(normalizedGitignoreLines(content));
|
|
997
|
+
for (const line of CLIO_GITIGNORE_DYNAMIC_LINES) {
|
|
998
|
+
if (!lines.has(line)) return false;
|
|
999
|
+
}
|
|
1000
|
+
return true;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
function migrateClioGitignore(content: string): string {
|
|
1004
|
+
const lines = content.split(/\r?\n/);
|
|
1005
|
+
const kept = lines.filter((line) => {
|
|
1006
|
+
const trimmed = line.trim();
|
|
1007
|
+
return !isBlanketClioIgnoreLine(trimmed) && !CLIO_GITIGNORE_DYNAMIC_LINES.has(trimmed);
|
|
1008
|
+
});
|
|
1009
|
+
while (kept.length > 0 && kept[kept.length - 1]?.trim() === "") kept.pop();
|
|
1010
|
+
const prefix = kept.length > 0 ? [...kept, ""] : [];
|
|
1011
|
+
return `${[...prefix, CLIO_GITIGNORE_LINE].join("\n")}\n`;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
async function ensureGitignore(cwd: string, input: RunBootstrapInput): Promise<void> {
|
|
1015
|
+
const gitignorePath = join(cwd, ".gitignore");
|
|
1016
|
+
let content = "";
|
|
1017
|
+
try {
|
|
1018
|
+
content = readFileSync(gitignorePath, "utf8");
|
|
1019
|
+
} catch {
|
|
1020
|
+
content = "";
|
|
1021
|
+
}
|
|
1022
|
+
if (hasBlanketClioIgnore(content)) {
|
|
1023
|
+
if (hasDynamicOnlyClioIgnore(content)) writeFileSync(gitignorePath, migrateClioGitignore(content), "utf8");
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
if (hasDynamicOnlyClioIgnore(content)) {
|
|
1027
|
+
writeFileSync(gitignorePath, migrateClioGitignore(content), "utf8");
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const confirmed = input.confirmGitignore ? await input.confirmGitignore() : false;
|
|
1031
|
+
if (!confirmed) {
|
|
1032
|
+
// The remedy is one flag away and the warning used to name neither it
|
|
1033
|
+
// nor the line, leaving the operator to guess the pattern Clio writes.
|
|
1034
|
+
warn(
|
|
1035
|
+
input.io,
|
|
1036
|
+
"clio-coder context init: .gitignore does not ignore .clio-coder/; local context, skills, agents, and handoffs may leak into commits.\n" +
|
|
1037
|
+
` rerun with --yes to append '${CLIO_GITIGNORE_LINE}' to .gitignore without prompting, or add that line yourself.\n`,
|
|
1038
|
+
);
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
writeFileSync(gitignorePath, migrateClioGitignore(content), "utf8");
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
function serializeBootstrapOutput(output: BootstrapStructuredOutput): string {
|
|
1045
|
+
return serializeClioMd({ ...output, fingerprint: null });
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
function writeClioMdFile(cwd: string, output: BootstrapStructuredOutput): string {
|
|
1049
|
+
const clioMdPath = join(cwd, "CLIO-CODER.md");
|
|
1050
|
+
mkdirSync(dirname(clioMdPath), { recursive: true });
|
|
1051
|
+
const serialized = serializeBootstrapOutput(output);
|
|
1052
|
+
const parsed = parseClioMd(serialized);
|
|
1053
|
+
if (!parsed.ok) throw new Error(`bootstrap produced invalid CLIO-CODER.md: ${parsed.errors.join("; ")}`);
|
|
1054
|
+
writeFileSync(clioMdPath, serialized, "utf8");
|
|
1055
|
+
return clioMdPath;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
function timestampForPath(now: Date): string {
|
|
1059
|
+
return now
|
|
1060
|
+
.toISOString()
|
|
1061
|
+
.replace(/[-:]/g, "")
|
|
1062
|
+
.replace(/\.\d{3}Z$/, "Z");
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
function writeClioMdProposal(cwd: string, now: Date, output: BootstrapStructuredOutput): string {
|
|
1066
|
+
const dir = join(cwd, ".clio-coder", "proposals");
|
|
1067
|
+
mkdirSync(dir, { recursive: true });
|
|
1068
|
+
const proposalPath = join(dir, `CLIO-CODER-${timestampForPath(now)}.md`);
|
|
1069
|
+
writeFileSync(proposalPath, serializeBootstrapOutput(output), "utf8");
|
|
1070
|
+
return proposalPath;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
function boundedStateString(value: string | undefined, maxChars: number): string | undefined {
|
|
1074
|
+
if (value === undefined) return undefined;
|
|
1075
|
+
const bounded = value.replace(/\s+/g, " ").trim().slice(0, maxChars);
|
|
1076
|
+
return bounded.length > 0 ? bounded : undefined;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
function safeStateCounter(value: number | undefined): number | undefined {
|
|
1080
|
+
return value !== undefined && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
function durableGenerationTelemetry(telemetry: BootstrapGenerationTelemetry): BootstrapGenerationState {
|
|
1084
|
+
const state: BootstrapGenerationState = {
|
|
1085
|
+
mode: telemetry.mode,
|
|
1086
|
+
parserOutcome: telemetry.parserOutcome,
|
|
1087
|
+
};
|
|
1088
|
+
const fallbackReason = boundedStateString(telemetry.fallbackReason, 500);
|
|
1089
|
+
if (fallbackReason) state.fallbackReason = fallbackReason;
|
|
1090
|
+
const run = telemetry.run;
|
|
1091
|
+
if (!run) return state;
|
|
1092
|
+
state.structuredOutputMode = run.structuredOutputMode;
|
|
1093
|
+
for (const [key, value] of [
|
|
1094
|
+
["runId", run.runId],
|
|
1095
|
+
["targetId", run.targetId],
|
|
1096
|
+
["wireModelId", run.wireModelId],
|
|
1097
|
+
["runtimeId", run.runtimeId],
|
|
1098
|
+
["runtimeKind", run.runtimeKind],
|
|
1099
|
+
["thinkingLevel", run.thinkingLevel],
|
|
1100
|
+
] as const) {
|
|
1101
|
+
const bounded = boundedStateString(value, 512);
|
|
1102
|
+
if (bounded) state[key] = bounded;
|
|
1103
|
+
}
|
|
1104
|
+
for (const [key, value] of [
|
|
1105
|
+
["tokenCount", run.tokens?.total],
|
|
1106
|
+
["toolCalls", run.toolCalls],
|
|
1107
|
+
["durationMs", run.durationMs],
|
|
1108
|
+
["promptBytes", run.promptBytes],
|
|
1109
|
+
["outputBytes", run.outputBytes],
|
|
1110
|
+
] as const) {
|
|
1111
|
+
const counter = safeStateCounter(value);
|
|
1112
|
+
if (counter !== undefined) state[key] = counter;
|
|
1113
|
+
}
|
|
1114
|
+
return state;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
function writeProjectState(
|
|
1118
|
+
cwd: string,
|
|
1119
|
+
projectType: ProjectType,
|
|
1120
|
+
now: Date,
|
|
1121
|
+
indexedAt: string,
|
|
1122
|
+
adoption: AdoptionScanResult,
|
|
1123
|
+
recordAdoption: boolean,
|
|
1124
|
+
codewikiVersion: number,
|
|
1125
|
+
fingerprint: Fingerprint,
|
|
1126
|
+
generation: BootstrapGenerationTelemetry,
|
|
1127
|
+
generated: boolean,
|
|
1128
|
+
): string {
|
|
1129
|
+
const statePath = resolveStatePath(cwd);
|
|
1130
|
+
const prev = readClioState(cwd);
|
|
1131
|
+
// lastBootstrap describes how the CLIO-CODER.md on disk was produced, not what the
|
|
1132
|
+
// most recent run happened to do. A run that generated nothing leaves the
|
|
1133
|
+
// handbook untouched, so overwriting a recorded `model` provenance with
|
|
1134
|
+
// `existing` would claim the handbook has no model authorship behind it.
|
|
1135
|
+
const lastBootstrap = generated
|
|
1136
|
+
? durableGenerationTelemetry(generation)
|
|
1137
|
+
: (prev?.lastBootstrap ?? durableGenerationTelemetry(generation));
|
|
1138
|
+
const contextSources = recordAdoption ? adoption.sourceSnapshots : prev?.contextSources;
|
|
1139
|
+
const contextSourceHash = contextSources ? adoptionSnapshotsHash(contextSources) : undefined;
|
|
1140
|
+
writeClioState(cwd, {
|
|
1141
|
+
version: 1,
|
|
1142
|
+
projectType,
|
|
1143
|
+
fingerprint,
|
|
1144
|
+
codewikiVersion,
|
|
1145
|
+
lastInitAt: now.toISOString(),
|
|
1146
|
+
lastSessionAt: now.toISOString(),
|
|
1147
|
+
lastIndexedAt: indexedAt,
|
|
1148
|
+
lastBootstrap,
|
|
1149
|
+
...(contextSources ? { contextSources } : {}),
|
|
1150
|
+
...(contextSourceHash ? { contextSourceHash } : {}),
|
|
1151
|
+
});
|
|
1152
|
+
return statePath;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
* Publish the deterministic index before Scout runs so a worker-side code_nav
|
|
1157
|
+
* call reuses this build instead of demand-building the same repository again.
|
|
1158
|
+
* This is an index checkpoint, not a completed init: lastInitAt remains unchanged
|
|
1159
|
+
* until CLIO-CODER.md handling succeeds below.
|
|
1160
|
+
*/
|
|
1161
|
+
function persistCodewikiForGeneration(
|
|
1162
|
+
cwd: string,
|
|
1163
|
+
projectType: ProjectType,
|
|
1164
|
+
indexedAt: string,
|
|
1165
|
+
codewiki: Codewiki,
|
|
1166
|
+
fingerprint: Fingerprint,
|
|
1167
|
+
): void {
|
|
1168
|
+
const prev = readClioState(cwd);
|
|
1169
|
+
writeClioState(cwd, {
|
|
1170
|
+
version: 1,
|
|
1171
|
+
projectType,
|
|
1172
|
+
fingerprint,
|
|
1173
|
+
codewikiVersion: codewiki.version,
|
|
1174
|
+
...(prev?.contextSources ? { contextSources: prev.contextSources } : {}),
|
|
1175
|
+
...(prev?.contextSourceHash ? { contextSourceHash: prev.contextSourceHash } : {}),
|
|
1176
|
+
...(prev?.lastInitAt ? { lastInitAt: prev.lastInitAt } : {}),
|
|
1177
|
+
...(prev?.lastBootstrap ? { lastBootstrap: prev.lastBootstrap } : {}),
|
|
1178
|
+
lastSessionAt: prev?.lastSessionAt ?? indexedAt,
|
|
1179
|
+
lastIndexedAt: indexedAt,
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
function summarizeAdoption(
|
|
1184
|
+
adoption: AdoptionScanResult,
|
|
1185
|
+
mode: RunBootstrapAdoptionSummary["mode"],
|
|
1186
|
+
): RunBootstrapAdoptionSummary {
|
|
1187
|
+
let projectSourceCount = 0;
|
|
1188
|
+
let globalSourceCount = 0;
|
|
1189
|
+
for (const source of adoption.sources) {
|
|
1190
|
+
if (source.scope === "global") globalSourceCount += 1;
|
|
1191
|
+
else projectSourceCount += 1;
|
|
1192
|
+
}
|
|
1193
|
+
return {
|
|
1194
|
+
mode,
|
|
1195
|
+
sourceCount: adoption.sources.length,
|
|
1196
|
+
projectSourceCount,
|
|
1197
|
+
globalSourceCount,
|
|
1198
|
+
importedRuleCount: adoption.importedRules.length,
|
|
1199
|
+
conflictCount: adoption.conflicts.length,
|
|
1200
|
+
rejectedCount: adoption.rejected.length,
|
|
1201
|
+
includeGlobal: adoption.includeGlobal,
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/**
|
|
1206
|
+
* Top entry-point modules from the codewiki, used to orient a fresh session.
|
|
1207
|
+
* Entries the indexer tagged as "entry point" come first; otherwise the most
|
|
1208
|
+
* imported modules (highest in-degree) stand in as the structural anchors.
|
|
1209
|
+
*/
|
|
1210
|
+
function codewikiEntryPoints(codewiki: Codewiki, limit = 6): string[] {
|
|
1211
|
+
const fileById = new Map(codewiki.files.map((file) => [file.id, file] as const));
|
|
1212
|
+
const tagged = codewiki.files
|
|
1213
|
+
.filter((file) => file.lang !== "config" && file.role === "entry")
|
|
1214
|
+
.map((file) => file.path)
|
|
1215
|
+
.sort((a, b) => a.localeCompare(b));
|
|
1216
|
+
if (tagged.length >= limit) return tagged.slice(0, limit);
|
|
1217
|
+
const inDegree = new Map<string, number>();
|
|
1218
|
+
for (const edge of codewiki.edges) {
|
|
1219
|
+
if (!("toFileId" in edge)) continue;
|
|
1220
|
+
inDegree.set(edge.toFileId, (inDegree.get(edge.toFileId) ?? 0) + 1);
|
|
1221
|
+
}
|
|
1222
|
+
const ranked = [...inDegree.entries()]
|
|
1223
|
+
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
1224
|
+
.map(([fileId]) => fileById.get(fileId)?.path)
|
|
1225
|
+
.filter((path): path is string => typeof path === "string")
|
|
1226
|
+
.filter((path) => !tagged.includes(path));
|
|
1227
|
+
return [...tagged, ...ranked].slice(0, limit);
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
export async function runBootstrap(input: RunBootstrapInput = {}): Promise<RunBootstrapResult> {
|
|
1231
|
+
const cwd = input.cwd ?? process.cwd();
|
|
1232
|
+
const projectType = detectProjectType(cwd);
|
|
1233
|
+
progress(input, {
|
|
1234
|
+
phase: "scan",
|
|
1235
|
+
status: "started",
|
|
1236
|
+
message: "scanning project and sibling agent context",
|
|
1237
|
+
detail: projectType,
|
|
1238
|
+
});
|
|
1239
|
+
const adoption = scanAgentConfigs({
|
|
1240
|
+
cwd,
|
|
1241
|
+
...(input.homeDir ? { homeDir: input.homeDir } : {}),
|
|
1242
|
+
includeGlobal: input.includeGlobalImports === true,
|
|
1243
|
+
});
|
|
1244
|
+
const siblingFiles = loadBootstrapSiblingFiles(adoption);
|
|
1245
|
+
progress(input, {
|
|
1246
|
+
phase: "scan",
|
|
1247
|
+
status: "completed",
|
|
1248
|
+
message:
|
|
1249
|
+
siblingFiles.length === 0
|
|
1250
|
+
? "no sibling context files found"
|
|
1251
|
+
: `folded ${siblingFiles.length} sibling context file${siblingFiles.length === 1 ? "" : "s"}`,
|
|
1252
|
+
current: siblingFiles.length,
|
|
1253
|
+
total: siblingFiles.length,
|
|
1254
|
+
});
|
|
1255
|
+
const now = input.now?.() ?? new Date();
|
|
1256
|
+
const indexedAt = now.toISOString();
|
|
1257
|
+
// Index the repository before generation so the generator can ground CLIO-CODER.md
|
|
1258
|
+
// in the real structure (entry points, key modules), not just sibling prose.
|
|
1259
|
+
progress(input, { phase: "codewiki", status: "started", message: "building codewiki index" });
|
|
1260
|
+
let codewiki: Codewiki;
|
|
1261
|
+
let codewikiFingerprint: Fingerprint;
|
|
1262
|
+
if (input.preview === true) {
|
|
1263
|
+
const candidate = await buildCodewikiCandidate(cwd, projectType);
|
|
1264
|
+
codewiki = candidate.codewiki;
|
|
1265
|
+
codewikiFingerprint = candidate.fingerprint;
|
|
1266
|
+
} else {
|
|
1267
|
+
const coordinated = await coordinateCodewikiWrite(cwd, () => ({ kind: "build", cwd, language: projectType }), {
|
|
1268
|
+
beforeCommit: (_result, workspace) => ensureGitignore(workspace, input),
|
|
1269
|
+
afterCommit: ({ codewiki: committed, fingerprint }, workspace) =>
|
|
1270
|
+
persistCodewikiForGeneration(workspace, projectType, indexedAt, committed, fingerprint),
|
|
1271
|
+
});
|
|
1272
|
+
if (!coordinated) throw new Error("codewiki bootstrap transaction did not commit");
|
|
1273
|
+
codewiki = coordinated.codewiki;
|
|
1274
|
+
codewikiFingerprint = coordinated.worker.fingerprint;
|
|
1275
|
+
}
|
|
1276
|
+
const codewikiEntryCount = indexedSourceFileCount(codewiki);
|
|
1277
|
+
progress(input, {
|
|
1278
|
+
phase: "codewiki",
|
|
1279
|
+
status: "completed",
|
|
1280
|
+
message: `indexed ${codewikiEntryCount} source file${codewikiEntryCount === 1 ? "" : "s"}`,
|
|
1281
|
+
current: codewikiEntryCount,
|
|
1282
|
+
total: codewikiEntryCount,
|
|
1283
|
+
});
|
|
1284
|
+
const hadClioMd = existsSync(join(cwd, "CLIO-CODER.md"));
|
|
1285
|
+
const useExistingClioMdAsSource = hadClioMd && input.rewriteClioMd !== true;
|
|
1286
|
+
const existingClioMdText = useExistingClioMdAsSource ? readExistingClioMdText(cwd) : null;
|
|
1287
|
+
const existingClioMd = useExistingClioMdAsSource ? tryReadClioMd(cwd) : null;
|
|
1288
|
+
const existingParsed = existingClioMd?.ok ? existingClioMd.value : undefined;
|
|
1289
|
+
const replaceClioMd = input.applyClioMd === true || input.rewriteClioMd === true;
|
|
1290
|
+
if (
|
|
1291
|
+
input.adopt === true &&
|
|
1292
|
+
input.preview !== true &&
|
|
1293
|
+
hadClioMd &&
|
|
1294
|
+
!existingParsed &&
|
|
1295
|
+
!replaceClioMd &&
|
|
1296
|
+
input.proposeClioMd !== true
|
|
1297
|
+
) {
|
|
1298
|
+
const detail = existingClioMd && !existingClioMd.ok ? ` (${existingClioMd.error})` : "";
|
|
1299
|
+
throw new Error(
|
|
1300
|
+
`cannot refresh Imported agent context because CLIO-CODER.md is malformed${detail}; use --apply or --rewrite after reviewing the handbook`,
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
// A supplied generator *is* the request to generate: both entry points
|
|
1304
|
+
// withhold `generate` for --heuristic and --preview and supply it otherwise.
|
|
1305
|
+
// An existing CLIO-CODER.md used to suppress generation entirely, so a plain
|
|
1306
|
+
// `clio-coder context init` on an initialized repository dispatched nothing, wrote
|
|
1307
|
+
// `lastBootstrap.mode: "existing"`, and looked identical to a run that had no
|
|
1308
|
+
// route at all. The handbook still reaches the generator as source (see
|
|
1309
|
+
// `useExistingClioMdAsSource`), so this refreshes rather than replaces.
|
|
1310
|
+
const shouldGenerate = !hadClioMd || replaceClioMd || input.proposeClioMd === true || input.generate !== undefined;
|
|
1311
|
+
let output: BootstrapStructuredOutput;
|
|
1312
|
+
let generation: BootstrapGenerationTelemetry = {
|
|
1313
|
+
mode: shouldGenerate ? "heuristic" : existingParsed ? "existing" : "heuristic",
|
|
1314
|
+
parserOutcome: "not-run",
|
|
1315
|
+
};
|
|
1316
|
+
let reportedGeneration: BootstrapGenerationTelemetry | undefined;
|
|
1317
|
+
const reportGeneration: BootstrapGenerationSink = (reported) => {
|
|
1318
|
+
if (reportedGeneration === undefined) reportedGeneration = reported;
|
|
1319
|
+
};
|
|
1320
|
+
if (shouldGenerate) {
|
|
1321
|
+
progress(input, {
|
|
1322
|
+
phase: "generate",
|
|
1323
|
+
status: "started",
|
|
1324
|
+
message: input.generate
|
|
1325
|
+
? "drafting CLIO-CODER.md with the bootstrap agent"
|
|
1326
|
+
: "drafting CLIO-CODER.md with heuristic",
|
|
1327
|
+
});
|
|
1328
|
+
output = await (input.generate ?? heuristicBootstrapOutput)({
|
|
1329
|
+
cwd,
|
|
1330
|
+
expectedProjectName: projectName(cwd),
|
|
1331
|
+
projectType,
|
|
1332
|
+
siblingFiles,
|
|
1333
|
+
adoption,
|
|
1334
|
+
codewiki,
|
|
1335
|
+
...(existingParsed ? { existingClioMd: existingParsed } : {}),
|
|
1336
|
+
...(existingClioMdText ? { existingClioMdText } : {}),
|
|
1337
|
+
...(input.onProgress ? { progress: input.onProgress } : {}),
|
|
1338
|
+
reportGeneration,
|
|
1339
|
+
});
|
|
1340
|
+
generation = reportedGeneration ?? generation;
|
|
1341
|
+
let retainedModelSections = 0;
|
|
1342
|
+
output = stabilizeGeneratedOutput(
|
|
1343
|
+
{
|
|
1344
|
+
cwd,
|
|
1345
|
+
expectedProjectName: projectName(cwd),
|
|
1346
|
+
projectType,
|
|
1347
|
+
siblingFiles,
|
|
1348
|
+
adoption,
|
|
1349
|
+
codewiki,
|
|
1350
|
+
...(existingParsed ? { existingClioMd: existingParsed } : {}),
|
|
1351
|
+
...(existingClioMdText ? { existingClioMdText } : {}),
|
|
1352
|
+
},
|
|
1353
|
+
output,
|
|
1354
|
+
() => {
|
|
1355
|
+
retainedModelSections += 1;
|
|
1356
|
+
},
|
|
1357
|
+
generation.mode === "model",
|
|
1358
|
+
);
|
|
1359
|
+
if (generation.mode === "model" && retainedModelSections === 0) {
|
|
1360
|
+
generation = {
|
|
1361
|
+
...generation,
|
|
1362
|
+
mode: "heuristic",
|
|
1363
|
+
fallbackReason: "Scout draft contributed no evidence-grounded custom sections",
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
progress(input, {
|
|
1367
|
+
phase: "generate",
|
|
1368
|
+
status: "completed",
|
|
1369
|
+
message: `${output.projectName}: ${output.sections?.length ?? 0} custom section${(output.sections?.length ?? 0) === 1 ? "" : "s"}`,
|
|
1370
|
+
detail: `${generation.mode}; parser=${generation.parserOutcome}`,
|
|
1371
|
+
});
|
|
1372
|
+
} else {
|
|
1373
|
+
output = existingParsed
|
|
1374
|
+
? bootstrapOutputFromParsed(existingParsed)
|
|
1375
|
+
: await heuristicBootstrapOutput({ cwd, projectType, siblingFiles, adoption, codewiki });
|
|
1376
|
+
progress(input, {
|
|
1377
|
+
phase: "generate",
|
|
1378
|
+
status: "completed",
|
|
1379
|
+
message: hadClioMd
|
|
1380
|
+
? "preserving existing CLIO-CODER.md; no generated rewrite requested"
|
|
1381
|
+
: "using heuristic CLIO-CODER.md draft",
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
if (input.adopt === true) {
|
|
1385
|
+
output = replaceImportedAgentContext(output, renderImportedAgentContext(adoption));
|
|
1386
|
+
}
|
|
1387
|
+
const readNames = siblingFiles.map((file) => file.path).sort((a, b) => a.localeCompare(b));
|
|
1388
|
+
const previewStatus = gitStatus(cwd);
|
|
1389
|
+
if (input.preview === true) {
|
|
1390
|
+
progress(input, { phase: "clio-md", status: "completed", message: "preview ready; no files written" });
|
|
1391
|
+
const summary: RunBootstrapSummary = {
|
|
1392
|
+
action: "previewed",
|
|
1393
|
+
contextFileCount: readNames.length,
|
|
1394
|
+
contextFileNames: readNames,
|
|
1395
|
+
codewikiEntries: codewikiEntryCount,
|
|
1396
|
+
dirtyFiles: countStatusLines(previewStatus),
|
|
1397
|
+
adoption: summarizeAdoption(adoption, "preview"),
|
|
1398
|
+
};
|
|
1399
|
+
out(input.io, formatBootstrapSummary(summary));
|
|
1400
|
+
return {
|
|
1401
|
+
clioMdPath: join(cwd, "CLIO-CODER.md"),
|
|
1402
|
+
statePath: resolveStatePath(cwd),
|
|
1403
|
+
siblingFiles,
|
|
1404
|
+
output,
|
|
1405
|
+
projectType,
|
|
1406
|
+
summary,
|
|
1407
|
+
adoption,
|
|
1408
|
+
telemetry: { generation },
|
|
1409
|
+
preload: measureProjectPreload(cwd),
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
let clioMdPath = join(cwd, "CLIO-CODER.md");
|
|
1414
|
+
let proposalPath: string | undefined;
|
|
1415
|
+
let action: RunBootstrapSummary["action"] = "preserved";
|
|
1416
|
+
progress(input, {
|
|
1417
|
+
phase: "clio-md",
|
|
1418
|
+
status: "started",
|
|
1419
|
+
message: hadClioMd ? "preserving CLIO-CODER.md" : "writing CLIO-CODER.md",
|
|
1420
|
+
});
|
|
1421
|
+
if (!hadClioMd) {
|
|
1422
|
+
clioMdPath = writeClioMdFile(cwd, output);
|
|
1423
|
+
action = "wrote";
|
|
1424
|
+
} else if (replaceClioMd) {
|
|
1425
|
+
clioMdPath = writeClioMdFile(cwd, output);
|
|
1426
|
+
action = "refreshed";
|
|
1427
|
+
} else if (input.adopt === true && existingParsed) {
|
|
1428
|
+
clioMdPath = writeClioMdFile(cwd, output);
|
|
1429
|
+
action = "refreshed";
|
|
1430
|
+
} else if (input.proposeClioMd === true) {
|
|
1431
|
+
proposalPath = writeClioMdProposal(cwd, now, output);
|
|
1432
|
+
action = "proposed";
|
|
1433
|
+
}
|
|
1434
|
+
progress(input, {
|
|
1435
|
+
phase: "clio-md",
|
|
1436
|
+
status: "completed",
|
|
1437
|
+
message:
|
|
1438
|
+
action === "wrote"
|
|
1439
|
+
? "CLIO-CODER.md written"
|
|
1440
|
+
: action === "refreshed"
|
|
1441
|
+
? "CLIO-CODER.md refreshed"
|
|
1442
|
+
: action === "proposed"
|
|
1443
|
+
? "CLIO-CODER.md proposal written"
|
|
1444
|
+
: "CLIO-CODER.md preserved",
|
|
1445
|
+
detail: proposalPath ?? clioMdPath,
|
|
1446
|
+
});
|
|
1447
|
+
const adoptionApplied = input.adopt === true && (action === "wrote" || action === "refreshed");
|
|
1448
|
+
progress(input, { phase: "state", status: "started", message: "persisting codewiki and project state" });
|
|
1449
|
+
const statePath = writeProjectState(
|
|
1450
|
+
cwd,
|
|
1451
|
+
projectType,
|
|
1452
|
+
now,
|
|
1453
|
+
indexedAt,
|
|
1454
|
+
adoption,
|
|
1455
|
+
adoptionApplied,
|
|
1456
|
+
codewiki.version,
|
|
1457
|
+
codewikiFingerprint,
|
|
1458
|
+
generation,
|
|
1459
|
+
shouldGenerate,
|
|
1460
|
+
);
|
|
1461
|
+
progress(input, {
|
|
1462
|
+
phase: "state",
|
|
1463
|
+
status: "completed",
|
|
1464
|
+
message: `state updated; ${codewikiEntryCount} codewiki entr${codewikiEntryCount === 1 ? "y" : "ies"}`,
|
|
1465
|
+
});
|
|
1466
|
+
|
|
1467
|
+
const postStatus = gitStatus(cwd);
|
|
1468
|
+
const summary: RunBootstrapSummary = {
|
|
1469
|
+
action,
|
|
1470
|
+
contextFileCount: readNames.length,
|
|
1471
|
+
contextFileNames: readNames,
|
|
1472
|
+
codewikiEntries: codewikiEntryCount,
|
|
1473
|
+
dirtyFiles: countStatusLines(postStatus),
|
|
1474
|
+
adoption: summarizeAdoption(adoption, adoptionApplied ? "adopt" : "scan"),
|
|
1475
|
+
...(proposalPath ? { proposalPath } : {}),
|
|
1476
|
+
};
|
|
1477
|
+
out(input.io, formatBootstrapSummary(summary));
|
|
1478
|
+
const preload = measureProjectPreload(cwd);
|
|
1479
|
+
out(input.io, ` preload: ${preload.label}\n`);
|
|
1480
|
+
if (preload.mode === "full" && preload.nearLimit) {
|
|
1481
|
+
warn(
|
|
1482
|
+
input.io,
|
|
1483
|
+
` warning: project context is within 10% of the preload limit (${preload.chars} chars of 8000, ${preload.lines} lines of 220); the next growth may flip it to a synopsis\n`,
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
progress(input, {
|
|
1487
|
+
phase: "done",
|
|
1488
|
+
status: "completed",
|
|
1489
|
+
message: `${summary.action} CLIO-CODER.md; ${summary.dirtyFiles} dirty file${summary.dirtyFiles === 1 ? "" : "s"}; preload: ${preload.label}`,
|
|
1490
|
+
});
|
|
1491
|
+
return {
|
|
1492
|
+
clioMdPath,
|
|
1493
|
+
statePath,
|
|
1494
|
+
siblingFiles,
|
|
1495
|
+
output,
|
|
1496
|
+
projectType,
|
|
1497
|
+
summary,
|
|
1498
|
+
adoption,
|
|
1499
|
+
telemetry: { generation },
|
|
1500
|
+
preload,
|
|
1501
|
+
};
|
|
1502
|
+
}
|