@iowarp/clio-coder 0.3.1 → 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 +90 -2
- package/CONTRIBUTING.md +23 -23
- package/README.md +284 -613
- package/dist/{acp-FPR54DGL.js → acp-BIYHVZIM.js} +43 -53
- package/dist/{agents-OGPIHPJH.js → agents-YT6SSRIT.js} +43 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
- package/dist/{chunk-PV4JUBVJ.js → chunk-2EHAIA3X.js} +40 -21
- package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/{chunk-MAR7Y6HW.js → chunk-3ZXDFGR5.js} +23 -16
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
- package/dist/chunk-4KLWL3UC.js +18 -0
- package/dist/chunk-4VP4KH3K.js +962 -0
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
- package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
- 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-TEKV33Q5.js → chunk-77VKQEHF.js} +65 -33
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/{chunk-M5T5VO65.js → chunk-7EYHLWU7.js} +837 -635
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/chunk-AO4RKG4M.js +277 -0
- package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
- package/dist/chunk-ARBGF5F7.js +174 -0
- package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/chunk-ED4KHGC3.js +143 -0
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/{chunk-RPTR2H26.js → chunk-EPVUXGXG.js} +21 -15
- 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-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
- package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/{chunk-4QKXUHSR.js → chunk-IGLFWIYI.js} +70 -20
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-PFEFKVGL.js → chunk-J5HN4RYU.js} +13 -11
- package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
- package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
- package/dist/chunk-KJ5LWLOE.js +1077 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-G34LV2PF.js → chunk-LBNRH5WM.js} +84 -170
- package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
- package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
- package/dist/chunk-MAW544W2.js +1882 -0
- package/dist/chunk-MBS4V7ZP.js +217 -0
- package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
- package/dist/chunk-MNA4JGU4.js +255 -0
- package/dist/chunk-MQSRRFWA.js +3428 -0
- package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/chunk-OHHN2SO4.js +5135 -0
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
- package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/{chunk-ASND7OZK.js → chunk-QTYWRVRA.js} +13 -13
- package/dist/{chunk-EYOKLTMF.js → chunk-SRF2PJNW.js} +17 -3
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/chunk-STBPMHSX.js +2456 -0
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-Q3RUPKEJ.js → chunk-V4RXGQ5Q.js} +58 -189
- 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-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-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
- package/dist/cli/index.js +62 -54
- 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-DMAOEKFB.js → components-KELWS457.js} +11 -6
- package/dist/{config-IRUQ7SE4.js → config-GTLUW2PR.js} +92 -55
- package/dist/configure-R6A64DHX.js +42 -0
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-3KWFLHJG.js → context-JFZEJ7W5.js} +15 -13
- package/dist/{context-5RADCKTR.js → context-RW5HC47S.js} +71 -35
- package/dist/{context-clear-7TSNPAAI.js → context-clear-6ZHBAZZT.js} +54 -28
- package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
- package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
- package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
- package/dist/{doctor-UC5NAJYQ.js → doctor-KI767GSN.js} +27 -17
- package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
- package/dist/{evidence-YEGUW4L3.js → evidence-UA6AWDQQ.js} +46 -26
- package/dist/{evolve-TXARCTPG.js → evolve-QNTFGV6Z.js} +45 -25
- package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
- package/dist/{fleet-6G3DHNYE.js → fleet-Q7UOMUSG.js} +163 -54
- package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
- package/dist/{init-KZ5QTF6M.js → init-WBB65ZHQ.js} +69 -32
- package/dist/{memory-73ESV5YC.js → memory-MD3O64RI.js} +48 -27
- package/dist/{models-A4PVNWJK.js → models-BZU34YWD.js} +39 -25
- package/dist/monitor-MEQA5C3I.js +661 -0
- package/dist/{chunk-FCIH3BIZ.js → orchestrator-CGFKEP27.js} +11832 -8687
- package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
- package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
- package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
- package/dist/{run-YTPEYQOH.js → run-IV4Q6RLN.js} +101 -61
- package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
- package/dist/{skills-2V6RA3OQ.js → skills-LQEKRDTN.js} +34 -14
- package/dist/{skills-eval-S2TVJO4F.js → skills-eval-3DC4HEWS.js} +70 -34
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-TYXLPB23.js → targets-C4SSGQOB.js} +43 -27
- package/dist/terminal-lease-IT5JW2NR.js +395 -0
- package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
- package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
- package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
- package/dist/{upgrade-33G2LMM5.js → upgrade-7TT7SQ3G.js} +45 -25
- package/dist/{usage-ZAFSXKKG.js → usage-GV4PKT3M.js} +62 -31
- package/dist/verify-G6V4D2G7.js +716 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-DQF6Z66B.js} +74 -34
- package/dist/worker/entry.js +221 -36
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +22 -17
- package/docs/acp.md +168 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +136 -7
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +114 -71
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +174 -46
- package/docs/context-engine.md +29 -6
- package/docs/development-pipeline.md +26 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +13 -5
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +9 -9
- package/docs/fleet-dispatch.md +7 -5
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +34 -27
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +45 -14
- 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 +3 -3
- package/docs/prompt-envelope-and-tools.md +24 -3
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -115
- package/docs/safety-model.md +9 -5
- 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 +1 -1
- package/docs/tool-usage.md +3 -3
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +47 -10
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +19 -22
- 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/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/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 +31 -4
- package/src/cli/clio.ts +68 -6
- package/src/cli/config-inspect.ts +28 -22
- package/src/cli/configure.ts +47 -9
- package/src/cli/context-clear.ts +2 -2
- package/src/cli/context-index.ts +21 -23
- package/src/cli/context.ts +13 -8
- package/src/cli/default-target.ts +9 -17
- package/src/cli/docs.ts +11 -5
- package/src/cli/evidence.ts +4 -1
- package/src/cli/extensions.ts +10 -1
- package/src/cli/fleet.ts +47 -6
- package/src/cli/index.ts +55 -26
- package/src/cli/memory.ts +3 -1
- package/src/cli/models.ts +1 -1
- package/src/cli/modes/json-stream.ts +37 -1
- package/src/cli/modes/print.ts +24 -9
- package/src/cli/run.ts +2 -2
- package/src/cli/skills-eval.ts +23 -8
- package/src/cli/skills.ts +19 -4
- package/src/cli/targets.ts +4 -0
- package/src/cli/text-layout.ts +15 -5
- package/src/cli/trace.ts +62 -14
- package/src/cli/upgrade.ts +18 -2
- package/src/cli/usage.ts +10 -3
- package/src/cli/wiki-generate.ts +2 -1
- package/src/core/agent-environment.ts +7 -0
- package/src/core/bash-exec.ts +72 -1
- package/src/core/boot-trace.ts +9 -4
- package/src/core/bus-events.ts +20 -4
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +131 -2
- package/src/core/defaults.ts +39 -5
- package/src/core/domain-loader.ts +12 -5
- package/src/core/git-commit-attribution.ts +362 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/response-schema.ts +1 -1
- package/src/core/safe-exec.ts +13 -1
- package/src/core/settings-layers.ts +155 -21
- package/src/core/skill-activation.ts +1 -1
- package/src/core/startup-timer.ts +3 -3
- package/src/core/state-file-lock.ts +13 -1
- package/src/core/termination.ts +78 -5
- package/src/domains/config/classify.ts +15 -3
- package/src/domains/config/extension.ts +19 -13
- package/src/domains/config/index.ts +10 -0
- package/src/domains/config/keybindings.ts +42 -6
- package/src/domains/context/bootstrap-prompt.ts +1 -1
- package/src/domains/context/bootstrap.ts +111 -18
- package/src/domains/context/clear.ts +16 -11
- package/src/domains/context/clio-md.ts +111 -9
- 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/coordinator.ts +182 -0
- package/src/domains/context/codewiki/indexer.ts +59 -144
- 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 +1 -1
- package/src/domains/context/contract.ts +11 -5
- package/src/domains/context/extension.ts +94 -143
- package/src/domains/context/fingerprint.ts +3 -1
- package/src/domains/context/index.ts +12 -22
- package/src/domains/context/project-metadata.ts +19 -0
- package/src/domains/context/prompt-context.ts +9 -10
- package/src/domains/context/refresh.ts +29 -21
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/wiki/generate.ts +39 -34
- package/src/domains/context/wiki/plan.ts +1 -1
- package/src/domains/context/wiki/prompts.ts +21 -8
- package/src/domains/dispatch/code-step.ts +20 -1
- package/src/domains/dispatch/extension.ts +158 -21
- package/src/domains/dispatch/failure-classification.ts +6 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/orphan-recovery.ts +50 -8
- package/src/domains/dispatch/receipt-integrity.ts +5 -0
- package/src/domains/dispatch/state.ts +31 -6
- package/src/domains/dispatch/transport.ts +2 -1
- package/src/domains/dispatch/types.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +21 -2
- package/src/domains/eval/metrics/context.ts +1 -1
- package/src/domains/eval/types.ts +0 -1
- package/src/domains/evidence/build.ts +41 -1
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +24 -4
- package/src/domains/middleware/hooks-io.ts +12 -0
- package/src/domains/middleware/skills-reminder.ts +30 -15
- package/src/domains/prompts/compiler.ts +142 -84
- package/src/domains/prompts/contract.ts +18 -2
- package/src/domains/prompts/extension.ts +39 -7
- package/src/domains/prompts/fragment-loader.ts +0 -1
- package/src/domains/prompts/fragments/identity/clio.md +2 -4
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
- package/src/domains/prompts/fragments/operating/contract.md +4 -50
- 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/preload.ts +3 -3
- package/src/domains/providers/auth/api-key.ts +1 -1
- package/src/domains/providers/auth/backend-file.ts +20 -10
- package/src/domains/providers/auth/backend-memory.ts +59 -4
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/oauth.ts +2 -1
- package/src/domains/providers/auth/storage.ts +97 -38
- package/src/domains/providers/capabilities.ts +12 -4
- package/src/domains/providers/contract.ts +15 -4
- package/src/domains/providers/extension.ts +18 -6
- package/src/domains/providers/model-runtime-capabilities.ts +15 -4
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
- package/src/domains/providers/plugins.ts +5 -3
- package/src/domains/providers/probe/fingerprint.ts +25 -5
- package/src/domains/providers/registry.ts +31 -10
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -2
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/support.ts +6 -3
- package/src/domains/providers/types/local-model-quirks.ts +7 -9
- package/src/domains/providers/types/runtime-descriptor.ts +12 -1
- package/src/domains/providers/types/target-descriptor.ts +22 -0
- package/src/domains/resources/contract.ts +0 -1
- package/src/domains/resources/extension.ts +1 -3
- package/src/domains/resources/loader.ts +3 -4
- package/src/domains/resources/prompts/loader.ts +16 -2
- package/src/domains/resources/prompts/substitute.ts +1 -65
- package/src/domains/resources/skills/content-hash.ts +2 -0
- package/src/domains/resources/skills/install.ts +17 -0
- package/src/domains/resources/skills/loader.ts +17 -10
- package/src/domains/resources/skills/marketplace.ts +55 -9
- package/src/domains/safety/action-classifier.ts +4 -2
- package/src/domains/safety/audit.ts +8 -2
- package/src/domains/safety/extension.ts +1 -1
- package/src/domains/session/compaction/branch-summary.ts +3 -2
- package/src/domains/session/compaction/cut-point.ts +2 -1
- package/src/domains/session/compaction/tokens.ts +2 -1
- package/src/domains/session/context-ledger.ts +14 -0
- package/src/domains/session/contract.ts +15 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +66 -3
- package/src/domains/session/extension.ts +93 -12
- package/src/domains/session/retry.ts +10 -18
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +207 -13
- package/src/domains/session/tree/active-path.ts +44 -5
- package/src/domains/session/tree/fork.ts +26 -27
- package/src/domains/session/tree/preview.ts +2 -2
- package/src/domains/session/workspace/git-probe.ts +17 -11
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/errors.ts +96 -0
- package/src/engine/acp/server.ts +1728 -146
- package/src/engine/acp/transport.ts +135 -14
- package/src/engine/acp/types.ts +26 -0
- package/src/engine/agent.ts +3 -3
- package/src/engine/ai.ts +32 -27
- package/src/engine/alcf-oauth.ts +26 -19
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/index.ts +3 -7
- package/src/engine/apis/llamacpp-residency.ts +49 -9
- package/src/engine/apis/lmstudio-residency.ts +5 -21
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +24 -3
- package/src/engine/apis/openai-completions.ts +170 -91
- package/src/engine/apis/residency.ts +139 -3
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +16 -12
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +16 -59
- package/src/engine/strip-tokenizer-sentinels.ts +1 -1
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +17 -9
- package/src/engine/types.ts +3 -6
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1 -1
- package/src/engine/worker-tools.ts +9 -4
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +288 -150
- package/src/interactive/application-controller.ts +89 -2
- package/src/interactive/chat-loop.ts +266 -41
- package/src/interactive/chat-panel.ts +173 -47
- package/src/interactive/chat-renderer.ts +262 -72
- package/src/interactive/clio-editor.ts +3 -8
- package/src/interactive/command-fallbacks.ts +2 -2
- package/src/interactive/context-overlay.ts +27 -1
- package/src/interactive/editor-submit.ts +228 -24
- 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/footer/dashboard.ts +4 -0
- package/src/interactive/footer/notifications.ts +1 -1
- package/src/interactive/footer/widgets.ts +20 -2
- package/src/interactive/footer-panel.ts +2 -2
- package/src/interactive/format-time.ts +14 -2
- package/src/interactive/interactive-application.ts +201 -17
- package/src/interactive/interactive-event-projection.ts +6 -1
- package/src/interactive/interactive-input-runtime.ts +50 -4
- package/src/interactive/interactive-presentation.ts +151 -19
- package/src/interactive/interactive-shell.ts +268 -14
- package/src/interactive/interactive-slash-runtime.ts +176 -114
- package/src/interactive/interactive-tickers.ts +38 -7
- package/src/interactive/keybinding-manager.ts +1 -1
- package/src/interactive/layout.ts +40 -3
- package/src/interactive/overlay-frame.ts +1 -1
- package/src/interactive/overlay-general-openers.ts +58 -1
- package/src/interactive/overlay-key-routing.ts +3 -0
- package/src/interactive/overlay-lifecycle.ts +13 -0
- package/src/interactive/overlay-permission-lifecycle.ts +2 -1
- package/src/interactive/overlay-session-lifecycle.ts +69 -12
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/help-reference.ts +15 -10
- package/src/interactive/overlays/model-selector.ts +34 -16
- package/src/interactive/overlays/session-selector.ts +18 -0
- package/src/interactive/overlays/settings.ts +105 -17
- package/src/interactive/overlays/skills-hub.ts +4 -4
- package/src/interactive/overlays/tree-selector.ts +41 -6
- package/src/interactive/render-trace.ts +499 -90
- package/src/interactive/renderers/compaction-summary.ts +2 -2
- package/src/interactive/renderers/diff.ts +115 -104
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/tool-execution.ts +386 -133
- package/src/interactive/renderers/worker-entry.ts +20 -4
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/slash-autocomplete.ts +6 -114
- package/src/interactive/slash-commands.ts +135 -47
- package/src/interactive/slash-spec.ts +9 -38
- package/src/interactive/status/controller.ts +5 -1
- 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 +368 -14
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/tokens.ts +1 -1
- package/src/interactive/turn-context.ts +4 -3
- package/src/interactive/turn-persistence.ts +30 -13
- package/src/interactive/turn-queues.ts +12 -0
- package/src/interactive/turn-recovery.ts +25 -8
- package/src/interactive/turn-runtime.ts +79 -12
- package/src/interactive/turn-state.ts +10 -0
- package/src/interactive/view/artifacts.ts +114 -4
- package/src/interactive/view/view-overlay.ts +3 -0
- package/src/interactive/welcome-dashboard.ts +17 -16
- package/src/interactive/worker-receipts.ts +52 -3
- package/src/interactive/worker-stream.ts +5 -1
- package/src/tools/agent-tools.ts +23 -3
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +23 -13
- package/src/tools/bash.ts +30 -2
- package/src/tools/bootstrap.ts +34 -431
- 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 +8 -22
- package/src/tools/codewiki/shared.ts +41 -38
- package/src/tools/context/docs-engine.ts +14 -3
- package/src/tools/context/index.ts +107 -28
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +5 -5
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +9 -4
- 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-types.ts +77 -0
- package/src/tools/dispatch.ts +67 -3161
- package/src/tools/find.ts +4 -2
- package/src/tools/grep.ts +2 -2
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +3 -3
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +2 -32
- package/src/tools/observers.ts +2 -2
- package/src/tools/registry.ts +39 -27
- package/src/tools/safe-exec.ts +2 -2
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +2 -13
- package/src/tools/tasks.ts +108 -11
- package/src/tools/truncate.ts +25 -184
- package/src/tools/verify/frontend.ts +3 -1
- package/src/tools/verify/index.ts +3 -38
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +2 -20
- package/src/tools/write.ts +7 -2
- package/src/worker/entry.ts +39 -2
- package/src/worker/spec-contract.ts +26 -5
- package/dist/chunk-7SS2CTV2.js +0 -61361
- package/dist/chunk-DKGKUHFA.js +0 -924
- package/dist/chunk-GEP36Y4X.js +0 -12796
- package/dist/chunk-XYWBQRDM.js +0 -137
- package/dist/clio-BZVGEUFJ.js +0 -58
- package/dist/configure-S7S6F6CL.js +0 -32
- 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 -939
- 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 -374
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/src/core/release.ts +0 -2
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
- package/src/engine/apis/lmstudio-native.ts +0 -1438
- package/src/engine/apis/thinking-replay.ts +0 -11
- package/src/tools/string-enum.ts +0 -15
|
@@ -4,20 +4,21 @@ import {
|
|
|
4
4
|
} from "./chunk-5WIGXA4T.js";
|
|
5
5
|
import {
|
|
6
6
|
loadMemoryRecordsSync
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-J5HN4RYU.js";
|
|
8
|
+
import {
|
|
9
|
+
sha256
|
|
10
|
+
} from "./chunk-6EJV5X2W.js";
|
|
8
11
|
import {
|
|
9
12
|
WIKI_INDEX,
|
|
10
13
|
WIKI_PLAN_FILE,
|
|
11
14
|
WIKI_QUICKSTART,
|
|
12
15
|
changedPathsSince,
|
|
13
|
-
compileGlobRegex,
|
|
14
16
|
computeWikiContentHash,
|
|
15
17
|
computeWikiContentHashOfDir,
|
|
16
18
|
currentWikiGitHead,
|
|
17
19
|
isGeneratedWikiFile,
|
|
18
20
|
listWikiPages,
|
|
19
21
|
listWikiPagesInDir,
|
|
20
|
-
normalizeGlobInput,
|
|
21
22
|
readWikiMeta,
|
|
22
23
|
readWikiPage,
|
|
23
24
|
readWikiPlanFile,
|
|
@@ -32,49 +33,53 @@ import {
|
|
|
32
33
|
wikiStaleness,
|
|
33
34
|
writeWikiMeta,
|
|
34
35
|
writeWikiPlanFile
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-X4RCMKVQ.js";
|
|
36
37
|
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
buildCodewikiCandidate,
|
|
39
|
+
coordinateCodewikiExclusive,
|
|
40
|
+
coordinateCodewikiWrite,
|
|
41
|
+
drainCodewikiWrites,
|
|
41
42
|
readClioState,
|
|
42
43
|
statePath,
|
|
43
44
|
writeClioState
|
|
44
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-MVVUPGPW.js";
|
|
46
|
+
import {
|
|
47
|
+
compileGlobRegex,
|
|
48
|
+
normalizeGlobInput
|
|
49
|
+
} from "./chunk-VG7TBQIY.js";
|
|
50
|
+
import {
|
|
51
|
+
detectProjectType
|
|
52
|
+
} from "./chunk-YHZX5GEU.js";
|
|
53
|
+
import {
|
|
54
|
+
computeFingerprintCached,
|
|
55
|
+
isStale
|
|
56
|
+
} from "./chunk-VJWL6YS5.js";
|
|
45
57
|
import {
|
|
46
|
-
buildCodewiki,
|
|
47
|
-
codewikiNeedsBackfill,
|
|
48
58
|
codewikiPath,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
enumerateWorkspaceFiles,
|
|
52
|
-
parseCodewikiRaw,
|
|
53
|
-
readCodewiki,
|
|
54
|
-
readCodewikiAsync,
|
|
55
|
-
syncCodewiki,
|
|
56
|
-
updateCodewikiPaths,
|
|
57
|
-
writeCodewiki
|
|
58
|
-
} from "./chunk-N6F52NLF.js";
|
|
59
|
+
readCodewiki
|
|
60
|
+
} from "./chunk-LBMZMYH2.js";
|
|
59
61
|
import {
|
|
60
|
-
|
|
61
|
-
} from "./chunk-
|
|
62
|
+
enumerateWorkspaceFiles
|
|
63
|
+
} from "./chunk-EKMEHE4H.js";
|
|
62
64
|
import {
|
|
63
65
|
ceilChars
|
|
64
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-LZSJBIVT.js";
|
|
65
67
|
import {
|
|
66
68
|
INTEROP_AGENT_KINDS
|
|
67
69
|
} from "./chunk-IHXBNWMM.js";
|
|
68
|
-
import {
|
|
69
|
-
BusChannels
|
|
70
|
-
} from "./chunk-Q5WJOSJ7.js";
|
|
71
70
|
import {
|
|
72
71
|
require_dist
|
|
73
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-APJ265NV.js";
|
|
74
73
|
import {
|
|
75
74
|
clioDataDir,
|
|
76
75
|
resolveClioDirs
|
|
77
76
|
} from "./chunk-BNAZZHFG.js";
|
|
77
|
+
import {
|
|
78
|
+
BusChannels
|
|
79
|
+
} from "./chunk-OQ33BKR3.js";
|
|
80
|
+
import {
|
|
81
|
+
classifyProjectPreload
|
|
82
|
+
} from "./chunk-JVCV3ICN.js";
|
|
78
83
|
import {
|
|
79
84
|
resolvePackageRoot
|
|
80
85
|
} from "./chunk-IWHMRKLL.js";
|
|
@@ -86,12 +91,6 @@ import {
|
|
|
86
91
|
// src/domains/context/index.ts
|
|
87
92
|
init_esm_shims();
|
|
88
93
|
|
|
89
|
-
// src/domains/context/extension.ts
|
|
90
|
-
init_esm_shims();
|
|
91
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
92
|
-
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
93
|
-
import { isAbsolute, relative as relative3 } from "node:path";
|
|
94
|
-
|
|
95
94
|
// src/domains/context/adoption.ts
|
|
96
95
|
init_esm_shims();
|
|
97
96
|
import { createHash } from "node:crypto";
|
|
@@ -159,7 +158,7 @@ var SECRET_LINE_PATTERNS = [
|
|
|
159
158
|
/\bxox[baprs]-[A-Za-z0-9-]{20,}\b/,
|
|
160
159
|
/\bAIza[0-9A-Za-z_-]{20,}\b/
|
|
161
160
|
];
|
|
162
|
-
function
|
|
161
|
+
function sha2562(text) {
|
|
163
162
|
return createHash("sha256").update(text).digest("hex");
|
|
164
163
|
}
|
|
165
164
|
function normalizeText(text) {
|
|
@@ -236,8 +235,8 @@ function discoverCandidateSpecs(cwd, home, includeGlobal) {
|
|
|
236
235
|
const specs = [];
|
|
237
236
|
const seen = /* @__PURE__ */ new Set();
|
|
238
237
|
let order = 0;
|
|
239
|
-
const add = (
|
|
240
|
-
const abs = resolve(
|
|
238
|
+
const add = (path2, scope, provider, kind) => {
|
|
239
|
+
const abs = resolve(path2);
|
|
241
240
|
if (seen.has(abs)) return;
|
|
242
241
|
seen.add(abs);
|
|
243
242
|
const scopedDir = scope === "project" && kind === "instructions" ? relative(cwd, dirname(abs)) : "";
|
|
@@ -509,7 +508,7 @@ function rejectedCandidate(spec, displayPath2, reason, evidence) {
|
|
|
509
508
|
kind: spec.kind,
|
|
510
509
|
...spec.directoryScope ? { directoryScope: spec.directoryScope } : {},
|
|
511
510
|
reason,
|
|
512
|
-
fingerprintSha256:
|
|
511
|
+
fingerprintSha256: sha2562(`rejected\0${reason}\0${evidence}`)
|
|
513
512
|
};
|
|
514
513
|
}
|
|
515
514
|
function statEvidence(stat) {
|
|
@@ -558,7 +557,7 @@ function readCandidate(spec, cwd, home) {
|
|
|
558
557
|
kindLabel: KIND_LABELS[spec.kind],
|
|
559
558
|
...spec.directoryScope ? { directoryScope: spec.directoryScope } : {},
|
|
560
559
|
content,
|
|
561
|
-
contentSha256:
|
|
560
|
+
contentSha256: sha2562(content),
|
|
562
561
|
byteLength: Buffer.byteLength(content, "utf8"),
|
|
563
562
|
itemCount: rules.length,
|
|
564
563
|
order: spec.order
|
|
@@ -622,7 +621,7 @@ function scanAgentConfigs(options) {
|
|
|
622
621
|
kind: result.kind,
|
|
623
622
|
...result.directoryScope ? { directoryScope: result.directoryScope } : {},
|
|
624
623
|
reason: "aggregate source byte budget exceeded",
|
|
625
|
-
fingerprintSha256:
|
|
624
|
+
fingerprintSha256: sha2562(`rejected\0aggregate source byte budget exceeded\0${result.contentSha256}`)
|
|
626
625
|
});
|
|
627
626
|
continue;
|
|
628
627
|
}
|
|
@@ -648,8 +647,8 @@ function scanAgentConfigs(options) {
|
|
|
648
647
|
};
|
|
649
648
|
}
|
|
650
649
|
function renderSourceList(paths) {
|
|
651
|
-
if (paths.length <= 3) return paths.map((
|
|
652
|
-
return `${paths.slice(0, 3).map((
|
|
650
|
+
if (paths.length <= 3) return paths.map((path2) => `\`${path2}\``).join(", ");
|
|
651
|
+
return `${paths.slice(0, 3).map((path2) => `\`${path2}\``).join(", ")} +${paths.length - 3} more`;
|
|
653
652
|
}
|
|
654
653
|
function quoteShort(text) {
|
|
655
654
|
const cleaned = text.replace(/\s+/g, " ").trim();
|
|
@@ -756,12 +755,12 @@ function adoptionSourcesChanged(snapshots, options = {}) {
|
|
|
756
755
|
init_esm_shims();
|
|
757
756
|
import { execFileSync } from "node:child_process";
|
|
758
757
|
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
759
|
-
import { dirname as
|
|
758
|
+
import { dirname as dirname3, join as join4, parse } from "node:path";
|
|
760
759
|
|
|
761
760
|
// src/domains/context/clio-md.ts
|
|
762
761
|
init_esm_shims();
|
|
763
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
764
|
-
import { join as join2 } from "node:path";
|
|
762
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
|
|
763
|
+
import { basename as basename2, dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
|
|
765
764
|
var FOOTER_RE = /<!--\s*clio:fingerprint v1\s*\n([\s\S]*?)\n\s*-->/;
|
|
766
765
|
var H1_RE = /^#\s+(.+?)\s*$/gm;
|
|
767
766
|
var H2_RE = /^##\s+(.+?)\s*$/gm;
|
|
@@ -973,7 +972,10 @@ function serializeClioMd(input) {
|
|
|
973
972
|
function renderProjectTypeFragment(projectType) {
|
|
974
973
|
return `<project-type>${projectType}</project-type>`;
|
|
975
974
|
}
|
|
976
|
-
function
|
|
975
|
+
function escapeXmlAttribute(value) {
|
|
976
|
+
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
977
|
+
}
|
|
978
|
+
function renderProjectContextFragment(parsed, sourcePath) {
|
|
977
979
|
const sections = [`# ${parsed.projectName}`, parsed.identity];
|
|
978
980
|
if (parsed.conventions.length > 0) {
|
|
979
981
|
sections.push("## Conventions", ...parsed.conventions.map((item) => `- ${item}`));
|
|
@@ -987,24 +989,82 @@ function renderProjectContextFragment(parsed) {
|
|
|
987
989
|
if (parsed.importedAgentContext) {
|
|
988
990
|
sections.push("## Imported agent context", parsed.importedAgentContext);
|
|
989
991
|
}
|
|
990
|
-
|
|
992
|
+
const source = sourcePath ? ` path="${escapeXmlAttribute(sourcePath)}"` : "";
|
|
993
|
+
return `<project-context${source}>
|
|
991
994
|
${sections.join("\n\n")}
|
|
992
995
|
</project-context>`;
|
|
993
996
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
+
var PROJECT_CONTEXT_CANDIDATES = ["CLIO-CODER.override.md", "CLIO-CODER.md"];
|
|
998
|
+
function selectedClioMdPath(directory) {
|
|
999
|
+
for (const filename of PROJECT_CONTEXT_CANDIDATES) {
|
|
1000
|
+
const filePath = join2(directory, filename);
|
|
1001
|
+
if (!existsSync2(filePath)) continue;
|
|
1002
|
+
try {
|
|
1003
|
+
if (statSync2(filePath).isFile()) return filePath;
|
|
1004
|
+
} catch {
|
|
1005
|
+
return filePath;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
return null;
|
|
1009
|
+
}
|
|
1010
|
+
function readClioMdPath(filePath) {
|
|
997
1011
|
let content;
|
|
998
1012
|
try {
|
|
999
1013
|
content = readFileSync2(filePath, "utf8");
|
|
1000
1014
|
} catch (err) {
|
|
1001
|
-
|
|
1002
|
-
return { ok: false, error: message };
|
|
1015
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
1003
1016
|
}
|
|
1004
1017
|
const parsed = parseClioMd(content);
|
|
1005
1018
|
if (!parsed.ok) return { ok: false, error: parsed.errors.join("; ") };
|
|
1006
1019
|
return { ok: true, value: parsed.value };
|
|
1007
1020
|
}
|
|
1021
|
+
function mergeClioMdFiles(files) {
|
|
1022
|
+
const nearest = files.at(-1)?.value;
|
|
1023
|
+
if (!nearest) return null;
|
|
1024
|
+
return {
|
|
1025
|
+
projectName: nearest.projectName,
|
|
1026
|
+
identity: files.map((file) => file.value.identity).join("\n\n"),
|
|
1027
|
+
conventions: files.flatMap((file) => file.value.conventions),
|
|
1028
|
+
invariants: files.flatMap((file) => file.value.invariants),
|
|
1029
|
+
sections: files.flatMap((file) => file.value.sections),
|
|
1030
|
+
importedAgentContext: files.map((file) => file.value.importedAgentContext).filter((value) => value !== null).join("\n\n") || null,
|
|
1031
|
+
fingerprint: nearest.fingerprint,
|
|
1032
|
+
firstInit: nearest.firstInit,
|
|
1033
|
+
warnings: files.flatMap((file) => file.value.warnings)
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
function loadProjectClioMd(cwd) {
|
|
1037
|
+
const directories = [];
|
|
1038
|
+
let directory = resolve2(cwd);
|
|
1039
|
+
while (true) {
|
|
1040
|
+
directories.unshift(directory);
|
|
1041
|
+
const parent = dirname2(directory);
|
|
1042
|
+
if (parent === directory) break;
|
|
1043
|
+
directory = parent;
|
|
1044
|
+
}
|
|
1045
|
+
const selectedPaths = [];
|
|
1046
|
+
for (const current of directories) {
|
|
1047
|
+
const selected = selectedClioMdPath(current);
|
|
1048
|
+
if (!selected) continue;
|
|
1049
|
+
if (basename2(selected) === "CLIO-CODER.override.md") {
|
|
1050
|
+
selectedPaths.length = 0;
|
|
1051
|
+
}
|
|
1052
|
+
selectedPaths.push(selected);
|
|
1053
|
+
}
|
|
1054
|
+
const files = [];
|
|
1055
|
+
const errors = [];
|
|
1056
|
+
for (const filePath of selectedPaths) {
|
|
1057
|
+
const read = readClioMdPath(filePath);
|
|
1058
|
+
if (read.ok) files.push({ path: filePath, value: read.value });
|
|
1059
|
+
else errors.push({ path: filePath, error: read.error });
|
|
1060
|
+
}
|
|
1061
|
+
return { files, errors, value: mergeClioMdFiles(files) };
|
|
1062
|
+
}
|
|
1063
|
+
function tryReadClioMd(cwd) {
|
|
1064
|
+
const filePath = join2(cwd, "CLIO-CODER.md");
|
|
1065
|
+
if (!existsSync2(filePath)) return null;
|
|
1066
|
+
return readClioMdPath(filePath);
|
|
1067
|
+
}
|
|
1008
1068
|
|
|
1009
1069
|
// src/domains/context/project-metadata.ts
|
|
1010
1070
|
init_esm_shims();
|
|
@@ -1062,6 +1122,14 @@ function tomlTableValue(raw, table, key) {
|
|
|
1062
1122
|
}
|
|
1063
1123
|
return null;
|
|
1064
1124
|
}
|
|
1125
|
+
function hasTomlTable(raw, table) {
|
|
1126
|
+
const header = `[${table}]`;
|
|
1127
|
+
return raw.split(/\r?\n/u).some((line) => {
|
|
1128
|
+
const trimmed = line.trim();
|
|
1129
|
+
if (!trimmed.startsWith(header)) return false;
|
|
1130
|
+
return /^\s*(?:#.*)?$/u.test(trimmed.slice(header.length));
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1065
1133
|
function keyEqualsValue(raw, key) {
|
|
1066
1134
|
const match = new RegExp(`^[ \\t]*${key}[ \\t]*(?:\\+?=)[ \\t]*(.+)$`, "mu").exec(raw);
|
|
1067
1135
|
const value = match?.[1]?.trim();
|
|
@@ -1354,13 +1422,12 @@ function renderPromptContext(cwd) {
|
|
|
1354
1422
|
const projectType = detectProjectType(cwd);
|
|
1355
1423
|
const pieces = [renderProjectTypeFragment(projectType)];
|
|
1356
1424
|
const warnings = [];
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1425
|
+
const loadedClioMd = loadProjectClioMd(cwd);
|
|
1426
|
+
const clioMd = loadedClioMd.value;
|
|
1427
|
+
for (const file of loadedClioMd.files) pieces.push(renderProjectContextFragment(file.value, file.path));
|
|
1428
|
+
for (const issue of loadedClioMd.errors) {
|
|
1429
|
+
warnings.push(`clio: malformed ${issue.path} ignored: ${issue.error}`);
|
|
1362
1430
|
}
|
|
1363
|
-
if (clio && !clio.ok) warnings.push(`clio: malformed CLIO-CODER.md ignored: ${clio.error}`);
|
|
1364
1431
|
const codewiki = readCodewiki(cwd);
|
|
1365
1432
|
if (codewiki) {
|
|
1366
1433
|
const state = readClioState(cwd);
|
|
@@ -1382,7 +1449,7 @@ function renderPromptContext(cwd) {
|
|
|
1382
1449
|
const suffix = notes.length > 0 ? ` (${notes.join("; ")}; run clio-coder context wiki --update)` : "";
|
|
1383
1450
|
pieces.push(`<wiki>${pages.length} pages at .clio-coder/wiki (start: quickstart.md)${suffix}</wiki>`);
|
|
1384
1451
|
}
|
|
1385
|
-
return { text: pieces.join("\n\n"), clioMd, warnings };
|
|
1452
|
+
return { text: pieces.join("\n\n"), clioMd, warnings, handbookFiles: loadedClioMd.files.map((file) => file.path) };
|
|
1386
1453
|
}
|
|
1387
1454
|
|
|
1388
1455
|
// src/domains/context/bootstrap.ts
|
|
@@ -1597,6 +1664,44 @@ function packageManager(cwd) {
|
|
|
1597
1664
|
return "npm";
|
|
1598
1665
|
}
|
|
1599
1666
|
var MUTATING_SCRIPT_RE = /(?:^|\s)--(?:fix|write)(?:\s|$)/;
|
|
1667
|
+
function cmakePresetName(presets, key) {
|
|
1668
|
+
if (typeof presets !== "object" || presets === null || Array.isArray(presets)) return null;
|
|
1669
|
+
const list = presets[key];
|
|
1670
|
+
if (!Array.isArray(list)) return null;
|
|
1671
|
+
for (const entry of list) {
|
|
1672
|
+
if (entry?.hidden === true) continue;
|
|
1673
|
+
const name2 = stringField2(entry, "name");
|
|
1674
|
+
if (name2 !== null) return name2;
|
|
1675
|
+
}
|
|
1676
|
+
return null;
|
|
1677
|
+
}
|
|
1678
|
+
function cmakeVerificationLines(cwd) {
|
|
1679
|
+
const presets = readJsonFile(join4(cwd, "CMakePresets.json"));
|
|
1680
|
+
if (presets === null) return [];
|
|
1681
|
+
const configure = cmakePresetName(presets, "configurePresets");
|
|
1682
|
+
const build = cmakePresetName(presets, "buildPresets");
|
|
1683
|
+
const test = cmakePresetName(presets, "testPresets");
|
|
1684
|
+
const lines = [];
|
|
1685
|
+
if (configure !== null) lines.push(`Configure with \`cmake --preset ${configure}\`.`);
|
|
1686
|
+
if (build !== null) lines.push(`Build with \`cmake --build --preset ${build}\`.`);
|
|
1687
|
+
if (test !== null) lines.push(`Run tests with \`ctest --preset ${test}\`.`);
|
|
1688
|
+
return lines;
|
|
1689
|
+
}
|
|
1690
|
+
function pythonVerificationLines(cwd) {
|
|
1691
|
+
let pyproject = "";
|
|
1692
|
+
try {
|
|
1693
|
+
pyproject = readFileSync4(join4(cwd, "pyproject.toml"), "utf8");
|
|
1694
|
+
} catch {
|
|
1695
|
+
pyproject = "";
|
|
1696
|
+
}
|
|
1697
|
+
if (existsSync4(join4(cwd, "tox.ini")) || hasTomlTable(pyproject, "tool.tox")) {
|
|
1698
|
+
return ["Run `tox` before handoff."];
|
|
1699
|
+
}
|
|
1700
|
+
if (existsSync4(join4(cwd, "pytest.ini")) || hasTomlTable(pyproject, "tool.pytest.ini_options")) {
|
|
1701
|
+
return ["Run `pytest` before handoff."];
|
|
1702
|
+
}
|
|
1703
|
+
return [];
|
|
1704
|
+
}
|
|
1600
1705
|
function verificationSection(cwd) {
|
|
1601
1706
|
const scripts = packageScripts(cwd);
|
|
1602
1707
|
const pm = packageManager(cwd);
|
|
@@ -1624,6 +1729,14 @@ function verificationSection(cwd) {
|
|
|
1624
1729
|
if (hasScript("ci")) {
|
|
1625
1730
|
lines.push(`Use ${command("ci")} for the full local gate before committing broad or shared behavior changes.`);
|
|
1626
1731
|
}
|
|
1732
|
+
lines.push(...cmakeVerificationLines(cwd));
|
|
1733
|
+
if (existsSync4(join4(cwd, "Cargo.toml"))) {
|
|
1734
|
+
lines.push("Run `cargo build` and `cargo test` before handoff.");
|
|
1735
|
+
}
|
|
1736
|
+
if (existsSync4(join4(cwd, "go.mod"))) {
|
|
1737
|
+
lines.push("Run `go build ./...` and `go test ./...` before handoff.");
|
|
1738
|
+
}
|
|
1739
|
+
lines.push(...pythonVerificationLines(cwd));
|
|
1627
1740
|
if (lines.length === 0) return null;
|
|
1628
1741
|
return { title: "Verification expectations", body: lines.join(" ") };
|
|
1629
1742
|
}
|
|
@@ -1751,12 +1864,10 @@ function stabilizeGeneratedOutput(input, base, onModelSectionRetained, groundMod
|
|
|
1751
1864
|
function codewikiSections(codewiki) {
|
|
1752
1865
|
const sections = [];
|
|
1753
1866
|
const entryPoints = codewikiEntryPoints(codewiki, 8);
|
|
1754
|
-
const indexedCount = indexedSourceFileCount(codewiki);
|
|
1755
1867
|
if (entryPoints.length > 0) {
|
|
1756
1868
|
sections.push({
|
|
1757
1869
|
title: "Context retrieval",
|
|
1758
1870
|
body: [
|
|
1759
|
-
`The codewiki currently indexes ${indexedCount} source file${indexedCount === 1 ? "" : "s"}.`,
|
|
1760
1871
|
`Start orientation with these indexed entry points: ${entryPoints.map((entry) => `\`${entry}\``).join(", ")}.`,
|
|
1761
1872
|
"Use `code_nav` (modes: symbol, path, entries, outline, deps, dependents, wiki) before broad reads when the task is navigational."
|
|
1762
1873
|
].join(" ")
|
|
@@ -1852,7 +1963,7 @@ function countStatusLines(status) {
|
|
|
1852
1963
|
return status.split("\n").map((line) => line.trim()).filter(Boolean).length;
|
|
1853
1964
|
}
|
|
1854
1965
|
function basenameList(paths) {
|
|
1855
|
-
const names = paths.map((
|
|
1966
|
+
const names = paths.map((path2) => parse(path2).base).sort((a, b) => a.localeCompare(b));
|
|
1856
1967
|
if (names.length === 0) return "";
|
|
1857
1968
|
if (names.length <= 3) return names.join(", ");
|
|
1858
1969
|
return `${names.slice(0, 3).join(", ")} +${names.length - 3}`;
|
|
@@ -1974,7 +2085,7 @@ function serializeBootstrapOutput(output) {
|
|
|
1974
2085
|
}
|
|
1975
2086
|
function writeClioMdFile(cwd, output) {
|
|
1976
2087
|
const clioMdPath = join4(cwd, "CLIO-CODER.md");
|
|
1977
|
-
mkdirSync(
|
|
2088
|
+
mkdirSync(dirname3(clioMdPath), { recursive: true });
|
|
1978
2089
|
const serialized = serializeBootstrapOutput(output);
|
|
1979
2090
|
const parsed = parseClioMd(serialized);
|
|
1980
2091
|
if (!parsed.ok) throw new Error(`bootstrap produced invalid CLIO-CODER.md: ${parsed.errors.join("; ")}`);
|
|
@@ -2032,8 +2143,7 @@ function durableGenerationTelemetry(telemetry) {
|
|
|
2032
2143
|
}
|
|
2033
2144
|
return state;
|
|
2034
2145
|
}
|
|
2035
|
-
function writeProjectState(cwd, projectType, now, indexedAt, adoption, recordAdoption, codewikiVersion, generation, generated) {
|
|
2036
|
-
const finalFingerprint = computeFingerprint(cwd);
|
|
2146
|
+
function writeProjectState(cwd, projectType, now, indexedAt, adoption, recordAdoption, codewikiVersion, fingerprint, generation, generated) {
|
|
2037
2147
|
const statePath2 = statePath(cwd);
|
|
2038
2148
|
const prev = readClioState(cwd);
|
|
2039
2149
|
const lastBootstrap = generated ? durableGenerationTelemetry(generation) : prev?.lastBootstrap ?? durableGenerationTelemetry(generation);
|
|
@@ -2042,7 +2152,7 @@ function writeProjectState(cwd, projectType, now, indexedAt, adoption, recordAdo
|
|
|
2042
2152
|
writeClioState(cwd, {
|
|
2043
2153
|
version: 1,
|
|
2044
2154
|
projectType,
|
|
2045
|
-
fingerprint
|
|
2155
|
+
fingerprint,
|
|
2046
2156
|
codewikiVersion,
|
|
2047
2157
|
lastInitAt: now.toISOString(),
|
|
2048
2158
|
lastSessionAt: now.toISOString(),
|
|
@@ -2053,13 +2163,12 @@ function writeProjectState(cwd, projectType, now, indexedAt, adoption, recordAdo
|
|
|
2053
2163
|
});
|
|
2054
2164
|
return statePath2;
|
|
2055
2165
|
}
|
|
2056
|
-
function persistCodewikiForGeneration(cwd, projectType, indexedAt, codewiki) {
|
|
2057
|
-
writeCodewiki(cwd, codewiki);
|
|
2166
|
+
function persistCodewikiForGeneration(cwd, projectType, indexedAt, codewiki, fingerprint) {
|
|
2058
2167
|
const prev = readClioState(cwd);
|
|
2059
2168
|
writeClioState(cwd, {
|
|
2060
2169
|
version: 1,
|
|
2061
2170
|
projectType,
|
|
2062
|
-
fingerprint
|
|
2171
|
+
fingerprint,
|
|
2063
2172
|
codewikiVersion: codewiki.version,
|
|
2064
2173
|
...prev?.contextSources ? { contextSources: prev.contextSources } : {},
|
|
2065
2174
|
...prev?.contextSourceHash ? { contextSourceHash: prev.contextSourceHash } : {},
|
|
@@ -2096,7 +2205,7 @@ function codewikiEntryPoints(codewiki, limit = 6) {
|
|
|
2096
2205
|
if (!("toFileId" in edge)) continue;
|
|
2097
2206
|
inDegree.set(edge.toFileId, (inDegree.get(edge.toFileId) ?? 0) + 1);
|
|
2098
2207
|
}
|
|
2099
|
-
const ranked = [...inDegree.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([fileId]) => fileById.get(fileId)?.path).filter((
|
|
2208
|
+
const ranked = [...inDegree.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([fileId]) => fileById.get(fileId)?.path).filter((path2) => typeof path2 === "string").filter((path2) => !tagged.includes(path2));
|
|
2100
2209
|
return [...tagged, ...ranked].slice(0, limit);
|
|
2101
2210
|
}
|
|
2102
2211
|
async function runBootstrap(input = {}) {
|
|
@@ -2124,7 +2233,21 @@ async function runBootstrap(input = {}) {
|
|
|
2124
2233
|
const now = input.now?.() ?? /* @__PURE__ */ new Date();
|
|
2125
2234
|
const indexedAt = now.toISOString();
|
|
2126
2235
|
progress(input, { phase: "codewiki", status: "started", message: "building codewiki index" });
|
|
2127
|
-
|
|
2236
|
+
let codewiki;
|
|
2237
|
+
let codewikiFingerprint;
|
|
2238
|
+
if (input.preview === true) {
|
|
2239
|
+
const candidate = await buildCodewikiCandidate(cwd, projectType);
|
|
2240
|
+
codewiki = candidate.codewiki;
|
|
2241
|
+
codewikiFingerprint = candidate.fingerprint;
|
|
2242
|
+
} else {
|
|
2243
|
+
const coordinated = await coordinateCodewikiWrite(cwd, () => ({ kind: "build", cwd, language: projectType }), {
|
|
2244
|
+
beforeCommit: (_result, workspace) => ensureGitignore(workspace, input),
|
|
2245
|
+
afterCommit: ({ codewiki: committed, fingerprint }, workspace) => persistCodewikiForGeneration(workspace, projectType, indexedAt, committed, fingerprint)
|
|
2246
|
+
});
|
|
2247
|
+
if (!coordinated) throw new Error("codewiki bootstrap transaction did not commit");
|
|
2248
|
+
codewiki = coordinated.codewiki;
|
|
2249
|
+
codewikiFingerprint = coordinated.worker.fingerprint;
|
|
2250
|
+
}
|
|
2128
2251
|
const codewikiEntryCount = indexedSourceFileCount(codewiki);
|
|
2129
2252
|
progress(input, {
|
|
2130
2253
|
phase: "codewiki",
|
|
@@ -2133,10 +2256,6 @@ async function runBootstrap(input = {}) {
|
|
|
2133
2256
|
current: codewikiEntryCount,
|
|
2134
2257
|
total: codewikiEntryCount
|
|
2135
2258
|
});
|
|
2136
|
-
if (input.preview !== true) {
|
|
2137
|
-
await ensureGitignore(cwd, input);
|
|
2138
|
-
persistCodewikiForGeneration(cwd, projectType, indexedAt, codewiki);
|
|
2139
|
-
}
|
|
2140
2259
|
const hadClioMd = existsSync4(join4(cwd, "CLIO-CODER.md"));
|
|
2141
2260
|
const useExistingClioMdAsSource = hadClioMd && input.rewriteClioMd !== true;
|
|
2142
2261
|
const existingClioMdText = useExistingClioMdAsSource ? readExistingClioMdText(cwd) : null;
|
|
@@ -2282,6 +2401,7 @@ async function runBootstrap(input = {}) {
|
|
|
2282
2401
|
adoption,
|
|
2283
2402
|
adoptionApplied,
|
|
2284
2403
|
codewiki.version,
|
|
2404
|
+
codewikiFingerprint,
|
|
2285
2405
|
generation,
|
|
2286
2406
|
shouldGenerate
|
|
2287
2407
|
);
|
|
@@ -2341,6 +2461,7 @@ var ACCUMULATED_CONTEXT_PATHS = [
|
|
|
2341
2461
|
];
|
|
2342
2462
|
var PRESERVED_CONTEXT_PATHS = [
|
|
2343
2463
|
"CLIO-CODER.md",
|
|
2464
|
+
"CLIO-CODER.override.md",
|
|
2344
2465
|
".clio-coder/agents",
|
|
2345
2466
|
".clio-coder/skills",
|
|
2346
2467
|
".clio-coder/wiki"
|
|
@@ -2364,17 +2485,20 @@ async function runContextClear(input = {}) {
|
|
|
2364
2485
|
out2(input.io, "clio-coder context reset cancelled; no files removed.\n");
|
|
2365
2486
|
return { action: "cancelled", removed: [], preserved: [...PRESERVED_CONTEXT_PATHS] };
|
|
2366
2487
|
}
|
|
2367
|
-
const removed =
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2488
|
+
const { removed, preserved } = await coordinateCodewikiExclusive(cwd, async (workspace) => {
|
|
2489
|
+
const removed2 = [];
|
|
2490
|
+
for (const relPath of ACCUMULATED_CONTEXT_PATHS) removeIfPresent(workspace, relPath, removed2);
|
|
2491
|
+
const preserved2 = [...PRESERVED_CONTEXT_PATHS];
|
|
2492
|
+
if (input.all === true) {
|
|
2493
|
+
const confirmedAll = await input.confirmAll?.();
|
|
2494
|
+
if (confirmedAll === true) {
|
|
2495
|
+
removeIfPresent(workspace, "CLIO-CODER.md", removed2);
|
|
2496
|
+
const index = preserved2.indexOf("CLIO-CODER.md");
|
|
2497
|
+
if (index !== -1) preserved2.splice(index, 1);
|
|
2498
|
+
}
|
|
2376
2499
|
}
|
|
2377
|
-
|
|
2500
|
+
return { removed: removed2, preserved: preserved2 };
|
|
2501
|
+
});
|
|
2378
2502
|
out2(
|
|
2379
2503
|
input.io,
|
|
2380
2504
|
[
|
|
@@ -2386,130 +2510,378 @@ async function runContextClear(input = {}) {
|
|
|
2386
2510
|
return { action: "cleared", removed, preserved };
|
|
2387
2511
|
}
|
|
2388
2512
|
|
|
2389
|
-
// src/domains/context/
|
|
2390
|
-
init_esm_shims();
|
|
2391
|
-
import { writeFileSync as writeFileSync3 } from "node:fs";
|
|
2392
|
-
import { join as join8 } from "node:path";
|
|
2393
|
-
|
|
2394
|
-
// src/domains/context/wiki/generate.ts
|
|
2395
|
-
init_esm_shims();
|
|
2396
|
-
import {
|
|
2397
|
-
closeSync,
|
|
2398
|
-
copyFileSync,
|
|
2399
|
-
existsSync as existsSync6,
|
|
2400
|
-
mkdirSync as mkdirSync3,
|
|
2401
|
-
mkdtempSync,
|
|
2402
|
-
openSync,
|
|
2403
|
-
readdirSync as readdirSync3,
|
|
2404
|
-
readFileSync as readFileSync6,
|
|
2405
|
-
renameSync,
|
|
2406
|
-
rmSync as rmSync3,
|
|
2407
|
-
statSync as statSync2,
|
|
2408
|
-
writeSync
|
|
2409
|
-
} from "node:fs";
|
|
2410
|
-
import { dirname as dirname4, join as join7 } from "node:path";
|
|
2411
|
-
|
|
2412
|
-
// src/domains/context/wiki/assemble.ts
|
|
2513
|
+
// src/domains/context/operator-profile.ts
|
|
2413
2514
|
init_esm_shims();
|
|
2414
|
-
|
|
2415
|
-
import {
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
var
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
}
|
|
2426
|
-
function writeText(filePath, text) {
|
|
2427
|
-
mkdirSync2(dirname3(filePath), { recursive: true });
|
|
2428
|
-
writeFileSync2(filePath, text, "utf8");
|
|
2515
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
2516
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
2517
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
2518
|
+
import { join as join6 } from "node:path";
|
|
2519
|
+
var RESPONSE_POSTURES = ["concise", "balanced", "thorough"];
|
|
2520
|
+
var VALIDATION_PREFERENCES = ["tests-first", "manual", "trust"];
|
|
2521
|
+
var COMMIT_MESSAGE_STYLES = ["conventional", "descriptive", "terse"];
|
|
2522
|
+
var OPERATOR_PROFILE_MAX_CHARS = 700;
|
|
2523
|
+
var OPERATOR_PROFILE_MAX_LOCAL_PATHS = 8;
|
|
2524
|
+
function isRecord2(value) {
|
|
2525
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2429
2526
|
}
|
|
2430
|
-
function
|
|
2431
|
-
|
|
2527
|
+
function readEnum(value, allowed, field, issues) {
|
|
2528
|
+
if (value === void 0) return void 0;
|
|
2529
|
+
if (typeof value === "string" && allowed.includes(value)) return value;
|
|
2530
|
+
issues.push(`${field} must be one of ${allowed.join(", ")}`);
|
|
2531
|
+
return void 0;
|
|
2432
2532
|
}
|
|
2433
|
-
function
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2533
|
+
function readProfileBlob(value, issues) {
|
|
2534
|
+
if (!isRecord2(value)) {
|
|
2535
|
+
if (value !== null && value !== void 0) issues.push("profile must be a mapping at the root");
|
|
2536
|
+
return {};
|
|
2537
|
+
}
|
|
2538
|
+
const profile = {};
|
|
2539
|
+
const posture = readEnum(value.responsePosture, RESPONSE_POSTURES, "responsePosture", issues);
|
|
2540
|
+
if (posture) profile.responsePosture = posture;
|
|
2541
|
+
const validation = readEnum(value.validationPreference, VALIDATION_PREFERENCES, "validationPreference", issues);
|
|
2542
|
+
if (validation) profile.validationPreference = validation;
|
|
2543
|
+
const commit = readEnum(value.commitMessageStyle, COMMIT_MESSAGE_STYLES, "commitMessageStyle", issues);
|
|
2544
|
+
if (commit) profile.commitMessageStyle = commit;
|
|
2545
|
+
if (value.localOnlyPaths !== void 0) {
|
|
2546
|
+
if (Array.isArray(value.localOnlyPaths)) {
|
|
2547
|
+
const paths = value.localOnlyPaths.filter((item) => typeof item === "string" && item.length > 0);
|
|
2548
|
+
if (paths.length > 0) profile.localOnlyPaths = paths.slice(0, OPERATOR_PROFILE_MAX_LOCAL_PATHS);
|
|
2549
|
+
} else {
|
|
2550
|
+
issues.push("localOnlyPaths must be an array of strings");
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
return profile;
|
|
2442
2554
|
}
|
|
2443
|
-
function
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
return {
|
|
2555
|
+
function readProfileFile(path2, issues) {
|
|
2556
|
+
if (!existsSync6(path2)) return { profile: {}, present: false };
|
|
2557
|
+
try {
|
|
2558
|
+
return { profile: readProfileBlob((0, import_yaml2.parse)(readFileSync5(path2, "utf8")), issues), present: true };
|
|
2559
|
+
} catch (err) {
|
|
2560
|
+
issues.push(`${path2}: invalid YAML: ${err instanceof Error ? err.message : String(err)}`);
|
|
2561
|
+
return { profile: {}, present: false };
|
|
2450
2562
|
}
|
|
2563
|
+
}
|
|
2564
|
+
function loadOperatorProfile(cwd, options = {}) {
|
|
2451
2565
|
const issues = [];
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2566
|
+
const userPath = options.userPath ?? join6(resolveClioDirs().config, "profile.yaml");
|
|
2567
|
+
const projectPath = join6(cwd, ".clio-coder", "profile.yaml");
|
|
2568
|
+
const user = readProfileFile(userPath, issues);
|
|
2569
|
+
const project = readProfileFile(projectPath, issues);
|
|
2570
|
+
const profile = { ...user.profile, ...project.profile };
|
|
2571
|
+
let origin = "none";
|
|
2572
|
+
let sourcePath;
|
|
2573
|
+
if (project.present) {
|
|
2574
|
+
origin = "project";
|
|
2575
|
+
sourcePath = projectPath;
|
|
2576
|
+
} else if (user.present) {
|
|
2577
|
+
origin = "user";
|
|
2578
|
+
sourcePath = userPath;
|
|
2460
2579
|
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
issues.push({ page: relPath, kind: "link", reference: href });
|
|
2466
|
-
}
|
|
2580
|
+
const result = { profile, origin, issues };
|
|
2581
|
+
if (sourcePath !== void 0) {
|
|
2582
|
+
result.sourcePath = sourcePath;
|
|
2583
|
+
result.hash = createHash2("sha256").update(JSON.stringify(profile)).digest("hex").slice(0, 16);
|
|
2467
2584
|
}
|
|
2468
|
-
|
|
2469
|
-
${renderRepairNote(issues)}`;
|
|
2470
|
-
if (rebuilt !== original) writeText(filePath, rebuilt);
|
|
2471
|
-
return { metadata: parsed.metadata, changed: rebuilt !== original, issues, empty: false };
|
|
2585
|
+
return result;
|
|
2472
2586
|
}
|
|
2473
|
-
function
|
|
2474
|
-
const
|
|
2475
|
-
|
|
2587
|
+
function renderOperatorProfile(profile) {
|
|
2588
|
+
const lines = [];
|
|
2589
|
+
if (profile.responsePosture) lines.push(`- Response posture: ${profile.responsePosture}.`);
|
|
2590
|
+
if (profile.validationPreference) lines.push(`- Validation preference: ${profile.validationPreference}.`);
|
|
2591
|
+
if (profile.commitMessageStyle) lines.push(`- Commit-message style: ${profile.commitMessageStyle}.`);
|
|
2592
|
+
if (profile.localOnlyPaths && profile.localOnlyPaths.length > 0) {
|
|
2593
|
+
lines.push(`- Keep local-only (do not push or share): ${profile.localOnlyPaths.join(", ")}.`);
|
|
2594
|
+
}
|
|
2595
|
+
if (lines.length === 0) return { text: "", tokenEstimate: 0 };
|
|
2596
|
+
const full = `## Operator profile
|
|
2597
|
+
${lines.join("\n")}`;
|
|
2598
|
+
const text = full.length > OPERATOR_PROFILE_MAX_CHARS ? `${full.slice(0, OPERATOR_PROFILE_MAX_CHARS - 1)}\u2026` : full;
|
|
2599
|
+
return { text, tokenEstimate: ceilChars(text.length) };
|
|
2476
2600
|
}
|
|
2477
|
-
|
|
2478
|
-
|
|
2601
|
+
|
|
2602
|
+
// src/domains/context/project-rules.ts
|
|
2603
|
+
init_esm_shims();
|
|
2604
|
+
var import_yaml3 = __toESM(require_dist(), 1);
|
|
2605
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
2606
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync6 } from "node:fs";
|
|
2607
|
+
import { join as join7, relative as relative2, sep as sep2 } from "node:path";
|
|
2608
|
+
var FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?/;
|
|
2609
|
+
function isRecord3(value) {
|
|
2610
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2479
2611
|
}
|
|
2480
|
-
function
|
|
2481
|
-
if (
|
|
2482
|
-
const
|
|
2483
|
-
|
|
2612
|
+
function readStringArray(value) {
|
|
2613
|
+
if (!Array.isArray(value)) return void 0;
|
|
2614
|
+
const out3 = [];
|
|
2615
|
+
for (const item of value) {
|
|
2616
|
+
if (typeof item === "string" && item.length > 0) out3.push(item);
|
|
2617
|
+
}
|
|
2618
|
+
return out3.length > 0 ? out3 : void 0;
|
|
2484
2619
|
}
|
|
2485
|
-
function
|
|
2486
|
-
const
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
`This wiki is generated by \`clio-coder context wiki\` from ${content.length} page${content.length === 1 ? "" : "s"}. Each page opens with front matter naming the sources, symbols, and tests it documents.`,
|
|
2491
|
-
"",
|
|
2492
|
-
"## Pages",
|
|
2493
|
-
""
|
|
2494
|
-
);
|
|
2495
|
-
let currentSection = null;
|
|
2496
|
-
for (const page of content) {
|
|
2497
|
-
const section = posix.dirname(page.path);
|
|
2498
|
-
if (section !== "." && section !== currentSection) {
|
|
2499
|
-
lines.push(`- **${section}/**`);
|
|
2500
|
-
currentSection = section;
|
|
2501
|
-
}
|
|
2502
|
-
const indent = section === "." ? "" : " ";
|
|
2503
|
-
const summary = page.metadata.summary.length > 0 ? ` \u2014 ${page.metadata.summary}` : "";
|
|
2504
|
-
lines.push(`${indent}- [${page.metadata.title}](${page.path})${summary}`);
|
|
2620
|
+
function validateGlobArray(value, field, id, issues) {
|
|
2621
|
+
const parsed = readStringArray(value);
|
|
2622
|
+
if (parsed === void 0) {
|
|
2623
|
+
issues.push(`${id}: frontmatter ${field} must be a non-empty string array`);
|
|
2624
|
+
return void 0;
|
|
2505
2625
|
}
|
|
2506
|
-
const
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2626
|
+
for (const pattern of parsed) {
|
|
2627
|
+
try {
|
|
2628
|
+
compileGlobRegex(pattern);
|
|
2629
|
+
} catch (err) {
|
|
2630
|
+
issues.push(
|
|
2631
|
+
`${id}: invalid ${field} glob ${JSON.stringify(pattern)}: ${err instanceof Error ? err.message : String(err)}`
|
|
2632
|
+
);
|
|
2633
|
+
return void 0;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
return parsed;
|
|
2637
|
+
}
|
|
2638
|
+
function walkMarkdown(dir, root, out3) {
|
|
2639
|
+
let entries;
|
|
2640
|
+
try {
|
|
2641
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
2642
|
+
} catch {
|
|
2643
|
+
return;
|
|
2644
|
+
}
|
|
2645
|
+
for (const entry of entries) {
|
|
2646
|
+
const full = join7(dir, entry.name);
|
|
2647
|
+
if (entry.isDirectory()) walkMarkdown(full, root, out3);
|
|
2648
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) out3.push(full);
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
function parseRule(filePath, root, issues) {
|
|
2652
|
+
let text;
|
|
2653
|
+
try {
|
|
2654
|
+
text = readFileSync6(filePath, "utf8").replace(/\r\n/g, "\n");
|
|
2655
|
+
} catch (err) {
|
|
2656
|
+
issues.push(`${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2657
|
+
return { excludes: [] };
|
|
2658
|
+
}
|
|
2659
|
+
const id = relative2(root, filePath).split(sep2).join("/");
|
|
2660
|
+
let body = text;
|
|
2661
|
+
let paths;
|
|
2662
|
+
let excludes = [];
|
|
2663
|
+
let enabled = true;
|
|
2664
|
+
let description2;
|
|
2665
|
+
let invalidFrontmatter = false;
|
|
2666
|
+
const match = FRONTMATTER_RE.exec(text);
|
|
2667
|
+
if (match) {
|
|
2668
|
+
body = text.slice(match[0].length);
|
|
2669
|
+
try {
|
|
2670
|
+
const front = (0, import_yaml3.parse)(match[1] ?? "");
|
|
2671
|
+
if (isRecord3(front)) {
|
|
2672
|
+
if (Object.hasOwn(front, "paths")) {
|
|
2673
|
+
const parsedPaths = validateGlobArray(front.paths, "paths", id, issues);
|
|
2674
|
+
if (parsedPaths === void 0) invalidFrontmatter = true;
|
|
2675
|
+
else paths = parsedPaths;
|
|
2676
|
+
}
|
|
2677
|
+
if (Object.hasOwn(front, "excludes")) {
|
|
2678
|
+
const parsedExcludes = validateGlobArray(front.excludes, "excludes", id, issues);
|
|
2679
|
+
if (parsedExcludes === void 0) invalidFrontmatter = true;
|
|
2680
|
+
else excludes = parsedExcludes;
|
|
2681
|
+
}
|
|
2682
|
+
if (Object.hasOwn(front, "enabled")) {
|
|
2683
|
+
if (typeof front.enabled === "boolean") enabled = front.enabled;
|
|
2684
|
+
else {
|
|
2685
|
+
issues.push(`${id}: frontmatter enabled must be a boolean`);
|
|
2686
|
+
invalidFrontmatter = true;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
if (Object.hasOwn(front, "description")) {
|
|
2690
|
+
if (typeof front.description === "string") description2 = front.description;
|
|
2691
|
+
else {
|
|
2692
|
+
issues.push(`${id}: frontmatter description must be a string`);
|
|
2693
|
+
invalidFrontmatter = true;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
} else if (front !== null && front !== void 0) {
|
|
2697
|
+
issues.push(`${id}: frontmatter must be a mapping`);
|
|
2698
|
+
invalidFrontmatter = true;
|
|
2699
|
+
}
|
|
2700
|
+
} catch (err) {
|
|
2701
|
+
issues.push(`${id}: invalid frontmatter: ${err instanceof Error ? err.message : String(err)}`);
|
|
2702
|
+
invalidFrontmatter = true;
|
|
2703
|
+
}
|
|
2704
|
+
} else if (text.startsWith("---\n")) {
|
|
2705
|
+
issues.push(`${id}: invalid frontmatter: missing closing marker`);
|
|
2706
|
+
invalidFrontmatter = true;
|
|
2707
|
+
}
|
|
2708
|
+
if (invalidFrontmatter) return { excludes: [] };
|
|
2709
|
+
const trimmedBody = body.trim();
|
|
2710
|
+
const hash = createHash3("sha256").update(trimmedBody).digest("hex").slice(0, 16);
|
|
2711
|
+
const rule = {
|
|
2712
|
+
id,
|
|
2713
|
+
sourcePath: join7(".clio-coder", "rules", id),
|
|
2714
|
+
hash,
|
|
2715
|
+
tokenEstimate: ceilChars(trimmedBody.length),
|
|
2716
|
+
enabled,
|
|
2717
|
+
body: trimmedBody
|
|
2718
|
+
};
|
|
2719
|
+
if (paths !== void 0) rule.paths = paths;
|
|
2720
|
+
if (description2 !== void 0) rule.description = description2;
|
|
2721
|
+
return { rule, excludes };
|
|
2722
|
+
}
|
|
2723
|
+
function loadProjectRules(cwd) {
|
|
2724
|
+
const root = join7(cwd, ".clio-coder", "rules");
|
|
2725
|
+
const issues = [];
|
|
2726
|
+
const files = [];
|
|
2727
|
+
walkMarkdown(root, root, files);
|
|
2728
|
+
files.sort();
|
|
2729
|
+
const rules = [];
|
|
2730
|
+
const excludeSet = /* @__PURE__ */ new Set();
|
|
2731
|
+
for (const file of files) {
|
|
2732
|
+
const parsed = parseRule(file, root, issues);
|
|
2733
|
+
if (parsed.rule) rules.push(parsed.rule);
|
|
2734
|
+
for (const glob of parsed.excludes) excludeSet.add(glob);
|
|
2735
|
+
}
|
|
2736
|
+
rules.sort((a, b) => a.id.localeCompare(b.id));
|
|
2737
|
+
return { rules, excludes: [...excludeSet], issues };
|
|
2738
|
+
}
|
|
2739
|
+
function ruleMatchesAnyPath(rule, workingPaths) {
|
|
2740
|
+
for (const pattern of rule.paths ?? []) {
|
|
2741
|
+
let regex;
|
|
2742
|
+
try {
|
|
2743
|
+
regex = compileGlobRegex(pattern);
|
|
2744
|
+
} catch {
|
|
2745
|
+
continue;
|
|
2746
|
+
}
|
|
2747
|
+
for (const path2 of workingPaths) {
|
|
2748
|
+
if (regex.test(normalizeGlobInput(path2))) return true;
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
return false;
|
|
2752
|
+
}
|
|
2753
|
+
function selectActiveRules(rules, workingContextPaths) {
|
|
2754
|
+
return rules.filter((rule) => {
|
|
2755
|
+
if (!rule.enabled) return false;
|
|
2756
|
+
if (rule.paths === void 0) return true;
|
|
2757
|
+
return ruleMatchesAnyPath(rule, workingContextPaths);
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
// src/domains/context/refresh.ts
|
|
2762
|
+
init_esm_shims();
|
|
2763
|
+
import { writeFileSync as writeFileSync3 } from "node:fs";
|
|
2764
|
+
import { join as join10 } from "node:path";
|
|
2765
|
+
|
|
2766
|
+
// src/domains/context/wiki/generate.ts
|
|
2767
|
+
init_esm_shims();
|
|
2768
|
+
import {
|
|
2769
|
+
closeSync,
|
|
2770
|
+
copyFileSync,
|
|
2771
|
+
existsSync as existsSync7,
|
|
2772
|
+
mkdirSync as mkdirSync3,
|
|
2773
|
+
mkdtempSync,
|
|
2774
|
+
openSync,
|
|
2775
|
+
readdirSync as readdirSync4,
|
|
2776
|
+
readFileSync as readFileSync8,
|
|
2777
|
+
renameSync,
|
|
2778
|
+
rmSync as rmSync3,
|
|
2779
|
+
statSync as statSync3,
|
|
2780
|
+
writeSync
|
|
2781
|
+
} from "node:fs";
|
|
2782
|
+
import { dirname as dirname5, join as join9 } from "node:path";
|
|
2783
|
+
|
|
2784
|
+
// src/domains/context/wiki/assemble.ts
|
|
2785
|
+
init_esm_shims();
|
|
2786
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync7, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2787
|
+
import { basename as basename3, dirname as dirname4, join as join8, normalize, posix, relative as relative3 } from "node:path";
|
|
2788
|
+
var SOURCE_CITATION = /`((?:src|tests?|scripts|benchmarks|docs|packages|apps|lib|config|\.github)\/[^`\s:#]+)(?::(\d+)(?:-\d+)?)?(?::[A-Za-z_$][\w$.-]*)?`/g;
|
|
2789
|
+
var INTERNAL_LINK = /\[[^\]]*\]\((?![a-z][a-z\d+.-]*:|\/\/|#)([^)\s]+\.md)(?:#[^)\s]*)?\)/gi;
|
|
2790
|
+
var REPAIR_NOTE = /^<!-- clio:wiki .*-->$/gm;
|
|
2791
|
+
function readText2(filePath) {
|
|
2792
|
+
try {
|
|
2793
|
+
return readFileSync7(filePath, "utf8");
|
|
2794
|
+
} catch {
|
|
2795
|
+
return "";
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
function writeText(filePath, text) {
|
|
2799
|
+
mkdirSync2(dirname4(filePath), { recursive: true });
|
|
2800
|
+
writeFileSync2(filePath, text, "utf8");
|
|
2801
|
+
}
|
|
2802
|
+
function stripRepairNotes(body) {
|
|
2803
|
+
return body.replace(REPAIR_NOTE, "").replace(/\n{3,}/g, "\n\n");
|
|
2804
|
+
}
|
|
2805
|
+
function renderRepairNote(issues) {
|
|
2806
|
+
const links = issues.filter((issue) => issue.kind === "link").map((issue) => issue.reference);
|
|
2807
|
+
const citations = issues.filter((issue) => issue.kind === "citation").map((issue) => issue.reference);
|
|
2808
|
+
const parts = [];
|
|
2809
|
+
if (links.length > 0) parts.push(`unresolved links: ${[...new Set(links)].join(", ")}`);
|
|
2810
|
+
if (citations.length > 0) parts.push(`unresolved sources: ${[...new Set(citations)].join(", ")}`);
|
|
2811
|
+
return parts.length === 0 ? "" : `
|
|
2812
|
+
<!-- clio:wiki ${parts.join("; ")} -->
|
|
2813
|
+
`;
|
|
2814
|
+
}
|
|
2815
|
+
function repairPage(dir, sourceRoot, relPath, knownPages) {
|
|
2816
|
+
const filePath = join8(dir, relPath);
|
|
2817
|
+
const original = readText2(filePath);
|
|
2818
|
+
const parsed = readWikiPage({ pagePath: relPath, content: original, sourceRoot });
|
|
2819
|
+
const body = stripRepairNotes(parsed.body);
|
|
2820
|
+
if (body.replace(/^#.*$/gm, "").trim().length === 0) {
|
|
2821
|
+
return { metadata: parsed.metadata, changed: false, issues: [], empty: true };
|
|
2822
|
+
}
|
|
2823
|
+
const issues = [];
|
|
2824
|
+
for (const cited of parsed.unresolvedPaths) {
|
|
2825
|
+
issues.push({ page: relPath, kind: "citation", reference: cited });
|
|
2826
|
+
}
|
|
2827
|
+
for (const match of body.matchAll(SOURCE_CITATION)) {
|
|
2828
|
+
const cited = match[1] ?? "";
|
|
2829
|
+
if (resolveSourcePath(sourceRoot, cited) === null) {
|
|
2830
|
+
issues.push({ page: relPath, kind: "citation", reference: cited });
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
for (const match of body.matchAll(INTERNAL_LINK)) {
|
|
2834
|
+
const href = match[1] ?? "";
|
|
2835
|
+
const target = posix.normalize(posix.join(posix.dirname(relPath), href));
|
|
2836
|
+
if (target.startsWith("..") || !knownPages.has(target)) {
|
|
2837
|
+
issues.push({ page: relPath, kind: "link", reference: href });
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
const rebuilt = `${renderWikiPage(parsed.metadata, body).trimEnd()}
|
|
2841
|
+
${renderRepairNote(issues)}`;
|
|
2842
|
+
if (rebuilt !== original) writeText(filePath, rebuilt);
|
|
2843
|
+
return { metadata: parsed.metadata, changed: rebuilt !== original, issues, empty: false };
|
|
2844
|
+
}
|
|
2845
|
+
function linkTo(fromDir, target) {
|
|
2846
|
+
const href = posix.relative(fromDir === "." ? "" : fromDir, target);
|
|
2847
|
+
return href.length > 0 ? href : posix.basename(target);
|
|
2848
|
+
}
|
|
2849
|
+
function escapeCell(value) {
|
|
2850
|
+
return value.replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
2851
|
+
}
|
|
2852
|
+
function codeList(values, limit) {
|
|
2853
|
+
if (values.length === 0) return "\u2014";
|
|
2854
|
+
const shown = values.slice(0, limit).map((value) => `\`${escapeCell(value)}\``);
|
|
2855
|
+
return values.length > limit ? `${shown.join(", ")}, \u2026` : shown.join(", ");
|
|
2856
|
+
}
|
|
2857
|
+
function renderQuickstart(sourceRoot, plan, pages) {
|
|
2858
|
+
const content = pages.filter((page) => page.path !== WIKI_QUICKSTART);
|
|
2859
|
+
const lines = [`# ${basename3(sourceRoot)} wiki`, ""];
|
|
2860
|
+
if (plan.overview.trim().length > 0) lines.push(plan.overview.trim(), "");
|
|
2861
|
+
lines.push(
|
|
2862
|
+
`This wiki is generated by \`clio-coder context wiki\` from ${content.length} page${content.length === 1 ? "" : "s"}. Each page opens with front matter naming the sources, symbols, and tests it documents.`,
|
|
2863
|
+
"",
|
|
2864
|
+
"## Pages",
|
|
2865
|
+
""
|
|
2866
|
+
);
|
|
2867
|
+
let currentSection = null;
|
|
2868
|
+
for (const page of content) {
|
|
2869
|
+
const section = posix.dirname(page.path);
|
|
2870
|
+
if (section !== "." && section !== currentSection) {
|
|
2871
|
+
lines.push(`- **${section}/**`);
|
|
2872
|
+
currentSection = section;
|
|
2873
|
+
}
|
|
2874
|
+
const indent = section === "." ? "" : " ";
|
|
2875
|
+
const summary = page.metadata.summary.length > 0 ? ` \u2014 ${page.metadata.summary}` : "";
|
|
2876
|
+
lines.push(`${indent}- [${page.metadata.title}](${page.path})${summary}`);
|
|
2877
|
+
}
|
|
2878
|
+
const routable = content.filter(
|
|
2879
|
+
(page) => page.metadata.sources.length > 0 || page.metadata.symbols.length > 0 || page.metadata.tests.length > 0
|
|
2880
|
+
);
|
|
2881
|
+
if (routable.length > 0) {
|
|
2882
|
+
lines.push(
|
|
2883
|
+
"",
|
|
2884
|
+
"## Task routing",
|
|
2513
2885
|
"",
|
|
2514
2886
|
"| Area | Page | Sources | Symbols | Tests | Validate |",
|
|
2515
2887
|
"| --- | --- | --- | --- | --- | --- |"
|
|
@@ -2553,7 +2925,7 @@ function assembleWikiTree(input) {
|
|
|
2553
2925
|
for (const relPath of authored) {
|
|
2554
2926
|
const result = repairPage(dir, sourceRoot, relPath, knownPages);
|
|
2555
2927
|
if (result.empty) {
|
|
2556
|
-
rmSync2(
|
|
2928
|
+
rmSync2(join8(dir, relPath), { force: true });
|
|
2557
2929
|
dropped.push(relPath);
|
|
2558
2930
|
continue;
|
|
2559
2931
|
}
|
|
@@ -2561,7 +2933,7 @@ function assembleWikiTree(input) {
|
|
|
2561
2933
|
issues.push(...result.issues);
|
|
2562
2934
|
assembled.push({ path: relPath, metadata: result.metadata });
|
|
2563
2935
|
}
|
|
2564
|
-
writeText(
|
|
2936
|
+
writeText(join8(dir, WIKI_QUICKSTART), renderQuickstart(sourceRoot, input.plan, assembled));
|
|
2565
2937
|
const directories = /* @__PURE__ */ new Set(["."]);
|
|
2566
2938
|
for (const page of assembled) {
|
|
2567
2939
|
let section = posix.dirname(page.path);
|
|
@@ -2574,12 +2946,12 @@ function assembleWikiTree(input) {
|
|
|
2574
2946
|
const pagesHere = assembled.filter((page) => posix.dirname(page.path) === directory);
|
|
2575
2947
|
const sectionsHere = [...directories].filter((candidate) => candidate !== "." && posix.dirname(candidate) === directory).sort();
|
|
2576
2948
|
const indexPath = directory === "." ? WIKI_INDEX : `${directory}/${WIKI_INDEX}`;
|
|
2577
|
-
writeText(
|
|
2949
|
+
writeText(join8(dir, indexPath), renderIndex(directory, pagesHere, sectionsHere));
|
|
2578
2950
|
}
|
|
2579
2951
|
for (const relPath of wikiMarkdownFilesInDir(dir)) {
|
|
2580
2952
|
if (!isGeneratedWikiFile(relPath) || relPath === WIKI_QUICKSTART) continue;
|
|
2581
2953
|
const directory = posix.dirname(relPath);
|
|
2582
|
-
if (!directories.has(directory)) rmSync2(
|
|
2954
|
+
if (!directories.has(directory)) rmSync2(join8(dir, relPath), { force: true });
|
|
2583
2955
|
}
|
|
2584
2956
|
return { pages: listWikiPagesInDir(dir), repaired, dropped, issues };
|
|
2585
2957
|
}
|
|
@@ -2587,14 +2959,14 @@ function pageSourceIndex(dir, sourceRoot) {
|
|
|
2587
2959
|
const index = /* @__PURE__ */ new Map();
|
|
2588
2960
|
for (const relPath of wikiMarkdownFilesInDir(dir)) {
|
|
2589
2961
|
if (isGeneratedWikiFile(relPath)) continue;
|
|
2590
|
-
const { metadata } = readWikiPage({ pagePath: relPath, content: readText2(
|
|
2962
|
+
const { metadata } = readWikiPage({ pagePath: relPath, content: readText2(join8(dir, relPath)), sourceRoot });
|
|
2591
2963
|
index.set(relPath, [...metadata.sources, ...metadata.tests]);
|
|
2592
2964
|
}
|
|
2593
2965
|
return index;
|
|
2594
2966
|
}
|
|
2595
2967
|
function normalizeRepoPath(sourceRoot, candidate) {
|
|
2596
|
-
const resolved = normalize(
|
|
2597
|
-
const rel =
|
|
2968
|
+
const resolved = normalize(join8(sourceRoot, candidate));
|
|
2969
|
+
const rel = relative3(sourceRoot, resolved);
|
|
2598
2970
|
return rel.split("\\").join("/");
|
|
2599
2971
|
}
|
|
2600
2972
|
|
|
@@ -2606,8 +2978,8 @@ var WIKI_DEPTH_STRATEGY = {
|
|
|
2606
2978
|
detailed: { areaDepth: 3, areaShare: 8e-3, minAreaLines: 150 }
|
|
2607
2979
|
};
|
|
2608
2980
|
var MAX_PAGE_SOURCES = 8;
|
|
2609
|
-
function areaForPath(
|
|
2610
|
-
const directories =
|
|
2981
|
+
function areaForPath(path2, maxDepth) {
|
|
2982
|
+
const directories = path2.split("/").filter(Boolean).slice(0, -1);
|
|
2611
2983
|
if (directories.length === 0) return ".";
|
|
2612
2984
|
return directories.slice(0, Math.max(1, maxDepth)).join("/");
|
|
2613
2985
|
}
|
|
@@ -2699,14 +3071,14 @@ function dedupePagePaths(plan) {
|
|
|
2699
3071
|
const seen = /* @__PURE__ */ new Set();
|
|
2700
3072
|
const pages = [];
|
|
2701
3073
|
for (const page of plan.pages) {
|
|
2702
|
-
let
|
|
3074
|
+
let path2 = page.path;
|
|
2703
3075
|
let suffix = 2;
|
|
2704
|
-
while (seen.has(
|
|
2705
|
-
|
|
3076
|
+
while (seen.has(path2)) {
|
|
3077
|
+
path2 = page.path.replace(/\.md$/, `-${suffix}.md`);
|
|
2706
3078
|
suffix += 1;
|
|
2707
3079
|
}
|
|
2708
|
-
seen.add(
|
|
2709
|
-
pages.push({ ...page, path });
|
|
3080
|
+
seen.add(path2);
|
|
3081
|
+
pages.push({ ...page, path: path2 });
|
|
2710
3082
|
}
|
|
2711
3083
|
return { ...plan, pages };
|
|
2712
3084
|
}
|
|
@@ -2726,29 +3098,38 @@ function indexedSourceFileCount2(codewiki) {
|
|
|
2726
3098
|
return codewiki.files.filter((file) => file.lang !== "config").length;
|
|
2727
3099
|
}
|
|
2728
3100
|
async function loadOrBuildCodewiki(cwd) {
|
|
2729
|
-
const existing = readCodewiki(cwd);
|
|
2730
|
-
const prev = readClioState(cwd);
|
|
2731
|
-
if (existing && !codewikiNeedsBackfill(existing)) {
|
|
2732
|
-
const fingerprint = computeFingerprint(cwd, existing);
|
|
2733
|
-
if (prev && !isStale(prev.fingerprint, fingerprint)) return existing;
|
|
2734
|
-
}
|
|
2735
3101
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2736
3102
|
const projectType = detectProjectType(cwd);
|
|
2737
|
-
const
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
3103
|
+
const coordinated = await coordinateCodewikiWrite(
|
|
3104
|
+
cwd,
|
|
3105
|
+
(current, workspace) => ({
|
|
3106
|
+
kind: "ensure",
|
|
3107
|
+
cwd: workspace,
|
|
3108
|
+
language: projectType,
|
|
3109
|
+
current,
|
|
3110
|
+
previous: readClioState(workspace)?.fingerprint ?? null
|
|
3111
|
+
}),
|
|
3112
|
+
{
|
|
3113
|
+
afterCommit: ({ codewiki, fingerprint, changed }, workspace) => {
|
|
3114
|
+
const prev = readClioState(workspace);
|
|
3115
|
+
if (!changed && prev) return;
|
|
3116
|
+
writeClioState(workspace, {
|
|
3117
|
+
version: 1,
|
|
3118
|
+
projectType: prev?.projectType ?? projectType,
|
|
3119
|
+
fingerprint,
|
|
3120
|
+
codewikiVersion: codewiki.version,
|
|
3121
|
+
...prev?.contextSources ? { contextSources: prev.contextSources } : {},
|
|
3122
|
+
...prev?.contextSourceHash ? { contextSourceHash: prev.contextSourceHash } : {},
|
|
3123
|
+
...prev?.lastBootstrap ? { lastBootstrap: prev.lastBootstrap } : {},
|
|
3124
|
+
...prev?.lastInitAt ? { lastInitAt: prev.lastInitAt } : {},
|
|
3125
|
+
lastSessionAt: prev?.lastSessionAt ?? generatedAt,
|
|
3126
|
+
lastIndexedAt: generatedAt
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
);
|
|
3131
|
+
if (!coordinated) throw new Error("codewiki wiki transaction did not commit");
|
|
3132
|
+
return { codewiki: coordinated.codewiki, fingerprint: coordinated.worker.fingerprint };
|
|
2752
3133
|
}
|
|
2753
3134
|
function failed(problems, pages) {
|
|
2754
3135
|
return { status: "failed", pages, problems };
|
|
@@ -2757,7 +3138,7 @@ var STAGING_PREFIX = "wiki-staging-";
|
|
|
2757
3138
|
var WIKI_PREV_DIR = "wiki-prev";
|
|
2758
3139
|
var WIKI_LOCK_FILE = "wiki.lock";
|
|
2759
3140
|
function clioDir(cwd) {
|
|
2760
|
-
return
|
|
3141
|
+
return join9(cwd, ".clio-coder");
|
|
2761
3142
|
}
|
|
2762
3143
|
function isProcessAlive(pid) {
|
|
2763
3144
|
try {
|
|
@@ -2769,7 +3150,7 @@ function isProcessAlive(pid) {
|
|
|
2769
3150
|
}
|
|
2770
3151
|
function readLockPid(lockPath) {
|
|
2771
3152
|
try {
|
|
2772
|
-
const parsed = Number.parseInt(
|
|
3153
|
+
const parsed = Number.parseInt(readFileSync8(lockPath, "utf8").trim(), 10);
|
|
2773
3154
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
|
2774
3155
|
} catch {
|
|
2775
3156
|
return null;
|
|
@@ -2778,7 +3159,7 @@ function readLockPid(lockPath) {
|
|
|
2778
3159
|
function acquireWikiLock(cwd) {
|
|
2779
3160
|
const dir = clioDir(cwd);
|
|
2780
3161
|
mkdirSync3(dir, { recursive: true });
|
|
2781
|
-
const lockPath =
|
|
3162
|
+
const lockPath = join9(dir, WIKI_LOCK_FILE);
|
|
2782
3163
|
const release = () => {
|
|
2783
3164
|
try {
|
|
2784
3165
|
rmSync3(lockPath, { force: true });
|
|
@@ -2828,10 +3209,10 @@ function removeDir(dir) {
|
|
|
2828
3209
|
function seedStaging(cwd, stagingDir) {
|
|
2829
3210
|
const source = wikiDir(cwd);
|
|
2830
3211
|
for (const relPath of wikiMarkdownFilesInDir(source)) {
|
|
2831
|
-
const target =
|
|
2832
|
-
mkdirSync3(
|
|
3212
|
+
const target = join9(stagingDir, relPath);
|
|
3213
|
+
mkdirSync3(dirname5(target), { recursive: true });
|
|
2833
3214
|
try {
|
|
2834
|
-
copyFileSync(
|
|
3215
|
+
copyFileSync(join9(source, relPath), target);
|
|
2835
3216
|
} catch {
|
|
2836
3217
|
}
|
|
2837
3218
|
}
|
|
@@ -2841,29 +3222,29 @@ function adoptOrCreateStaging(cwd) {
|
|
|
2841
3222
|
mkdirSync3(dir, { recursive: true });
|
|
2842
3223
|
let entries;
|
|
2843
3224
|
try {
|
|
2844
|
-
entries =
|
|
3225
|
+
entries = readdirSync4(dir, { withFileTypes: true });
|
|
2845
3226
|
} catch {
|
|
2846
3227
|
entries = [];
|
|
2847
3228
|
}
|
|
2848
|
-
const candidates = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(STAGING_PREFIX)).map((entry) =>
|
|
2849
|
-
const at =
|
|
2850
|
-
const bt =
|
|
3229
|
+
const candidates = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(STAGING_PREFIX)).map((entry) => join9(dir, entry.name)).sort((a, b) => {
|
|
3230
|
+
const at = statSync3(a).mtimeMs;
|
|
3231
|
+
const bt = statSync3(b).mtimeMs;
|
|
2851
3232
|
return bt - at;
|
|
2852
3233
|
});
|
|
2853
|
-
const resumable = candidates.find((candidate) =>
|
|
3234
|
+
const resumable = candidates.find((candidate) => existsSync7(join9(candidate, WIKI_PLAN_FILE)));
|
|
2854
3235
|
for (const candidate of candidates) {
|
|
2855
3236
|
if (candidate !== resumable) removeDir(candidate);
|
|
2856
3237
|
}
|
|
2857
3238
|
if (resumable !== void 0) return { dir: resumable, adopted: true };
|
|
2858
|
-
const fresh = mkdtempSync(
|
|
3239
|
+
const fresh = mkdtempSync(join9(dir, STAGING_PREFIX));
|
|
2859
3240
|
seedStaging(cwd, fresh);
|
|
2860
3241
|
return { dir: fresh, adopted: false };
|
|
2861
3242
|
}
|
|
2862
3243
|
function promoteStaging(cwd, stagingDir, writeMeta) {
|
|
2863
3244
|
const wiki = wikiDir(cwd);
|
|
2864
|
-
const prev =
|
|
3245
|
+
const prev = join9(clioDir(cwd), WIKI_PREV_DIR);
|
|
2865
3246
|
removeDir(prev);
|
|
2866
|
-
const hadWiki =
|
|
3247
|
+
const hadWiki = existsSync7(wiki);
|
|
2867
3248
|
if (hadWiki) renameSync(wiki, prev);
|
|
2868
3249
|
try {
|
|
2869
3250
|
renameSync(stagingDir, wiki);
|
|
@@ -2891,7 +3272,7 @@ function resolvePlan(input) {
|
|
|
2891
3272
|
if (input.mode === "update" && input.previousPlan !== void 0) {
|
|
2892
3273
|
const pageSources = pageSourceIndex(input.stagingDir, input.cwd);
|
|
2893
3274
|
const changed = new Set(
|
|
2894
|
-
changedPathsSince(input.cwd, input.gitHead).map((
|
|
3275
|
+
changedPathsSince(input.cwd, input.gitHead).map((path2) => normalizeRepoPath(input.cwd, path2))
|
|
2895
3276
|
);
|
|
2896
3277
|
return {
|
|
2897
3278
|
plan: scopePlanForUpdate({
|
|
@@ -2940,8 +3321,8 @@ async function runWikiGenerate(input = { model: "configured-clio-target" }) {
|
|
|
2940
3321
|
}
|
|
2941
3322
|
try {
|
|
2942
3323
|
progress2(input, { phase: "codewiki", status: "started", message: "loading codewiki for wiki generation" });
|
|
2943
|
-
const codewiki = await loadOrBuildCodewiki(cwd);
|
|
2944
|
-
const sourceTreeHash =
|
|
3324
|
+
const { codewiki, fingerprint } = await loadOrBuildCodewiki(cwd);
|
|
3325
|
+
const sourceTreeHash = fingerprint.treeHash;
|
|
2945
3326
|
const generation = planWikiGeneration(codewiki, input.depth ?? "auto");
|
|
2946
3327
|
progress2(input, {
|
|
2947
3328
|
phase: "codewiki",
|
|
@@ -3015,7 +3396,7 @@ async function runWikiGenerate(input = { model: "configured-clio-target" }) {
|
|
|
3015
3396
|
message: `assembled ${report.pages.length} page${report.pages.length === 1 ? "" : "s"}`,
|
|
3016
3397
|
detail: `${report.repaired} repaired; ${report.issues.length} unresolved reference${report.issues.length === 1 ? "" : "s"}` + (report.dropped.length > 0 ? `; ${report.dropped.length} empty page dropped` : "") + (pendingCount > 0 ? `; ${pendingCount} page${pendingCount === 1 ? "" : "s"} still to write` : "")
|
|
3017
3398
|
});
|
|
3018
|
-
rmSync3(
|
|
3399
|
+
rmSync3(join9(staging.dir, WIKI_PLAN_FILE), { force: true });
|
|
3019
3400
|
const afterHash = computeWikiContentHashOfDir(staging.dir);
|
|
3020
3401
|
const stagedPages = listWikiPagesInDir(staging.dir);
|
|
3021
3402
|
const problems = report.issues.map((issue) => `${issue.page} has an unresolved ${issue.kind}: ${issue.reference}`);
|
|
@@ -3098,7 +3479,7 @@ function curateClioMd(cwd, codewiki) {
|
|
|
3098
3479
|
});
|
|
3099
3480
|
if (!changed) return "unchanged";
|
|
3100
3481
|
writeFileSync3(
|
|
3101
|
-
|
|
3482
|
+
join10(cwd, "CLIO-CODER.md"),
|
|
3102
3483
|
serializeClioMd({
|
|
3103
3484
|
projectName: handbook.projectName,
|
|
3104
3485
|
identity: handbook.identity,
|
|
@@ -3133,23 +3514,30 @@ async function runContextRefresh(input = {}) {
|
|
|
3133
3514
|
const projectType = prev?.projectType ?? detectProjectType(cwd);
|
|
3134
3515
|
const indexedAt = now().toISOString();
|
|
3135
3516
|
input.onProgress?.({ phase: "codewiki", status: "started", message: "rebuilding codewiki" });
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
const
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3517
|
+
let fingerprint;
|
|
3518
|
+
let clioMd = "absent";
|
|
3519
|
+
const coordinated = await coordinateCodewikiWrite(cwd, () => ({ kind: "build", cwd, language: projectType }), {
|
|
3520
|
+
afterCommit: (result, workspace) => {
|
|
3521
|
+
fingerprint = result.fingerprint;
|
|
3522
|
+
clioMd = curateClioMd(workspace, result.codewiki);
|
|
3523
|
+
input.onProgress?.({ phase: "state", status: "running", message: "writing state" });
|
|
3524
|
+
const latest = readClioState(workspace);
|
|
3525
|
+
writeClioState(workspace, {
|
|
3526
|
+
version: 1,
|
|
3527
|
+
projectType,
|
|
3528
|
+
fingerprint: result.fingerprint,
|
|
3529
|
+
codewikiVersion: result.codewiki.version,
|
|
3530
|
+
...latest?.contextSources ? { contextSources: latest.contextSources } : {},
|
|
3531
|
+
...latest?.contextSourceHash ? { contextSourceHash: latest.contextSourceHash } : {},
|
|
3532
|
+
...latest?.lastBootstrap ? { lastBootstrap: latest.lastBootstrap } : {},
|
|
3533
|
+
...latest?.lastInitAt ? { lastInitAt: latest.lastInitAt } : {},
|
|
3534
|
+
lastSessionAt: latest?.lastSessionAt ?? indexedAt,
|
|
3535
|
+
lastIndexedAt: indexedAt
|
|
3536
|
+
});
|
|
3537
|
+
}
|
|
3152
3538
|
});
|
|
3539
|
+
if (!coordinated || !fingerprint) throw new Error("codewiki refresh transaction did not commit");
|
|
3540
|
+
const codewiki = coordinated.codewiki;
|
|
3153
3541
|
const entries = indexedSourceFileCount3(codewiki);
|
|
3154
3542
|
let wikiResult;
|
|
3155
3543
|
let hint;
|
|
@@ -3166,7 +3554,8 @@ async function runContextRefresh(input = {}) {
|
|
|
3166
3554
|
} else if (hasWiki) {
|
|
3167
3555
|
hint = incompleteWikiHint(cwd) ?? (wikiStaleness(cwd).state === "stale" ? STALE_WIKI_REFRESH_HINT : void 0);
|
|
3168
3556
|
}
|
|
3169
|
-
const
|
|
3557
|
+
const committedClioMd = clioMd;
|
|
3558
|
+
const handbookNote = committedClioMd === "updated" ? "; CLIO-CODER.md index sections updated" : "";
|
|
3170
3559
|
input.io?.stdout(
|
|
3171
3560
|
`clio-coder context refresh: codewiki rebuilt (${entries} source file${entries === 1 ? "" : "s"})${handbookNote}
|
|
3172
3561
|
`
|
|
@@ -3176,17 +3565,23 @@ async function runContextRefresh(input = {}) {
|
|
|
3176
3565
|
action: "refreshed",
|
|
3177
3566
|
codewikiEntries: entries,
|
|
3178
3567
|
fingerprint,
|
|
3179
|
-
clioMd,
|
|
3568
|
+
clioMd: committedClioMd,
|
|
3180
3569
|
...wikiResult ? { wiki: wikiResult } : {},
|
|
3181
3570
|
...hint ? { hint } : {}
|
|
3182
3571
|
};
|
|
3183
3572
|
}
|
|
3184
3573
|
|
|
3574
|
+
// src/domains/context/runtime.ts
|
|
3575
|
+
init_esm_shims();
|
|
3576
|
+
|
|
3185
3577
|
// src/domains/context/extension.ts
|
|
3186
|
-
|
|
3578
|
+
init_esm_shims();
|
|
3579
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
3580
|
+
import { isAbsolute, join as join11, relative as relative4, resolve as resolve3 } from "node:path";
|
|
3581
|
+
function persistState(cwd, fingerprint, indexedAt, prev, codewikiVersion, projectType) {
|
|
3187
3582
|
writeClioState(cwd, {
|
|
3188
3583
|
version: 1,
|
|
3189
|
-
projectType: prev?.projectType ??
|
|
3584
|
+
projectType: prev?.projectType ?? projectType,
|
|
3190
3585
|
fingerprint,
|
|
3191
3586
|
codewikiVersion,
|
|
3192
3587
|
...prev?.contextSources ? { contextSources: prev.contextSources } : {},
|
|
@@ -3200,23 +3595,26 @@ function persistState(cwd, fingerprint, indexedAt, prev, codewikiVersion) {
|
|
|
3200
3595
|
async function ensureCodewikiFresh(cwd) {
|
|
3201
3596
|
if (process.env.CLIO_CODER_BOOTSTRAP_GENERATE_CHILD === "1") return;
|
|
3202
3597
|
const state = readClioState(cwd);
|
|
3203
|
-
if (!state && !
|
|
3204
|
-
const slicer = createSlicer();
|
|
3205
|
-
const codewiki = await readCodewikiAsync(cwd);
|
|
3206
|
-
const fingerprint = await computeFingerprintAsync(cwd, codewiki, { slicer });
|
|
3207
|
-
const stale = !state || isStale(state.fingerprint, fingerprint) || !existsSync7(codewikiPath(cwd)) || !codewiki || codewikiNeedsBackfill(codewiki);
|
|
3208
|
-
if (!stale) return;
|
|
3598
|
+
if (!state && !existsSync8(codewikiPath(cwd))) return;
|
|
3209
3599
|
const indexedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3600
|
+
await coordinateCodewikiWrite(
|
|
3601
|
+
cwd,
|
|
3602
|
+
(current, workspace) => {
|
|
3603
|
+
const language = readClioState(workspace)?.projectType ?? current?.language;
|
|
3604
|
+
return {
|
|
3605
|
+
kind: "ensure",
|
|
3606
|
+
cwd,
|
|
3607
|
+
...language ? { language } : {},
|
|
3608
|
+
current,
|
|
3609
|
+
previous: readClioState(workspace)?.fingerprint ?? null
|
|
3610
|
+
};
|
|
3611
|
+
},
|
|
3612
|
+
{
|
|
3613
|
+
afterCommit: ({ codewiki, fingerprint }, workspace) => persistState(workspace, fingerprint, indexedAt, readClioState(workspace), codewiki.version, codewiki.language)
|
|
3614
|
+
}
|
|
3615
|
+
);
|
|
3214
3616
|
}
|
|
3215
3617
|
var CONTEXT_STATE_CACHE_TTL_MS = 1500;
|
|
3216
|
-
var CODEWIKI_CACHE_LIMIT = 4;
|
|
3217
|
-
function codewikiContentHash(raw) {
|
|
3218
|
-
return createHash2("sha256").update(raw).digest("hex");
|
|
3219
|
-
}
|
|
3220
3618
|
function memoryCount() {
|
|
3221
3619
|
try {
|
|
3222
3620
|
return loadMemoryRecordsSync(clioDataDir()).length;
|
|
@@ -3225,11 +3623,12 @@ function memoryCount() {
|
|
|
3225
3623
|
}
|
|
3226
3624
|
}
|
|
3227
3625
|
function resolveClioMdState(cwd) {
|
|
3228
|
-
const clio =
|
|
3229
|
-
if (
|
|
3230
|
-
if (
|
|
3626
|
+
const clio = loadProjectClioMd(cwd);
|
|
3627
|
+
if (clio.files.length === 0 && clio.errors.length === 0) return "none";
|
|
3628
|
+
if (clio.errors.length > 0) return "malformed";
|
|
3231
3629
|
const state = readClioState(cwd);
|
|
3232
|
-
|
|
3630
|
+
const localStandardIsEffective = clio.files.some((file) => file.path === join11(resolve3(cwd), "CLIO-CODER.md"));
|
|
3631
|
+
if (localStandardIsEffective && state?.contextSources !== void 0 && adoptionSourcesChanged(state.contextSources, { cwd })) {
|
|
3233
3632
|
return "stale";
|
|
3234
3633
|
}
|
|
3235
3634
|
return "ok";
|
|
@@ -3258,12 +3657,12 @@ function collectStartupHints(cwd, options = {}) {
|
|
|
3258
3657
|
} catch {
|
|
3259
3658
|
projectType = "unknown";
|
|
3260
3659
|
}
|
|
3261
|
-
const clio =
|
|
3262
|
-
if (
|
|
3660
|
+
const clio = loadProjectClioMd(cwd);
|
|
3661
|
+
if (clio.files.length === 0 && clio.errors.length === 0 && projectType !== "unknown" && options.noContextFiles !== true) {
|
|
3263
3662
|
hints.push("clio: No CLIO-CODER.md detected. Run /context init to explore the repo and bootstrap context.");
|
|
3264
3663
|
}
|
|
3265
|
-
|
|
3266
|
-
hints.push(`clio: malformed
|
|
3664
|
+
for (const issue of clio.errors) {
|
|
3665
|
+
hints.push(`clio: malformed ${issue.path} ignored: ${issue.error}`);
|
|
3267
3666
|
}
|
|
3268
3667
|
const state = readClioState(cwd);
|
|
3269
3668
|
if (!state) return hints;
|
|
@@ -3274,44 +3673,9 @@ function collectStartupHints(cwd, options = {}) {
|
|
|
3274
3673
|
}
|
|
3275
3674
|
function createContextBundle(_context, options = {}) {
|
|
3276
3675
|
let lastCwd = process.cwd();
|
|
3676
|
+
let stopping = false;
|
|
3277
3677
|
let startupHints = [];
|
|
3278
3678
|
const contextState = createContextStateReader();
|
|
3279
|
-
const codewikiCache = /* @__PURE__ */ new Map();
|
|
3280
|
-
const rememberCodewiki = (cwd, hash, codewiki) => {
|
|
3281
|
-
codewikiCache.delete(cwd);
|
|
3282
|
-
codewikiCache.set(cwd, { hash, codewiki });
|
|
3283
|
-
while (codewikiCache.size > CODEWIKI_CACHE_LIMIT) {
|
|
3284
|
-
const oldest = codewikiCache.keys().next().value;
|
|
3285
|
-
if (oldest === void 0) break;
|
|
3286
|
-
codewikiCache.delete(oldest);
|
|
3287
|
-
}
|
|
3288
|
-
};
|
|
3289
|
-
const readCachedCodewiki = (cwd) => {
|
|
3290
|
-
let raw;
|
|
3291
|
-
try {
|
|
3292
|
-
raw = readFileSync7(codewikiPath(cwd), "utf8");
|
|
3293
|
-
} catch {
|
|
3294
|
-
codewikiCache.delete(cwd);
|
|
3295
|
-
return null;
|
|
3296
|
-
}
|
|
3297
|
-
const hash = codewikiContentHash(raw);
|
|
3298
|
-
const cached = codewikiCache.get(cwd);
|
|
3299
|
-
if (cached && cached.hash === hash) {
|
|
3300
|
-
rememberCodewiki(cwd, hash, cached.codewiki);
|
|
3301
|
-
return cached.codewiki;
|
|
3302
|
-
}
|
|
3303
|
-
const codewiki = parseCodewikiRaw(raw);
|
|
3304
|
-
if (!codewiki) {
|
|
3305
|
-
codewikiCache.delete(cwd);
|
|
3306
|
-
return null;
|
|
3307
|
-
}
|
|
3308
|
-
rememberCodewiki(cwd, hash, codewiki);
|
|
3309
|
-
return codewiki;
|
|
3310
|
-
};
|
|
3311
|
-
const writeCachedCodewiki = (cwd, codewiki) => {
|
|
3312
|
-
const serialized = writeCodewiki(cwd, codewiki);
|
|
3313
|
-
rememberCodewiki(cwd, codewikiContentHash(serialized), codewiki);
|
|
3314
|
-
};
|
|
3315
3679
|
const onStart = () => {
|
|
3316
3680
|
lastCwd = process.cwd();
|
|
3317
3681
|
void ensureCodewikiFresh(lastCwd).catch(() => {
|
|
@@ -3323,23 +3687,30 @@ function createContextBundle(_context, options = {}) {
|
|
|
3323
3687
|
};
|
|
3324
3688
|
let incrementalQueue = Promise.resolve();
|
|
3325
3689
|
const noteFileChanges = (paths, cwd = lastCwd) => {
|
|
3690
|
+
if (stopping) return;
|
|
3691
|
+
const workspace = resolve3(cwd);
|
|
3326
3692
|
incrementalQueue = incrementalQueue.then(async () => {
|
|
3327
3693
|
if (paths.length === 0) return;
|
|
3328
|
-
const
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3694
|
+
const rel = paths.map((p) => isAbsolute(p) ? relative4(workspace, p) : p).filter((p) => p.length > 0 && !p.startsWith(".."));
|
|
3695
|
+
await coordinateCodewikiWrite(
|
|
3696
|
+
workspace,
|
|
3697
|
+
(current) => current ? { kind: "incremental", cwd: workspace, current, paths: rel } : null,
|
|
3698
|
+
{
|
|
3699
|
+
requireExisting: true,
|
|
3700
|
+
afterCommit: ({ codewiki, fingerprint, changed }, committedWorkspace) => {
|
|
3701
|
+
if (!changed) return;
|
|
3702
|
+
persistState(
|
|
3703
|
+
committedWorkspace,
|
|
3704
|
+
fingerprint,
|
|
3705
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
3706
|
+
readClioState(committedWorkspace),
|
|
3707
|
+
codewiki.version,
|
|
3708
|
+
codewiki.language
|
|
3709
|
+
);
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3341
3712
|
);
|
|
3342
|
-
contextState.invalidate(
|
|
3713
|
+
contextState.invalidate(workspace);
|
|
3343
3714
|
}).catch(() => {
|
|
3344
3715
|
});
|
|
3345
3716
|
};
|
|
@@ -3349,33 +3720,13 @@ function createContextBundle(_context, options = {}) {
|
|
|
3349
3720
|
unsubscribeSessionStart = _context.bus.on(BusChannels.SessionStart, onStart);
|
|
3350
3721
|
},
|
|
3351
3722
|
async stop() {
|
|
3723
|
+
stopping = true;
|
|
3352
3724
|
unsubscribeSessionStart?.();
|
|
3353
3725
|
unsubscribeSessionStart = null;
|
|
3354
|
-
await incrementalQueue;
|
|
3355
|
-
const slicer = createSlicer();
|
|
3356
|
-
const projectType = detectProjectType(lastCwd);
|
|
3726
|
+
await Promise.all([incrementalQueue, drainCodewikiWrites(lastCwd)]);
|
|
3357
3727
|
const state = readClioState(lastCwd);
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
let lastIndexedAt = state?.lastIndexedAt;
|
|
3361
|
-
if (!state || isStale(state.fingerprint, fingerprint) || !codewiki || codewikiNeedsBackfill(codewiki)) {
|
|
3362
|
-
lastIndexedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3363
|
-
codewiki = codewiki ? await syncCodewiki(lastCwd, codewiki, { slicer }) : await buildCodewiki({ cwd: lastCwd, language: projectType, generatedAt: lastIndexedAt }, { slicer });
|
|
3364
|
-
writeCachedCodewiki(lastCwd, codewiki);
|
|
3365
|
-
fingerprint = await computeFingerprintAsync(lastCwd, codewiki, { slicer });
|
|
3366
|
-
}
|
|
3367
|
-
writeClioState(lastCwd, {
|
|
3368
|
-
version: 1,
|
|
3369
|
-
projectType,
|
|
3370
|
-
fingerprint,
|
|
3371
|
-
...codewiki ? { codewikiVersion: codewiki.version } : {},
|
|
3372
|
-
...state?.contextSources ? { contextSources: state.contextSources } : {},
|
|
3373
|
-
...state?.contextSourceHash ? { contextSourceHash: state.contextSourceHash } : {},
|
|
3374
|
-
...state?.lastBootstrap ? { lastBootstrap: state.lastBootstrap } : {},
|
|
3375
|
-
...state?.lastInitAt ? { lastInitAt: state.lastInitAt } : {},
|
|
3376
|
-
lastSessionAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3377
|
-
...lastIndexedAt ? { lastIndexedAt } : {}
|
|
3378
|
-
});
|
|
3728
|
+
if (!state) return;
|
|
3729
|
+
writeClioState(lastCwd, { ...state, lastSessionAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
3379
3730
|
}
|
|
3380
3731
|
};
|
|
3381
3732
|
const contract = {
|
|
@@ -3466,16 +3817,13 @@ function createContextBundle(_context, options = {}) {
|
|
|
3466
3817
|
},
|
|
3467
3818
|
renderPromptContext,
|
|
3468
3819
|
projectStructuredContext(cwd = process.cwd()) {
|
|
3469
|
-
const clio =
|
|
3470
|
-
if (!clio
|
|
3471
|
-
const
|
|
3472
|
-
(section) => section.title.toLowerCase() === "verification expectations"
|
|
3473
|
-
);
|
|
3474
|
-
const verificationBody = verification?.body.trim() ?? "";
|
|
3820
|
+
const clio = loadProjectClioMd(cwd).value;
|
|
3821
|
+
if (!clio) return null;
|
|
3822
|
+
const verificationBody = clio.sections.filter((section) => section.title.toLowerCase() === "verification expectations").map((section) => section.body.trim()).filter((body) => body.length > 0).join("\n\n");
|
|
3475
3823
|
return {
|
|
3476
|
-
projectName: clio.
|
|
3477
|
-
conventions: [...clio.
|
|
3478
|
-
invariants: [...clio.
|
|
3824
|
+
projectName: clio.projectName,
|
|
3825
|
+
conventions: [...clio.conventions],
|
|
3826
|
+
invariants: [...clio.invariants],
|
|
3479
3827
|
...verificationBody.length > 0 ? { verificationExpectations: verificationBody } : {}
|
|
3480
3828
|
};
|
|
3481
3829
|
},
|
|
@@ -3493,264 +3841,128 @@ var ContextManifest = {
|
|
|
3493
3841
|
dependsOn: ["resources"]
|
|
3494
3842
|
};
|
|
3495
3843
|
|
|
3496
|
-
// src/domains/context/
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
var OPERATOR_PROFILE_MAX_LOCAL_PATHS = 8;
|
|
3507
|
-
function isRecord2(value) {
|
|
3508
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3509
|
-
}
|
|
3510
|
-
function readEnum(value, allowed, field, issues) {
|
|
3511
|
-
if (value === void 0) return void 0;
|
|
3512
|
-
if (typeof value === "string" && allowed.includes(value)) return value;
|
|
3513
|
-
issues.push(`${field} must be one of ${allowed.join(", ")}`);
|
|
3514
|
-
return void 0;
|
|
3515
|
-
}
|
|
3516
|
-
function readProfileBlob(value, issues) {
|
|
3517
|
-
if (!isRecord2(value)) {
|
|
3518
|
-
if (value !== null && value !== void 0) issues.push("profile must be a mapping at the root");
|
|
3519
|
-
return {};
|
|
3520
|
-
}
|
|
3521
|
-
const profile = {};
|
|
3522
|
-
const posture = readEnum(value.responsePosture, RESPONSE_POSTURES, "responsePosture", issues);
|
|
3523
|
-
if (posture) profile.responsePosture = posture;
|
|
3524
|
-
const validation = readEnum(value.validationPreference, VALIDATION_PREFERENCES, "validationPreference", issues);
|
|
3525
|
-
if (validation) profile.validationPreference = validation;
|
|
3526
|
-
const commit = readEnum(value.commitMessageStyle, COMMIT_MESSAGE_STYLES, "commitMessageStyle", issues);
|
|
3527
|
-
if (commit) profile.commitMessageStyle = commit;
|
|
3528
|
-
if (value.localOnlyPaths !== void 0) {
|
|
3529
|
-
if (Array.isArray(value.localOnlyPaths)) {
|
|
3530
|
-
const paths = value.localOnlyPaths.filter((item) => typeof item === "string" && item.length > 0);
|
|
3531
|
-
if (paths.length > 0) profile.localOnlyPaths = paths.slice(0, OPERATOR_PROFILE_MAX_LOCAL_PATHS);
|
|
3532
|
-
} else {
|
|
3533
|
-
issues.push("localOnlyPaths must be an array of strings");
|
|
3534
|
-
}
|
|
3535
|
-
}
|
|
3536
|
-
return profile;
|
|
3537
|
-
}
|
|
3538
|
-
function readProfileFile(path, issues) {
|
|
3539
|
-
if (!existsSync8(path)) return { profile: {}, present: false };
|
|
3540
|
-
try {
|
|
3541
|
-
return { profile: readProfileBlob((0, import_yaml2.parse)(readFileSync8(path, "utf8")), issues), present: true };
|
|
3542
|
-
} catch (err) {
|
|
3543
|
-
issues.push(`${path}: invalid YAML: ${err instanceof Error ? err.message : String(err)}`);
|
|
3544
|
-
return { profile: {}, present: false };
|
|
3545
|
-
}
|
|
3546
|
-
}
|
|
3547
|
-
function loadOperatorProfile(cwd, options = {}) {
|
|
3548
|
-
const issues = [];
|
|
3549
|
-
const userPath = options.userPath ?? join9(resolveClioDirs().config, "profile.yaml");
|
|
3550
|
-
const projectPath = join9(cwd, ".clio-coder", "profile.yaml");
|
|
3551
|
-
const user = readProfileFile(userPath, issues);
|
|
3552
|
-
const project = readProfileFile(projectPath, issues);
|
|
3553
|
-
const profile = { ...user.profile, ...project.profile };
|
|
3554
|
-
let origin = "none";
|
|
3555
|
-
let sourcePath;
|
|
3556
|
-
if (project.present) {
|
|
3557
|
-
origin = "project";
|
|
3558
|
-
sourcePath = projectPath;
|
|
3559
|
-
} else if (user.present) {
|
|
3560
|
-
origin = "user";
|
|
3561
|
-
sourcePath = userPath;
|
|
3562
|
-
}
|
|
3563
|
-
const result = { profile, origin, issues };
|
|
3564
|
-
if (sourcePath !== void 0) {
|
|
3565
|
-
result.sourcePath = sourcePath;
|
|
3566
|
-
result.hash = createHash3("sha256").update(JSON.stringify(profile)).digest("hex").slice(0, 16);
|
|
3567
|
-
}
|
|
3568
|
-
return result;
|
|
3569
|
-
}
|
|
3570
|
-
function renderOperatorProfile(profile) {
|
|
3571
|
-
const lines = [];
|
|
3572
|
-
if (profile.responsePosture) lines.push(`- Response posture: ${profile.responsePosture}.`);
|
|
3573
|
-
if (profile.validationPreference) lines.push(`- Validation preference: ${profile.validationPreference}.`);
|
|
3574
|
-
if (profile.commitMessageStyle) lines.push(`- Commit-message style: ${profile.commitMessageStyle}.`);
|
|
3575
|
-
if (profile.localOnlyPaths && profile.localOnlyPaths.length > 0) {
|
|
3576
|
-
lines.push(`- Keep local-only (do not push or share): ${profile.localOnlyPaths.join(", ")}.`);
|
|
3577
|
-
}
|
|
3578
|
-
if (lines.length === 0) return { text: "", tokenEstimate: 0 };
|
|
3579
|
-
const full = `## Operator profile
|
|
3580
|
-
${lines.join("\n")}`;
|
|
3581
|
-
const text = full.length > OPERATOR_PROFILE_MAX_CHARS ? `${full.slice(0, OPERATOR_PROFILE_MAX_CHARS - 1)}\u2026` : full;
|
|
3582
|
-
return { text, tokenEstimate: ceilChars(text.length) };
|
|
3844
|
+
// src/domains/context/runtime.ts
|
|
3845
|
+
var ContextDomainModule = {
|
|
3846
|
+
manifest: ContextManifest,
|
|
3847
|
+
createExtension: createContextBundle
|
|
3848
|
+
};
|
|
3849
|
+
function createContextDomainModule(options = {}) {
|
|
3850
|
+
return {
|
|
3851
|
+
manifest: ContextManifest,
|
|
3852
|
+
createExtension: (context) => createContextBundle(context, options)
|
|
3853
|
+
};
|
|
3583
3854
|
}
|
|
3584
3855
|
|
|
3585
|
-
// src/domains/context/
|
|
3856
|
+
// src/domains/context/wiki/prompts.ts
|
|
3586
3857
|
init_esm_shims();
|
|
3587
|
-
|
|
3588
|
-
import {
|
|
3589
|
-
import {
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
}
|
|
3595
|
-
|
|
3596
|
-
|
|
3858
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
3859
|
+
import { existsSync as existsSync9, realpathSync, statSync as statSync4 } from "node:fs";
|
|
3860
|
+
import { isAbsolute as isAbsolute2, join as join12, relative as relative5 } from "node:path";
|
|
3861
|
+
|
|
3862
|
+
// src/domains/prompts/fragment-loader.ts
|
|
3863
|
+
init_esm_shims();
|
|
3864
|
+
var import_yaml4 = __toESM(require_dist(), 1);
|
|
3865
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync9 } from "node:fs";
|
|
3866
|
+
import path from "node:path";
|
|
3867
|
+
var frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
3868
|
+
var fragmentIdRegex = /^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;
|
|
3869
|
+
function defaultRootDir() {
|
|
3870
|
+
return path.join(resolvePackageRoot(), "src", "domains", "prompts", "fragments");
|
|
3871
|
+
}
|
|
3872
|
+
function walk(root) {
|
|
3597
3873
|
const out3 = [];
|
|
3598
|
-
for (const item of value) {
|
|
3599
|
-
if (typeof item === "string" && item.length > 0) out3.push(item);
|
|
3600
|
-
}
|
|
3601
|
-
return out3.length > 0 ? out3 : void 0;
|
|
3602
|
-
}
|
|
3603
|
-
function validateGlobArray(value, field, id, issues) {
|
|
3604
|
-
const parsed = readStringArray(value);
|
|
3605
|
-
if (parsed === void 0) {
|
|
3606
|
-
issues.push(`${id}: frontmatter ${field} must be a non-empty string array`);
|
|
3607
|
-
return void 0;
|
|
3608
|
-
}
|
|
3609
|
-
for (const pattern of parsed) {
|
|
3610
|
-
try {
|
|
3611
|
-
compileGlobRegex(pattern);
|
|
3612
|
-
} catch (err) {
|
|
3613
|
-
issues.push(
|
|
3614
|
-
`${id}: invalid ${field} glob ${JSON.stringify(pattern)}: ${err instanceof Error ? err.message : String(err)}`
|
|
3615
|
-
);
|
|
3616
|
-
return void 0;
|
|
3617
|
-
}
|
|
3618
|
-
}
|
|
3619
|
-
return parsed;
|
|
3620
|
-
}
|
|
3621
|
-
function walkMarkdown(dir, root, out3) {
|
|
3622
3874
|
let entries;
|
|
3623
3875
|
try {
|
|
3624
|
-
entries =
|
|
3876
|
+
entries = readdirSync5(root, { withFileTypes: true });
|
|
3625
3877
|
} catch {
|
|
3626
|
-
return;
|
|
3878
|
+
return out3;
|
|
3627
3879
|
}
|
|
3628
3880
|
for (const entry of entries) {
|
|
3629
|
-
const full =
|
|
3630
|
-
if (entry.isDirectory())
|
|
3631
|
-
|
|
3881
|
+
const full = path.join(root, entry.name);
|
|
3882
|
+
if (entry.isDirectory()) {
|
|
3883
|
+
out3.push(...walk(full));
|
|
3884
|
+
continue;
|
|
3885
|
+
}
|
|
3886
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
3887
|
+
out3.push(full);
|
|
3888
|
+
}
|
|
3632
3889
|
}
|
|
3890
|
+
return out3.sort((left, right) => left.localeCompare(right));
|
|
3633
3891
|
}
|
|
3634
|
-
function
|
|
3635
|
-
|
|
3892
|
+
function parseFragment(filePath, rootDir) {
|
|
3893
|
+
const raw = readFileSync9(filePath, "utf8");
|
|
3894
|
+
const rawRel = path.relative(rootDir, filePath);
|
|
3895
|
+
const relPath = rawRel.split(path.sep).join("/");
|
|
3896
|
+
const match = raw.match(frontmatterRegex);
|
|
3897
|
+
if (!match) {
|
|
3898
|
+
throw new Error(`fragment-loader: ${relPath}: missing or malformed YAML frontmatter`);
|
|
3899
|
+
}
|
|
3900
|
+
const frontmatterText = match[1] ?? "";
|
|
3901
|
+
const body = match[2] ?? "";
|
|
3902
|
+
let parsed;
|
|
3636
3903
|
try {
|
|
3637
|
-
|
|
3904
|
+
parsed = import_yaml4.default.parse(frontmatterText);
|
|
3638
3905
|
} catch (err) {
|
|
3639
|
-
|
|
3640
|
-
|
|
3906
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
3907
|
+
throw new Error(`fragment-loader: ${relPath}: invalid YAML frontmatter (${reason})`);
|
|
3641
3908
|
}
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
let paths;
|
|
3645
|
-
let excludes = [];
|
|
3646
|
-
let enabled = true;
|
|
3647
|
-
let description2;
|
|
3648
|
-
let invalidFrontmatter = false;
|
|
3649
|
-
const match = FRONTMATTER_RE.exec(text);
|
|
3650
|
-
if (match) {
|
|
3651
|
-
body = text.slice(match[0].length);
|
|
3652
|
-
try {
|
|
3653
|
-
const front = (0, import_yaml3.parse)(match[1] ?? "");
|
|
3654
|
-
if (isRecord3(front)) {
|
|
3655
|
-
if (Object.hasOwn(front, "paths")) {
|
|
3656
|
-
const parsedPaths = validateGlobArray(front.paths, "paths", id, issues);
|
|
3657
|
-
if (parsedPaths === void 0) invalidFrontmatter = true;
|
|
3658
|
-
else paths = parsedPaths;
|
|
3659
|
-
}
|
|
3660
|
-
if (Object.hasOwn(front, "excludes")) {
|
|
3661
|
-
const parsedExcludes = validateGlobArray(front.excludes, "excludes", id, issues);
|
|
3662
|
-
if (parsedExcludes === void 0) invalidFrontmatter = true;
|
|
3663
|
-
else excludes = parsedExcludes;
|
|
3664
|
-
}
|
|
3665
|
-
if (Object.hasOwn(front, "enabled")) {
|
|
3666
|
-
if (typeof front.enabled === "boolean") enabled = front.enabled;
|
|
3667
|
-
else {
|
|
3668
|
-
issues.push(`${id}: frontmatter enabled must be a boolean`);
|
|
3669
|
-
invalidFrontmatter = true;
|
|
3670
|
-
}
|
|
3671
|
-
}
|
|
3672
|
-
if (Object.hasOwn(front, "description")) {
|
|
3673
|
-
if (typeof front.description === "string") description2 = front.description;
|
|
3674
|
-
else {
|
|
3675
|
-
issues.push(`${id}: frontmatter description must be a string`);
|
|
3676
|
-
invalidFrontmatter = true;
|
|
3677
|
-
}
|
|
3678
|
-
}
|
|
3679
|
-
} else if (front !== null && front !== void 0) {
|
|
3680
|
-
issues.push(`${id}: frontmatter must be a mapping`);
|
|
3681
|
-
invalidFrontmatter = true;
|
|
3682
|
-
}
|
|
3683
|
-
} catch (err) {
|
|
3684
|
-
issues.push(`${id}: invalid frontmatter: ${err instanceof Error ? err.message : String(err)}`);
|
|
3685
|
-
invalidFrontmatter = true;
|
|
3686
|
-
}
|
|
3687
|
-
} else if (text.startsWith("---\n")) {
|
|
3688
|
-
issues.push(`${id}: invalid frontmatter: missing closing marker`);
|
|
3689
|
-
invalidFrontmatter = true;
|
|
3909
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3910
|
+
throw new Error(`fragment-loader: ${relPath}: frontmatter must be a YAML object`);
|
|
3690
3911
|
}
|
|
3691
|
-
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
|
|
3912
|
+
const fm = parsed;
|
|
3913
|
+
const id = fm.id;
|
|
3914
|
+
if (typeof id !== "string" || !fragmentIdRegex.test(id)) {
|
|
3915
|
+
throw new Error(`fragment-loader: ${relPath}: frontmatter.id must be a dot-separated namespace`);
|
|
3916
|
+
}
|
|
3917
|
+
const version = fm.version;
|
|
3918
|
+
if (version !== 1) {
|
|
3919
|
+
throw new Error(`fragment-loader: ${relPath}: frontmatter.version must be 1`);
|
|
3920
|
+
}
|
|
3921
|
+
const description2 = fm.description;
|
|
3922
|
+
if (typeof description2 !== "string" || description2.trim() === "") {
|
|
3923
|
+
throw new Error(`fragment-loader: ${relPath}: frontmatter.description must be a non-empty string`);
|
|
3924
|
+
}
|
|
3925
|
+
const dynamicRaw = fm.dynamic;
|
|
3926
|
+
if (dynamicRaw !== void 0 && typeof dynamicRaw !== "boolean") {
|
|
3927
|
+
throw new Error(`fragment-loader: ${relPath}: frontmatter.dynamic must be a boolean when present`);
|
|
3928
|
+
}
|
|
3929
|
+
return {
|
|
3930
|
+
path: filePath,
|
|
3931
|
+
relPath,
|
|
3695
3932
|
id,
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3933
|
+
version,
|
|
3934
|
+
description: description2,
|
|
3935
|
+
dynamic: dynamicRaw === true,
|
|
3936
|
+
body,
|
|
3937
|
+
contentHash: sha256(raw)
|
|
3701
3938
|
};
|
|
3702
|
-
if (paths !== void 0) rule.paths = paths;
|
|
3703
|
-
if (description2 !== void 0) rule.description = description2;
|
|
3704
|
-
return { rule, excludes };
|
|
3705
3939
|
}
|
|
3706
|
-
function
|
|
3707
|
-
const
|
|
3708
|
-
const
|
|
3709
|
-
const files =
|
|
3710
|
-
|
|
3711
|
-
files.sort();
|
|
3712
|
-
const rules = [];
|
|
3713
|
-
const excludeSet = /* @__PURE__ */ new Set();
|
|
3940
|
+
function loadFragments(options) {
|
|
3941
|
+
const rootDir = typeof options === "string" ? options : options?.rootDir;
|
|
3942
|
+
const resolvedRoot = rootDir ? path.resolve(rootDir) : defaultRootDir();
|
|
3943
|
+
const files = walk(resolvedRoot);
|
|
3944
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3714
3945
|
for (const file of files) {
|
|
3715
|
-
const
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
}
|
|
3722
|
-
function ruleMatchesAnyPath(rule, workingPaths) {
|
|
3723
|
-
for (const pattern of rule.paths ?? []) {
|
|
3724
|
-
let regex;
|
|
3725
|
-
try {
|
|
3726
|
-
regex = compileGlobRegex(pattern);
|
|
3727
|
-
} catch {
|
|
3728
|
-
continue;
|
|
3729
|
-
}
|
|
3730
|
-
for (const path of workingPaths) {
|
|
3731
|
-
if (regex.test(normalizeGlobInput(path))) return true;
|
|
3946
|
+
const fragment = parseFragment(file, resolvedRoot);
|
|
3947
|
+
const existing = byId.get(fragment.id);
|
|
3948
|
+
if (existing) {
|
|
3949
|
+
throw new Error(
|
|
3950
|
+
`fragment-loader: duplicate fragment id "${fragment.id}" in ${existing.relPath} and ${fragment.relPath}`
|
|
3951
|
+
);
|
|
3732
3952
|
}
|
|
3953
|
+
byId.set(fragment.id, fragment);
|
|
3733
3954
|
}
|
|
3734
|
-
return
|
|
3735
|
-
}
|
|
3736
|
-
function selectActiveRules(rules, workingContextPaths) {
|
|
3737
|
-
return rules.filter((rule) => {
|
|
3738
|
-
if (!rule.enabled) return false;
|
|
3739
|
-
if (rule.paths === void 0) return true;
|
|
3740
|
-
return ruleMatchesAnyPath(rule, workingContextPaths);
|
|
3741
|
-
});
|
|
3955
|
+
return { byId, rootDir: resolvedRoot };
|
|
3742
3956
|
}
|
|
3743
3957
|
|
|
3744
3958
|
// src/domains/context/wiki/prompts.ts
|
|
3745
|
-
init_esm_shims();
|
|
3746
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
3747
|
-
import { existsSync as existsSync9, readFileSync as readFileSync10, realpathSync, statSync as statSync3 } from "node:fs";
|
|
3748
|
-
import { isAbsolute as isAbsolute2, join as join11, relative as relative5 } from "node:path";
|
|
3749
|
-
function fragmentPath(fragment) {
|
|
3750
|
-
return join11(resolvePackageRoot(), "src", "domains", "prompts", "fragments", "wiki", `${fragment}.md`);
|
|
3751
|
-
}
|
|
3752
3959
|
function readWikiFragment(fragment, substitutions) {
|
|
3753
|
-
|
|
3960
|
+
const id = `wiki.${fragment}`;
|
|
3961
|
+
const loaded = loadFragments().byId.get(id);
|
|
3962
|
+
if (!loaded) {
|
|
3963
|
+
throw new Error(`context/wiki: fragment "${id}" not found; check prompts/fragments/wiki/${fragment}.md frontmatter`);
|
|
3964
|
+
}
|
|
3965
|
+
let text = loaded.body.trim();
|
|
3754
3966
|
for (const [token, value] of Object.entries(substitutions)) {
|
|
3755
3967
|
text = text.split(`{{${token}}}`).join(value);
|
|
3756
3968
|
}
|
|
@@ -3780,11 +3992,11 @@ function repositoryGuidancePaths(cwd) {
|
|
|
3780
3992
|
const seen = /* @__PURE__ */ new Set();
|
|
3781
3993
|
const paths = [];
|
|
3782
3994
|
for (const relPath of REPOSITORY_GUIDANCE_CANDIDATES) {
|
|
3783
|
-
const absPath =
|
|
3995
|
+
const absPath = join12(cwd, relPath);
|
|
3784
3996
|
if (!existsSync9(absPath)) continue;
|
|
3785
3997
|
try {
|
|
3786
3998
|
const resolved = realpathSync(absPath);
|
|
3787
|
-
const stat =
|
|
3999
|
+
const stat = statSync4(resolved);
|
|
3788
4000
|
if (!isWithin(root, resolved) || !stat.isFile() || stat.size === 0 || seen.has(resolved)) continue;
|
|
3789
4001
|
seen.add(resolved);
|
|
3790
4002
|
paths.push(relPath);
|
|
@@ -3800,7 +4012,7 @@ function repositoryGuidance(cwd) {
|
|
|
3800
4012
|
}
|
|
3801
4013
|
return [
|
|
3802
4014
|
"Read every detected instruction file before drafting:",
|
|
3803
|
-
...paths.map((
|
|
4015
|
+
...paths.map((path2) => `- ${path2}`),
|
|
3804
4016
|
"Treat these files as repository instructions, not implementation proof. If one designates a planning, specification, or engineering-truth authority, read that authority before making status claims, then verify mutable implementation claims against live source, configuration, and tests."
|
|
3805
4017
|
].join("\n");
|
|
3806
4018
|
}
|
|
@@ -3851,7 +4063,7 @@ function buildWikiPlanPrompt(input) {
|
|
|
3851
4063
|
const plan = input.plan ?? generation.plan;
|
|
3852
4064
|
const unclaimed = input.unclaimedAreas ?? [];
|
|
3853
4065
|
const sections = [
|
|
3854
|
-
readWikiFragment("plan", { planPath:
|
|
4066
|
+
readWikiFragment("plan", { planPath: join12(input.outputDir, WIKI_PLAN_FILE) }),
|
|
3855
4067
|
"## Repository scale",
|
|
3856
4068
|
`${generation.sourceFiles} indexed source files, ${generation.sourceLines} source lines, decomposed at ${generation.depth} depth into ${generation.plan.pages.length} candidate pages.`,
|
|
3857
4069
|
"## Candidate plan",
|
|
@@ -3901,7 +4113,7 @@ function buildWikiPagePrompt(input) {
|
|
|
3901
4113
|
const siblingLines = input.siblings.filter((sibling) => sibling.path !== page.path).map((sibling) => `- ${sibling.path} \u2014 ${sibling.title}`);
|
|
3902
4114
|
const sections = [
|
|
3903
4115
|
readWikiFragment("page", {
|
|
3904
|
-
pagePath:
|
|
4116
|
+
pagePath: join12(input.outputDir, page.path),
|
|
3905
4117
|
pageRelPath: page.path,
|
|
3906
4118
|
pageTitle: page.title
|
|
3907
4119
|
}),
|
|
@@ -3922,25 +4134,13 @@ ${page.sources.map((source) => `- ${source}`).join("\n")}` : "No anchor sources
|
|
|
3922
4134
|
if (input.seeded) {
|
|
3923
4135
|
sections.push(
|
|
3924
4136
|
"## Revision",
|
|
3925
|
-
`A previous version of this page is already at ${
|
|
4137
|
+
`A previous version of this page is already at ${join12(input.outputDir, page.path)}. Read it first and revise it in place. Correct what the current source contradicts and fill what it omits; keep accurate prose as it stands.`
|
|
3926
4138
|
);
|
|
3927
4139
|
}
|
|
3928
4140
|
return `${sections.join("\n\n")}
|
|
3929
4141
|
`;
|
|
3930
4142
|
}
|
|
3931
4143
|
|
|
3932
|
-
// src/domains/context/index.ts
|
|
3933
|
-
var ContextDomainModule = {
|
|
3934
|
-
manifest: ContextManifest,
|
|
3935
|
-
createExtension: createContextBundle
|
|
3936
|
-
};
|
|
3937
|
-
function createContextDomainModule(options = {}) {
|
|
3938
|
-
return {
|
|
3939
|
-
manifest: ContextManifest,
|
|
3940
|
-
createExtension: (context) => createContextBundle(context, options)
|
|
3941
|
-
};
|
|
3942
|
-
}
|
|
3943
|
-
|
|
3944
4144
|
export {
|
|
3945
4145
|
adoptionSnapshotsHash,
|
|
3946
4146
|
scanAgentConfigs,
|
|
@@ -3948,11 +4148,17 @@ export {
|
|
|
3948
4148
|
adoptionSourcesChanged,
|
|
3949
4149
|
parseClioMd,
|
|
3950
4150
|
serializeClioMd,
|
|
4151
|
+
loadProjectClioMd,
|
|
3951
4152
|
tryReadClioMd,
|
|
3952
4153
|
renderPromptContext,
|
|
3953
4154
|
fallbackBootstrapOutput,
|
|
3954
4155
|
runBootstrap,
|
|
3955
4156
|
runContextClear,
|
|
4157
|
+
OPERATOR_PROFILE_MAX_CHARS,
|
|
4158
|
+
loadOperatorProfile,
|
|
4159
|
+
renderOperatorProfile,
|
|
4160
|
+
loadProjectRules,
|
|
4161
|
+
selectActiveRules,
|
|
3956
4162
|
assembleWikiTree,
|
|
3957
4163
|
WIKI_DEPTH_STRATEGY,
|
|
3958
4164
|
pagePathForArea,
|
|
@@ -3960,14 +4166,10 @@ export {
|
|
|
3960
4166
|
planWikiGeneration,
|
|
3961
4167
|
runWikiGenerate,
|
|
3962
4168
|
runContextRefresh,
|
|
3963
|
-
OPERATOR_PROFILE_MAX_CHARS,
|
|
3964
|
-
loadOperatorProfile,
|
|
3965
|
-
renderOperatorProfile,
|
|
3966
|
-
loadProjectRules,
|
|
3967
|
-
selectActiveRules,
|
|
3968
|
-
buildWikiPlanPrompt,
|
|
3969
|
-
buildWikiPagePrompt,
|
|
3970
4169
|
ContextDomainModule,
|
|
3971
|
-
createContextDomainModule
|
|
4170
|
+
createContextDomainModule,
|
|
4171
|
+
loadFragments,
|
|
4172
|
+
buildWikiPlanPrompt,
|
|
4173
|
+
buildWikiPagePrompt
|
|
3972
4174
|
};
|
|
3973
|
-
//# sourceMappingURL=chunk-
|
|
4175
|
+
//# sourceMappingURL=chunk-7EYHLWU7.js.map
|