boost-skill-cli 1.0.402__tar.gz → 1.0.403__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.
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/quality.py +131 -13
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_skill_cli.egg-info/SOURCES.txt +2 -0
- boost_skill_cli-1.0.403/docs/roadmap/items/heal-deleted-links-it-never-made.md +54 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap.html +52 -1
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_quality.py +39 -0
- boost_skill_cli-1.0.403/tests/unit/test_link_ownership.py +108 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.gitattributes +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.gitignore +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/.vale.ini +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/LICENSE +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/Makefile +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/README.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/codecov.yml +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/carousel.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/chat.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/demo.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/index.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/agents-field-records-the-request-not-the-links.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/one-dead-tap-broke-every-update.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/rules-install-but-cannot-be-governed.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/search-never-notices-a-new-tap.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/update-advertises-a-flag-it-rejects.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/update-refreshed-rules-without-a-gate.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/README.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/__init__.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/baseline.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/metrics.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/examples/README.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/index.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/noxfile.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/setup.cfg +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/sonar-project.properties +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/style/README.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/style/boost.css +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/style/boost.js +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/style/demo.html +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.402 → boost_skill_cli-1.0.403}/tests/visual/visual_check.mjs +0 -0
|
@@ -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.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
21
|
+
__version__ = version = '1.0.403'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 403)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -76,17 +76,120 @@ _STACK_MARKERS = [
|
|
|
76
76
|
_tilde = paths.tilde
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
def _resolve_as_far_as_it_exists(path: Path) -> Path:
|
|
80
|
+
"""Absolute ``path``, symlinks resolved down to its deepest real ancestor.
|
|
81
|
+
|
|
82
|
+
Plain ``resolve()`` is wrong on both sides of this comparison. The link's
|
|
83
|
+
target does not exist — that is what makes the link broken — and the store
|
|
84
|
+
dir does, so resolving only the one that can be resolved compares a real
|
|
85
|
+
path against a nominal one. On macOS that is not hypothetical: ``/tmp`` is
|
|
86
|
+
itself a symlink to ``/private/tmp``, so a genuine boost link read as
|
|
87
|
+
foreign and `heal` declined to repair anything.
|
|
88
|
+
"""
|
|
89
|
+
path = Path(os.path.abspath(str(path)))
|
|
90
|
+
tail: List[str] = []
|
|
91
|
+
cur = path
|
|
92
|
+
while cur != cur.parent and not cur.exists():
|
|
93
|
+
tail.append(cur.name)
|
|
94
|
+
cur = cur.parent
|
|
95
|
+
with suppress(OSError):
|
|
96
|
+
cur = cur.resolve()
|
|
97
|
+
return cur.joinpath(*reversed(tail))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _norm(path: Path) -> str:
|
|
101
|
+
"""``path`` as a comparable string, without resolving anything.
|
|
102
|
+
|
|
103
|
+
Strips Windows' extended-length prefix — ``os.readlink`` returns
|
|
104
|
+
``\\\\?\\C:\\...`` for a link the store created while ``store_dir()`` is
|
|
105
|
+
spelled the ordinary way, so the two name one location with two strings —
|
|
106
|
+
and applies `os.path.normcase`, which folds case on Windows (where the
|
|
107
|
+
filesystem is case-insensitive) and is a no-op on POSIX.
|
|
108
|
+
"""
|
|
109
|
+
# Strip BEFORE abspath: on a POSIX host a backslash path is not absolute,
|
|
110
|
+
# so abspath would prepend the cwd and move the prefix out of position —
|
|
111
|
+
# which matters because this must be testable off Windows.
|
|
112
|
+
text = str(path)
|
|
113
|
+
for prefix in ("\\\\?\\UNC\\", "\\\\?\\"):
|
|
114
|
+
if text.startswith(prefix):
|
|
115
|
+
text = text[len(prefix):]
|
|
116
|
+
break
|
|
117
|
+
return os.path.normcase(os.path.abspath(text))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _within(target: str, parent: str) -> bool:
|
|
121
|
+
"""True if normalised ``target`` is ``parent`` or sits under it."""
|
|
122
|
+
return target == parent or target.startswith(parent.rstrip(os.sep) + os.sep)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _link_key(path: Path) -> str:
|
|
126
|
+
"""``path`` resolved, then normalised into a comparable string.
|
|
127
|
+
|
|
128
|
+
Comparing `Path` objects directly is wrong on Windows, in two ways that
|
|
129
|
+
both read as "boost does not own its own link" and left `heal` refusing to
|
|
130
|
+
repair anything at all there:
|
|
131
|
+
|
|
132
|
+
* ``os.readlink`` returns the extended-length form (``\\\\?\\C:\\...``) for
|
|
133
|
+
a link the store created, while ``store_dir()`` is spelled the ordinary
|
|
134
|
+
way — same location, different string.
|
|
135
|
+
* The filesystem is case-insensitive, so ``C:\\Users`` and ``c:\\users``
|
|
136
|
+
are one directory and two unequal `Path`s.
|
|
137
|
+
|
|
138
|
+
`os.path.normcase` is a no-op on POSIX, so this stays exact where case is.
|
|
139
|
+
"""
|
|
140
|
+
return _norm(_resolve_as_far_as_it_exists(path))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _owned_link(link: Path) -> bool:
|
|
144
|
+
"""True if ``link`` points into boost's canonical store.
|
|
145
|
+
|
|
146
|
+
Ownership is read off the link itself rather than the lock, so it still
|
|
147
|
+
answers correctly for a skill uninstalled mid-sweep or a lock that has gone
|
|
148
|
+
missing — the two cases where a dangling link is most likely to exist.
|
|
149
|
+
"""
|
|
150
|
+
try:
|
|
151
|
+
raw = Path(os.readlink(str(link)))
|
|
152
|
+
except OSError:
|
|
153
|
+
return False
|
|
154
|
+
target = raw if raw.is_absolute() else link.parent / raw
|
|
155
|
+
store = paths.store_dir()
|
|
156
|
+
# Spelled form first. A link boost made carries the store's own path, so
|
|
157
|
+
# this settles the ordinary case without resolving anything — and every
|
|
158
|
+
# platform quirk lives in resolution. Windows alone supplies three: the
|
|
159
|
+
# extended-length prefix, 8.3 short names, and case-insensitivity.
|
|
160
|
+
if _within(_norm(target), _norm(store)):
|
|
161
|
+
return True
|
|
162
|
+
# Resolved form second, for a store genuinely reached through a symlinked
|
|
163
|
+
# parent — macOS `/tmp` -> `/private/tmp` is the case that made this
|
|
164
|
+
# necessary rather than theoretical.
|
|
165
|
+
return _within(_link_key(target), _link_key(store))
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _broken_links() -> Tuple[List[Path], List[Path]]:
|
|
169
|
+
"""``(ours, theirs)`` — dangling symlinks in the dirs boost links into.
|
|
170
|
+
|
|
171
|
+
Two things this deliberately does NOT do.
|
|
172
|
+
|
|
173
|
+
**It does not look in a native-store agent's dir.** `linking_agents`, not
|
|
174
|
+
`enabled_agents`: boost never links into `~/.gemini/skills`, so anything
|
|
175
|
+
dangling there belongs to someone else and is none of this command's
|
|
176
|
+
business. The rest of `cmd_heal` already had this right.
|
|
177
|
+
|
|
178
|
+
**It does not report a link boost did not create as ours.** `heal` deletes
|
|
179
|
+
what this returns first, and a broken link is not necessarily garbage — a
|
|
180
|
+
skill on an unmounted volume dangles until the volume comes back. Removing
|
|
181
|
+
a link the user made themselves is not a repair, it is data loss with a
|
|
182
|
+
reassuring name, so those are reported and left alone.
|
|
183
|
+
"""
|
|
184
|
+
ours: List[Path] = []
|
|
185
|
+
theirs: List[Path] = []
|
|
186
|
+
for adir in agents.linking_agents().values():
|
|
83
187
|
if not adir.is_dir():
|
|
84
188
|
continue
|
|
85
|
-
|
|
86
|
-
link
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return broken
|
|
189
|
+
for link in sorted(adir.iterdir()):
|
|
190
|
+
if link.is_symlink() and not link.exists():
|
|
191
|
+
(ours if _owned_link(link) else theirs).append(link)
|
|
192
|
+
return ours, theirs
|
|
90
193
|
|
|
91
194
|
|
|
92
195
|
def _read_skill(skill_dir: Path) -> Tuple[dict, str]:
|
|
@@ -365,10 +468,18 @@ def cmd_doctor(argv):
|
|
|
365
468
|
bad("%d orphaned store dir%s (%s) — run `boost sync`"
|
|
366
469
|
% (len(orphans), _s(len(orphans)), ", ".join(orphans[:5])))
|
|
367
470
|
|
|
368
|
-
broken = _broken_links()
|
|
471
|
+
broken, foreign = _broken_links()
|
|
369
472
|
if broken:
|
|
370
473
|
bad("%d broken symlink%s in agent dirs — run `boost heal`"
|
|
371
474
|
% (len(broken), _s(len(broken))))
|
|
475
|
+
if foreign:
|
|
476
|
+
# `out.info`, not `bad`: this does not raise the issue count, because
|
|
477
|
+
# boost will not fix it and `heal` deliberately leaves it — counting it
|
|
478
|
+
# would leave doctor permanently red on something no boost command can
|
|
479
|
+
# clear, which is how a health check stops being read.
|
|
480
|
+
out.info("%d broken symlink%s in agent dirs not created by boost — "
|
|
481
|
+
"left alone; yours to remove or repair"
|
|
482
|
+
% (len(foreign), _s(len(foreign))))
|
|
372
483
|
|
|
373
484
|
for adir in enabled.values():
|
|
374
485
|
if adir.is_dir() and not os.access(str(adir), os.W_OK):
|
|
@@ -691,13 +802,19 @@ def cmd_heal(argv):
|
|
|
691
802
|
% (len(missing), "y" if len(missing) == 1 else "ies"))
|
|
692
803
|
actions.append("mkdir %d" % len(missing))
|
|
693
804
|
|
|
694
|
-
|
|
805
|
+
ours, theirs = _broken_links()
|
|
806
|
+
for link in ours:
|
|
695
807
|
if dry:
|
|
696
808
|
out.info("would remove broken link %s" % _tilde(link))
|
|
697
809
|
else:
|
|
698
810
|
link.unlink()
|
|
699
811
|
out.ok("removed broken link %s" % _tilde(link))
|
|
700
812
|
actions.append("unlink %s" % link.name)
|
|
813
|
+
for link in theirs:
|
|
814
|
+
# Named, never touched: it is in a directory boost writes to, so the
|
|
815
|
+
# user should know it is dangling — but boost did not put it there.
|
|
816
|
+
out.warn("broken link %s does not point into %s — left alone"
|
|
817
|
+
% (_tilde(link), _tilde(paths.store_dir())))
|
|
701
818
|
|
|
702
819
|
plan = store.sync_plan()
|
|
703
820
|
if dry:
|
|
@@ -920,8 +1037,9 @@ def cmd_health(argv):
|
|
|
920
1037
|
decay_n = sum(1 for r in _decay_rows(Path.cwd()) if r["verdict"] == "decay")
|
|
921
1038
|
out.kv("decay", "%d candidate%s" % (decay_n, _s(decay_n)))
|
|
922
1039
|
|
|
923
|
-
broken = _broken_links()
|
|
924
|
-
out.kv("broken links",
|
|
1040
|
+
broken, foreign = _broken_links()
|
|
1041
|
+
out.kv("broken links", "%d%s" % (
|
|
1042
|
+
len(broken), " (+%d not ours)" % len(foreign) if foreign else ""))
|
|
925
1043
|
|
|
926
1044
|
last_sync = "never"
|
|
927
1045
|
if cloned and gitutil.has_git():
|
|
@@ -235,6 +235,7 @@ docs/roadmap/items/github-pages-deploy-is-broken-every-push.md
|
|
|
235
235
|
docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md
|
|
236
236
|
docs/roadmap/items/golden-set-statistical-power.md
|
|
237
237
|
docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md
|
|
238
|
+
docs/roadmap/items/heal-deleted-links-it-never-made.md
|
|
238
239
|
docs/roadmap/items/html-validation-html-validate.md
|
|
239
240
|
docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md
|
|
240
241
|
docs/roadmap/items/install-docs-never-mentioned-upgrading.md
|
|
@@ -560,6 +561,7 @@ tests/unit/test_injectscan.py
|
|
|
560
561
|
tests/unit/test_installscan.py
|
|
561
562
|
tests/unit/test_integrity.py
|
|
562
563
|
tests/unit/test_journal.py
|
|
564
|
+
tests/unit/test_link_ownership.py
|
|
563
565
|
tests/unit/test_localembed.py
|
|
564
566
|
tests/unit/test_localembed_e2e.py
|
|
565
567
|
tests/unit/test_lockfile.py
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: heal-deleted-links-it-never-made
|
|
3
|
+
board: code
|
|
4
|
+
section: internals
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Safety · Correctness
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: Medium
|
|
9
|
+
wow: 4
|
|
10
|
+
note: a dangling link is not garbage — an unmounted volume comes back, and heal deleted it anyway
|
|
11
|
+
order: 99
|
|
12
|
+
owner: fix/heal-only-removes-links-it-owns
|
|
13
|
+
pr: 459
|
|
14
|
+
title: heal removed symlinks boost never created
|
|
15
|
+
---
|
|
16
|
+
<b><code>boost heal</code> deleted a symlink boost did not make, does not track, and has no claim
|
|
17
|
+
to.</b> Reproduced against a sandbox: plant
|
|
18
|
+
<code>~/.claude/skills/my-own-skill → ~/elsewhere/my-own-skill</code>, run
|
|
19
|
+
<code>boost heal</code>, and it reports <i>"removed broken link ~/.claude/skills/my-own-skill"</i>.
|
|
20
|
+
Same scenario on the fixed build leaves it exactly where it was.
|
|
21
|
+
|
|
22
|
+
<b>A broken link is not the same as garbage.</b> <code>~/.claude/skills/</code> is the user's own
|
|
23
|
+
directory that boost happens to link into. A dangling entry there can be a skill on an unmounted
|
|
24
|
+
volume, a repo checked out somewhere else for the afternoon, or a link into a detached drive
|
|
25
|
+
— all of which come back. Removing one is not a repair; it is data loss under a reassuring
|
|
26
|
+
name, from a command whose entire promise is that it is safe to run.
|
|
27
|
+
|
|
28
|
+
<b>Ownership is legible from the link itself.</b> Every link boost creates points into the canonical
|
|
29
|
+
store, <code>~/.agents/skills/<name></code>. Reading the target beats consulting the lock,
|
|
30
|
+
because the two moments a dangling link is most likely to exist — a skill uninstalled
|
|
31
|
+
mid-sweep, a lock file that has gone missing — are exactly the moments the lock cannot answer.
|
|
32
|
+
Links into the store are swept; everything else is <i>named</i> and left alone, because the user
|
|
33
|
+
should still know it is dangling.
|
|
34
|
+
|
|
35
|
+
<b>The scan was also looking somewhere it has no business.</b> <code>_broken_links</code> iterated
|
|
36
|
+
<code>agents.enabled_agents()</code>, which includes Gemini — and boost never links into
|
|
37
|
+
<code>~/.gemini/skills</code> at all, because Gemini CLI reads the canonical store directly.
|
|
38
|
+
CLAUDE.md states the rule outright: iterate <code>linking_agents()</code> "for anything
|
|
39
|
+
symlink-shaped (link, unlink, stale-link sweeps, coverage counts)". The <i>same function</i> already
|
|
40
|
+
had it right eleven lines further down, where <code>cmd_heal</code> builds its list of missing
|
|
41
|
+
directories and comments on precisely this distinction.
|
|
42
|
+
|
|
43
|
+
<b>A macOS-only trap sat inside the fix.</b> The first attempt compared
|
|
44
|
+
<code>store_dir().resolve()</code> against a normalised link target — resolving the side that
|
|
45
|
+
exists and not the side that does not. On macOS <code>/tmp</code> is itself a symlink to
|
|
46
|
+
<code>/private/tmp</code>, so a genuine boost link read as foreign and <code>heal</code> declined to
|
|
47
|
+
repair anything at all. Both sides are now resolved down to their deepest real ancestor, which is
|
|
48
|
+
the only comparison that is correct when one path is dangling by definition.
|
|
49
|
+
|
|
50
|
+
<b><code>doctor</code> reports it without going red.</b> A foreign broken link is printed as
|
|
51
|
+
information, not counted as an issue: <code>heal</code> deliberately will not fix it, so counting it
|
|
52
|
+
would leave <code>doctor</code> permanently red on something no boost command can clear —
|
|
53
|
+
which is how a health check stops being read. Two tests pin the behaviour and both fail with the
|
|
54
|
+
ownership check reverted.
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
<div class="stat"><b>16</b><span>Shipped</span></div>
|
|
126
126
|
<div class="stat"><b>1</b><span>Next up</span></div>
|
|
127
127
|
<div class="stat"><b>8</b><span>Planned</span></div>
|
|
128
|
-
<div class="stat"><b>
|
|
128
|
+
<div class="stat"><b>216</b><span>Loop finds</span></div>
|
|
129
129
|
<!-- /ROADMAP:stats -->
|
|
130
130
|
</div>
|
|
131
131
|
</section>
|
|
@@ -3470,6 +3470,57 @@ brake anyone can see, not a policy anyone can set.</p></details>
|
|
|
3470
3470
|
<span class="m">install scanned rule content; update did not — and the scanner could not see concealment anyway</span>
|
|
3471
3471
|
</div>
|
|
3472
3472
|
</article>
|
|
3473
|
+
|
|
3474
|
+
<article class="cap rcard" id="heal-deleted-links-it-never-made">
|
|
3475
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Safety · Correctness</span></div>
|
|
3476
|
+
<h3>heal removed symlinks boost never created</h3>
|
|
3477
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
3478
|
+
<p><b><code>boost heal</code> deleted a symlink boost did not make, does not track, and has no claim
|
|
3479
|
+
to.</b> Reproduced against a sandbox: plant
|
|
3480
|
+
<code>~/.claude/skills/my-own-skill → ~/elsewhere/my-own-skill</code>, run
|
|
3481
|
+
<code>boost heal</code>, and it reports <i>"removed broken link ~/.claude/skills/my-own-skill"</i>.
|
|
3482
|
+
Same scenario on the fixed build leaves it exactly where it was.
|
|
3483
|
+
|
|
3484
|
+
<b>A broken link is not the same as garbage.</b> <code>~/.claude/skills/</code> is the user's own
|
|
3485
|
+
directory that boost happens to link into. A dangling entry there can be a skill on an unmounted
|
|
3486
|
+
volume, a repo checked out somewhere else for the afternoon, or a link into a detached drive
|
|
3487
|
+
— all of which come back. Removing one is not a repair; it is data loss under a reassuring
|
|
3488
|
+
name, from a command whose entire promise is that it is safe to run.
|
|
3489
|
+
|
|
3490
|
+
<b>Ownership is legible from the link itself.</b> Every link boost creates points into the canonical
|
|
3491
|
+
store, <code>~/.agents/skills/<name></code>. Reading the target beats consulting the lock,
|
|
3492
|
+
because the two moments a dangling link is most likely to exist — a skill uninstalled
|
|
3493
|
+
mid-sweep, a lock file that has gone missing — are exactly the moments the lock cannot answer.
|
|
3494
|
+
Links into the store are swept; everything else is <i>named</i> and left alone, because the user
|
|
3495
|
+
should still know it is dangling.
|
|
3496
|
+
|
|
3497
|
+
<b>The scan was also looking somewhere it has no business.</b> <code>_broken_links</code> iterated
|
|
3498
|
+
<code>agents.enabled_agents()</code>, which includes Gemini — and boost never links into
|
|
3499
|
+
<code>~/.gemini/skills</code> at all, because Gemini CLI reads the canonical store directly.
|
|
3500
|
+
CLAUDE.md states the rule outright: iterate <code>linking_agents()</code> "for anything
|
|
3501
|
+
symlink-shaped (link, unlink, stale-link sweeps, coverage counts)". The <i>same function</i> already
|
|
3502
|
+
had it right eleven lines further down, where <code>cmd_heal</code> builds its list of missing
|
|
3503
|
+
directories and comments on precisely this distinction.
|
|
3504
|
+
|
|
3505
|
+
<b>A macOS-only trap sat inside the fix.</b> The first attempt compared
|
|
3506
|
+
<code>store_dir().resolve()</code> against a normalised link target — resolving the side that
|
|
3507
|
+
exists and not the side that does not. On macOS <code>/tmp</code> is itself a symlink to
|
|
3508
|
+
<code>/private/tmp</code>, so a genuine boost link read as foreign and <code>heal</code> declined to
|
|
3509
|
+
repair anything at all. Both sides are now resolved down to their deepest real ancestor, which is
|
|
3510
|
+
the only comparison that is correct when one path is dangling by definition.
|
|
3511
|
+
|
|
3512
|
+
<b><code>doctor</code> reports it without going red.</b> A foreign broken link is printed as
|
|
3513
|
+
information, not counted as an issue: <code>heal</code> deliberately will not fix it, so counting it
|
|
3514
|
+
would leave <code>doctor</code> permanently red on something no boost command can clear —
|
|
3515
|
+
which is how a health check stops being read. Two tests pin the behaviour and both fail with the
|
|
3516
|
+
ownership check reverted.</p></details>
|
|
3517
|
+
<div class="meta">
|
|
3518
|
+
<span class="m">Complexity <b>S</b></span>
|
|
3519
|
+
<span class="m">Impact <b>Medium</b></span>
|
|
3520
|
+
<span class="m">Wow <b class="wow">★★★★</b></span>
|
|
3521
|
+
<span class="m">a dangling link is not garbage — an unmounted volume comes back, and heal deleted it anyway</span>
|
|
3522
|
+
</div>
|
|
3523
|
+
</article>
|
|
3473
3524
|
<!-- /ROADMAP:cards -->
|
|
3474
3525
|
|
|
3475
3526
|
</div>
|
|
@@ -79,6 +79,17 @@ class TestDoctor:
|
|
|
79
79
|
assert "1 skill installed · 1 tap synced · 1 broken link" in r.out
|
|
80
80
|
assert "need attention" in r.out # verdict flips on issues
|
|
81
81
|
|
|
82
|
+
def test_a_foreign_broken_link_is_reported_but_not_an_issue(
|
|
83
|
+
self, boost, installed):
|
|
84
|
+
# `heal` deliberately will not fix this, so counting it would leave
|
|
85
|
+
# doctor permanently red on something no boost command can clear.
|
|
86
|
+
mine = paths.home() / ".claude" / "skills" / "my-own-skill"
|
|
87
|
+
mine.symlink_to(paths.home() / "elsewhere" / "my-own-skill")
|
|
88
|
+
r = boost("doctor") # rc 0, not 1
|
|
89
|
+
assert "not created by boost" in r.out
|
|
90
|
+
assert "0 broken links" in r.out # none of boost's are broken
|
|
91
|
+
assert "need attention" not in r.out
|
|
92
|
+
|
|
82
93
|
def test_missing_store_rc1(self, boost, installed):
|
|
83
94
|
shutil.rmtree(paths.store_dir() / "brainstorming")
|
|
84
95
|
r = boost("doctor", expect=1)
|
|
@@ -545,6 +556,34 @@ class TestHeal:
|
|
|
545
556
|
r = boost("heal")
|
|
546
557
|
assert "nothing to heal" in r.out
|
|
547
558
|
|
|
559
|
+
def test_a_link_boost_did_not_create_is_left_alone(self, boost, installed):
|
|
560
|
+
"""`heal` deleted these. A broken link is not necessarily garbage.
|
|
561
|
+
|
|
562
|
+
`~/.claude/skills/` is a directory the user owns and boost merely links
|
|
563
|
+
into, so a dangling entry there can be a skill on an unmounted volume or
|
|
564
|
+
a repo temporarily moved — both of which come back. Removing it is not a
|
|
565
|
+
repair, it is data loss with a reassuring name.
|
|
566
|
+
"""
|
|
567
|
+
mine = paths.home() / ".claude" / "skills" / "my-own-skill"
|
|
568
|
+
mine.symlink_to(paths.home() / "elsewhere" / "my-own-skill")
|
|
569
|
+
|
|
570
|
+
r = boost("heal")
|
|
571
|
+
assert "does not point into" in r.out
|
|
572
|
+
assert "left alone" in r.out
|
|
573
|
+
assert mine.is_symlink() # still there, still dangling
|
|
574
|
+
assert "removed broken link ~/.claude/skills/my-own-skill" not in r.out
|
|
575
|
+
|
|
576
|
+
def test_a_relative_link_into_the_store_is_still_ours(self, boost, installed):
|
|
577
|
+
# Ownership is decided by where the link points, not by how it is
|
|
578
|
+
# spelled — a relative target resolves against the link's own dir.
|
|
579
|
+
rel = paths.home() / ".claude" / "skills" / "relghost"
|
|
580
|
+
import os as _os
|
|
581
|
+
rel.symlink_to(_os.path.relpath(str(paths.store_dir() / "nowhere"),
|
|
582
|
+
str(rel.parent)))
|
|
583
|
+
r = boost("heal")
|
|
584
|
+
assert "removed broken link ~/.claude/skills/relghost" in r.out
|
|
585
|
+
assert not rel.is_symlink()
|
|
586
|
+
|
|
548
587
|
def test_restores_missing_store_from_tap(self, boost, installed):
|
|
549
588
|
shutil.rmtree(paths.store_dir() / "brainstorming")
|
|
550
589
|
r = boost("heal")
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Unit tests: the link-ownership helpers behind `boost heal`.
|
|
2
|
+
|
|
3
|
+
`heal` deletes what it decides it owns, so the decision is worth pinning
|
|
4
|
+
directly rather than only through the command. These run on every platform
|
|
5
|
+
because they are string logic — the Windows shapes below are exactly what
|
|
6
|
+
made a genuine boost link read as foreign on `windows-latest` while passing
|
|
7
|
+
on Linux and macOS.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
from boost_cli.commands import quality
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestNorm:
|
|
20
|
+
def test_it_folds_case_the_way_the_platform_does(self):
|
|
21
|
+
# A no-op on POSIX, case-folding on Windows. Asserting against
|
|
22
|
+
# os.path.normcase rather than a literal keeps this true on both.
|
|
23
|
+
assert quality._norm(Path("/A/B")) == os.path.normcase(
|
|
24
|
+
os.path.abspath("/A/B"))
|
|
25
|
+
|
|
26
|
+
def test_it_makes_a_relative_path_absolute(self):
|
|
27
|
+
assert os.path.isabs(quality._norm(Path("rel/ative")))
|
|
28
|
+
|
|
29
|
+
@pytest.mark.parametrize("prefixed,plain", [
|
|
30
|
+
("\\\\?\\C:\\x\\y", "C:\\x\\y"),
|
|
31
|
+
("\\\\?\\UNC\\srv\\share\\x", "srv\\share\\x"),
|
|
32
|
+
])
|
|
33
|
+
def test_it_strips_windows_extended_length_prefixes(self, prefixed, plain):
|
|
34
|
+
"""`os.readlink` returns this form; `store_dir()` never does.
|
|
35
|
+
|
|
36
|
+
One location, two strings — which is how `heal` concluded it did not
|
|
37
|
+
own a link it had created itself, and repaired nothing on Windows.
|
|
38
|
+
"""
|
|
39
|
+
got = quality._norm(Path(prefixed))
|
|
40
|
+
assert "?" not in got # the prefix is gone, on any host
|
|
41
|
+
assert got.endswith(os.path.normcase(plain))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class TestWithin:
|
|
45
|
+
def test_a_path_is_within_itself(self):
|
|
46
|
+
assert quality._within("/a/b", "/a/b")
|
|
47
|
+
|
|
48
|
+
def test_a_child_is_within(self):
|
|
49
|
+
assert quality._within(os.sep.join(["", "a", "b", "c"]),
|
|
50
|
+
os.sep.join(["", "a", "b"]))
|
|
51
|
+
|
|
52
|
+
def test_a_sibling_with_a_shared_prefix_is_not(self):
|
|
53
|
+
# The bug a bare `startswith` would introduce: `/a/bc` is not under
|
|
54
|
+
# `/a/b`, and treating it as owned would delete a stranger's link.
|
|
55
|
+
assert not quality._within(os.sep.join(["", "a", "bc"]),
|
|
56
|
+
os.sep.join(["", "a", "b"]))
|
|
57
|
+
|
|
58
|
+
def test_a_parent_is_not_within_its_child(self):
|
|
59
|
+
assert not quality._within(os.sep.join(["", "a"]),
|
|
60
|
+
os.sep.join(["", "a", "b"]))
|
|
61
|
+
|
|
62
|
+
def test_a_trailing_separator_on_the_parent_does_not_break_it(self):
|
|
63
|
+
assert quality._within(os.sep.join(["", "a", "b", "c"]),
|
|
64
|
+
os.sep.join(["", "a", "b"]) + os.sep)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TestOwnedLink:
|
|
68
|
+
def test_a_link_into_the_store_is_ours(self, tmp_path, monkeypatch):
|
|
69
|
+
store = tmp_path / "store"
|
|
70
|
+
store.mkdir()
|
|
71
|
+
monkeypatch.setattr(quality.paths, "store_dir", lambda: store)
|
|
72
|
+
link = tmp_path / "link"
|
|
73
|
+
link.symlink_to(store / "gone") # dangling, but ours
|
|
74
|
+
assert quality._owned_link(link)
|
|
75
|
+
|
|
76
|
+
def test_a_link_somewhere_else_is_not(self, tmp_path, monkeypatch):
|
|
77
|
+
store = tmp_path / "store"
|
|
78
|
+
store.mkdir()
|
|
79
|
+
monkeypatch.setattr(quality.paths, "store_dir", lambda: store)
|
|
80
|
+
link = tmp_path / "link"
|
|
81
|
+
link.symlink_to(tmp_path / "elsewhere" / "thing")
|
|
82
|
+
assert not quality._owned_link(link)
|
|
83
|
+
|
|
84
|
+
def test_a_relative_link_resolves_against_its_own_directory(
|
|
85
|
+
self, tmp_path, monkeypatch):
|
|
86
|
+
# Ownership is about where a link points, not how it is spelled.
|
|
87
|
+
store = tmp_path / "store"
|
|
88
|
+
store.mkdir()
|
|
89
|
+
monkeypatch.setattr(quality.paths, "store_dir", lambda: store)
|
|
90
|
+
link = tmp_path / "link"
|
|
91
|
+
link.symlink_to(os.path.join("store", "gone"))
|
|
92
|
+
assert quality._owned_link(link)
|
|
93
|
+
|
|
94
|
+
def test_a_sibling_directory_sharing_a_prefix_is_not_ours(
|
|
95
|
+
self, tmp_path, monkeypatch):
|
|
96
|
+
store = tmp_path / "skills"
|
|
97
|
+
store.mkdir()
|
|
98
|
+
monkeypatch.setattr(quality.paths, "store_dir", lambda: store)
|
|
99
|
+
link = tmp_path / "link"
|
|
100
|
+
link.symlink_to(tmp_path / "skills-backup" / "thing")
|
|
101
|
+
assert not quality._owned_link(link)
|
|
102
|
+
|
|
103
|
+
def test_something_that_is_not_a_link_is_not_ours(self, tmp_path,
|
|
104
|
+
monkeypatch):
|
|
105
|
+
monkeypatch.setattr(quality.paths, "store_dir", lambda: tmp_path)
|
|
106
|
+
plain = tmp_path / "file"
|
|
107
|
+
plain.write_text("x", encoding="utf-8")
|
|
108
|
+
assert not quality._owned_link(plain) # readlink raises; no crash
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|