@ngockhoale/ukit 1.1.6
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 +179 -0
- package/LICENSE +21 -0
- package/README.md +189 -0
- package/bin/ukit +30 -0
- package/manifests/platform.full.yaml +1194 -0
- package/package.json +71 -0
- package/scripts/bug/triage.mjs +37 -0
- package/scripts/index/build-index.mjs +35 -0
- package/scripts/index/query-index.mjs +92 -0
- package/scripts/index/refresh-index.mjs +85 -0
- package/scripts/release/verify-release.mjs +56 -0
- package/src/bug/triageBug.js +123 -0
- package/src/cli/adapters.js +148 -0
- package/src/cli/commands/diff.js +51 -0
- package/src/cli/commands/doctor.js +125 -0
- package/src/cli/commands/indexArgs.js +73 -0
- package/src/cli/commands/indexTools.js +509 -0
- package/src/cli/commands/install.js +293 -0
- package/src/cli/commands/memory.js +126 -0
- package/src/cli/commands/status.js +8 -0
- package/src/cli/commands/uninstall.js +51 -0
- package/src/cli/index.js +109 -0
- package/src/context/detectProjectContext.js +49 -0
- package/src/context/detectProviders.js +12 -0
- package/src/core/applyPlan.js +89 -0
- package/src/core/buildPlan.js +228 -0
- package/src/core/compact/index.js +294 -0
- package/src/core/compact/threshold.js +936 -0
- package/src/core/diffPlan.js +73 -0
- package/src/core/ensureGitignore.js +117 -0
- package/src/core/fileOps.js +188 -0
- package/src/core/memory/hygiene.js +160 -0
- package/src/core/memory/index.js +2 -0
- package/src/core/memory/retrieval.js +476 -0
- package/src/core/memory/store.js +202 -0
- package/src/core/metadata.js +132 -0
- package/src/core/migrateLegacy.js +139 -0
- package/src/core/output/index.js +1309 -0
- package/src/core/paths.js +13 -0
- package/src/core/report.js +17 -0
- package/src/core/router/advisor.js +42 -0
- package/src/core/router/index.js +2 -0
- package/src/core/router/router.js +164 -0
- package/src/core/runInstallPipeline.js +365 -0
- package/src/core/runtimeConfig.js +190 -0
- package/src/core/runtimePaths.js +24 -0
- package/src/core/status.js +186 -0
- package/src/core/token/index.js +328 -0
- package/src/core/uninstall.js +246 -0
- package/src/core/validation/confidence.js +89 -0
- package/src/core/validation/index.js +2 -0
- package/src/core/validation/validator.js +165 -0
- package/src/index/buildIndex.js +1392 -0
- package/src/index/gitHooks.js +109 -0
- package/src/index/importResolution.js +377 -0
- package/src/index/languageTools.js +127 -0
- package/src/index/paths.js +27 -0
- package/src/index/queryIndex.js +637 -0
- package/src/index/relatedTests.js +237 -0
- package/src/index/resolveContext.js +345 -0
- package/src/index/routeCatalog.js +258 -0
- package/src/index/taskRouting.js +677 -0
- package/src/index/verificationPlan.js +437 -0
- package/src/manifest/loadManifest.js +22 -0
- package/src/manifest/selectItems.js +78 -0
- package/src/manifest/validateManifest.js +115 -0
- package/src/render/buildVariables.js +39 -0
- package/src/render/renderTemplate.js +44 -0
- package/src/stack/detectStack.js +213 -0
- package/templates/.claude/agents/bug-debugger.md +57 -0
- package/templates/.claude/agents/feature-implementer.md +55 -0
- package/templates/.claude/config/providers.md +25 -0
- package/templates/.claude/hooks/auto-allow-bash.sh +155 -0
- package/templates/.claude/hooks/auto-prune-bash.sh +75 -0
- package/templates/.claude/hooks/block-dangerous.sh +54 -0
- package/templates/.claude/hooks/compress-output.sh +17 -0
- package/templates/.claude/hooks/protect-files.sh +37 -0
- package/templates/.claude/hooks/reinject-context.sh +28 -0
- package/templates/.claude/hooks/session-start.md +13 -0
- package/templates/.claude/hooks/skill-router.sh +1681 -0
- package/templates/.claude/hooks/verification-guard.sh +271 -0
- package/templates/.claude/settings.json +144 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/mce/mc.xsd +75 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/pack.py +159 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/unpack.py +29 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/validate.py +69 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/validation/base.py +951 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/validation/docx.py +274 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/.claude/skills/_shared/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/.claude/skills/backend-api/SKILL.md +26 -0
- package/templates/.claude/skills/canvas-design/LICENSE.txt +202 -0
- package/templates/.claude/skills/canvas-design/SKILL.md +130 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/templates/.claude/skills/code-review/SKILL.md +97 -0
- package/templates/.claude/skills/debugging-toolkit/SKILL.md +156 -0
- package/templates/.claude/skills/delivery/SKILL.md +92 -0
- package/templates/.claude/skills/discover-security/SKILL.md +86 -0
- package/templates/.claude/skills/docker-packaging/SKILL.md +60 -0
- package/templates/.claude/skills/docs-manager/SKILL.md +465 -0
- package/templates/.claude/skills/docs-manager/init-project-docs.sh +70 -0
- package/templates/.claude/skills/docs-manager/templates/README.md.template +50 -0
- package/templates/.claude/skills/docs-manager/templates/agent-roles.md.template +24 -0
- package/templates/.claude/skills/docs-manager/templates/coding-conventions.md.template +28 -0
- package/templates/.claude/skills/docs-manager/templates/memory.md.template +30 -0
- package/templates/.claude/skills/docs-manager/templates/onboarding.md.template +20 -0
- package/templates/.claude/skills/docs-manager/templates/project.md.template +26 -0
- package/templates/.claude/skills/docs-quality/SKILL.md +148 -0
- package/templates/.claude/skills/docx/LICENSE.txt +30 -0
- package/templates/.claude/skills/docx/SKILL.md +197 -0
- package/templates/.claude/skills/docx/docx-js.md +350 -0
- package/templates/.claude/skills/docx/ooxml.md +610 -0
- package/templates/.claude/skills/docx/scripts/__init__.py +1 -0
- package/templates/.claude/skills/docx/scripts/document.py +1276 -0
- package/templates/.claude/skills/docx/scripts/templates/comments.xml +3 -0
- package/templates/.claude/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/templates/.claude/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/.claude/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/templates/.claude/skills/docx/scripts/templates/people.xml +3 -0
- package/templates/.claude/skills/docx/scripts/utilities.py +374 -0
- package/templates/.claude/skills/duraone/SKILL.md +204 -0
- package/templates/.claude/skills/duraone/references/backend.md +636 -0
- package/templates/.claude/skills/duraone/references/frontend.md +1506 -0
- package/templates/.claude/skills/duraone/references/sql.md +631 -0
- package/templates/.claude/skills/duraone/references/workflow.md +520 -0
- package/templates/.claude/skills/executing-plans/SKILL.md +76 -0
- package/templates/.claude/skills/file-organizer/SKILL.md +433 -0
- package/templates/.claude/skills/frontend/SKILL.md +26 -0
- package/templates/.claude/skills/frontend-design/LICENSE.txt +177 -0
- package/templates/.claude/skills/frontend-design/SKILL.md +42 -0
- package/templates/.claude/skills/frontend-vue/SKILL.md +127 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Box.vue +137 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Button.vue +93 -0
- package/templates/.claude/skills/frontend-vue/components/Control/ButtonBar.vue +29 -0
- package/templates/.claude/skills/frontend-vue/components/Control/ButtonFloat.vue +62 -0
- package/templates/.claude/skills/frontend-vue/components/Control/CheckButton.vue +75 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Checkbox.vue +58 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Datetime.vue +148 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Dropdownlist.vue +156 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Input.vue +106 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Label.vue +38 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Master/BoxColumn.vue +24 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Popup/Confirm.vue +33 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Popup/Info.vue +32 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Popup/ModalInfo.vue +39 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Popup/Reject.vue +64 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Tag.vue +82 -0
- package/templates/.claude/skills/frontend-vue/components/Control/Upload.vue +61 -0
- package/templates/.claude/skills/frontend-vue/components/ControlMobile/Dropdownlist.vue +103 -0
- package/templates/.claude/skills/frontend-vue/components/ControlMobile/PagingBar.vue +108 -0
- package/templates/.claude/skills/frontend-vue/components/ControlMobile/UploadImage.vue +137 -0
- package/templates/.claude/skills/frontend-vue/components/Grid/AG.vue +806 -0
- package/templates/.claude/skills/frontend-vue/components/Grid/AntTable.vue +253 -0
- package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditor.vue +43 -0
- package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditorEnable.vue +55 -0
- package/templates/.claude/skills/frontend-vue/components/Grid/HtmlTable.vue +40 -0
- package/templates/.claude/skills/frontend-vue/components/PDFViewer.vue +25 -0
- package/templates/.claude/skills/frontend-vue/components/Panel/FormView.vue +309 -0
- package/templates/.claude/skills/frontend-vue/components/Partial/Footer.vue +23 -0
- package/templates/.claude/skills/frontend-vue/components/Partial/Header.vue +265 -0
- package/templates/.claude/skills/frontend-vue/components/Partial/Sidebar.vue +122 -0
- package/templates/.claude/skills/frontend-vue/components/Template.vue +16 -0
- package/templates/.claude/skills/frontend-vue/components/View/Form.vue +89 -0
- package/templates/.claude/skills/frontend-vue/composables/indexDBStore.js +140 -0
- package/templates/.claude/skills/frontend-vue/composables/masterApi.js +362 -0
- package/templates/.claude/skills/frontend-vue/composables/state.js +578 -0
- package/templates/.claude/skills/frontend-vue/composables/useRequest.js +221 -0
- package/templates/.claude/skills/frontend-vue/composables/useSession.js +179 -0
- package/templates/.claude/skills/frontend-vue/composables/useTranslation.js +54 -0
- package/templates/.claude/skills/frontend-vue/composables/useWebSocket.js +257 -0
- package/templates/.claude/skills/frontend-vue/composables/userObj.js +111 -0
- package/templates/.claude/skills/frontend-vue/composables/utils.js +322 -0
- package/templates/.claude/skills/frontend-vue/reference/composables-example.vue +320 -0
- package/templates/.claude/skills/frontend-vue/reference/form-example.vue +183 -0
- package/templates/.claude/skills/frontend-vue/reference/grid-example.vue +147 -0
- package/templates/.claude/skills/frontend-vue/reference/masterdata-example/[id].vue +106 -0
- package/templates/.claude/skills/frontend-vue/reference/masterdata-example/index.vue +58 -0
- package/templates/.claude/skills/frontend-vue/reference/popup-example.vue +159 -0
- package/templates/.claude/skills/pdf/LICENSE.txt +30 -0
- package/templates/.claude/skills/pdf/SKILL.md +294 -0
- package/templates/.claude/skills/pdf/forms.md +205 -0
- package/templates/.claude/skills/pdf/reference.md +612 -0
- package/templates/.claude/skills/pdf/scripts/check_bounding_boxes.py +70 -0
- package/templates/.claude/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/.claude/skills/pdf/scripts/check_fillable_fields.py +12 -0
- package/templates/.claude/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/templates/.claude/skills/pdf/scripts/create_validation_image.py +41 -0
- package/templates/.claude/skills/pdf/scripts/extract_form_field_info.py +152 -0
- package/templates/.claude/skills/pdf/scripts/fill_fillable_fields.py +114 -0
- package/templates/.claude/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/.claude/skills/pdf-processing/SKILL.md +107 -0
- package/templates/.claude/skills/pdf-processing-pro/FORMS.md +610 -0
- package/templates/.claude/skills/pdf-processing-pro/OCR.md +137 -0
- package/templates/.claude/skills/pdf-processing-pro/SKILL.md +296 -0
- package/templates/.claude/skills/pdf-processing-pro/TABLES.md +626 -0
- package/templates/.claude/skills/pdf-processing-pro/scripts/analyze_form.py +307 -0
- package/templates/.claude/skills/postgres/SKILL.md +69 -0
- package/templates/.claude/skills/postgres/reference/fn_get_examples.sql +208 -0
- package/templates/.claude/skills/postgres/reference/fn_rpt_examples.sql +239 -0
- package/templates/.claude/skills/postgres/reference/utility_functions.sql +94 -0
- package/templates/.claude/skills/pptx/LICENSE.txt +30 -0
- package/templates/.claude/skills/pptx/SKILL.md +484 -0
- package/templates/.claude/skills/pptx/html2pptx.md +625 -0
- package/templates/.claude/skills/pptx/ooxml.md +427 -0
- package/templates/.claude/skills/pptx/scripts/html2pptx.js +979 -0
- package/templates/.claude/skills/pptx/scripts/inventory.py +1020 -0
- package/templates/.claude/skills/pptx/scripts/rearrange.py +231 -0
- package/templates/.claude/skills/pptx/scripts/replace.py +385 -0
- package/templates/.claude/skills/pptx/scripts/thumbnail.py +450 -0
- package/templates/.claude/skills/repo-maintenance/SKILL.md +97 -0
- package/templates/.claude/skills/research/EXAMPLES.md +434 -0
- package/templates/.claude/skills/research/REFERENCE.md +399 -0
- package/templates/.claude/skills/research/SKILL.md +136 -0
- package/templates/.claude/skills/root-cause-tracing/SKILL.md +174 -0
- package/templates/.claude/skills/root-cause-tracing/find-polluter.sh +63 -0
- package/templates/.claude/skills/sharing-skills/SKILL.md +194 -0
- package/templates/.claude/skills/sql-optimization-patterns/SKILL.md +493 -0
- package/templates/.claude/skills/subagent-driven-development/SKILL.md +189 -0
- package/templates/.claude/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/templates/.claude/skills/systematic-debugging/SKILL.md +295 -0
- package/templates/.claude/skills/systematic-debugging/test-academic.md +14 -0
- package/templates/.claude/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/templates/.claude/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/templates/.claude/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/templates/.claude/skills/test-driven-development/SKILL.md +364 -0
- package/templates/.claude/skills/testing-anti-patterns/SKILL.md +302 -0
- package/templates/.claude/skills/testing-quality/SKILL.md +97 -0
- package/templates/.claude/skills/verification-before-completion/SKILL.md +139 -0
- package/templates/.claude/skills/webapp-testing/LICENSE.txt +202 -0
- package/templates/.claude/skills/webapp-testing/SKILL.md +96 -0
- package/templates/.claude/skills/webapp-testing/examples/console_logging.py +35 -0
- package/templates/.claude/skills/webapp-testing/examples/element_discovery.py +40 -0
- package/templates/.claude/skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/templates/.claude/skills/webapp-testing/scripts/with_server.py +106 -0
- package/templates/.claude/ukit/index/build-index.mjs +28 -0
- package/templates/.claude/ukit/index/cache-utils.mjs +140 -0
- package/templates/.claude/ukit/index/lib/index-core.mjs +2800 -0
- package/templates/.claude/ukit/index/query-index.mjs +150 -0
- package/templates/.claude/ukit/index/refresh-index.mjs +57 -0
- package/templates/.claude/ukit/index/reset-auto-permissions.mjs +76 -0
- package/templates/.claude/ukit/index/resolve-context.mjs +279 -0
- package/templates/.claude/ukit/index/route-catalog.mjs +258 -0
- package/templates/.claude/ukit/index/route-task.mjs +1994 -0
- package/templates/.claude/ukit/index/triage.mjs +133 -0
- package/templates/.claude/ukit/index/verify-context.mjs +689 -0
- package/templates/.claude/ukit/runtime/compact-threshold.mjs +1013 -0
- package/templates/.claude/ukit/runtime/output-compression.mjs +1340 -0
- package/templates/.claude/ukit/runtime/reinject-context.mjs +874 -0
- package/templates/.claude/ukit/runtime/token-utils.mjs +500 -0
- package/templates/.codex/README.md +83 -0
- package/templates/.codex/settings.json +187 -0
- package/templates/.gitignore +75 -0
- package/templates/AGENTS.md +116 -0
- package/templates/CLAUDE.md +93 -0
- package/templates/adapter-presets/antigravity/README.md +22 -0
- package/templates/adapter-presets/antigravity/rules.md +49 -0
- package/templates/adapter-presets/claude/settings.local.json +42 -0
- package/templates/adapter-presets/codex/settings.local.json +6 -0
- package/templates/adapter-presets/opencode/opencode.template.json +1 -0
- package/templates/docs/BUGFIX.md +20 -0
- package/templates/docs/BUG_INDEX.md +12 -0
- package/templates/docs/BUG_METRICS.md +7 -0
- package/templates/docs/BUG_TEMPLATE.md +13 -0
- package/templates/docs/CODE_MAP.md +35 -0
- package/templates/docs/INSTALL.md +113 -0
- package/templates/docs/MEMORY.md +49 -0
- package/templates/docs/PROJECT.md +50 -0
- package/templates/docs/UKIT_USAGE_GUIDE.md +147 -0
- package/templates/docs/WORKLOG.md +10 -0
- package/templates/ukit/README.md +14 -0
- package/templates/ukit/storage/cache/compact-history.json +3 -0
- package/templates/ukit/storage/cache/compact-pressure.json +1 -0
- package/templates/ukit/storage/cache/output-history.json +3 -0
- package/templates/ukit/storage/cache/prompt-cache.json +3 -0
- package/templates/ukit/storage/config.json +37 -0
- package/templates/ukit/storage/memory/projects/.gitkeep +2 -0
- package/templates/ukit/storage/memory/sessions/.gitkeep +0 -0
- package/templates/ukit/storage/memory/user.json +5 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
export function buildPathConfig({ packageRoot, projectRoot }) {
|
|
4
|
+
return {
|
|
5
|
+
packageRoot,
|
|
6
|
+
projectRoot,
|
|
7
|
+
manifestPath: path.join(packageRoot, 'manifests', 'platform.full.yaml'),
|
|
8
|
+
templatesRoot: path.join(packageRoot, 'templates'),
|
|
9
|
+
ukitRoot: path.join(projectRoot, '.claude', 'ukit', '.ukit'),
|
|
10
|
+
installMetaPath: path.join(projectRoot, '.claude', 'ukit', '.ukit', 'install.json'),
|
|
11
|
+
backupRoot: path.join(projectRoot, '.claude', 'ukit', '.ukit', 'backups'),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function summarizeDiff(diffResults) {
|
|
2
|
+
const summary = { create: 0, update: 0, unchanged: 0, skip: 0 };
|
|
3
|
+
for (const entry of diffResults) {
|
|
4
|
+
if (entry.action in summary) {
|
|
5
|
+
summary[entry.action] += 1;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return summary;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function toDiffRows(diffResults) {
|
|
12
|
+
return diffResults.map((entry) => ({
|
|
13
|
+
id: entry.id,
|
|
14
|
+
action: entry.action,
|
|
15
|
+
targetPath: entry.targetPath,
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function shouldEscalate(trigger) {
|
|
2
|
+
if (!trigger || typeof trigger !== 'object') {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (trigger.type === 'user_requested') {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (trigger.type === 'complexity_detected') {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (trigger.type === 'retry_exceeded') {
|
|
15
|
+
return (trigger.attempts ?? 0) >= 2;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (trigger.type === 'validation_failed') {
|
|
19
|
+
return (trigger.attempts ?? 0) >= 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function askAdvisor(request) {
|
|
26
|
+
const strategy = request?.question
|
|
27
|
+
? `Break the task into verifiable steps, focusing on: ${request.question}`
|
|
28
|
+
: 'Break the task into smaller verifiable steps.';
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
strategy,
|
|
32
|
+
steps: [
|
|
33
|
+
'Restate the goal in one short sentence.',
|
|
34
|
+
'List the smallest changes that can be verified locally.',
|
|
35
|
+
'Run focused checks before expanding the scope.',
|
|
36
|
+
],
|
|
37
|
+
warnings: [
|
|
38
|
+
'Fallback advisor response used because no external advisor integration is wired in this local runtime.',
|
|
39
|
+
],
|
|
40
|
+
confidence: 55,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
const HIGH_COMPLEXITY_KEYWORDS = [
|
|
2
|
+
'architecture',
|
|
3
|
+
'architect',
|
|
4
|
+
'design',
|
|
5
|
+
'trade-off',
|
|
6
|
+
'tradeoff',
|
|
7
|
+
'security',
|
|
8
|
+
'compare',
|
|
9
|
+
'why',
|
|
10
|
+
'reasoning',
|
|
11
|
+
'scalable',
|
|
12
|
+
'system design',
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const LOW_COMPLEXITY_KEYWORDS = [
|
|
16
|
+
'rename',
|
|
17
|
+
'add field',
|
|
18
|
+
'change text',
|
|
19
|
+
'format',
|
|
20
|
+
'typo',
|
|
21
|
+
'update label',
|
|
22
|
+
'refactor name',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const REVIEW_KEYWORDS = ['review', 'code review', 'audit'];
|
|
26
|
+
const DEBUG_KEYWORDS = ['debug', 'bug', 'stack trace', 'error', 'crash', 'retry', 'failed attempt', 'failure'];
|
|
27
|
+
const CODING_HINTS = ['src/', 'package.json', 'function', 'class', 'implement', 'file', '.js', '.ts', '.tsx', '.jsx', '```'];
|
|
28
|
+
|
|
29
|
+
function normalize(text) {
|
|
30
|
+
return String(text ?? '').toLowerCase();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function countFileHints(text) {
|
|
34
|
+
const explicitCount = Number.parseInt(normalize(text).match(/\b(\d+)\s+files?\b/)?.[1] ?? '0', 10);
|
|
35
|
+
const pathMatches = normalize(text).match(/\b[\w./-]+\.(?:js|ts|tsx|jsx|json|md|yaml|yml)\b/g) ?? [];
|
|
36
|
+
return Math.max(explicitCount, new Set(pathMatches).size);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function detectComplexity(message, context = '') {
|
|
40
|
+
const combined = normalize(`${message}\n${context}`);
|
|
41
|
+
const wordCount = combined.split(/\s+/).filter(Boolean).length;
|
|
42
|
+
const fileHints = countFileHints(combined);
|
|
43
|
+
const hasRetryPattern = /\b(retry|failed|failure|attempt)\b/.test(combined);
|
|
44
|
+
const highSignals = HIGH_COMPLEXITY_KEYWORDS.filter((keyword) => combined.includes(keyword)).length;
|
|
45
|
+
const lowSignals = LOW_COMPLEXITY_KEYWORDS.filter((keyword) => combined.includes(keyword)).length;
|
|
46
|
+
|
|
47
|
+
if (highSignals > 0 || fileHints > 5 || (hasRetryPattern && /\b(debug|error|crash|stack trace)\b/.test(combined))) {
|
|
48
|
+
return 'high';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (lowSignals > 0 || (fileHints <= 1 && wordCount <= 24 && !hasRetryPattern)) {
|
|
52
|
+
return 'low';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return 'medium';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function detectTaskType(message, context = '', complexity = 'medium') {
|
|
59
|
+
const combined = normalize(`${message}\n${context}`);
|
|
60
|
+
|
|
61
|
+
if (DEBUG_KEYWORDS.some((keyword) => combined.includes(keyword)) && complexity === 'high') {
|
|
62
|
+
return 'debug_hard';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (HIGH_COMPLEXITY_KEYWORDS.some((keyword) => combined.includes(keyword))) {
|
|
66
|
+
return 'reasoning';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (REVIEW_KEYWORDS.some((keyword) => combined.includes(keyword))) {
|
|
70
|
+
return 'review';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (CODING_HINTS.some((keyword) => combined.includes(keyword))) {
|
|
74
|
+
return 'coding';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return 'simple_chat';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function recommendTier(type, complexity) {
|
|
81
|
+
if (type === 'simple_chat' && complexity === 'low') {
|
|
82
|
+
return 'fast';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (type === 'reasoning') {
|
|
86
|
+
return 'powerful';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (type === 'debug_hard' && complexity === 'high') {
|
|
90
|
+
return 'powerful';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (type === 'review') {
|
|
94
|
+
return complexity === 'high' ? 'powerful' : 'balanced';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (type === 'coding') {
|
|
98
|
+
return complexity === 'high' ? 'powerful' : 'balanced';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return complexity === 'low' ? 'fast' : 'balanced';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function buildReason(type, complexity) {
|
|
105
|
+
if (type === 'simple_chat') {
|
|
106
|
+
return 'Short conversational request without strong coding or reasoning signals.';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (type === 'debug_hard') {
|
|
110
|
+
return 'Debugging request includes repeated failures or stack-trace style signals.';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (type === 'reasoning') {
|
|
114
|
+
return 'Request asks for architecture, comparison, trade-offs, or deeper analysis.';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (type === 'review') {
|
|
118
|
+
return complexity === 'high'
|
|
119
|
+
? 'Review request touches higher-risk or cross-cutting areas.'
|
|
120
|
+
: 'Review request is scoped enough for the balanced tier.';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (type === 'coding') {
|
|
124
|
+
return complexity === 'high'
|
|
125
|
+
? 'Implementation spans multiple modules or difficult trade-offs.'
|
|
126
|
+
: 'Normal implementation work is best handled by the balanced tier.';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return 'Fallback routing decision.';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function classifyTask(userMessage, context = '') {
|
|
133
|
+
const complexity = detectComplexity(userMessage, context);
|
|
134
|
+
const type = detectTaskType(userMessage, context, complexity);
|
|
135
|
+
const recommendedTier = recommendTier(type, complexity);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
type,
|
|
139
|
+
complexity,
|
|
140
|
+
recommendedTier,
|
|
141
|
+
reason: buildReason(type, complexity),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function selectModel(classification, config) {
|
|
146
|
+
const tier = classification?.recommendedTier ?? 'balanced';
|
|
147
|
+
if (config?.[tier]) {
|
|
148
|
+
return config[tier];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (tier === 'powerful' && config?.advisorModel) {
|
|
152
|
+
return config.advisorModel;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (tier === 'balanced' && config?.defaultModel) {
|
|
156
|
+
return config.defaultModel;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (tier === 'fast' && config?.fast) {
|
|
160
|
+
return config.fast;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return config?.defaultModel ?? config?.balanced ?? config?.fast ?? config?.powerful ?? null;
|
|
164
|
+
}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { loadManifest } from '../manifest/loadManifest.js';
|
|
4
|
+
import { detectStack } from '../stack/detectStack.js';
|
|
5
|
+
import { detectProjectContext } from '../context/detectProjectContext.js';
|
|
6
|
+
import { detectProviders } from '../context/detectProviders.js';
|
|
7
|
+
import { buildTemplateVariables } from '../render/buildVariables.js';
|
|
8
|
+
import { buildInstallPlan } from './buildPlan.js';
|
|
9
|
+
import { diffInstallPlan } from './diffPlan.js';
|
|
10
|
+
import { applyDiffResults } from './applyPlan.js';
|
|
11
|
+
import { summarizeDiff, toDiffRows } from './report.js';
|
|
12
|
+
import { writeInstallMetadata } from './metadata.js';
|
|
13
|
+
import { cleanupLegacyPaths, migrateLegacyRuntimeRoot } from './migrateLegacy.js';
|
|
14
|
+
import { ensureGitignore } from './ensureGitignore.js';
|
|
15
|
+
import { readJsonIfExists, removeFileOrLinkOnly, resolveProjectRelativePath } from './fileOps.js';
|
|
16
|
+
|
|
17
|
+
const AUTO_PRUNE_OBSOLETE_PREFIXES = [
|
|
18
|
+
'.claude/skills/',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
function normalizeRelativePath(relativePath) {
|
|
22
|
+
if (typeof relativePath !== 'string') {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const trimmed = relativePath.trim();
|
|
27
|
+
if (!trimmed) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return trimmed.replace(/\\/g, '/');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildManagedRelativePathSet(plan, projectRoot) {
|
|
35
|
+
return new Set(
|
|
36
|
+
(plan?.entries || [])
|
|
37
|
+
.map((entry) => normalizeRelativePath(path.relative(projectRoot, entry.targetPath)))
|
|
38
|
+
.filter(Boolean),
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function buildTrackedManagedRelativePathSet(plan, projectRoot) {
|
|
43
|
+
return new Set(
|
|
44
|
+
(plan?.entries || [])
|
|
45
|
+
.filter((entry) => entry?.mergeStrategy !== 'skip')
|
|
46
|
+
.map((entry) => normalizeRelativePath(path.relative(projectRoot, entry.targetPath)))
|
|
47
|
+
.filter(Boolean),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function shouldAutoPruneObsoletePath(relativePath) {
|
|
52
|
+
return AUTO_PRUNE_OBSOLETE_PREFIXES.some((prefix) => relativePath.startsWith(prefix));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function isDirEmpty(dirPath) {
|
|
56
|
+
try {
|
|
57
|
+
const entries = await fs.readdir(dirPath);
|
|
58
|
+
return entries.length === 0;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function cleanupEmptyParents(targetPath, projectRoot) {
|
|
65
|
+
let currentDir = path.dirname(targetPath);
|
|
66
|
+
const stopDir = path.resolve(projectRoot);
|
|
67
|
+
|
|
68
|
+
while (currentDir.startsWith(stopDir) && currentDir !== stopDir) {
|
|
69
|
+
let stat;
|
|
70
|
+
try {
|
|
71
|
+
stat = await fs.lstat(currentDir);
|
|
72
|
+
} catch {
|
|
73
|
+
currentDir = path.dirname(currentDir);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!stat.isDirectory()) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!(await isDirEmpty(currentDir))) {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await fs.rmdir(currentDir);
|
|
86
|
+
currentDir = path.dirname(currentDir);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function isTrackedManagedDirectoryTree({
|
|
91
|
+
dirPath,
|
|
92
|
+
projectRoot,
|
|
93
|
+
trackedPathSet,
|
|
94
|
+
trackedPaths,
|
|
95
|
+
}) {
|
|
96
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
97
|
+
if (entries.length === 0) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
103
|
+
const relativePath = normalizeRelativePath(path.relative(projectRoot, fullPath));
|
|
104
|
+
if (!relativePath) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (entry.isDirectory()) {
|
|
109
|
+
const trackedDescendantPrefix = `${relativePath}/`;
|
|
110
|
+
const hasTrackedDescendant = trackedPaths.some((trackedPath) => trackedPath.startsWith(trackedDescendantPrefix));
|
|
111
|
+
if (!hasTrackedDescendant) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const nestedSafe = await isTrackedManagedDirectoryTree({
|
|
116
|
+
dirPath: fullPath,
|
|
117
|
+
projectRoot,
|
|
118
|
+
trackedPathSet,
|
|
119
|
+
trackedPaths,
|
|
120
|
+
});
|
|
121
|
+
if (!nestedSafe) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!trackedPathSet.has(relativePath)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function normalizeTrackedMetadataPath(entry) {
|
|
136
|
+
return normalizeRelativePath(typeof entry === 'string' ? entry : entry?.p);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function removeManagedDirectoriesForLinkTargets({
|
|
140
|
+
installMetaData,
|
|
141
|
+
projectRoot,
|
|
142
|
+
plan,
|
|
143
|
+
}) {
|
|
144
|
+
if (installMetaData?.tool !== 'ukit') {
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const trackedPathSet = new Set(
|
|
149
|
+
(Array.isArray(installMetaData?.files) ? installMetaData.files : [])
|
|
150
|
+
.map((entry) => normalizeTrackedMetadataPath(entry))
|
|
151
|
+
.filter(Boolean),
|
|
152
|
+
);
|
|
153
|
+
if (trackedPathSet.size === 0) {
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
const trackedPaths = [...trackedPathSet];
|
|
157
|
+
|
|
158
|
+
let removedCount = 0;
|
|
159
|
+
for (const entry of plan?.entries ?? []) {
|
|
160
|
+
if (entry?.type !== 'link') {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let stat;
|
|
165
|
+
try {
|
|
166
|
+
stat = await fs.lstat(entry.targetPath);
|
|
167
|
+
} catch {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const safeToReplace = await isTrackedManagedDirectoryTree({
|
|
176
|
+
dirPath: entry.targetPath,
|
|
177
|
+
projectRoot,
|
|
178
|
+
trackedPathSet,
|
|
179
|
+
trackedPaths,
|
|
180
|
+
});
|
|
181
|
+
if (!safeToReplace) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
await fs.rm(entry.targetPath, { recursive: true, force: true });
|
|
186
|
+
removedCount += 1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return removedCount;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function pruneObsoleteManagedPaths({
|
|
193
|
+
installMetaData,
|
|
194
|
+
projectRoot,
|
|
195
|
+
managedRelativePaths,
|
|
196
|
+
managedLinkRelativePaths = [],
|
|
197
|
+
}) {
|
|
198
|
+
if (installMetaData?.tool !== 'ukit') {
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const previousFiles = Array.isArray(installMetaData?.files) ? installMetaData.files : [];
|
|
203
|
+
if (previousFiles.length === 0) {
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const activePathSet = new Set(
|
|
208
|
+
[...managedRelativePaths]
|
|
209
|
+
.map((value) => normalizeRelativePath(value))
|
|
210
|
+
.filter(Boolean),
|
|
211
|
+
);
|
|
212
|
+
const activeLinkPathSet = new Set(
|
|
213
|
+
managedLinkRelativePaths
|
|
214
|
+
.map((value) => normalizeRelativePath(value))
|
|
215
|
+
.filter(Boolean),
|
|
216
|
+
);
|
|
217
|
+
const activeLinkPaths = [...activeLinkPathSet];
|
|
218
|
+
|
|
219
|
+
let removedCount = 0;
|
|
220
|
+
for (const entry of previousFiles) {
|
|
221
|
+
const relativePath = normalizeRelativePath(typeof entry === 'string' ? entry : entry?.p);
|
|
222
|
+
if (!relativePath || activePathSet.has(relativePath) || !shouldAutoPruneObsoletePath(relativePath)) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (activeLinkPaths.some((linkPath) => relativePath.startsWith(`${linkPath}/`))) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const absolutePath = resolveProjectRelativePath(projectRoot, relativePath);
|
|
230
|
+
if (!absolutePath) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const removed = await removeFileOrLinkOnly(absolutePath);
|
|
235
|
+
if (removed) {
|
|
236
|
+
removedCount += 1;
|
|
237
|
+
await cleanupEmptyParents(absolutePath, projectRoot);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return removedCount;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export async function runInstallPipeline({
|
|
245
|
+
packageVersion,
|
|
246
|
+
pathConfig,
|
|
247
|
+
dryRun,
|
|
248
|
+
selectedAdapterItemIds,
|
|
249
|
+
retainedManagedRelativePaths = [],
|
|
250
|
+
}) {
|
|
251
|
+
// Check for an existing install before making any changes.
|
|
252
|
+
// cleanupLegacyPaths() is only safe to run on reinstalls: on a fresh install
|
|
253
|
+
// there are no legacy UKit files to migrate, so running it risks deleting user
|
|
254
|
+
// files that happen to share a legacy path name (e.g. .claude/skills/delivery.md).
|
|
255
|
+
const installMetaData = await readJsonIfExists(pathConfig.installMetaPath);
|
|
256
|
+
const isReinstall = Boolean(installMetaData?.tool === 'ukit');
|
|
257
|
+
|
|
258
|
+
if (isReinstall && !dryRun) {
|
|
259
|
+
await migrateLegacyRuntimeRoot(pathConfig.projectRoot);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const manifest = await loadManifest(pathConfig.manifestPath);
|
|
263
|
+
const stackContext = await detectStack(pathConfig.projectRoot);
|
|
264
|
+
const projectContext = await detectProjectContext(pathConfig.projectRoot);
|
|
265
|
+
const providerContext = await detectProviders(pathConfig.projectRoot);
|
|
266
|
+
|
|
267
|
+
const variables = buildTemplateVariables({
|
|
268
|
+
projectContext,
|
|
269
|
+
stackContext,
|
|
270
|
+
packageVersion,
|
|
271
|
+
providerContext,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const plan = await buildInstallPlan({
|
|
275
|
+
manifest,
|
|
276
|
+
stackContext,
|
|
277
|
+
templatesRoot: pathConfig.templatesRoot,
|
|
278
|
+
variables,
|
|
279
|
+
projectRoot: pathConfig.projectRoot,
|
|
280
|
+
selectedAdapterItemIds,
|
|
281
|
+
});
|
|
282
|
+
const managedRelativePaths = buildManagedRelativePathSet(plan, pathConfig.projectRoot);
|
|
283
|
+
const trackedManagedRelativePaths = buildTrackedManagedRelativePathSet(plan, pathConfig.projectRoot);
|
|
284
|
+
const managedLinkRelativePaths = (plan.entries ?? [])
|
|
285
|
+
.filter((entry) => entry?.type === 'link')
|
|
286
|
+
.map((entry) => normalizeRelativePath(path.relative(pathConfig.projectRoot, entry.targetPath)))
|
|
287
|
+
.filter(Boolean);
|
|
288
|
+
|
|
289
|
+
if (!dryRun) {
|
|
290
|
+
await removeManagedDirectoriesForLinkTargets({
|
|
291
|
+
installMetaData,
|
|
292
|
+
projectRoot: pathConfig.projectRoot,
|
|
293
|
+
plan,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const diffResults = await diffInstallPlan(plan);
|
|
298
|
+
const plannedSummary = summarizeDiff(diffResults);
|
|
299
|
+
|
|
300
|
+
if (!dryRun) {
|
|
301
|
+
const { writes, skippedUpdates } = await applyDiffResults(diffResults, {
|
|
302
|
+
backupRoot: pathConfig.backupRoot,
|
|
303
|
+
projectRoot: pathConfig.projectRoot,
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Only run migration cleanup on reinstalls. Fresh installs have no legacy
|
|
307
|
+
// UKit files to migrate, so running cleanup risks deleting user files that
|
|
308
|
+
// happen to share a legacy path name (e.g. .claude/skills/delivery.md).
|
|
309
|
+
if (isReinstall) {
|
|
310
|
+
await cleanupLegacyPaths(pathConfig.projectRoot);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
await ensureGitignore(pathConfig.projectRoot);
|
|
314
|
+
await pruneObsoleteManagedPaths({
|
|
315
|
+
installMetaData,
|
|
316
|
+
projectRoot: pathConfig.projectRoot,
|
|
317
|
+
managedRelativePaths,
|
|
318
|
+
managedLinkRelativePaths,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Adjust summary to reflect link updates that were skipped for safety
|
|
322
|
+
// (the planned diff counted them as 'update', but apply skipped them).
|
|
323
|
+
const summary =
|
|
324
|
+
skippedUpdates > 0
|
|
325
|
+
? {
|
|
326
|
+
...plannedSummary,
|
|
327
|
+
update: plannedSummary.update - skippedUpdates,
|
|
328
|
+
skip: plannedSummary.skip + skippedUpdates,
|
|
329
|
+
}
|
|
330
|
+
: plannedSummary;
|
|
331
|
+
|
|
332
|
+
await writeInstallMetadata({
|
|
333
|
+
installMetaPath: pathConfig.installMetaPath,
|
|
334
|
+
packageVersion,
|
|
335
|
+
manifest,
|
|
336
|
+
stackContext,
|
|
337
|
+
providerContext,
|
|
338
|
+
summary,
|
|
339
|
+
writes,
|
|
340
|
+
projectRoot: pathConfig.projectRoot,
|
|
341
|
+
managedRelativePaths: [...trackedManagedRelativePaths],
|
|
342
|
+
retainedManagedRelativePaths,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
return {
|
|
346
|
+
manifest,
|
|
347
|
+
stackContext,
|
|
348
|
+
projectContext,
|
|
349
|
+
providerContext,
|
|
350
|
+
summary,
|
|
351
|
+
rows: toDiffRows(diffResults),
|
|
352
|
+
writes,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
manifest,
|
|
358
|
+
stackContext,
|
|
359
|
+
projectContext,
|
|
360
|
+
providerContext,
|
|
361
|
+
summary: plannedSummary,
|
|
362
|
+
rows: toDiffRows(diffResults),
|
|
363
|
+
writes: [],
|
|
364
|
+
};
|
|
365
|
+
}
|