boost-skill-cli 1.0.200__tar.gz → 1.0.201__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.200/boost_skill_cli.egg-info → boost_skill_cli-1.0.201}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201/boost_skill_cli.egg-info}/PKG-INFO +1 -1
- boost_skill_cli-1.0.201/docs/roadmap/items/finish-mutation-hardening-across-core.md +31 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap.html +18 -6
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_agents.py +7 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_ai.py +4 -1
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_catalog.py +40 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_config.py +18 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_lockfile.py +30 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_output.py +6 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_paths.py +13 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_policy.py +35 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_registry.py +13 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_util.py +72 -0
- boost_skill_cli-1.0.200/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -19
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.gitattributes +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.gitignore +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/.vale.ini +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/LICENSE +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/Makefile +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/README.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/index.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/examples/README.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/index.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/noxfile.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/setup.cfg +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/style/README.md +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/style/boost.css +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/style/boost.js +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/style/demo.html +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.200 → boost_skill_cli-1.0.201}/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.201'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 201)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: finish-mutation-hardening-across-core
|
|
3
|
+
board: code
|
|
4
|
+
section: planned
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Testing
|
|
7
|
+
complexity: L
|
|
8
|
+
impact: Med
|
|
9
|
+
wow: 2
|
|
10
|
+
note: behavioral gaps closed
|
|
11
|
+
order: 1
|
|
12
|
+
owner: loop/mutation-hardening
|
|
13
|
+
pr: 225
|
|
14
|
+
title: Finish mutation hardening across <code>core/</code>
|
|
15
|
+
---
|
|
16
|
+
Audited the surviving mutants across all ten listed modules — catalog, util,
|
|
17
|
+
ai, registry, lockfile, policy, config, output, agents, paths — and
|
|
18
|
+
killed every one that reflected a real behavioral coverage gap: the
|
|
19
|
+
<code>search</code> desc-bonus accumulation and <code>classify_workflow</code>
|
|
20
|
+
signature logic; <code>score_skill</code> signal detection and the
|
|
21
|
+
<code>rel_time</code> bucket boundaries; <code>registry.remove</code> keeping
|
|
22
|
+
other taps; a 3-level <code>config.unset</code> slicing bug; the untested
|
|
23
|
+
<code>lockfile.remove_rule</code>/<code>remove_workflow</code> returns and
|
|
24
|
+
corrupt-history skip; the entirely-untested <code>policy.check_capabilities</code>;
|
|
25
|
+
and <code>confirm()</code>'s safe default. The residual survivors are
|
|
26
|
+
<b>equivalent mutants</b> — encoding defaults, macOS case-folding (killed
|
|
27
|
+
on CI's Linux runner), <code>+=</code> vs <code>=</code> on a zero-init score,
|
|
28
|
+
<code>//</code> vs <code>/</code> under <code>%d</code>, dead defensive defaults
|
|
29
|
+
carried by <code>DEFAULTS</code>, and test-double-stubbed plumbing kwargs —
|
|
30
|
+
none of which represents a missing assertion. The required mutation gate
|
|
31
|
+
stays green with margin.
|
|
@@ -459,17 +459,29 @@ message, so routing it through the helper would change user-facing errors.</p>
|
|
|
459
459
|
|
|
460
460
|
<!-- ROADMAP:cards section=planned -->
|
|
461
461
|
<article class="cap rcard">
|
|
462
|
-
<div class="head"><span class="pill
|
|
462
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Testing</span></div>
|
|
463
463
|
<h3>Finish mutation hardening across <code>core/</code></h3>
|
|
464
|
-
<p>
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
464
|
+
<p>Audited the surviving mutants across all ten listed modules — catalog, util,
|
|
465
|
+
ai, registry, lockfile, policy, config, output, agents, paths — and
|
|
466
|
+
killed every one that reflected a real behavioral coverage gap: the
|
|
467
|
+
<code>search</code> desc-bonus accumulation and <code>classify_workflow</code>
|
|
468
|
+
signature logic; <code>score_skill</code> signal detection and the
|
|
469
|
+
<code>rel_time</code> bucket boundaries; <code>registry.remove</code> keeping
|
|
470
|
+
other taps; a 3-level <code>config.unset</code> slicing bug; the untested
|
|
471
|
+
<code>lockfile.remove_rule</code>/<code>remove_workflow</code> returns and
|
|
472
|
+
corrupt-history skip; the entirely-untested <code>policy.check_capabilities</code>;
|
|
473
|
+
and <code>confirm()</code>'s safe default. The residual survivors are
|
|
474
|
+
<b>equivalent mutants</b> — encoding defaults, macOS case-folding (killed
|
|
475
|
+
on CI's Linux runner), <code>+=</code> vs <code>=</code> on a zero-init score,
|
|
476
|
+
<code>//</code> vs <code>/</code> under <code>%d</code>, dead defensive defaults
|
|
477
|
+
carried by <code>DEFAULTS</code>, and test-double-stubbed plumbing kwargs —
|
|
478
|
+
none of which represents a missing assertion. The required mutation gate
|
|
479
|
+
stays green with margin.</p>
|
|
468
480
|
<div class="meta">
|
|
469
481
|
<span class="m">Complexity <b>L</b></span>
|
|
470
482
|
<span class="m">Impact <b>Med</b></span>
|
|
471
483
|
<span class="m">Wow <b class="wow">★★</b></span>
|
|
472
|
-
<span class="m"
|
|
484
|
+
<span class="m">behavioral gaps closed</span>
|
|
473
485
|
</div>
|
|
474
486
|
</article>
|
|
475
487
|
|
|
@@ -72,3 +72,10 @@ class TestEnsureAgentDirs:
|
|
|
72
72
|
assert (sandbox / ".claude" / "skills").is_dir()
|
|
73
73
|
assert (sandbox / ".windsurf" / "skills").is_dir()
|
|
74
74
|
assert not (sandbox / ".cursor" / "skills").exists()
|
|
75
|
+
|
|
76
|
+
def test_is_idempotent_when_dirs_exist(self, sandbox):
|
|
77
|
+
# a second call over already-existing dirs must not raise — pins
|
|
78
|
+
# exist_ok=True (a False/dropped flag would raise FileExistsError).
|
|
79
|
+
agents.ensure_agent_dirs()
|
|
80
|
+
agents.ensure_agent_dirs()
|
|
81
|
+
assert (sandbox / ".claude" / "skills").is_dir()
|
|
@@ -202,7 +202,9 @@ class TestAskApi:
|
|
|
202
202
|
monkeypatch.setenv("ANTHROPIC_API_KEY", "sekret")
|
|
203
203
|
captured = _with_api(monkeypatch, {"content": [{"type": "text", "text": "x"}]})
|
|
204
204
|
assert ai.ask("p") == "x"
|
|
205
|
-
|
|
205
|
+
body = json.loads(captured["req"].data.decode())
|
|
206
|
+
assert "system" not in body
|
|
207
|
+
assert body["max_tokens"] == 1500 # the ask() default budget (pins 1500)
|
|
206
208
|
|
|
207
209
|
def test_api_urlerror_returns_none(self, ai_on, monkeypatch):
|
|
208
210
|
_without_cli(monkeypatch)
|
|
@@ -226,6 +228,7 @@ class TestAskAuthor:
|
|
|
226
228
|
assert ai.ask_author("p", system="s") == "authored"
|
|
227
229
|
assert calls[0]["cmd"][2:4] == ["--model", AUTHOR_MODEL]
|
|
228
230
|
assert calls[0]["cmd"][-2:] == ["--append-system-prompt", "s"]
|
|
231
|
+
assert calls[0]["input"] == "p" # the prompt is forwarded, not dropped
|
|
229
232
|
assert calls[0]["timeout"] == 240
|
|
230
233
|
|
|
231
234
|
def test_author_api_max_tokens(self, ai_on, monkeypatch):
|
|
@@ -287,6 +287,26 @@ class TestScanRulesAndWorkflows:
|
|
|
287
287
|
# a bare prompt .md with no dir marker and no subagent frontmatter
|
|
288
288
|
assert catalog._classify_workflow(Path("prompts/idea.md"), {}) is False
|
|
289
289
|
|
|
290
|
+
def test_classify_workflow_signature_needs_name_and_description(self):
|
|
291
|
+
# Outside a workflow dir, the frontmatter signature requires BOTH a name
|
|
292
|
+
# AND a description AND a workflow meta key. (Pins the `and` between
|
|
293
|
+
# name/description — an `or` would classify a name-only file.)
|
|
294
|
+
loose = Path("prompts/agent.md")
|
|
295
|
+
full = {"name": "a", "description": "d", "tools": ["x"]}
|
|
296
|
+
assert catalog._classify_workflow(loose, full) is True
|
|
297
|
+
assert catalog._classify_workflow(loose, {"name": "a", "tools": ["x"]}) is False
|
|
298
|
+
assert catalog._classify_workflow(
|
|
299
|
+
loose, {"description": "d", "tools": ["x"]}) is False
|
|
300
|
+
|
|
301
|
+
def test_classify_workflow_signature_needs_a_workflow_meta_key(self):
|
|
302
|
+
# name+description alone do NOT make a loose .md a workflow — it needs one
|
|
303
|
+
# of the subagent/slash-command keys. (Pins `WORKFLOW_META_KEYS & set` —
|
|
304
|
+
# a `|` would make the set truthy for any frontmatter.)
|
|
305
|
+
loose = Path("prompts/agent.md")
|
|
306
|
+
assert catalog._classify_workflow(loose, {"name": "a", "description": "d"}) is False
|
|
307
|
+
assert catalog._classify_workflow(
|
|
308
|
+
loose, {"name": "a", "description": "d", "model": "opus"}) is True
|
|
309
|
+
|
|
290
310
|
def test_mixed_kinds_all_present(self, tmp_path):
|
|
291
311
|
root = tmp_path / "tap"
|
|
292
312
|
write_skill(root / "skills" / "s", "---\nname: s\n---")
|
|
@@ -445,6 +465,16 @@ class TestResolveOne:
|
|
|
445
465
|
assert ei.value.message == "no skill named 'brainstorm' in any tap"
|
|
446
466
|
assert ei.value.hint == "closest matches: brainstorming"
|
|
447
467
|
|
|
468
|
+
def test_miss_hint_caps_at_three_joined_by_comma(self, sandbox):
|
|
469
|
+
# Five near-matches, but the hint lists exactly the top THREE, comma-
|
|
470
|
+
# joined. (Pins `search(name)[:3]` and the `", "` join separator.)
|
|
471
|
+
_fake_taps(("t", [_entry("planner-%d" % i, "t") for i in range(5)]))
|
|
472
|
+
with pytest.raises(BoostError) as ei:
|
|
473
|
+
catalog.resolve_one("planner")
|
|
474
|
+
listed = ei.value.hint.replace("closest matches: ", "").split(", ")
|
|
475
|
+
assert len(listed) == 3
|
|
476
|
+
assert all(n.startswith("planner-") for n in listed)
|
|
477
|
+
|
|
448
478
|
def test_miss_no_close_match_no_hint(self, sandbox):
|
|
449
479
|
_fake_taps(("t", [_entry("brainstorming", "t")]))
|
|
450
480
|
with pytest.raises(BoostError) as ei:
|
|
@@ -525,6 +555,16 @@ class TestSearchRanking:
|
|
|
525
555
|
assert [(m["name"], s) for m, s in catalog.search("planning", entries=[e])] \
|
|
526
556
|
== [("x", 2)]
|
|
527
557
|
|
|
558
|
+
def test_desc_bonus_adds_to_name_score_not_replaces(self):
|
|
559
|
+
# An entry that matches BOTH the name and the description must accrue the
|
|
560
|
+
# description bonus (+30) ON TOP of the name-tier score, never reset to
|
|
561
|
+
# it. name "fmt-tool" starts-with "fmt" (+80) + token "fmt" in name (+12)
|
|
562
|
+
# + desc "a fmt helper" contains "fmt" (+30) + token in desc (+6) + token
|
|
563
|
+
# in blob (+2) = 130. (Pins `score += 30`, not `score = 30`.)
|
|
564
|
+
e = _entry("fmt-tool", "t", desc="a fmt helper")
|
|
565
|
+
assert [(m["name"], s) for m, s in catalog.search("fmt", entries=[e])] \
|
|
566
|
+
== [("fmt-tool", 130)]
|
|
567
|
+
|
|
528
568
|
|
|
529
569
|
class TestMetaText:
|
|
530
570
|
def test_flattens_keys_and_values_lowercased(self):
|
|
@@ -80,6 +80,15 @@ class TestSaveRoundtrip:
|
|
|
80
80
|
assert json.loads(raw) == {"a": 1}
|
|
81
81
|
assert raw.endswith("\n")
|
|
82
82
|
|
|
83
|
+
def test_save_is_pretty_printed_and_preserves_key_order(self, sandbox):
|
|
84
|
+
# 2-space indent and insertion order (sort_keys=False) — the config file
|
|
85
|
+
# is human-edited, so it must stay readable and stable, not compacted or
|
|
86
|
+
# alphabetized. Pins indent=2 and sort_keys=False.
|
|
87
|
+
config.save({"zeta": 1, "alpha": 2})
|
|
88
|
+
raw = paths.config_path().read_text(encoding="utf-8")
|
|
89
|
+
assert '\n "zeta": 1' in raw # 2-space indent, not compact
|
|
90
|
+
assert raw.index('"zeta"') < raw.index('"alpha"') # insertion, not sorted
|
|
91
|
+
|
|
83
92
|
|
|
84
93
|
class TestCaching:
|
|
85
94
|
def test_reads_only_once_when_file_unchanged(self, sandbox, monkeypatch):
|
|
@@ -198,6 +207,15 @@ class TestUnset:
|
|
|
198
207
|
assert config.unset("never.was.here") is False
|
|
199
208
|
assert config.unset("absent_top") is False
|
|
200
209
|
|
|
210
|
+
def test_unset_deeply_nested_key_targets_the_leaf(self, sandbox):
|
|
211
|
+
# a 3-level key exercises the parent-walk `parts[:-1]` and leaf `parts[-1]`
|
|
212
|
+
# correctly — a 2-level key can't tell them from `parts[:1]` / `parts[1]`.
|
|
213
|
+
cfg = config.load()
|
|
214
|
+
cfg["deep"] = {"mid": {"leaf": 1, "keep": 2}}
|
|
215
|
+
config.save(cfg)
|
|
216
|
+
assert config.unset("deep.mid.leaf") is True
|
|
217
|
+
assert config.load()["deep"]["mid"] == {"keep": 2} # only leaf removed
|
|
218
|
+
|
|
201
219
|
def test_path_through_scalar_returns_false(self, sandbox):
|
|
202
220
|
assert config.unset("ai.model.sub") is False
|
|
203
221
|
|
|
@@ -182,3 +182,33 @@ class TestHistory:
|
|
|
182
182
|
lockfile.history_read("20990101T000000Z")
|
|
183
183
|
assert ei.value.message == "no lock history entry 20990101T000000Z"
|
|
184
184
|
assert ei.value.hint == "list entries with `boost replay`"
|
|
185
|
+
|
|
186
|
+
def test_history_list_skips_corrupt_without_stopping(self, sandbox):
|
|
187
|
+
# a corrupt snapshot that sorts BEFORE a valid one must be skipped, not
|
|
188
|
+
# halt the scan — pins the `continue` (a `break` would drop the later
|
|
189
|
+
# valid entry). The seed in _seed_history can't catch this because its
|
|
190
|
+
# corrupt file is newest, hence last.
|
|
191
|
+
paths.ensure_dirs()
|
|
192
|
+
d = paths.lock_history_dir()
|
|
193
|
+
(d / "lock-20200101T000000Z.json").write_text("not json", encoding="utf-8")
|
|
194
|
+
(d / "lock-20200102T000000Z.json").write_text(
|
|
195
|
+
json.dumps({"updated": "v", "skills": {"x": {}}}), encoding="utf-8")
|
|
196
|
+
assert [e["id"] for e in lockfile.history_list()] == ["20200102T000000Z"]
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class TestRulesAndWorkflows:
|
|
200
|
+
def test_rule_roundtrip_and_remove(self, sandbox):
|
|
201
|
+
lockfile.set_rule("r", {"v": "1"})
|
|
202
|
+
assert lockfile.get_rule("r") == {"v": "1"}
|
|
203
|
+
assert lockfile.installed_rules() == {"r": {"v": "1"}}
|
|
204
|
+
assert lockfile.remove_rule("r") is True # present -> True
|
|
205
|
+
assert lockfile.get_rule("r") is None
|
|
206
|
+
assert lockfile.remove_rule("r") is False # absent -> False
|
|
207
|
+
|
|
208
|
+
def test_workflow_roundtrip_and_remove(self, sandbox):
|
|
209
|
+
lockfile.set_workflow("w", {"v": "2"})
|
|
210
|
+
assert lockfile.get_workflow("w") == {"v": "2"}
|
|
211
|
+
assert lockfile.installed_workflows() == {"w": {"v": "2"}}
|
|
212
|
+
assert lockfile.remove_workflow("w") is True # present -> True
|
|
213
|
+
assert lockfile.get_workflow("w") is None
|
|
214
|
+
assert lockfile.remove_workflow("w") is False # absent -> False
|
|
@@ -844,6 +844,12 @@ class TestConfirm:
|
|
|
844
844
|
monkeypatch.setattr(sys, "stdin", FakeStream(tty=False))
|
|
845
845
|
assert output.confirm("go?", default=False) is False
|
|
846
846
|
|
|
847
|
+
def test_default_is_false_when_unspecified(self, monkeypatch):
|
|
848
|
+
# safety: with no explicit default, an unattended (non-tty) confirm must
|
|
849
|
+
# NOT proceed — pins the `default: bool = False` signature default.
|
|
850
|
+
monkeypatch.setattr(sys, "stdin", FakeStream(tty=False))
|
|
851
|
+
assert output.confirm("delete everything?") is False
|
|
852
|
+
|
|
847
853
|
def _tty(self, monkeypatch, answer):
|
|
848
854
|
monkeypatch.setattr(sys, "stdin", FakeStream(tty=True))
|
|
849
855
|
prompts = []
|
|
@@ -143,6 +143,19 @@ class TestRepoRoot:
|
|
|
143
143
|
assert root == Path(paths.__file__).resolve().parent.parent.parent
|
|
144
144
|
|
|
145
145
|
|
|
146
|
+
class TestPackageAndStatePaths:
|
|
147
|
+
def test_package_root_is_the_boost_cli_dir(self):
|
|
148
|
+
root = paths.package_root()
|
|
149
|
+
assert root.name == "boost_cli"
|
|
150
|
+
assert (root / "core" / "paths.py").is_file()
|
|
151
|
+
assert root == Path(paths.__file__).resolve().parent.parent
|
|
152
|
+
|
|
153
|
+
def test_trusted_keys_path_name_and_location(self, sandbox):
|
|
154
|
+
p = paths.trusted_keys_path()
|
|
155
|
+
assert p.name == "trusted_keys.json"
|
|
156
|
+
assert p.parent == paths.state_dir()
|
|
157
|
+
|
|
158
|
+
|
|
146
159
|
class TestLauncher:
|
|
147
160
|
def test_prefers_console_script_on_path(self, monkeypatch):
|
|
148
161
|
monkeypatch.setattr("boost_cli.core.paths.shutil.which",
|
|
@@ -153,6 +153,41 @@ class TestCheckInstall:
|
|
|
153
153
|
assert policy.check_install({}, 0) == []
|
|
154
154
|
|
|
155
155
|
|
|
156
|
+
class TestCheckCapabilities:
|
|
157
|
+
def test_declared_denied_capability_violates(self, sandbox):
|
|
158
|
+
set_policy(denied_capabilities=["network"])
|
|
159
|
+
v = policy.check_capabilities({"capabilities": ["network"]}, "body")
|
|
160
|
+
assert v == ["declares the 'network' capability, denied by policy"]
|
|
161
|
+
|
|
162
|
+
def test_declared_but_not_denied_is_allowed(self, sandbox):
|
|
163
|
+
set_policy(denied_capabilities=["shell"])
|
|
164
|
+
assert policy.check_capabilities({"capabilities": ["network"]}, "body") == []
|
|
165
|
+
|
|
166
|
+
def test_empty_denylist_short_circuits(self, sandbox):
|
|
167
|
+
# no denied capabilities -> allowed regardless of what the skill declares
|
|
168
|
+
set_policy(denied_capabilities=[])
|
|
169
|
+
assert policy.check_capabilities({"capabilities": ["network", "shell"]}, "x") == []
|
|
170
|
+
|
|
171
|
+
def test_master_switch_bypasses(self, sandbox):
|
|
172
|
+
set_policy(denied_capabilities=["network"])
|
|
173
|
+
cfg = config.load()
|
|
174
|
+
cfg["policy_enforce"] = False
|
|
175
|
+
config.save(cfg)
|
|
176
|
+
assert policy.check_capabilities({"capabilities": ["network"]}, "body") == []
|
|
177
|
+
|
|
178
|
+
def test_detected_only_needs_strict_flag(self, sandbox):
|
|
179
|
+
# a body that *looks* like it uses the network but doesn't declare it:
|
|
180
|
+
# denied, yet only enforced when enforce_detected_capabilities is on.
|
|
181
|
+
body = "import requests\nrequests.get('https://example.com')\n"
|
|
182
|
+
set_policy(denied_capabilities=["network"],
|
|
183
|
+
enforce_detected_capabilities=False)
|
|
184
|
+
assert policy.check_capabilities({}, body) == []
|
|
185
|
+
set_policy(denied_capabilities=["network"],
|
|
186
|
+
enforce_detected_capabilities=True)
|
|
187
|
+
v = policy.check_capabilities({}, body)
|
|
188
|
+
assert v == ["looks like it uses 'network' (detected), denied by policy"]
|
|
189
|
+
|
|
190
|
+
|
|
156
191
|
class TestCheckTapSigning:
|
|
157
192
|
def test_off_by_default(self, sandbox, tmp_path):
|
|
158
193
|
clone = tmp_path / "c"
|
|
@@ -207,6 +207,19 @@ class TestAddRemove:
|
|
|
207
207
|
assert not tap.cache_file.exists()
|
|
208
208
|
assert config.get("taps") == []
|
|
209
209
|
|
|
210
|
+
def test_remove_only_drops_the_named_tap(self, sandbox):
|
|
211
|
+
# Removing one of several taps must leave the others in config. Pins the
|
|
212
|
+
# `cfg["taps"] = [t ... if t["name"] != tap.name]` rewrite and its
|
|
213
|
+
# `config.save(cfg)` — a wrong key, empty default, or save(None) would
|
|
214
|
+
# blow away the survivors instead of keeping them.
|
|
215
|
+
cfg = config.load()
|
|
216
|
+
cfg["taps"] = [{"name": "one", "url": "u1", "curated": False},
|
|
217
|
+
{"name": "two", "url": "u2", "curated": False},
|
|
218
|
+
{"name": "three", "url": "u3", "curated": False}]
|
|
219
|
+
config.save(cfg)
|
|
220
|
+
registry.remove("two")
|
|
221
|
+
assert [t["name"] for t in config.get("taps")] == ["one", "three"]
|
|
222
|
+
|
|
210
223
|
def test_remove_unknown_raises(self, sandbox):
|
|
211
224
|
with pytest.raises(BoostError):
|
|
212
225
|
registry.remove("nope")
|
|
@@ -73,6 +73,22 @@ class TestRelTime:
|
|
|
73
73
|
def test_55_days_is_seven_weeks(self):
|
|
74
74
|
assert util.rel_time(iso_ago(55 * 86400)) == "7w ago"
|
|
75
75
|
|
|
76
|
+
def test_exactly_60_seconds_rolls_to_minutes(self):
|
|
77
|
+
# the seconds bucket is `secs < 60`; at 60 it must roll to minutes.
|
|
78
|
+
# (Pins the 60 boundary literal — a 61 would keep it "60s ago".)
|
|
79
|
+
assert util.rel_time(iso_ago(60)) == "1m ago"
|
|
80
|
+
|
|
81
|
+
def test_exactly_3600_seconds_rolls_to_hours(self):
|
|
82
|
+
# the minutes bucket is `secs < 3600`; at one hour it rolls to hours.
|
|
83
|
+
# (Pins the 3600 boundary — a 3601 would say "60m ago".)
|
|
84
|
+
assert util.rel_time(iso_ago(3600)) == "1h ago"
|
|
85
|
+
|
|
86
|
+
def test_60_days_is_absolute_date_not_weeks(self):
|
|
87
|
+
# past the `secs < 604800 * 8` (eight-week) cutoff, output is a date, not
|
|
88
|
+
# "8w ago". (Pins the *8 multiplier — a *9 would extend weeks to 60 days.)
|
|
89
|
+
then = datetime.now(timezone.utc) - timedelta(days=60)
|
|
90
|
+
assert util.rel_time(then.strftime(ISO_FMT)) == then.strftime("%Y-%m-%d")
|
|
91
|
+
|
|
76
92
|
def test_100_days_is_absolute_date(self):
|
|
77
93
|
then = datetime.now(timezone.utc) - timedelta(days=100)
|
|
78
94
|
assert util.rel_time(then.strftime(ISO_FMT)) == then.strftime("%Y-%m-%d")
|
|
@@ -377,6 +393,62 @@ class TestScoreSkill:
|
|
|
377
393
|
d = make_skill(tmp_path, text)
|
|
378
394
|
assert util.score_skill(d) == (95, [])
|
|
379
395
|
|
|
396
|
+
def test_48001_chars_is_penalized(self, tmp_path):
|
|
397
|
+
# one char over the 48_000 cutoff (`> 48_000`) crosses into the penalty;
|
|
398
|
+
# pins the boundary against a `> 48_001` off-by-one.
|
|
399
|
+
base = full_text()
|
|
400
|
+
text = base + "P" * (48_001 - len(base))
|
|
401
|
+
assert len(text) == 48_001
|
|
402
|
+
d = make_skill(tmp_path, text)
|
|
403
|
+
score, notes = util.score_skill(d)
|
|
404
|
+
assert score == 85
|
|
405
|
+
assert "very large SKILL.md (>48KB) — consider splitting" in notes
|
|
406
|
+
|
|
407
|
+
def test_heading_on_a_later_line_still_counts(self, tmp_path):
|
|
408
|
+
# the heading probe uses re.MULTILINE, so a heading below the first line
|
|
409
|
+
# must still register (no "no markdown headings" note). Pins re.M — a
|
|
410
|
+
# dropped flag would only match a heading at the very start of the body.
|
|
411
|
+
body = ("Intro prose that runs on for a while so the body clears the two "
|
|
412
|
+
"hundred character minimum comfortably and then some more.\n\n"
|
|
413
|
+
"## Later Heading\n\n- a bullet keeps the examples check happy.\n")
|
|
414
|
+
d = make_skill(tmp_path, full_text(body=body))
|
|
415
|
+
_score, notes = util.score_skill(d)
|
|
416
|
+
assert "no markdown headings in body" not in notes
|
|
417
|
+
|
|
418
|
+
def test_code_fence_alone_satisfies_examples(self, tmp_path):
|
|
419
|
+
# a ``` fence with NO numbered list and NO bullet must satisfy the
|
|
420
|
+
# examples check. Pins the leading `"```" in body or ...` term (an `and`
|
|
421
|
+
# or a corrupted literal would demand a list too).
|
|
422
|
+
body = ("# Heading\n\nProse padding to exceed two hundred characters so the "
|
|
423
|
+
"length bonus applies and nothing else trips a note here today.\n\n"
|
|
424
|
+
"```bash\necho hello\n```\n")
|
|
425
|
+
d = make_skill(tmp_path, full_text(body=body))
|
|
426
|
+
_score, notes = util.score_skill(d)
|
|
427
|
+
assert "no examples, steps, or code blocks" not in notes
|
|
428
|
+
|
|
429
|
+
def test_numbered_list_below_first_line_satisfies_examples(self, tmp_path):
|
|
430
|
+
# a numbered list (not on the first line, no fence, no bullet) satisfies
|
|
431
|
+
# the examples check via re.MULTILINE. Pins the `^\d+\. ` probe + its flag.
|
|
432
|
+
body = ("# Heading\n\nSome prose padding to comfortably exceed the two "
|
|
433
|
+
"hundred character minimum for the length bonus to apply now.\n\n"
|
|
434
|
+
"1. The first and only concrete step in this body.\n")
|
|
435
|
+
d = make_skill(tmp_path, full_text(body=body))
|
|
436
|
+
_score, notes = util.score_skill(d)
|
|
437
|
+
assert "no examples, steps, or code blocks" not in notes
|
|
438
|
+
|
|
439
|
+
def test_license_file_on_disk_adds_five_over_a_plain_extra(self, tmp_path):
|
|
440
|
+
# a LICENSE *file* (not just frontmatter) earns the license +5 on top of
|
|
441
|
+
# the extras +5 any sidecar earns. Isolating vs a plain extra pins the
|
|
442
|
+
# "LICENSE" filename literal against a corrupted/renamed check.
|
|
443
|
+
# minimal bodies keep both scores well below the 100 cap so the +5 shows
|
|
444
|
+
(tmp_path / "a").mkdir()
|
|
445
|
+
(tmp_path / "b").mkdir()
|
|
446
|
+
licensed = make_skill(tmp_path / "a", "hi",
|
|
447
|
+
extra_files={"LICENSE": "MIT\n"})
|
|
448
|
+
plain = make_skill(tmp_path / "b", "hi",
|
|
449
|
+
extra_files={"notes.md": "x\n"})
|
|
450
|
+
assert util.score_skill(licensed)[0] - util.score_skill(plain)[0] == 5
|
|
451
|
+
|
|
380
452
|
|
|
381
453
|
class TestAtomicWriteText:
|
|
382
454
|
def test_writes_content(self, tmp_path):
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: finish-mutation-hardening-across-core
|
|
3
|
-
board: code
|
|
4
|
-
section: planned
|
|
5
|
-
status: planned
|
|
6
|
-
category: Testing
|
|
7
|
-
complexity: L
|
|
8
|
-
impact: Med
|
|
9
|
-
wow: 2
|
|
10
|
-
note: ~146 survivors
|
|
11
|
-
order: 1
|
|
12
|
-
owner:
|
|
13
|
-
pr:
|
|
14
|
-
title: Finish mutation hardening across <code>core/</code>
|
|
15
|
-
---
|
|
16
|
-
Work down the remaining survivor counts, biggest first: catalog (27),
|
|
17
|
-
util (26), ai (21), registry (20), lockfile (13),
|
|
18
|
-
policy (12), config (9), output (8), agents (6),
|
|
19
|
-
paths (4).
|
|
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
|
|
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
|