@iowarp/clio-coder 0.4.1 → 0.4.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 +92 -0
- package/CONTRIBUTING.md +59 -36
- package/README.md +404 -472
- package/SECURITY.md +2 -1
- package/dist/{acp-ZILU3AUO.js → acp-TMDQZDIG.js} +7 -7
- package/dist/{agents-HYWGBGQR.js → agents-5N5NG3XG.js} +28 -28
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-N3QT7CBO.js → auth-Z5CCBXKQ.js} +8 -9
- package/dist/{builtins-UJLMOVOV.js → builtins-K6TNDT24.js} +4 -4
- package/dist/{chunk-GVQJ5CCZ.js → chunk-2HFQNRV3.js} +7 -7
- package/dist/{chunk-QMXC4JB7.js → chunk-2NHR3NAY.js} +163 -1401
- package/dist/chunk-2X4RYJTJ.js +39 -0
- package/dist/{chunk-Y45G3AXC.js → chunk-2Z2IKEXI.js} +6 -10
- package/dist/{chunk-EIMVLWB3.js → chunk-34BHNEE3.js} +7 -3
- package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
- package/dist/chunk-3EBYEESD.js +314 -0
- package/dist/{chunk-CTJ4RNAA.js → chunk-3F7VUY77.js} +2 -2
- package/dist/{chunk-AP73CFDC.js → chunk-3KIPBMUA.js} +2 -2
- package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
- package/dist/{chunk-VEGN6WIQ.js → chunk-462T4EGZ.js} +2 -2
- package/dist/{chunk-AFKWHWXF.js → chunk-4JDLP6ZS.js} +33 -16
- package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
- package/dist/{chunk-AKB4GYDL.js → chunk-54ODD65L.js} +5 -5
- package/dist/{chunk-BBTJOK6Y.js → chunk-5KW52TEP.js} +3 -3
- package/dist/{chunk-6CCS4G3W.js → chunk-5PFYMY2V.js} +2 -2
- package/dist/chunk-77QIVUZB.js +1334 -0
- package/dist/{chunk-7OBGU7UB.js → chunk-7BHIY2MW.js} +7 -13
- package/dist/{chunk-3QSOM6PA.js → chunk-AZ4WMN4W.js} +2 -2
- package/dist/{chunk-6NJQITNH.js → chunk-B74PXLU7.js} +6 -3
- package/dist/{chunk-R23Z6K6I.js → chunk-B7HM5Z7T.js} +15 -15
- package/dist/{chunk-R32CLGZ6.js → chunk-BO7Y52RY.js} +81 -20
- package/dist/{chunk-UEDMSP56.js → chunk-BYMNWQ7O.js} +123 -148
- package/dist/{chunk-ZJLUDYFY.js → chunk-CRFOIAX3.js} +4 -4
- package/dist/{chunk-2NM363SV.js → chunk-CYZW7JHJ.js} +7 -7
- package/dist/{chunk-6HMJX2VU.js → chunk-DYHAXKHD.js} +38 -10
- package/dist/{chunk-THYWACCR.js → chunk-DZAW46HP.js} +3 -3
- package/dist/{chunk-FYUN5KZ3.js → chunk-DZEK6CJN.js} +17 -17
- package/dist/{chunk-3I5NY75V.js → chunk-E7GT7O5N.js} +5 -5
- package/dist/{chunk-VKFQTNDV.js → chunk-F2I26BDK.js} +4 -4
- package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
- package/dist/{chunk-IXJT6DCX.js → chunk-FVDGR2ZL.js} +3 -3
- package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
- package/dist/{chunk-7EPLI7VL.js → chunk-HIICAHCJ.js} +2 -2
- package/dist/{chunk-E67WX76H.js → chunk-HKMD33FO.js} +29 -80
- package/dist/chunk-HLAFFSEK.js +360 -0
- package/dist/{chunk-UAPGZHYC.js → chunk-I64IFBLB.js} +9 -2
- package/dist/{chunk-XKA2ICR3.js → chunk-I66ZTYNP.js} +440 -175
- package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
- package/dist/{chunk-PVAMAVBB.js → chunk-IDNA72AH.js} +102 -2
- package/dist/{chunk-GCSMB2KY.js → chunk-IKOZFYBN.js} +1 -1
- package/dist/{chunk-2VG7KLYV.js → chunk-IKSLQ4XV.js} +5460 -3241
- package/dist/{chunk-QKIFBZKT.js → chunk-IMXMHHMQ.js} +166 -25
- package/dist/{chunk-74YWRRU5.js → chunk-JBCS7CRR.js} +2 -2
- package/dist/{chunk-BDPT6GTK.js → chunk-JWJGP5DQ.js} +2 -2
- package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
- package/dist/chunk-KPXDY6QF.js +47 -0
- package/dist/{chunk-ABLSQ6JX.js → chunk-LJID3DYZ.js} +7 -1
- package/dist/{chunk-VKRH2TCS.js → chunk-M2DAX4F6.js} +2 -2
- package/dist/{chunk-6I5ILFOF.js → chunk-M2WXEHER.js} +2 -2
- package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
- package/dist/{chunk-N5UK64DP.js → chunk-MCMZMDAC.js} +2 -2
- package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
- package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
- package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
- package/dist/{chunk-HUAS7ITX.js → chunk-O3YUNJZ2.js} +13 -21
- package/dist/{chunk-MA3H6DM5.js → chunk-P75RZCJW.js} +25 -3
- package/dist/{chunk-IG7BCQBA.js → chunk-PGF63K6I.js} +2 -2
- package/dist/chunk-PJX3WQUQ.js +42 -0
- package/dist/{chunk-6DWBAZ5U.js → chunk-Q4XWMHX6.js} +4 -6
- package/dist/{chunk-OJTRZGR3.js → chunk-QQLGQY2A.js} +8 -8
- package/dist/{chunk-J4HBWF6Y.js → chunk-RLYRBIYQ.js} +115 -20
- package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
- package/dist/{chunk-C537JADH.js → chunk-SSEYRH53.js} +6 -7
- package/dist/chunk-SZAA6XDG.js +30 -0
- package/dist/{chunk-MOPSG2X7.js → chunk-TPEQIQIE.js} +6 -6
- package/dist/{chunk-JA5QWE4Z.js → chunk-UBRFI4HS.js} +1879 -1650
- package/dist/{chunk-BTGG6BG2.js → chunk-UH347SHR.js} +154 -15
- package/dist/{chunk-5YHDIDBP.js → chunk-UH632ZYL.js} +2 -2
- package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
- package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
- package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
- package/dist/{chunk-UXN6JT4W.js → chunk-W4YEMFBX.js} +2 -2
- package/dist/{chunk-TD3PGPQA.js → chunk-W6NIE6OW.js} +2 -2
- package/dist/{chunk-TVH4ONAM.js → chunk-X7IARSHT.js} +3 -3
- package/dist/{chunk-PJJ6MY27.js → chunk-XE3PCIXH.js} +3 -3
- package/dist/{chunk-FEFIFZTL.js → chunk-XGDPUNND.js} +2 -2
- package/dist/{chunk-SCYB3HA4.js → chunk-XOXV5GKE.js} +51 -16
- package/dist/{chunk-QTFGO774.js → chunk-XQRY4DTA.js} +24 -11
- package/dist/{chunk-BJGUKIG4.js → chunk-YJISEZKC.js} +2 -2
- package/dist/{chunk-GPPB3JBE.js → chunk-ZGNYYXQ6.js} +2 -2
- package/dist/{chunk-SINK3QR6.js → chunk-ZNT2M6TG.js} +7 -7
- package/dist/{chunk-7RY5VZPH.js → chunk-ZW4HH5JJ.js} +6 -6
- package/dist/cli/index.js +33 -32
- package/dist/{clio-IT3G3VQH.js → clio-7VB377CC.js} +7 -7
- package/dist/{code-nav-RK6S7F6E.js → code-nav-YVLCYA7V.js} +85 -17
- package/dist/{config-3QZRWZJF.js → config-4HVOS65E.js} +88 -43
- package/dist/{configure-FL7Y3KJF.js → configure-PIWO7B24.js} +10 -10
- package/dist/{context-5HE7ODYK.js → context-IYEHL3WQ.js} +33 -31
- package/dist/{context-XNHL75JV.js → context-KQYIWPWT.js} +47 -34
- package/dist/{context-KYQFRVDC.js → context-N6ZE3LGJ.js} +11 -11
- package/dist/{context-clear-N545L53A.js → context-clear-G4OGZJDS.js} +33 -31
- package/dist/{context-working-set-QHKXSV2F.js → context-working-set-BWLF6LJP.js} +7 -7
- package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-2QQAITS3.js} +38 -38
- package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
- package/dist/{doctor-ZGPEGHIP.js → doctor-LHBD36VU.js} +23 -22
- package/dist/{eval-GXLL44RD.js → eval-C45FYRJ6.js} +21 -20
- package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-6DEJPLBF.js} +2 -2
- package/dist/{evidence-HWLBRH3Q.js → evidence-6SHONYAF.js} +30 -28
- package/dist/{evolve-FTZBMNVW.js → evolve-KRKMV72X.js} +30 -28
- package/dist/{extensions-VHRBEID7.js → extensions-KPZ2UHBB.js} +5 -3
- package/dist/{fleet-CKZHJWZJ.js → fleet-IVTCKDHT.js} +62 -61
- package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-EDWL3IT7.js} +5 -5
- package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-YP3YEFGK.js} +4 -4
- package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-ZFWKHY2M.js} +16 -14
- package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-FVUNCBML.js} +31 -29
- package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-UN5XED4R.js} +2 -2
- package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-XOWC4HSX.js} +17 -15
- package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-UN3SODEL.js} +30 -28
- package/dist/{fleet-view-WAMJYNDT.js → fleet-view-TWHJKCN6.js} +31 -29
- package/dist/{init-5XQRBOFV.js → init-T2QORQ3Y.js} +50 -49
- package/dist/{interop-34TVO25M.js → interop-IN5I2A66.js} +5 -5
- package/dist/{library-3QY6KF57.js → library-LSCATDLZ.js} +15 -13
- package/dist/{memory-L4UTIIIW.js → memory-HYOKAGGJ.js} +31 -29
- package/dist/{models-ZVX3QOWE.js → models-2GPMFYCM.js} +22 -21
- package/dist/{monitor-CEKVSYTS.js → monitor-E4ASVUJH.js} +34 -32
- package/dist/{orchestrator-77BAP6BC.js → orchestrator-DDMPR3PY.js} +984 -583
- package/dist/{panes-7STHOAUJ.js → panes-E3RUXOW5.js} +4 -4
- package/dist/{panes-SHAUIRXY.js → panes-IXKLOKA2.js} +23 -8
- package/dist/{reset-EOLM7GVE.js → reset-OAQP3W4O.js} +4 -4
- package/dist/{resources-74GKTLSF.js → resources-OTRSN34L.js} +15 -13
- package/dist/{run-HBAUJNNZ.js → run-5DEYH5QK.js} +60 -59
- package/dist/{share-G3APVLVP.js → share-IHWTLO3M.js} +19 -15
- package/dist/{skills-35HHUKCR.js → skills-IYMXMKW4.js} +17 -15
- package/dist/{skills-eval-QN4HSHDC.js → skills-eval-DROHSJAR.js} +36 -36
- package/dist/{skills-inventory-J357J34F.js → skills-inventory-D7X4L4ZX.js} +15 -13
- package/dist/{slash-commands-JZZCQA32.js → slash-commands-QBM7UZ3B.js} +21 -18
- package/dist/{steer-XAVHJM22.js → steer-Z5DO23FJ.js} +2 -2
- package/dist/{targets-DSM6CY3M.js → targets-P2FUC4IL.js} +25 -28
- package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-YREJ3JX2.js} +5 -5
- package/dist/{tools-MKNWVPBH.js → tools-5B7RO6MV.js} +4 -4
- package/dist/{trace-ECQ7TIYZ.js → trace-YMGMUM6A.js} +55 -7
- package/dist/{upgrade-H7TOM7YL.js → upgrade-PXK3S2YM.js} +11 -9
- package/dist/{usage-X52N3IDJ.js → usage-ME5MPXGX.js} +36 -34
- package/dist/{verifiers-EJTVVSMA.js → verifiers-BVZ7IWOO.js} +5 -5
- package/dist/{verify-YJL6XET2.js → verify-5K7ZKQFC.js} +4 -4
- package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
- package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-F5W5QTYY.js} +48 -47
- package/dist/{with-panes-OBOBFIIR.js → with-panes-BYOJCLAM.js} +51 -255
- package/dist/worker/entry.js +45 -30
- package/docs/README.md +176 -81
- package/docs/{acp.md → architecture/acp.md} +36 -20
- package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
- package/docs/{architecture.md → architecture/architecture.md} +43 -22
- package/docs/{artifact-placement.md → architecture/artifact-placement.md} +26 -23
- package/docs/architecture/artifact-versions.md +90 -0
- package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
- package/docs/{context-engine.md → architecture/context-engine.md} +25 -25
- package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
- package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
- package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
- package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
- package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
- package/docs/{model-catalog.md → architecture/model-catalog.md} +40 -17
- package/docs/{observability.md → architecture/observability.md} +26 -13
- package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
- package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +55 -20
- package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +35 -24
- package/docs/{safety-model.md → architecture/safety-model.md} +20 -15
- package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
- package/docs/architecture/time-conventions.md +125 -0
- package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
- package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
- package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
- package/docs/{built-in-agents.md → guide/built-in-agents.md} +50 -34
- package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +65 -60
- package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +227 -289
- package/docs/guide/configuration-reference.md +1158 -0
- package/docs/{environment-variables.md → guide/environment-variables.md} +31 -28
- package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
- package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
- package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
- package/docs/{glossary.md → guide/glossary.md} +14 -11
- package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +44 -13
- package/docs/guide/panes-and-files.md +290 -0
- package/docs/{proactive-memory.md → guide/proactive-memory.md} +79 -66
- package/docs/{resource-library.md → guide/resource-library.md} +13 -4
- package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +7 -3
- package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
- package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
- package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
- package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
- package/docs/{development-pipeline.md → process/development-pipeline.md} +24 -26
- package/docs/process/documentation-coverage.md +100 -0
- package/docs/process/documentation-guide.md +187 -0
- package/docs/{eval-runner.md → process/eval-runner.md} +41 -50
- package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
- package/docs/{evolution.md → process/evolution.md} +2 -2
- package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
- package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
- package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
- package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
- package/evals/README.md +2 -2
- package/package.json +9 -7
- package/skills/README.md +46 -37
- package/skills/coding/ast-grep/SKILL.md +2 -2
- package/skills/coding/coding-standards/SKILL.md +2 -2
- package/skills/coding/prototype/SKILL.md +2 -2
- package/skills/coding/tdd/SKILL.md +2 -2
- package/skills/context/context-handoff/SKILL.md +2 -2
- package/skills/context/context-prime/SKILL.md +2 -2
- package/skills/git/file-ticket/SKILL.md +2 -2
- package/skills/git/fix-issue/SKILL.md +3 -3
- package/skills/git/resolve-merge-conflicts/SKILL.md +2 -2
- package/skills/git/ship/SKILL.md +2 -2
- package/skills/git/worktree-create/SKILL.md +2 -2
- package/skills/git/worktree-merge/SKILL.md +2 -2
- package/skills/meta/clio-coder-dev/SKILL.md +9 -5
- package/skills/meta/clio-coder-dev/evals.md +3 -2
- package/skills/meta/clio-coder-test/SKILL.md +102 -95
- package/skills/meta/clio-coder-test/evals.md +9 -4
- package/skills/meta/clio-coder-test/references/harness.md +100 -124
- package/skills/meta/clio-coder-test/references/test-map.md +77 -50
- package/skills/meta/credentials/SKILL.md +2 -2
- package/skills/meta/find-skills/SKILL.md +2 -2
- package/skills/meta/herdr/SKILL.md +2 -2
- package/skills/meta/skill-craft/SKILL.md +22 -16
- package/skills/planning/architecture/SKILL.md +2 -2
- package/skills/planning/backlog/SKILL.md +2 -2
- package/skills/planning/prd/SKILL.md +2 -2
- package/skills/planning/product-intent/SKILL.md +2 -2
- package/skills/planning/tech-spec/SKILL.md +2 -2
- package/skills/registry.yaml +62 -62
- package/skills/research/arxiv-literature/SKILL.md +2 -2
- package/skills/research/experiment-protocol/SKILL.md +2 -2
- package/skills/research/scientific-debugging/SKILL.md +2 -2
- package/skills/research/scientific-modernization/SKILL.md +2 -2
- package/skills/skill-marketplace.json +62 -62
- package/skills/workflow/cut-it/SKILL.md +2 -2
- package/skills/workflow/design-council/SKILL.md +2 -2
- package/skills/workflow/grill-me/SKILL.md +2 -2
- package/skills/workflow/workflow-distiller/SKILL.md +2 -2
- package/src/cli/args.ts +2 -2
- package/src/cli/bootstrap-generate.ts +1 -1
- package/src/cli/config-inspect.ts +65 -12
- package/src/cli/configure.ts +0 -4
- package/src/cli/docs.ts +22 -14
- package/src/cli/doctor-naming.ts +5 -5
- package/src/cli/doctor-toolchain.ts +3 -3
- package/src/cli/eval.ts +1 -2
- package/src/cli/extensions.ts +2 -1
- package/src/cli/fleet.ts +1 -1
- package/src/cli/index.ts +2 -1
- package/src/cli/internal-dispatch.ts +3 -4
- package/src/cli/panes.ts +19 -5
- package/src/cli/run.ts +2 -2
- package/src/cli/share.ts +5 -1
- package/src/cli/skills-eval.ts +3 -3
- package/src/cli/targets.ts +2 -6
- package/src/cli/trace.ts +55 -4
- package/src/cli/wiki-generate.ts +1 -1
- package/src/core/artifact-paths.ts +1 -1
- package/src/core/bash-exec.ts +131 -86
- package/src/core/bus-events.ts +51 -6
- package/src/core/config.ts +5 -1
- package/src/core/defaults.ts +7 -4
- package/src/core/dispatch-outcome.ts +16 -0
- package/src/core/guardrails.ts +10 -49
- package/src/core/prompt-hint.ts +9 -0
- package/src/domains/agents/builtins/architect.md +2 -3
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +2 -2
- package/src/domains/agents/builtins/documenter.md +2 -2
- package/src/domains/agents/builtins/git-master.md +1 -1
- package/src/domains/agents/builtins/oracle.md +1 -1
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +2 -2
- package/src/domains/agents/builtins/verifier.md +2 -2
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/catalog.ts +12 -14
- package/src/domains/agents/contract.ts +2 -0
- package/src/domains/agents/extension.ts +23 -1
- package/src/domains/config/keybindings.ts +8 -0
- package/src/domains/context/extension.ts +0 -3
- package/src/domains/context/working-set/path-index.ts +1 -0
- package/src/domains/dispatch/capability-match.ts +10 -0
- package/src/domains/dispatch/extension.ts +105 -22
- package/src/domains/dispatch/host-verification.ts +435 -39
- package/src/domains/dispatch/intent-requirements.ts +10 -0
- package/src/domains/dispatch/intent.ts +18 -1
- package/src/domains/dispatch/path-scope.ts +235 -24
- package/src/domains/dispatch/run-event-journal.ts +4 -15
- package/src/domains/dispatch/state.ts +2 -3
- package/src/domains/dispatch/transport.ts +45 -21
- package/src/domains/dispatch/types.ts +55 -3
- package/src/domains/eval/artifacts/store.ts +5 -0
- package/src/domains/eval/store.ts +8 -1
- package/src/domains/evidence/trust-status.ts +10 -1
- package/src/domains/extensions/contract.ts +15 -1
- package/src/domains/extensions/discovery.ts +238 -41
- package/src/domains/extensions/extension.ts +105 -6
- package/src/domains/extensions/index.ts +24 -0
- package/src/domains/extensions/integrity.ts +189 -0
- package/src/domains/extensions/manager.ts +17 -1
- package/src/domains/extensions/resource-path.ts +27 -0
- package/src/domains/extensions/resources.ts +18 -38
- package/src/domains/extensions/snapshot-store.ts +39 -0
- package/src/domains/extensions/snapshot.ts +180 -0
- package/src/domains/extensions/state.ts +385 -57
- package/src/domains/extensions/types.ts +118 -1
- package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
- package/src/domains/lifecycle/migrations/index.ts +2 -0
- package/src/domains/lifecycle/naming-resources.ts +19 -4
- package/src/domains/lifecycle/naming-yazi.ts +10 -5
- package/src/domains/middleware/contract.ts +26 -0
- package/src/domains/middleware/extension.ts +24 -24
- package/src/domains/middleware/hook-receipts.ts +27 -4
- package/src/domains/middleware/hooks-io.ts +65 -32
- package/src/domains/middleware/hooks.ts +64 -0
- package/src/domains/middleware/index.ts +28 -4
- package/src/domains/middleware/registrations.ts +326 -0
- package/src/domains/middleware/runtime.ts +28 -0
- package/src/domains/middleware/snapshot.ts +20 -7
- package/src/domains/mux/contract.ts +38 -0
- package/src/domains/mux/detect.ts +6 -13
- package/src/domains/mux/index.ts +1 -1
- package/src/domains/mux/operations.ts +44 -5
- package/src/domains/mux/yazi/assets/yazi.toml +2 -2
- package/src/domains/mux/yazi/session.ts +53 -4
- package/src/domains/mux/yazi/theme.ts +117 -17
- package/src/domains/observability/contract.ts +10 -11
- package/src/domains/observability/extension.ts +11 -3
- package/src/domains/observability/projection.ts +14 -90
- package/src/domains/observability/trace-store.ts +43 -7
- package/src/domains/prompts/compiler.ts +73 -53
- package/src/domains/prompts/contract.ts +15 -3
- package/src/domains/prompts/extension.ts +97 -9
- package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
- package/src/domains/prompts/fragments/identity/clio.md +6 -12
- package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
- package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
- package/src/domains/prompts/fragments/operating/contract.md +7 -15
- package/src/domains/prompts/fragments/operating/delegation.md +32 -34
- package/src/domains/prompts/fragments/operating/skills.md +10 -24
- package/src/domains/prompts/fragments/operating/worker.md +1 -8
- package/src/domains/providers/index.ts +1 -1
- package/src/domains/providers/model-runtime-capabilities.ts +85 -21
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +669 -104
- package/src/domains/providers/runtime-resolution.ts +31 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
- package/src/domains/providers/types/cost-provenance.ts +19 -0
- package/src/domains/providers/types/local-model-quirks.ts +85 -37
- package/src/domains/resources/skills/loader.ts +16 -19
- package/src/domains/safety/call-target.ts +1 -1
- package/src/domains/safety/loop-detector.ts +7 -4
- package/src/domains/session/task-board.ts +10 -9
- package/src/domains/share/archive.ts +164 -7
- package/src/engine/acp/server.ts +62 -9
- package/src/engine/apis/llamacpp-residency.ts +3 -4
- package/src/engine/apis/lmstudio.ts +3 -3
- package/src/engine/apis/ollama-native.ts +6 -6
- package/src/engine/apis/openai-completions.ts +28 -25
- package/src/engine/apis/output-budget.ts +8 -18
- package/src/engine/apis/residency.ts +8 -27
- package/src/engine/gemma-channel-filter.ts +19 -0
- package/src/engine/loop-guard.ts +92 -12
- package/src/engine/worker-runtime.ts +40 -11
- package/src/engine/worker-tools.ts +3 -1
- package/src/entry/extension-hook-sources.ts +28 -0
- package/src/entry/extension-reload.ts +309 -0
- package/src/entry/orchestrator.ts +59 -35
- package/src/interactive/application-controller.ts +2 -1
- package/src/interactive/bus-notices.ts +8 -1
- package/src/interactive/chat-loop-messages.ts +3 -13
- package/src/interactive/chat-loop.ts +10 -1
- package/src/interactive/chat-panel.ts +36 -13
- package/src/interactive/chat-renderer.ts +71 -7
- package/src/interactive/dispatch-board.ts +6 -11
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/interactive-application.ts +39 -4
- package/src/interactive/interactive-input-runtime.ts +4 -0
- package/src/interactive/interactive-presentation.ts +2 -2
- package/src/interactive/interactive-slash-runtime.ts +2 -0
- package/src/interactive/overlays/extensions.ts +9 -1
- package/src/interactive/overlays/help-reference.ts +13 -0
- package/src/interactive/overlays/settings.ts +27 -16
- package/src/interactive/panes-runtime.ts +111 -35
- package/src/interactive/prompt-cache-identity.ts +88 -0
- package/src/interactive/slash-commands.ts +129 -14
- package/src/interactive/stream-pacing-policy.ts +0 -23
- package/src/interactive/turn-context.ts +30 -15
- package/src/interactive/yazi-bridge.ts +60 -6
- package/src/tools/agent-tools.ts +30 -1
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +3 -3
- package/src/tools/bash.ts +1 -1
- package/src/tools/bootstrap.ts +4 -0
- package/src/tools/builtin-tool-catalog.ts +52 -22
- package/src/tools/codewiki/code-nav-surface.ts +6 -0
- package/src/tools/codewiki/code-nav.ts +99 -13
- package/src/tools/context/docs-engine.ts +20 -7
- package/src/tools/context/index.ts +29 -12
- package/src/tools/core-bootstrap.ts +28 -6
- package/src/tools/credential-present.ts +1 -2
- package/src/tools/dispatch-arguments.ts +5 -1
- package/src/tools/dispatch-plan.ts +48 -4
- package/src/tools/dispatch-run-events.ts +1 -1
- package/src/tools/dispatch-schema.ts +338 -0
- package/src/tools/dispatch-types.ts +3 -0
- package/src/tools/dispatch.ts +9 -254
- package/src/tools/ledger.ts +3 -5
- package/src/tools/monitor-surface.ts +5 -13
- package/src/tools/observation.ts +4 -5
- package/src/tools/panes-surface.ts +4 -11
- package/src/tools/panes.ts +4 -2
- package/src/tools/policy.ts +15 -2
- package/src/tools/read.ts +5 -6
- package/src/tools/registry.ts +30 -7
- package/src/tools/result-shaping.ts +18 -14
- package/src/tools/steer-surface.ts +1 -1
- package/src/tools/tasks.ts +1 -1
- package/src/tools/truncate.ts +6 -5
- package/src/tools/verify/surface.ts +6 -12
- package/src/tools/web-fetch-surface.ts +1 -3
- package/dist/chunk-5QIAJV2D.js +0 -48
- package/dist/chunk-JZWT5J3Y.js +0 -814
- package/dist/chunk-K7VKOLQQ.js +0 -15
- package/dist/chunk-PMZCIOCJ.js +0 -25
- package/dist/chunk-SUW5DORT.js +0 -819
- package/dist/chunk-UOV2BYIW.js +0 -107
- package/dist/chunk-WR6U3OVP.js +0 -45
- package/docs/artifact-versions.md +0 -67
- package/docs/documentation-coverage.md +0 -46
- package/docs/documentation-guide.md +0 -167
- package/docs/time-conventions.md +0 -101
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composition-root coordinator for extension generations.
|
|
3
|
+
*
|
|
4
|
+
* The extensions bundle owns the snapshot store and the middleware bundle
|
|
5
|
+
* owns the registration table; neither knows the other exists. This module
|
|
6
|
+
* is the only writer of both for the "user-hooks" owner and the only caller
|
|
7
|
+
* of the extensions reload, and it sequences them so no observer can see
|
|
8
|
+
* resources from one generation paired with hooks from another:
|
|
9
|
+
*
|
|
10
|
+
* 1. capture and canonicalize the workspace once;
|
|
11
|
+
* 2. prepare the extension candidate (build, validate, reserve generation)
|
|
12
|
+
* and require its snapshot to be for that exact workspace;
|
|
13
|
+
* 3. build the user-hook registrations from the candidate's captured
|
|
14
|
+
* declarations plus the project files under that workspace;
|
|
15
|
+
* 4. prepare the middleware replacement (validate, build the next state);
|
|
16
|
+
* 5. confirm both prepared states are still current, then publish both
|
|
17
|
+
* with two assignment-only calls in adjacent statements;
|
|
18
|
+
* 6. only then emit conflicts, the reload event, and issue lines.
|
|
19
|
+
*
|
|
20
|
+
* Neither publish primitive validates, refuses, throws, or calls out, so a
|
|
21
|
+
* partial publication is impossible by construction: every failure or stale
|
|
22
|
+
* state is detected before step 5 and discards both prepared states. Boot
|
|
23
|
+
* uses the same path, so the first extension generation and the first hook
|
|
24
|
+
* set become live together; before that, readers take the ephemeral
|
|
25
|
+
* generation-0 path. Everything here is synchronous; the reentrancy guard
|
|
26
|
+
* exists for a caller that re-enters from a callback.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { realpathSync } from "node:fs";
|
|
30
|
+
import path from "node:path";
|
|
31
|
+
import type { ExtensionsReloadedPayload } from "../core/bus-events.js";
|
|
32
|
+
import type {
|
|
33
|
+
ExtensionReloadCommitted,
|
|
34
|
+
ExtensionReloadRejection,
|
|
35
|
+
ExtensionSnapshotDiagnostics,
|
|
36
|
+
ExtensionsContract,
|
|
37
|
+
} from "../domains/extensions/index.js";
|
|
38
|
+
import { EXTENSION_SNAPSHOT_DIAGNOSTIC_MESSAGE_CAP } from "../domains/extensions/index.js";
|
|
39
|
+
import {
|
|
40
|
+
type BuildUserHookRegistrationsResult,
|
|
41
|
+
buildUserHookRegistrations,
|
|
42
|
+
type CapturedHookSourceSet,
|
|
43
|
+
type HookReceiptSink,
|
|
44
|
+
type MiddlewareContract,
|
|
45
|
+
type MiddlewareRegistrationConflict,
|
|
46
|
+
type UserHookCommandRunner,
|
|
47
|
+
} from "../domains/middleware/index.js";
|
|
48
|
+
import { capturedHookSourcesFor } from "./extension-hook-sources.js";
|
|
49
|
+
|
|
50
|
+
export interface ExtensionReloadHookSummary {
|
|
51
|
+
/** Registrations published for the owner in this generation. */
|
|
52
|
+
registered: number;
|
|
53
|
+
dropped: number;
|
|
54
|
+
fileIssues: number;
|
|
55
|
+
issues: number;
|
|
56
|
+
overridden: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type ExtensionReloadOutcome =
|
|
60
|
+
| (ExtensionReloadCommitted & { hooks: ExtensionReloadHookSummary; lines: ReadonlyArray<string> })
|
|
61
|
+
| (ExtensionReloadRejection & { lines: ReadonlyArray<string> });
|
|
62
|
+
|
|
63
|
+
export interface ExtensionReloadCoordinatorDeps {
|
|
64
|
+
/** Absent on a degraded boot where the extensions domain failed to start. */
|
|
65
|
+
extensions: Pick<ExtensionsContract, "prepareReload" | "snapshot"> | undefined;
|
|
66
|
+
middleware: Pick<MiddlewareContract, "prepareRegistrationReplacement" | "replaceRegistrations" | "ownedGeneration">;
|
|
67
|
+
/** Read once per run and canonicalized; the candidate must be for exactly this workspace. */
|
|
68
|
+
cwd: () => string;
|
|
69
|
+
recordReceipt: HookReceiptSink;
|
|
70
|
+
runCommand?: UserHookCommandRunner;
|
|
71
|
+
now?: () => number;
|
|
72
|
+
/** One operator line per issue; stderr in headless runs, dropped or noticed by the host in interactive runs. */
|
|
73
|
+
report: (line: string) => void;
|
|
74
|
+
/** Called once per published generation, after both references are live. */
|
|
75
|
+
onCommitted?: (event: ExtensionsReloadedPayload) => void;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ExtensionReloadCoordinator {
|
|
79
|
+
/**
|
|
80
|
+
* Boot: publish generation 1 and its user hooks together. On a rejected
|
|
81
|
+
* build, or without an extensions domain, the project's own hooks are
|
|
82
|
+
* published under generation 1 and no extension generation exists.
|
|
83
|
+
*/
|
|
84
|
+
applyBoot(): ExtensionReloadOutcome;
|
|
85
|
+
/** Operator or programmatic reload. Synchronous and never throws. */
|
|
86
|
+
reload(): ExtensionReloadOutcome;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Cap on issue lines carried in one outcome so an operator surface stays bounded. */
|
|
90
|
+
export const EXTENSION_RELOAD_REPORT_LINE_CAP = 40;
|
|
91
|
+
|
|
92
|
+
function failure(message: string): ExtensionSnapshotDiagnostics {
|
|
93
|
+
return {
|
|
94
|
+
entries: [{ type: "error", message: message.slice(0, EXTENSION_SNAPSHOT_DIAGNOSTIC_MESSAGE_CAP) }],
|
|
95
|
+
truncated: 0,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function issueLines(
|
|
100
|
+
built: BuildUserHookRegistrationsResult,
|
|
101
|
+
dropped: ReadonlyArray<MiddlewareRegistrationConflict>,
|
|
102
|
+
): string[] {
|
|
103
|
+
const lines: string[] = [];
|
|
104
|
+
for (const issue of built.fileIssues) lines.push(`[clio-coder:hooks] ${issue.message}`);
|
|
105
|
+
for (const issue of built.issues) {
|
|
106
|
+
lines.push(`[clio-coder:hooks] ${issue.source.sourcePath}#${issue.index}: ${issue.issues.join("; ")}`);
|
|
107
|
+
}
|
|
108
|
+
for (const { loser, winner } of built.overridden) {
|
|
109
|
+
lines.push(`[clio-coder:hooks] ${loser.source.sourcePath} hook '${loser.id}' overridden by ${winner.sourcePath}`);
|
|
110
|
+
}
|
|
111
|
+
for (const conflict of dropped) {
|
|
112
|
+
lines.push(
|
|
113
|
+
`[clio-coder:hooks] hook '${conflict.id}' dropped: id is held by a ${conflict.conflictsWith} registration`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return lines;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function createExtensionReloadCoordinator(deps: ExtensionReloadCoordinatorDeps): ExtensionReloadCoordinator {
|
|
120
|
+
let inFlight = false;
|
|
121
|
+
|
|
122
|
+
const build = (workspace: string, captured: CapturedHookSourceSet | null): BuildUserHookRegistrationsResult =>
|
|
123
|
+
buildUserHookRegistrations({
|
|
124
|
+
cwd: workspace,
|
|
125
|
+
workspaceRoot: workspace,
|
|
126
|
+
...(captured !== null ? { capturedSources: captured } : {}),
|
|
127
|
+
recordReceipt: deps.recordReceipt,
|
|
128
|
+
...(deps.runCommand !== undefined ? { runCommand: deps.runCommand } : {}),
|
|
129
|
+
...(deps.now !== undefined ? { now: deps.now } : {}),
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const emitLines = (lines: ReadonlyArray<string>): void => {
|
|
133
|
+
for (const line of lines) {
|
|
134
|
+
try {
|
|
135
|
+
deps.report(line);
|
|
136
|
+
} catch {
|
|
137
|
+
// Reporting is observability; it must never affect the reload.
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const rejected = (rejection: ExtensionReloadRejection): ExtensionReloadOutcome => {
|
|
143
|
+
const lines = rejection.diagnostics.entries.map((entry) => `[clio-coder:extensions] ${entry.message}`);
|
|
144
|
+
emitLines(lines);
|
|
145
|
+
return { ...rejection, lines: lines.slice(0, EXTENSION_RELOAD_REPORT_LINE_CAP) };
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const canonicalWorkspace = (): string | null => {
|
|
149
|
+
try {
|
|
150
|
+
return realpathSync(path.resolve(deps.cwd()));
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Degraded boot: no extension generation will ever exist, so the project's
|
|
158
|
+
* own hooks are published alone under generation 1. Readers keep taking
|
|
159
|
+
* the ephemeral path, which pairs no generation with no generation.
|
|
160
|
+
*/
|
|
161
|
+
const publishProjectHooksOnly = (workspace: string): void => {
|
|
162
|
+
if (deps.middleware.ownedGeneration("user-hooks") !== 0) return;
|
|
163
|
+
const built = build(workspace, null);
|
|
164
|
+
const report = deps.middleware.replaceRegistrations("user-hooks", 1, built.registrations);
|
|
165
|
+
const lines = issueLines(built, report.dropped);
|
|
166
|
+
if (!report.applied) lines.push(`[clio-coder:hooks] project hooks were not applied: ${report.reason ?? "refused"}`);
|
|
167
|
+
emitLines(lines);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const run = (boot: boolean): ExtensionReloadOutcome => {
|
|
171
|
+
const activeGeneration = deps.extensions?.snapshot()?.generation ?? 0;
|
|
172
|
+
if (inFlight) {
|
|
173
|
+
return rejected({
|
|
174
|
+
status: "rejected",
|
|
175
|
+
reason: "reentrant",
|
|
176
|
+
generation: activeGeneration,
|
|
177
|
+
diagnostics: { entries: [], truncated: 0 },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
inFlight = true;
|
|
181
|
+
try {
|
|
182
|
+
const workspace = canonicalWorkspace();
|
|
183
|
+
if (workspace === null) {
|
|
184
|
+
return rejected({
|
|
185
|
+
status: "rejected",
|
|
186
|
+
reason: "build-failed",
|
|
187
|
+
generation: activeGeneration,
|
|
188
|
+
diagnostics: failure("the working directory could not be resolved"),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
if (deps.extensions === undefined) {
|
|
192
|
+
if (boot) publishProjectHooksOnly(workspace);
|
|
193
|
+
return rejected({
|
|
194
|
+
status: "rejected",
|
|
195
|
+
reason: "build-failed",
|
|
196
|
+
generation: 0,
|
|
197
|
+
diagnostics: failure("extensions domain is not loaded; restart to recover it"),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const prepared = deps.extensions.prepareReload();
|
|
201
|
+
if (prepared.status === "rejected") {
|
|
202
|
+
if (boot) publishProjectHooksOnly(workspace);
|
|
203
|
+
return rejected(prepared);
|
|
204
|
+
}
|
|
205
|
+
const candidate = prepared.candidate;
|
|
206
|
+
if (candidate.snapshot.cwd !== workspace) {
|
|
207
|
+
candidate.discard();
|
|
208
|
+
return rejected({
|
|
209
|
+
status: "rejected",
|
|
210
|
+
reason: "workspace-changed",
|
|
211
|
+
generation: candidate.previousGeneration,
|
|
212
|
+
diagnostics: failure(
|
|
213
|
+
`extension snapshot was built for ${candidate.snapshot.cwd} but the session workspace is ${workspace}`,
|
|
214
|
+
),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
let built: BuildUserHookRegistrationsResult;
|
|
218
|
+
try {
|
|
219
|
+
built = build(workspace, capturedHookSourcesFor(candidate.snapshot));
|
|
220
|
+
} catch (error) {
|
|
221
|
+
candidate.discard();
|
|
222
|
+
return rejected({
|
|
223
|
+
status: "rejected",
|
|
224
|
+
reason: "build-failed",
|
|
225
|
+
generation: candidate.previousGeneration,
|
|
226
|
+
diagnostics: failure(
|
|
227
|
+
`user hook registrations could not be built: ${error instanceof Error ? error.message : String(error)}`,
|
|
228
|
+
),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
const preparedReplacement = deps.middleware.prepareRegistrationReplacement(
|
|
232
|
+
"user-hooks",
|
|
233
|
+
candidate.generation,
|
|
234
|
+
built.registrations,
|
|
235
|
+
);
|
|
236
|
+
if (preparedReplacement.status === "rejected") {
|
|
237
|
+
candidate.discard();
|
|
238
|
+
return rejected({
|
|
239
|
+
status: "rejected",
|
|
240
|
+
reason: "stale",
|
|
241
|
+
generation: candidate.previousGeneration,
|
|
242
|
+
diagnostics: failure(
|
|
243
|
+
`middleware refused generation ${candidate.generation} (${preparedReplacement.reason}; active ${preparedReplacement.activeGeneration})`,
|
|
244
|
+
),
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
const replacement = preparedReplacement.replacement;
|
|
248
|
+
// Final freshness validation. After this point neither primitive can
|
|
249
|
+
// refuse, so a stale side here discards both and publishes neither.
|
|
250
|
+
if (!candidate.current() || !replacement.current()) {
|
|
251
|
+
replacement.discard();
|
|
252
|
+
candidate.discard();
|
|
253
|
+
return rejected({
|
|
254
|
+
status: "rejected",
|
|
255
|
+
reason: "stale",
|
|
256
|
+
generation: candidate.previousGeneration,
|
|
257
|
+
diagnostics: failure(`generation ${candidate.generation} was superseded before it could be published`),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
candidate.publish();
|
|
261
|
+
replacement.publish();
|
|
262
|
+
// Both references are live. Observers may run from here on.
|
|
263
|
+
replacement.emitConflicts();
|
|
264
|
+
const lines = issueLines(built, replacement.dropped);
|
|
265
|
+
try {
|
|
266
|
+
deps.onCommitted?.({
|
|
267
|
+
generation: candidate.generation,
|
|
268
|
+
previousGeneration: candidate.previousGeneration,
|
|
269
|
+
changed: candidate.changed,
|
|
270
|
+
digest: candidate.snapshot.digest,
|
|
271
|
+
});
|
|
272
|
+
} catch (error) {
|
|
273
|
+
// Publication is already complete. An observability callback cannot
|
|
274
|
+
// turn a live paired generation into a thrown or rejected outcome.
|
|
275
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
276
|
+
lines.push(
|
|
277
|
+
`[clio-coder:extensions] committed generation observer failed: ${message.slice(0, EXTENSION_SNAPSHOT_DIAGNOSTIC_MESSAGE_CAP)}`,
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
emitLines(lines);
|
|
281
|
+
return {
|
|
282
|
+
status: "committed",
|
|
283
|
+
generation: candidate.generation,
|
|
284
|
+
previousGeneration: candidate.previousGeneration,
|
|
285
|
+
changed: candidate.changed,
|
|
286
|
+
digest: candidate.snapshot.digest,
|
|
287
|
+
added: candidate.added,
|
|
288
|
+
removed: candidate.removed,
|
|
289
|
+
modified: candidate.modified,
|
|
290
|
+
diagnostics: candidate.snapshot.diagnostics,
|
|
291
|
+
hooks: {
|
|
292
|
+
registered: replacement.size,
|
|
293
|
+
dropped: replacement.dropped.length,
|
|
294
|
+
fileIssues: built.fileIssues.length,
|
|
295
|
+
issues: built.issues.length,
|
|
296
|
+
overridden: built.overridden.length,
|
|
297
|
+
},
|
|
298
|
+
lines: lines.slice(0, EXTENSION_RELOAD_REPORT_LINE_CAP),
|
|
299
|
+
};
|
|
300
|
+
} finally {
|
|
301
|
+
inFlight = false;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
return {
|
|
306
|
+
applyBoot: () => run(true),
|
|
307
|
+
reload: () => run(false),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
@@ -88,8 +88,7 @@ import {
|
|
|
88
88
|
createMarketplaceOfferRegistration,
|
|
89
89
|
createMiddlewareToolChoiceControl,
|
|
90
90
|
createSkillsReminderRegistration,
|
|
91
|
-
|
|
92
|
-
installUserHooks,
|
|
91
|
+
formatRegistrationConflict,
|
|
93
92
|
type MiddlewareContract,
|
|
94
93
|
MiddlewareDomainModule,
|
|
95
94
|
writeMiddlewareDiagnosticToStderr,
|
|
@@ -181,6 +180,7 @@ import { createChatLoop } from "../interactive/chat-loop.js";
|
|
|
181
180
|
import { type RunIo, startInteractive } from "../interactive/index.js";
|
|
182
181
|
import { buildModelReplayAgentMessagesFromTurns } from "../interactive/model-session-replay.js";
|
|
183
182
|
import type { BootOptions } from "./boot-options.js";
|
|
183
|
+
import { createExtensionReloadCoordinator } from "./extension-reload.js";
|
|
184
184
|
import { resolvePanesEnablement } from "./panes-activation.js";
|
|
185
185
|
|
|
186
186
|
export type { BootOptions, HeadlessSamplingOverrides } from "./boot-options.js";
|
|
@@ -200,6 +200,7 @@ import { type AskUserHandler, cancelledAskUserResult } from "../tools/ask-user.j
|
|
|
200
200
|
import { registerAllTools } from "../tools/bootstrap.js";
|
|
201
201
|
import { isGitRepository, recoverCleanupReadyCompeteGroups } from "../tools/compete-worktrees.js";
|
|
202
202
|
import { createDispatchBackgroundRegistry } from "../tools/dispatch-background.js";
|
|
203
|
+
import { dispatchSchemaCompositionFor } from "../tools/dispatch-schema.js";
|
|
203
204
|
import { createFileMutationObserver, createSkillActivationObserver } from "../tools/observers.js";
|
|
204
205
|
import { createRegistry } from "../tools/registry.js";
|
|
205
206
|
import { sweepExpiredToolOffloads } from "../tools/result-shaping.js";
|
|
@@ -1026,7 +1027,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1026
1027
|
else resolvedResumeId = latest.id;
|
|
1027
1028
|
}
|
|
1028
1029
|
}
|
|
1029
|
-
const resumeId = resolvedResumeId
|
|
1030
|
+
const resumeId = resolvedResumeId;
|
|
1030
1031
|
let resumedSessionAtBoot = false;
|
|
1031
1032
|
if (resumeId && session && headlessResumeFailure === null) {
|
|
1032
1033
|
try {
|
|
@@ -1038,7 +1039,6 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1038
1039
|
else bootStderr(`Clio Coder: failed to resume session ${resumeId}: ${detail}\n`);
|
|
1039
1040
|
}
|
|
1040
1041
|
}
|
|
1041
|
-
Reflect.deleteProperty(process.env, "CLIO_CODER_RESUME_SESSION_ID");
|
|
1042
1042
|
if (headlessResumeFailure !== null) {
|
|
1043
1043
|
bootStderr(`clio-coder run: ${headlessResumeFailure}\n`);
|
|
1044
1044
|
await termination.shutdown(2);
|
|
@@ -1050,6 +1050,20 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1050
1050
|
// middleware.hookFailed (the interactive warn notice consumes it) and keep
|
|
1051
1051
|
// stderr for non-interactive runs, which have no notice subscriber.
|
|
1052
1052
|
middleware.setDiagnosticSink((diagnostic) => {
|
|
1053
|
+
if (diagnostic.kind === "registration_conflict") {
|
|
1054
|
+
// Registration bookkeeping has no hook occurrence; the affected owner
|
|
1055
|
+
// today declares user hooks, which never run on on_compaction, so the
|
|
1056
|
+
// payload's hook slot carries that as the "no evaluation" marker.
|
|
1057
|
+
bus.emit(BusChannels.MiddlewareHookFailed, {
|
|
1058
|
+
kind: "registration_conflict",
|
|
1059
|
+
registrationId: diagnostic.registrationId,
|
|
1060
|
+
hook: "on_compaction",
|
|
1061
|
+
at: Date.now(),
|
|
1062
|
+
message: formatRegistrationConflict(diagnostic),
|
|
1063
|
+
});
|
|
1064
|
+
if (!interactive) writeMiddlewareDiagnosticToStderr(diagnostic);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1053
1067
|
bus.emit(BusChannels.MiddlewareHookFailed, {
|
|
1054
1068
|
kind: diagnostic.kind,
|
|
1055
1069
|
registrationId: diagnostic.registrationId,
|
|
@@ -1082,15 +1096,14 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1082
1096
|
});
|
|
1083
1097
|
}
|
|
1084
1098
|
|
|
1085
|
-
//
|
|
1086
|
-
//
|
|
1087
|
-
// settings section before any guard registration or tool reads it.
|
|
1099
|
+
// Install guardrail policy before any guard registration or tool reads it.
|
|
1100
|
+
// The effective session view replaces this boot projection below.
|
|
1088
1101
|
const resolvedSettings = config?.get() ?? readSettings();
|
|
1089
1102
|
configureGuardrails(guardrailValuesFromSettings(resolvedSettings));
|
|
1090
1103
|
|
|
1091
|
-
// The
|
|
1092
|
-
//
|
|
1093
|
-
//
|
|
1104
|
+
// The journal sink sits on the dispatch event path, where reading settings
|
|
1105
|
+
// would be both a cost and a throw site. The effective session view replaces
|
|
1106
|
+
// this boot projection below.
|
|
1094
1107
|
configureRunEventJournal(resolvedSettings.fleet.history.journal);
|
|
1095
1108
|
|
|
1096
1109
|
// Guard registrations on the middleware contract, in order: loop guard,
|
|
@@ -1104,7 +1117,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1104
1117
|
safety,
|
|
1105
1118
|
bus,
|
|
1106
1119
|
turnBlockBudget: INTERACTIVE_LOOP_BLOCK_BUDGET,
|
|
1107
|
-
turnToolCallBudget: readOrchTurnToolCallBudget(),
|
|
1120
|
+
turnToolCallBudget: () => readOrchTurnToolCallBudget(),
|
|
1108
1121
|
// Interactive/headless/ACP all share this orchestrator guard: at the
|
|
1109
1122
|
// block budget, lock tools for the rest of the turn so the model
|
|
1110
1123
|
// answers from what it gathered instead of hard-cancelling a turn that
|
|
@@ -1299,24 +1312,26 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1299
1312
|
// same effect machinery. They register after the guards, so safety stays
|
|
1300
1313
|
// authoritative: a hook may add effects (including request block_tool) but
|
|
1301
1314
|
// cannot grant a permission safety would deny. Loading is best-effort.
|
|
1315
|
+
// The coordinator is the only writer of the "user-hooks" owner and the only
|
|
1316
|
+
// caller of the extensions reload; it publishes the extension generation
|
|
1317
|
+
// and the hook registrations with two adjacent assignments on one stack
|
|
1318
|
+
// and emits extensions.reloaded only after both. The boot generation is
|
|
1319
|
+
// published here too (the extensions bundle publishes nothing at start),
|
|
1320
|
+
// so no consumer ever sees extension resources paired with hooks from a
|
|
1321
|
+
// different generation. The owner slot is anchored here, so user hooks
|
|
1322
|
+
// keep evaluating after the guards and before the assessors below.
|
|
1302
1323
|
const hookReceiptLog = createHookReceiptLog({ persistPath: join(clioStateDir(), "hook-receipts.json") });
|
|
1303
|
-
const
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
cwd: process.cwd(),
|
|
1308
|
-
extensions: extensionHookRoots,
|
|
1309
|
-
registerHook: (registration) => middleware.registerHook(registration),
|
|
1324
|
+
const extensionReload = createExtensionReloadCoordinator({
|
|
1325
|
+
extensions,
|
|
1326
|
+
middleware,
|
|
1327
|
+
cwd: () => process.cwd(),
|
|
1310
1328
|
recordReceipt: (receipt) => hookReceiptLog.record(receipt),
|
|
1329
|
+
report: (line) => {
|
|
1330
|
+
if (!interactive) process.stderr.write(`${line}\n`);
|
|
1331
|
+
},
|
|
1332
|
+
onCommitted: (event) => bus.emit(BusChannels.ExtensionsReloaded, event),
|
|
1311
1333
|
});
|
|
1312
|
-
|
|
1313
|
-
for (const issue of userHooks.fileIssues) {
|
|
1314
|
-
process.stderr.write(`[clio-coder:hooks] ${issue.message}\n`);
|
|
1315
|
-
}
|
|
1316
|
-
for (const issue of userHooks.issues) {
|
|
1317
|
-
process.stderr.write(`[clio-coder:hooks] ${issue.source.sourcePath}#${issue.index}: ${issue.issues.join("; ")}\n`);
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1334
|
+
extensionReload.applyBoot();
|
|
1320
1335
|
termination.onDrain(() => hookReceiptLog.flush());
|
|
1321
1336
|
// Autonomy is hot-reloaded for interactive and headless admissions. ACP
|
|
1322
1337
|
// server prompts use the snapshot captured at session/new.
|
|
@@ -1494,6 +1509,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1494
1509
|
...(panes && mux?.mode !== "none" ? { panes } : {}),
|
|
1495
1510
|
getCostCeilingUsd: () => result.getContract<SchedulingContract>("scheduling")?.ceilingUsd() ?? 0,
|
|
1496
1511
|
...(config ? { getWorkerRosters: () => config.get().fleet.rosters } : {}),
|
|
1512
|
+
...(config ? { getDispatchSchemaComposition: () => dispatchSchemaCompositionFor(config.get().fleet) } : {}),
|
|
1497
1513
|
getSkillLoaderOptions: () => ({
|
|
1498
1514
|
trustProjectCompatRoots: config?.get().integrations.projectResources.trustProjectImports === true,
|
|
1499
1515
|
disableDiscovery: options.noSkills === true || options.headless?.noSkills === true,
|
|
@@ -1518,8 +1534,13 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1518
1534
|
// view, so the live session reflects them immediately while settings.yaml
|
|
1519
1535
|
// (the global default for new sessions) stays untouched until the operator
|
|
1520
1536
|
// chooses to save globally.
|
|
1537
|
+
// Overrides are keyed by settings path, the same ids the /settings overlay
|
|
1538
|
+
// commits (`setAtPath` walks the dotted path). The headless `--autonomy`
|
|
1539
|
+
// flag was keyed by the bare word, which wrote a top-level `autonomy` key
|
|
1540
|
+
// nothing reads, so `run --autonomy full-auto` compiled and admitted at
|
|
1541
|
+
// whatever settings.yaml said.
|
|
1521
1542
|
const sessionOverrides: SessionOverrides = new Map(
|
|
1522
|
-
options.headless?.autonomy === undefined ? [] : [["autonomy", options.headless.autonomy]],
|
|
1543
|
+
options.headless?.autonomy === undefined ? [] : [["safety.autonomy", options.headless.autonomy]],
|
|
1523
1544
|
);
|
|
1524
1545
|
// The effective view is derived by deep-cloning the saved snapshot, and it
|
|
1525
1546
|
// is read on the tool-admission hot path (every call resolves autonomy
|
|
@@ -1534,9 +1555,10 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1534
1555
|
let cachedSettingsView: ClioSettings | null = null;
|
|
1535
1556
|
const bumpSessionState = (): void => {
|
|
1536
1557
|
sessionStateGeneration += 1;
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1558
|
+
const settings = getCurrentSettings();
|
|
1559
|
+
configureGuardrails(guardrailValuesFromSettings(settings));
|
|
1560
|
+
configureRunEventJournal(settings.fleet.history.journal);
|
|
1561
|
+
setGitCommitAttributionEnabled(settings.integrations.git.commitAttribution);
|
|
1540
1562
|
};
|
|
1541
1563
|
const getCurrentSettings = (): ClioSettings => {
|
|
1542
1564
|
// Recents live in the data dir (core/recent-models.ts), never in
|
|
@@ -1562,10 +1584,11 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1562
1584
|
};
|
|
1563
1585
|
effectiveSettingsForDispatch = getCurrentSettings;
|
|
1564
1586
|
bumpSessionState();
|
|
1565
|
-
// The config bundle publishes
|
|
1566
|
-
//
|
|
1567
|
-
|
|
1568
|
-
|
|
1587
|
+
// The config bundle publishes saved values on reload; session-scoped
|
|
1588
|
+
// overrides must win, so re-derive every process-local projection from the
|
|
1589
|
+
// effective session view after it.
|
|
1590
|
+
const unsubscribeSettingsProjectionSync = bus.on(BusChannels.ConfigHotReload, () => bumpSessionState());
|
|
1591
|
+
termination.onDrain(() => unsubscribeSettingsProjectionSync());
|
|
1569
1592
|
const getTaskMemorySeedOffer = (): { source: string; count: number } | null => {
|
|
1570
1593
|
return taskMemoryHandoffSeedOffer(process.cwd(), getCurrentSettings().context.memory.enabled);
|
|
1571
1594
|
};
|
|
@@ -1892,7 +1915,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
1892
1915
|
await chat.whenSettled();
|
|
1893
1916
|
});
|
|
1894
1917
|
|
|
1895
|
-
// A boot-time resume (
|
|
1918
|
+
// A boot-time resume (headless --session or --continue) must replay the resumed
|
|
1896
1919
|
// session into the chat loop the same way the interactive /resume overlay
|
|
1897
1920
|
// does. Without this, the first submit runs with an empty provider context
|
|
1898
1921
|
// and parents its user turn at null, appending a second root that silently
|
|
@@ -2117,6 +2140,7 @@ export async function bootOrchestrator(options: BootOptions = {}): Promise<BootR
|
|
|
2117
2140
|
...(initialNotices.length > 0 ? { initialNotices } : {}),
|
|
2118
2141
|
...(resources ? { resources } : {}),
|
|
2119
2142
|
...(extensions ? { extensions } : {}),
|
|
2143
|
+
reloadExtensions: () => extensionReload.reload(),
|
|
2120
2144
|
...(interop ? { interop } : {}),
|
|
2121
2145
|
...(share ? { share } : {}),
|
|
2122
2146
|
...(mux ? { mux } : {}),
|
|
@@ -18,11 +18,12 @@ const CLOSED_ACTION_ORDER = [
|
|
|
18
18
|
"clio-coder.thinking.expandAll",
|
|
19
19
|
] as const satisfies ReadonlyArray<ClioKeybinding>;
|
|
20
20
|
|
|
21
|
-
const GLOBAL_ACTION_ORDER = [
|
|
21
|
+
export const GLOBAL_ACTION_ORDER = [
|
|
22
22
|
"clio-coder.status.toggle",
|
|
23
23
|
"clio-coder.thinking.cycle",
|
|
24
24
|
"clio-coder.session.tree",
|
|
25
25
|
"clio-coder.dispatchBoard.toggle",
|
|
26
|
+
"clio-coder.files.toggle",
|
|
26
27
|
"clio-coder.tasks.open",
|
|
27
28
|
"clio-coder.decisions.open",
|
|
28
29
|
"clio-coder.dispatch.background",
|
|
@@ -72,7 +72,7 @@ function isSafetyBlockedPayload(value: unknown): value is SafetyBlockedPayload {
|
|
|
72
72
|
function isMiddlewareHookFailedPayload(value: unknown): value is MiddlewareHookFailedPayload {
|
|
73
73
|
if (!value || typeof value !== "object") return false;
|
|
74
74
|
const p = value as Record<string, unknown>;
|
|
75
|
-
if (p.kind !== "hook_failed" && p.kind !== "budget_exceeded") return false;
|
|
75
|
+
if (p.kind !== "hook_failed" && p.kind !== "budget_exceeded" && p.kind !== "registration_conflict") return false;
|
|
76
76
|
if (typeof p.registrationId !== "string" || p.registrationId.length === 0) return false;
|
|
77
77
|
if (typeof p.hook !== "string" || p.hook.length === 0) return false;
|
|
78
78
|
if (p.message !== undefined && typeof p.message !== "string") return false;
|
|
@@ -142,6 +142,13 @@ function middlewareHookFailedNotice(
|
|
|
142
142
|
options: MiddlewareHookFailedNoticeOptions = {},
|
|
143
143
|
): BusNotice | null {
|
|
144
144
|
if (!isMiddlewareHookFailedPayload(payload)) return null;
|
|
145
|
+
if (payload.kind === "registration_conflict") {
|
|
146
|
+
const detail =
|
|
147
|
+
payload.message !== undefined && payload.message.length > 0
|
|
148
|
+
? payload.message
|
|
149
|
+
: `registration '${payload.registrationId}' conflicts with an existing id`;
|
|
150
|
+
return { level: "warn", text: `[middleware] ${detail}` };
|
|
151
|
+
}
|
|
145
152
|
if (payload.kind === "hook_failed") {
|
|
146
153
|
const detail = payload.message !== undefined && payload.message.length > 0 ? `: ${payload.message}` : "";
|
|
147
154
|
return {
|
|
@@ -21,12 +21,13 @@ import {
|
|
|
21
21
|
} from "../core/response-model-id.js";
|
|
22
22
|
import type { PendingSkillRequest, PendingSkillToolPolicy, SkillDeclaredToolPolicy } from "../core/skill-activation.js";
|
|
23
23
|
import { ToolNames } from "../core/tool-names.js";
|
|
24
|
-
import {
|
|
24
|
+
import { sha256 } from "../domains/prompts/hash.js";
|
|
25
25
|
import { toContextOverflowError } from "../domains/providers/errors.js";
|
|
26
26
|
import type { ResolvedRuntimeTarget } from "../domains/providers/index.js";
|
|
27
27
|
import { ceilChars, extractReasoningTokens } from "../domains/session/context-accounting.js";
|
|
28
28
|
import type { AgentMessage } from "../engine/types.js";
|
|
29
29
|
import type { AskUserToolPolicy } from "../tools/registry.js";
|
|
30
|
+
import { attachedToolSchemaBytes, attachedToolSchemasFromState } from "./prompt-cache-identity.js";
|
|
30
31
|
|
|
31
32
|
/** Minimal structural view of the engine agent used by state-inspection helpers. */
|
|
32
33
|
export interface AgentStateView {
|
|
@@ -291,18 +292,7 @@ export function pendingSkillRequestPreamble(requests: ReadonlyArray<PendingSkill
|
|
|
291
292
|
* tool-surface change.
|
|
292
293
|
*/
|
|
293
294
|
export function toolSignatureFromState(tools: ReadonlyArray<unknown>): string {
|
|
294
|
-
|
|
295
|
-
for (const tool of tools) {
|
|
296
|
-
if (!tool || typeof tool !== "object" || Array.isArray(tool)) continue;
|
|
297
|
-
const record = tool as Record<string, unknown>;
|
|
298
|
-
schemas.push({
|
|
299
|
-
name: typeof record.name === "string" ? record.name : "",
|
|
300
|
-
description: typeof record.description === "string" ? record.description : "",
|
|
301
|
-
parameters: record.parameters ?? null,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
schemas.sort((a, b) => a.name.localeCompare(b.name));
|
|
305
|
-
return sha256(canonicalJson(schemas));
|
|
295
|
+
return sha256(attachedToolSchemaBytes(attachedToolSchemasFromState(tools)));
|
|
306
296
|
}
|
|
307
297
|
|
|
308
298
|
/**
|
|
@@ -648,7 +648,9 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
|
|
|
648
648
|
const retrySettings = (): RetrySettings => normalizeRetrySettings(deps.getSettings().chat.retry);
|
|
649
649
|
|
|
650
650
|
const currentToolInvokeOptions = (): Partial<ToolInvokeOptions> => {
|
|
651
|
-
const options: Partial<ToolInvokeOptions> = {
|
|
651
|
+
const options: Partial<ToolInvokeOptions> = {
|
|
652
|
+
toolResultMaxBytes: deps.getSettings().context.toolResultMaxBytes,
|
|
653
|
+
};
|
|
652
654
|
const sessionId = deps.session?.current()?.id ?? null;
|
|
653
655
|
if (sessionId) options.sessionId = sessionId;
|
|
654
656
|
const turnId = state.activeUserTurnId ?? state.lastTurnId;
|
|
@@ -764,6 +766,12 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
|
|
|
764
766
|
deps.bus?.on(BusChannels.ConfigHotReload, () => {
|
|
765
767
|
context.invalidateSessionPromptCache();
|
|
766
768
|
}) ?? null;
|
|
769
|
+
// A committed extension generation with new content can change the skill
|
|
770
|
+
// and prompt inputs the session prompt compiles from; same invalidation.
|
|
771
|
+
const unsubscribeExtensionsReload =
|
|
772
|
+
deps.bus?.on(BusChannels.ExtensionsReloaded, (payload) => {
|
|
773
|
+
if (payload.changed) context.invalidateSessionPromptCache();
|
|
774
|
+
}) ?? null;
|
|
767
775
|
|
|
768
776
|
const unsubscribeSynthesisLock =
|
|
769
777
|
deps.bus?.on(BusChannels.LoopBlocked, (payload) => {
|
|
@@ -1417,6 +1425,7 @@ export function createChatLoop(deps: CreateChatLoopDeps): ChatLoop {
|
|
|
1417
1425
|
|
|
1418
1426
|
dispose(): void {
|
|
1419
1427
|
unsubscribeConfigReload?.();
|
|
1428
|
+
unsubscribeExtensionsReload?.();
|
|
1420
1429
|
unsubscribeSynthesisLock?.();
|
|
1421
1430
|
unsubscribePrewarmCompaction();
|
|
1422
1431
|
prewarm.dispose();
|