boost-skill-cli 1.0.76__tar.gz → 1.0.78__tar.gz

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.
Files changed (228) hide show
  1. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/configuration.py +7 -1
  4. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/config.py +44 -3
  5. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  6. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/memoize-config-load-in-process.md +3 -3
  7. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap.html +1 -1
  8. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_config.py +47 -0
  9. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/.gitattributes +0 -0
  10. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/.gitignore +0 -0
  11. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/CLAUDE.md +0 -0
  12. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/CONTRIBUTING.md +0 -0
  13. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/LICENSE +0 -0
  14. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/MANIFEST.in +0 -0
  15. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/Makefile +0 -0
  16. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/README.md +0 -0
  17. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/SECURITY.md +0 -0
  18. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost +0 -0
  19. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/__init__.py +0 -0
  20. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/__main__.py +0 -0
  21. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/cli.py +0 -0
  22. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/cliparse.py +0 -0
  23. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/__init__.py +0 -0
  24. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/bmad.py +0 -0
  25. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/discovery.py +0 -0
  26. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/hooks.py +0 -0
  27. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/info.py +0 -0
  28. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/intelligence.py +0 -0
  29. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/pkg.py +0 -0
  30. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/quality.py +0 -0
  31. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/taps.py +0 -0
  32. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/commands/team.py +0 -0
  33. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/__init__.py +0 -0
  34. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/agents.py +0 -0
  35. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/ai.py +0 -0
  36. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/catalog.py +0 -0
  37. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/claude_settings.py +0 -0
  38. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/dense.py +0 -0
  39. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/embed.py +0 -0
  40. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/frontmatter.py +0 -0
  41. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/gitutil.py +0 -0
  42. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/journal.py +0 -0
  43. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/lockfile.py +0 -0
  44. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/logs.py +0 -0
  45. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/mcp.py +0 -0
  46. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/output.py +0 -0
  47. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/paths.py +0 -0
  48. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/policy.py +0 -0
  49. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/rag.py +0 -0
  50. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/registry.py +0 -0
  51. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/store.py +0 -0
  52. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/core/util.py +0 -0
  53. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/data/registries.json +0 -0
  54. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/errors.py +0 -0
  55. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_cli/spin.py +0 -0
  56. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  57. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  58. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  59. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_skill_cli.egg-info/requires.txt +0 -0
  60. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/boost_skill_cli.egg-info/top_level.txt +0 -0
  61. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/.claude/settings.local.json +0 -0
  62. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/DEBUGGING.md +0 -0
  63. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/demo.gif +0 -0
  64. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/demo.tape +0 -0
  65. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/design-roadmap.html +0 -0
  66. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/index.html +0 -0
  67. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/mcp-hub.html +0 -0
  68. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/rag-architecture.md +0 -0
  69. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D01.md +0 -0
  70. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D02.md +0 -0
  71. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D03.md +0 -0
  72. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D04.md +0 -0
  73. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D05.md +0 -0
  74. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D06.md +0 -0
  75. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D07.md +0 -0
  76. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D08.md +0 -0
  77. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D09.md +0 -0
  78. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D10.md +0 -0
  79. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D11.md +0 -0
  80. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D12.md +0 -0
  81. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D13.md +0 -0
  82. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D14.md +0 -0
  83. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D15.md +0 -0
  84. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D16.md +0 -0
  85. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D17.md +0 -0
  86. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D18.md +0 -0
  87. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D19.md +0 -0
  88. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D20.md +0 -0
  89. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D21.md +0 -0
  90. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D22.md +0 -0
  91. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D23.md +0 -0
  92. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D24.md +0 -0
  93. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D25.md +0 -0
  94. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/BOOST-D26.md +0 -0
  95. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  96. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  97. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  98. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  99. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  100. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  101. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  102. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  103. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  104. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  105. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  106. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  107. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  108. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  109. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  110. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  111. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  112. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  113. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  114. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  115. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  116. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  117. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  118. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  119. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
  120. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  121. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  122. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  123. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  124. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  125. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  126. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  127. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  128. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  129. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  130. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  131. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  132. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  133. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  134. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  135. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  136. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  137. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  138. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  139. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  140. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  141. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  142. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  143. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  144. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  145. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  146. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  147. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  148. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  149. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  150. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  151. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  152. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  153. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  154. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  155. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  156. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  157. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  158. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  159. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  160. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  161. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  162. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  163. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  164. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  165. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  166. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  167. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  168. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  169. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  170. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  171. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  172. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  173. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  174. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  175. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  176. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  177. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/index.html +0 -0
  178. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/pyproject.toml +0 -0
  179. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/scripts/build_registries.py +0 -0
  180. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/scripts/build_roadmap.py +0 -0
  181. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/scripts/mutation_gate.py +0 -0
  182. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/setup.cfg +0 -0
  183. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/style/README.md +0 -0
  184. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/style/boost.css +0 -0
  185. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/style/boost.js +0 -0
  186. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/style/demo.html +0 -0
  187. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/conftest.py +0 -0
  188. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_bmad.py +0 -0
  189. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_configuration.py +0 -0
  190. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_discovery.py +0 -0
  191. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_hooks.py +0 -0
  192. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_info.py +0 -0
  193. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_intelligence.py +0 -0
  194. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_pkg.py +0 -0
  195. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_quality.py +0 -0
  196. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_taps.py +0 -0
  197. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_cli_team.py +0 -0
  198. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/functional/test_everyday_loop.py +0 -0
  199. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/make_fixture.py +0 -0
  200. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/smoke.sh +0 -0
  201. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_agents.py +0 -0
  202. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_ai.py +0 -0
  203. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_catalog.py +0 -0
  204. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_claude_settings.py +0 -0
  205. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_cliparse.py +0 -0
  206. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_dense.py +0 -0
  207. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_dense_fallback.py +0 -0
  208. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_embed.py +0 -0
  209. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_errors_and_cli_table.py +0 -0
  210. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_frontmatter.py +0 -0
  211. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_gitutil.py +0 -0
  212. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_journal.py +0 -0
  213. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_lockfile.py +0 -0
  214. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_logs.py +0 -0
  215. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_mcp.py +0 -0
  216. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_mutation_hardening.py +0 -0
  217. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_output.py +0 -0
  218. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_paths.py +0 -0
  219. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_policy.py +0 -0
  220. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_rag.py +0 -0
  221. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_registries_fresh.py +0 -0
  222. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_registry.py +0 -0
  223. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_roadmap_fresh.py +0 -0
  224. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_spin.py +0 -0
  225. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_store.py +0 -0
  226. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_token_parity.py +0 -0
  227. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_util.py +0 -0
  228. {boost_skill_cli-1.0.76 → boost_skill_cli-1.0.78}/tests/unit/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.76
3
+ Version: 1.0.78
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.0.76'
22
- __version_tuple__ = version_tuple = (1, 0, 76)
21
+ __version__ = version = '1.0.78'
22
+ __version_tuple__ = version_tuple = (1, 0, 78)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -737,6 +737,8 @@ _PAGE_CSS = ("body{background:#111;color:#ddd;font-family:ui-monospace,SFMono-Re
737
737
  "th,td{text-align:left;padding:.3rem .8rem .3rem 0;"
738
738
  "border-bottom:1px solid #2a2a2a}.dim{color:#777}")
739
739
 
740
+ _SKILL_NAME_RE = re.compile(r"^[A-Za-z0-9._-]+$")
741
+
740
742
 
741
743
  def _serve_page() -> str:
742
744
  installed = lockfile.installed()
@@ -761,7 +763,7 @@ def _serve_page() -> str:
761
763
 
762
764
  def _skill_text(name: str):
763
765
  """SKILL.md text for an installed skill, else from a tap. None if unknown."""
764
- if not re.match(r"^[A-Za-z0-9._-]+$", name):
766
+ if not _SKILL_NAME_RE.fullmatch(name):
765
767
  return None
766
768
  fp = store.skill_store_dir(name) / "SKILL.md"
767
769
  if fp.is_file():
@@ -803,6 +805,10 @@ class _CatalogHandler(BaseHTTPRequestHandler):
803
805
  json.dumps(lockfile.read(), indent=2).encode())
804
806
  elif path.startswith("/skill/"):
805
807
  name = path[len("/skill/"):].strip("/")
808
+ if not _SKILL_NAME_RE.fullmatch(name):
809
+ self._send(404, "application/json",
810
+ json.dumps({"error": "no skill named %r" % name}).encode())
811
+ return
806
812
  text = _skill_text(name)
807
813
  if text is None:
808
814
  self._send(404, "application/json",
@@ -77,7 +77,30 @@ def _merge(base: dict, override: dict) -> dict:
77
77
  return out
78
78
 
79
79
 
80
- def load() -> dict:
80
+ # In-process cache of the merged config. get() is on many hot paths
81
+ # (ai.enabled, per-skill enabled_agents, log level, policy) and every call
82
+ # used to re-read config.json and re-merge/deep-copy DEFAULTS. We cache the
83
+ # merged result keyed on the config path + its stat stamp, so any write —
84
+ # save(), an external edit, or a HOME/BOOST_HOME switch between tests — is
85
+ # picked up automatically without an explicit invalidation call.
86
+ _cache: dict | None = None
87
+ _cache_key: tuple | None = None
88
+
89
+
90
+ def _stat_stamp(p: Any) -> tuple:
91
+ """Identity of the config file: (path, mtime_ns, size).
92
+
93
+ A missing file stamps as (path, None, None); any create/modify/delete
94
+ changes the stamp, which is what invalidates the cache.
95
+ """
96
+ try:
97
+ st = p.stat()
98
+ except OSError:
99
+ return (str(p), None, None)
100
+ return (str(p), st.st_mtime_ns, st.st_size)
101
+
102
+
103
+ def _read() -> dict:
81
104
  p = paths.config_path()
82
105
  if not p.exists():
83
106
  return deepcopy(DEFAULTS)
@@ -88,6 +111,24 @@ def load() -> dict:
88
111
  return _merge(DEFAULTS, user)
89
112
 
90
113
 
114
+ def _cached() -> dict:
115
+ """The merged config, re-read from disk only when the file changes."""
116
+ global _cache, _cache_key
117
+ key = _stat_stamp(paths.config_path())
118
+ cache = _cache
119
+ if cache is None or _cache_key != key:
120
+ cache = _read()
121
+ _cache = cache
122
+ _cache_key = key
123
+ return cache
124
+
125
+
126
+ def load() -> dict:
127
+ # A defensive copy so callers can mutate the result (set_value/unset do)
128
+ # without corrupting the shared cache.
129
+ return deepcopy(_cached())
130
+
131
+
91
132
  def save(cfg: dict) -> None:
92
133
  paths.ensure_dirs()
93
134
  util.atomic_write_text(
@@ -95,12 +136,12 @@ def save(cfg: dict) -> None:
95
136
 
96
137
 
97
138
  def get(dotted: str, default=None):
98
- node = load()
139
+ node = _cached()
99
140
  for part in dotted.split("."):
100
141
  if not isinstance(node, dict) or part not in node:
101
142
  return default
102
143
  node = node[part]
103
- return node
144
+ return deepcopy(node)
104
145
 
105
146
 
106
147
  def set_value(dotted: str, raw: str) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.76
3
+ Version: 1.0.78
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -2,15 +2,15 @@
2
2
  id: memoize-config-load-in-process
3
3
  board: code
4
4
  section: internals
5
- status: next
5
+ status: shipped
6
6
  category: Performance
7
7
  complexity: S
8
8
  impact: Med-High
9
9
  wow: 3
10
10
  note:
11
11
  order: 4
12
- owner:
13
- pr:
12
+ owner: loop/memoize-config
13
+ pr: 88
14
14
  title: Memoize <code>config.load()</code> in-process
15
15
  ---
16
16
  Every <code>config.get()</code> re-reads <code>config.json</code> and runs a recursive <code>deepcopy</code> of <code>DEFAULTS</code> (<code>core/config.py:80–102</code>). It's called all over hot paths — <code>ai.enabled</code>, per-skill <code>enabled_agents</code> in sync loops, log-level and policy checks — so one command triggers <b>dozens of full reads + deep-copies</b>. Cache the load, invalidate on <code>save</code>.
@@ -432,7 +432,7 @@
432
432
  </article>
433
433
 
434
434
  <article class="cap rcard">
435
- <div class="head"><span class="pill next">Next</span><span class="cat">Performance</span></div>
435
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Performance</span></div>
436
436
  <h3>Memoize <code>config.load()</code> in-process</h3>
437
437
  <p>Every <code>config.get()</code> re-reads <code>config.json</code> and runs a recursive <code>deepcopy</code> of <code>DEFAULTS</code> (<code>core/config.py:80–102</code>). It's called all over hot paths — <code>ai.enabled</code>, per-skill <code>enabled_agents</code> in sync loops, log-level and policy checks — so one command triggers <b>dozens of full reads + deep-copies</b>. Cache the load, invalidate on <code>save</code>.</p>
438
438
  <div class="meta">
@@ -81,6 +81,53 @@ class TestSaveRoundtrip:
81
81
  assert raw.endswith("\n")
82
82
 
83
83
 
84
+ class TestCaching:
85
+ def test_reads_only_once_when_file_unchanged(self, sandbox, monkeypatch):
86
+ calls = {"n": 0}
87
+ real = config._read
88
+
89
+ def counting():
90
+ calls["n"] += 1
91
+ return real()
92
+
93
+ monkeypatch.setattr(config, "_cache", None)
94
+ monkeypatch.setattr(config, "_cache_key", None)
95
+ monkeypatch.setattr(config, "_read", counting)
96
+ config.get("ai.model")
97
+ config.get("serve.port")
98
+ config.load()
99
+ assert calls["n"] == 1 # cached: file never re-read
100
+
101
+ def test_external_write_invalidates_cache(self, sandbox):
102
+ paths.ensure_dirs()
103
+ paths.config_path().write_text(json.dumps({"serve": {"port": 1}}))
104
+ assert config.get("serve.port") == 1
105
+ # A different size on disk changes the stat stamp -> reload.
106
+ paths.config_path().write_text(json.dumps({"serve": {"port": 22222}}))
107
+ assert config.get("serve.port") == 22222
108
+
109
+ def test_save_visible_to_get(self, sandbox):
110
+ assert config.get("telemetry") is False # warm the cache
111
+ config.save({"telemetry": True})
112
+ assert config.get("telemetry") is True
113
+
114
+ def test_get_returns_isolated_container(self, sandbox):
115
+ agents = config.get("agents")
116
+ agents["claude-code"]["enabled"] = False
117
+ assert config.get("agents")["claude-code"]["enabled"] is True
118
+
119
+ def test_load_returns_isolated_copy(self, sandbox):
120
+ first = config.load()
121
+ first["serve"]["port"] = 424242
122
+ assert config.get("serve.port") == 8787
123
+ assert config.load()["serve"]["port"] == 8787
124
+
125
+ def test_missing_file_stamps_then_reloads_on_create(self, sandbox):
126
+ assert config.get("serve.port") == 8787 # no file yet -> defaults
127
+ config.save({"serve": {"port": 7000}})
128
+ assert config.get("serve.port") == 7000
129
+
130
+
84
131
  class TestGet:
85
132
  def test_dotted_hit(self, sandbox):
86
133
  assert config.get("ai.model") == "claude-haiku-4-5-20251001"
File without changes