boost-skill-cli 1.0.95__tar.gz → 1.0.96__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 (244) hide show
  1. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/rag.py +4 -3
  4. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  5. boost_skill_cli-1.0.96/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +21 -0
  6. boost_skill_cli-1.0.96/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +22 -0
  7. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/one-shared-atomic-write-helper.md +3 -3
  8. boost_skill_cli-1.0.96/docs/roadmap/items/untrack-generated-build-noise.md +19 -0
  9. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap.html +53 -45
  10. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_rag.py +37 -0
  11. boost_skill_cli-1.0.95/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -16
  12. boost_skill_cli-1.0.95/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -20
  13. boost_skill_cli-1.0.95/docs/roadmap/items/untrack-generated-build-noise.md +0 -19
  14. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/.gitattributes +0 -0
  15. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/.gitignore +0 -0
  16. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/CLAUDE.md +0 -0
  17. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/CONTRIBUTING.md +0 -0
  18. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/LICENSE +0 -0
  19. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/MANIFEST.in +0 -0
  20. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/Makefile +0 -0
  21. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/README.md +0 -0
  22. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/SECURITY.md +0 -0
  23. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost +0 -0
  24. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/__init__.py +0 -0
  25. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/__main__.py +0 -0
  26. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/cli.py +0 -0
  27. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/cliparse.py +0 -0
  28. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/__init__.py +0 -0
  29. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/bmad.py +0 -0
  30. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/configuration.py +0 -0
  31. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/discovery.py +0 -0
  32. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/hooks.py +0 -0
  33. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/info.py +0 -0
  34. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/intelligence.py +0 -0
  35. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/pkg.py +0 -0
  36. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/quality.py +0 -0
  37. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/taps.py +0 -0
  38. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/commands/team.py +0 -0
  39. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/__init__.py +0 -0
  40. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/agents.py +0 -0
  41. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/ai.py +0 -0
  42. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/catalog.py +0 -0
  43. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/claude_settings.py +0 -0
  44. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/config.py +0 -0
  45. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/dense.py +0 -0
  46. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/embed.py +0 -0
  47. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/frontmatter.py +0 -0
  48. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/gitutil.py +0 -0
  49. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/journal.py +0 -0
  50. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/lockfile.py +0 -0
  51. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/logs.py +0 -0
  52. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/mcp.py +0 -0
  53. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/output.py +0 -0
  54. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/paths.py +0 -0
  55. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/policy.py +0 -0
  56. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/registry.py +0 -0
  57. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/serve.py +0 -0
  58. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/staleness.py +0 -0
  59. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/store.py +0 -0
  60. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/typosquat.py +0 -0
  61. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/core/util.py +0 -0
  62. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/data/registries.json +0 -0
  63. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/errors.py +0 -0
  64. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_cli/spin.py +0 -0
  65. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  66. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  67. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  68. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_skill_cli.egg-info/requires.txt +0 -0
  69. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/boost_skill_cli.egg-info/top_level.txt +0 -0
  70. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/.claude/settings.local.json +0 -0
  71. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/DEBUGGING.md +0 -0
  72. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/demo.gif +0 -0
  73. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/demo.tape +0 -0
  74. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/design-roadmap.html +0 -0
  75. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/index.html +0 -0
  76. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/mcp-hub.html +0 -0
  77. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/rag-architecture.md +0 -0
  78. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D01.md +0 -0
  79. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D02.md +0 -0
  80. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D03.md +0 -0
  81. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D04.md +0 -0
  82. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D05.md +0 -0
  83. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D06.md +0 -0
  84. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D07.md +0 -0
  85. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D08.md +0 -0
  86. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D09.md +0 -0
  87. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D10.md +0 -0
  88. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D11.md +0 -0
  89. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D12.md +0 -0
  90. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D13.md +0 -0
  91. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D14.md +0 -0
  92. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D15.md +0 -0
  93. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D16.md +0 -0
  94. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D17.md +0 -0
  95. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D18.md +0 -0
  96. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D19.md +0 -0
  97. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D20.md +0 -0
  98. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D21.md +0 -0
  99. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D22.md +0 -0
  100. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D23.md +0 -0
  101. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D24.md +0 -0
  102. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D25.md +0 -0
  103. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/BOOST-D26.md +0 -0
  104. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  105. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  106. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  107. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  108. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  109. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  110. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  111. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  112. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  113. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  114. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  115. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  116. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  117. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  118. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  119. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  120. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  121. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  122. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  123. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  124. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  125. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  126. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  127. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  128. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  129. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  130. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  131. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  132. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  133. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  134. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  135. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  136. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  137. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  138. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  139. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  140. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  141. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  142. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  143. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  144. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  145. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  146. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  147. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  148. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  149. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  150. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  151. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  152. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  153. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  154. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  155. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  156. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  157. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  158. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  159. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  160. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  161. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  162. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  163. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  164. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  165. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  166. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  167. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  168. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  169. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  170. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  171. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  172. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  173. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  174. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  175. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  176. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  177. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  178. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  179. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  180. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  181. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  182. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  183. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  184. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  185. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  186. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  187. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  188. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/docs/roadmap/items/workspace-scope-install.md +0 -0
  189. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/index.html +0 -0
  190. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/pyproject.toml +0 -0
  191. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/scripts/build_registries.py +0 -0
  192. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/scripts/build_roadmap.py +0 -0
  193. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/scripts/mutation_gate.py +0 -0
  194. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/setup.cfg +0 -0
  195. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/style/README.md +0 -0
  196. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/style/boost.css +0 -0
  197. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/style/boost.js +0 -0
  198. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/style/demo.html +0 -0
  199. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/conftest.py +0 -0
  200. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_bmad.py +0 -0
  201. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_configuration.py +0 -0
  202. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_discovery.py +0 -0
  203. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_hooks.py +0 -0
  204. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_info.py +0 -0
  205. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_intelligence.py +0 -0
  206. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_pkg.py +0 -0
  207. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_quality.py +0 -0
  208. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_taps.py +0 -0
  209. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_cli_team.py +0 -0
  210. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/functional/test_everyday_loop.py +0 -0
  211. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/make_fixture.py +0 -0
  212. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/smoke.sh +0 -0
  213. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_agents.py +0 -0
  214. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_ai.py +0 -0
  215. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_catalog.py +0 -0
  216. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_claude_settings.py +0 -0
  217. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_cliparse.py +0 -0
  218. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_config.py +0 -0
  219. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_dense.py +0 -0
  220. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_dense_fallback.py +0 -0
  221. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_embed.py +0 -0
  222. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_errors_and_cli_table.py +0 -0
  223. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_frontmatter.py +0 -0
  224. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_gitutil.py +0 -0
  225. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_journal.py +0 -0
  226. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_lockfile.py +0 -0
  227. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_logs.py +0 -0
  228. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_mcp.py +0 -0
  229. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_mutation_hardening.py +0 -0
  230. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_output.py +0 -0
  231. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_paths.py +0 -0
  232. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_pkg_confusions.py +0 -0
  233. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_policy.py +0 -0
  234. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_registries_fresh.py +0 -0
  235. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_registry.py +0 -0
  236. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_roadmap_fresh.py +0 -0
  237. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_serve.py +0 -0
  238. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_spin.py +0 -0
  239. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_staleness.py +0 -0
  240. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_store.py +0 -0
  241. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_token_parity.py +0 -0
  242. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_typosquat.py +0 -0
  243. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/tests/unit/test_util.py +0 -0
  244. {boost_skill_cli-1.0.95 → boost_skill_cli-1.0.96}/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.95
3
+ Version: 1.0.96
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.95'
22
- __version_tuple__ = version_tuple = (1, 0, 95)
21
+ __version__ = version = '1.0.96'
22
+ __version_tuple__ = version_tuple = (1, 0, 96)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -27,7 +27,7 @@ try: # TypedDict lives in typing on 3.9+, kept optional for safety
27
27
  except ImportError: # pragma: no cover - 3.9+ always has it
28
28
  TypedDict = None # type: ignore
29
29
 
30
- from . import ai, catalog, frontmatter, gitutil, paths, registry
30
+ from . import ai, catalog, frontmatter, gitutil, paths, registry, util
31
31
 
32
32
  INDEX_VERSION = 1
33
33
  ENGINE = "bm25"
@@ -249,14 +249,15 @@ def _save(docs: List[dict], commits: Dict[str, str]) -> None:
249
249
  }
250
250
  paths.ensure_dirs()
251
251
  p = index_path()
252
- p.write_text(json.dumps(payload))
252
+ # Atomic swap: a bare write_text here can leave a truncated/corrupt index
253
+ # on disk if the process dies mid-write or a query reads concurrently.
254
+ util.atomic_write_text(p, json.dumps(payload))
253
255
  # Drop the mtime-keyed cache so a reindex is visible to an immediately
254
256
  # following query even when the filesystem mtime granularity is coarse.
255
257
  _CACHE.pop(str(p), None)
256
258
 
257
259
 
258
260
  def _now() -> str:
259
- from . import util
260
261
  return util.now_iso()
261
262
 
262
263
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.95
3
+ Version: 1.0.96
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -0,0 +1,21 @@
1
+ ---
2
+ id: atomic-corruption-safe-lock-file-writes
3
+ board: code
4
+ section: shipped
5
+ status: shipped
6
+ category: Correctness · Robustness
7
+ complexity: M
8
+ impact: High
9
+ wow: 4
10
+ note: already fixed in #65
11
+ order: 1
12
+ owner: loop/roadmap-hygiene-stale-cards
13
+ pr: 65
14
+ title: Atomic, corruption-safe lock-file writes
15
+ ---
16
+ Shipped in <b>#65</b> (this card lingered as "next" after the fact).
17
+ <code>core/lockfile.py</code> now writes through <code>util.atomic_write_text</code>
18
+ (temp file + <code>os.replace()</code>) and <code>read()</code> tells "empty"
19
+ apart from "corrupt": an unparseable lock is preserved as <code>&lt;lock&gt;.corrupt</code>
20
+ and surfaced loudly rather than silently overwritten, so an interrupted or
21
+ concurrent write can no longer drop every prior install record.
@@ -0,0 +1,22 @@
1
+ ---
2
+ id: github-pages-deploy-is-broken-every-push
3
+ board: code
4
+ section: shipped
5
+ status: shipped
6
+ category: Bug · Infra
7
+ complexity: S
8
+ impact: High
9
+ wow: 2
10
+ note: root cause removed in #60
11
+ order: 1
12
+ owner: loop/roadmap-hygiene-stale-cards
13
+ pr: 60
14
+ title: GitHub Pages deploy is broken every push
15
+ ---
16
+ Fixed by <b>#60</b>: the bogus <code>mutants/None</code> gitlink (a stray mutmut
17
+ artifact with no <code>.gitmodules</code> entry) that made Pages' submodule
18
+ checkout abort with <code>fatal: No url found for submodule path 'mutants/None'</code>
19
+ is gone. Verified: the Pages "build and deployment" now completes successfully and
20
+ the site serves — the boards live at
21
+ <code>jonnyeclectic.github.io/boost/docs/roadmap.html</code> (200), since Pages
22
+ publishes from the repo root.
@@ -2,15 +2,15 @@
2
2
  id: one-shared-atomic-write-helper
3
3
  board: code
4
4
  section: internals
5
- status: planned
5
+ status: shipped
6
6
  category: Robustness
7
7
  complexity: S
8
8
  impact: Med
9
9
  wow: 2
10
10
  note:
11
11
  order: 8
12
- owner:
13
- pr:
12
+ owner: loop/atomic-rag-save
13
+ pr: 108
14
14
  title: One shared atomic-write helper
15
15
  ---
16
16
  <code>journal._maybe_rotate</code> is a racy read-modify-write that concurrent appends can truncate mid-line; <code>rag._save</code> and <code>config.save</code> repeat the non-atomic pattern (<code>journal.py:63 · rag.py:252 · config.py:93</code>). Factor a single <code>atomic_write</code> into <code>core</code> and route all four through it.
@@ -0,0 +1,19 @@
1
+ ---
2
+ id: untrack-generated-build-noise
3
+ board: code
4
+ section: shipped
5
+ status: shipped
6
+ category: Hygiene · DX
7
+ complexity: S
8
+ impact: Med
9
+ wow: 1
10
+ note: already fixed in #60
11
+ order: 2
12
+ owner: loop/roadmap-hygiene-stale-cards
13
+ pr: 60
14
+ title: Untrack generated build noise
15
+ ---
16
+ Shipped in <b>#60</b>. The generated <code>mutants/**</code>,
17
+ <code>__pycache__/*.pyc</code> and <code>.coverage</code> files were removed from
18
+ the index (verified: <code>git ls-files</code> now tracks zero of them), so they
19
+ no longer churn every diff or force path-scoped <code>git add</code>s.
@@ -115,8 +115,8 @@
115
115
  <section class="block reveal">
116
116
  <div class="stats">
117
117
  <!-- ROADMAP:stats -->
118
- <div class="stat"><b>11</b><span>Shipped</span></div>
119
- <div class="stat"><b>3</b><span>Next up</span></div>
118
+ <div class="stat"><b>14</b><span>Shipped</span></div>
119
+ <div class="stat"><b>1</b><span>Next up</span></div>
120
120
  <div class="stat"><b>4</b><span>Planned</span></div>
121
121
  <div class="stat"><b>89</b><span>Loop finds</span></div>
122
122
  <!-- /ROADMAP:stats -->
@@ -132,6 +132,41 @@
132
132
  <div class="rgrid">
133
133
 
134
134
  <!-- ROADMAP:cards section=shipped -->
135
+ <article class="cap rcard">
136
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Correctness · Robustness</span></div>
137
+ <h3>Atomic, corruption-safe lock-file writes</h3>
138
+ <p>Shipped in <b>#65</b> (this card lingered as "next" after the fact).
139
+ <code>core/lockfile.py</code> now writes through <code>util.atomic_write_text</code>
140
+ (temp file + <code>os.replace()</code>) and <code>read()</code> tells "empty"
141
+ apart from "corrupt": an unparseable lock is preserved as <code>&lt;lock&gt;.corrupt</code>
142
+ and surfaced loudly rather than silently overwritten, so an interrupted or
143
+ concurrent write can no longer drop every prior install record.</p>
144
+ <div class="meta">
145
+ <span class="m">Complexity <b>M</b></span>
146
+ <span class="m hi">Impact <b>High</b></span>
147
+ <span class="m">Wow <b class="wow">★★★★</b></span>
148
+ <span class="m">already fixed in</span>
149
+ </div>
150
+ </article>
151
+
152
+ <article class="cap rcard">
153
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug · Infra</span></div>
154
+ <h3>GitHub Pages deploy is broken every push</h3>
155
+ <p>Fixed by <b>#60</b>: the bogus <code>mutants/None</code> gitlink (a stray mutmut
156
+ artifact with no <code>.gitmodules</code> entry) that made Pages' submodule
157
+ checkout abort with <code>fatal: No url found for submodule path 'mutants/None'</code>
158
+ is gone. Verified: the Pages "build and deployment" now completes successfully and
159
+ the site serves — the boards live at
160
+ <code>jonnyeclectic.github.io/boost/docs/roadmap.html</code> (200), since Pages
161
+ publishes from the repo root.</p>
162
+ <div class="meta">
163
+ <span class="m">Complexity <b>S</b></span>
164
+ <span class="m hi">Impact <b>High</b></span>
165
+ <span class="m">Wow <b class="wow">★★</b></span>
166
+ <span class="m">root cause removed in</span>
167
+ </div>
168
+ </article>
169
+
135
170
  <article class="cap rcard">
136
171
  <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Testing · Bug</span></div>
137
172
  <h3>Mutation hardening — <code>core/store.py</code></h3>
@@ -162,6 +197,21 @@
162
197
  </div>
163
198
  </article>
164
199
 
200
+ <article class="cap rcard">
201
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Hygiene · DX</span></div>
202
+ <h3>Untrack generated build noise</h3>
203
+ <p>Shipped in <b>#60</b>. The generated <code>mutants/**</code>,
204
+ <code>__pycache__/*.pyc</code> and <code>.coverage</code> files were removed from
205
+ the index (verified: <code>git ls-files</code> now tracks zero of them), so they
206
+ no longer churn every diff or force path-scoped <code>git add</code>s.</p>
207
+ <div class="meta">
208
+ <span class="m">Complexity <b>S</b></span>
209
+ <span class="m">Impact <b>Med</b></span>
210
+ <span class="m">Wow <b class="wow">★</b></span>
211
+ <span class="m">already fixed in</span>
212
+ </div>
213
+ </article>
214
+
165
215
  <article class="cap rcard">
166
216
  <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Correctness</span></div>
167
217
  <h3>Consolidate skill-staleness / drift logic into core</h3>
@@ -337,37 +387,6 @@ by new unit tests covering every branch.</p>
337
387
  <div class="rgrid">
338
388
 
339
389
  <!-- ROADMAP:cards section=next -->
340
- <article class="cap rcard">
341
- <div class="head"><span class="pill next">Next</span><span class="cat">Bug · Infra</span></div>
342
- <h3>GitHub Pages deploy is broken every push</h3>
343
- <p>Root cause found: a bogus <code>mutants/None</code> gitlink (a stray
344
- mutmut artifact) was committed with no <code>.gitmodules</code> entry,
345
- so Pages' submodule checkout aborts with
346
- <code>fatal: No url found for submodule path 'mutants/None'</code>.
347
- Fix: stop tracking <code>mutants/</code>.</p>
348
- <div class="meta">
349
- <span class="m">Complexity <b>S</b></span>
350
- <span class="m hi">Impact <b>High</b></span>
351
- <span class="m">Wow <b class="wow">★★</b></span>
352
- <span class="m">docs site down</span>
353
- </div>
354
- </article>
355
-
356
- <article class="cap rcard">
357
- <div class="head"><span class="pill next">Next</span><span class="cat">Hygiene · DX</span></div>
358
- <h3>Untrack generated build noise</h3>
359
- <p>Over a hundred <code>mutants/**</code>, <code>__pycache__/*.pyc</code>
360
- and <code>.coverage</code> files are tracked despite being in
361
- <code>.gitignore</code> — they churn every diff and forced careful
362
- path-scoped <code>git add</code>s. Remove from the index.</p>
363
- <div class="meta">
364
- <span class="m">Complexity <b>S</b></span>
365
- <span class="m">Impact <b>Med</b></span>
366
- <span class="m">Wow <b class="wow">★</b></span>
367
- <span class="m">unblocks Pages</span>
368
- </div>
369
- </article>
370
-
371
390
  <article class="cap rcard">
372
391
  <div class="head"><span class="pill next">Next</span><span class="cat">Design</span></div>
373
392
  <h3>Reconcile the theme drift</h3>
@@ -462,17 +481,6 @@ by new unit tests covering every branch.</p>
462
481
  <div class="rgrid">
463
482
 
464
483
  <!-- ROADMAP:cards section=internals -->
465
- <article class="cap rcard">
466
- <div class="head"><span class="pill next">Next</span><span class="cat">Correctness · Robustness</span></div>
467
- <h3>Atomic, corruption-safe lock-file writes</h3>
468
- <p><code>read()</code> returns an empty skeleton on <b>any</b> JSON error and <code>write()</code> is a bare <code>write_text</code> at <code>core/lockfile.py:55</code>. An interrupted or concurrent write truncates the lock — the next <code>set_skill()</code> then <b>permanently drops every prior install record</b> while store dirs linger as orphans. Write to a temp file + <code>os.replace()</code>, and tell "empty" apart from "corrupt".</p>
469
- <div class="meta">
470
- <span class="m">Complexity <b>M</b></span>
471
- <span class="m hi">Impact <b>High</b></span>
472
- <span class="m">Wow <b class="wow">★★★★</b></span>
473
- </div>
474
- </article>
475
-
476
484
  <article class="cap rcard">
477
485
  <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Performance</span></div>
478
486
  <h3>Memoize <code>config.load()</code> in-process</h3>
@@ -496,7 +504,7 @@ by new unit tests covering every branch.</p>
496
504
  </article>
497
505
 
498
506
  <article class="cap rcard">
499
- <div class="head"><span class="pill planned">Planned</span><span class="cat">Robustness</span></div>
507
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Robustness</span></div>
500
508
  <h3>One shared atomic-write helper</h3>
501
509
  <p><code>journal._maybe_rotate</code> is a racy read-modify-write that concurrent appends can truncate mid-line; <code>rag._save</code> and <code>config.save</code> repeat the non-atomic pattern (<code>journal.py:63 · rag.py:252 · config.py:93</code>). Factor a single <code>atomic_write</code> into <code>core</code> and route all four through it.</p>
502
510
  <div class="meta">
@@ -9,6 +9,7 @@ from __future__ import annotations
9
9
 
10
10
  import json
11
11
  import math
12
+ from pathlib import Path
12
13
 
13
14
  import pytest
14
15
 
@@ -861,3 +862,39 @@ class TestEngineRouting:
861
862
  def test_none_when_no_index_at_all(self, sandbox, monkeypatch):
862
863
  monkeypatch.setattr(dense_mod, "ready", lambda: False)
863
864
  assert rag.search("react", smart=False) is None
865
+
866
+
867
+ class TestAtomicIndexSave:
868
+ """`_save` must route the index through util.atomic_write_text so a crash
869
+ or concurrent reader never sees a truncated/corrupt BM25 index."""
870
+
871
+ def test_save_routes_through_atomic_write_text(self, corpus, monkeypatch):
872
+ _root, entries = corpus
873
+ calls = []
874
+ real = rag.util.atomic_write_text
875
+
876
+ def spy(path, text, *a, **k):
877
+ calls.append(Path(path))
878
+ return real(path, text, *a, **k)
879
+
880
+ monkeypatch.setattr(rag.util, "atomic_write_text", spy)
881
+ rag.build(entries=entries, force=True)
882
+ # The index write went through the atomic helper, not a bare write_text.
883
+ assert rag.index_path() in calls
884
+
885
+ def test_index_is_complete_json_and_leaves_no_temp_turd(self, corpus):
886
+ _root, entries = corpus
887
+ rag.build(entries=entries, force=True)
888
+ p = rag.index_path()
889
+ payload = json.loads(p.read_text()) # parseable ⇒ not truncated
890
+ assert payload["docs"] and "postings" in payload
891
+ # atomic_write_text writes to ".<name>.*.tmp" then os.replace — the
892
+ # temp file must not survive a successful save.
893
+ assert list(p.parent.glob("." + p.name + ".*")) == []
894
+
895
+ def test_rebuild_replaces_index_atomically(self, corpus):
896
+ _root, entries = corpus
897
+ rag.build(entries=entries, force=True)
898
+ rag.build(entries=entries, force=True) # second save swaps in place
899
+ payload = json.loads(rag.index_path().read_text())
900
+ assert payload["stats"]["docs"] >= 2
@@ -1,16 +0,0 @@
1
- ---
2
- id: atomic-corruption-safe-lock-file-writes
3
- board: code
4
- section: internals
5
- status: next
6
- category: Correctness · Robustness
7
- complexity: M
8
- impact: High
9
- wow: 4
10
- note:
11
- order: 1
12
- owner:
13
- pr:
14
- title: Atomic, corruption-safe lock-file writes
15
- ---
16
- <code>read()</code> returns an empty skeleton on <b>any</b> JSON error and <code>write()</code> is a bare <code>write_text</code> at <code>core/lockfile.py:55</code>. An interrupted or concurrent write truncates the lock — the next <code>set_skill()</code> then <b>permanently drops every prior install record</b> while store dirs linger as orphans. Write to a temp file + <code>os.replace()</code>, and tell "empty" apart from "corrupt".
@@ -1,20 +0,0 @@
1
- ---
2
- id: github-pages-deploy-is-broken-every-push
3
- board: code
4
- section: next
5
- status: next
6
- category: Bug · Infra
7
- complexity: S
8
- impact: High
9
- wow: 2
10
- note: docs site down
11
- order: 1
12
- owner:
13
- pr:
14
- title: GitHub Pages deploy is broken every push
15
- ---
16
- Root cause found: a bogus <code>mutants/None</code> gitlink (a stray
17
- mutmut artifact) was committed with no <code>.gitmodules</code> entry,
18
- so Pages' submodule checkout aborts with
19
- <code>fatal: No url found for submodule path 'mutants/None'</code>.
20
- Fix: stop tracking <code>mutants/</code>.
@@ -1,19 +0,0 @@
1
- ---
2
- id: untrack-generated-build-noise
3
- board: code
4
- section: next
5
- status: next
6
- category: Hygiene · DX
7
- complexity: S
8
- impact: Med
9
- wow: 1
10
- note: unblocks Pages
11
- order: 2
12
- owner:
13
- pr:
14
- title: Untrack generated build noise
15
- ---
16
- Over a hundred <code>mutants/**</code>, <code>__pycache__/*.pyc</code>
17
- and <code>.coverage</code> files are tracked despite being in
18
- <code>.gitignore</code> — they churn every diff and forced careful
19
- path-scoped <code>git add</code>s. Remove from the index.
File without changes