boost-skill-cli 1.0.374__tar.gz → 1.0.375__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.374/boost_skill_cli.egg-info → boost_skill_cli-1.0.375}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375/boost_skill_cli.egg-info}/PKG-INFO +1 -1
- boost_skill_cli-1.0.375/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +83 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap.html +44 -2
- boost_skill_cli-1.0.375/scripts/ensure_eval_corpus.sh +45 -0
- boost_skill_cli-1.0.375/scripts/eval_corpus.py +423 -0
- boost_skill_cli-1.0.375/tests/eval/taps.txt +98 -0
- boost_skill_cli-1.0.375/tests/unit/test_eval_corpus.py +461 -0
- boost_skill_cli-1.0.374/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -42
- boost_skill_cli-1.0.374/scripts/ensure_eval_corpus.sh +0 -30
- boost_skill_cli-1.0.374/scripts/eval_corpus.py +0 -142
- boost_skill_cli-1.0.374/tests/eval/taps.txt +0 -68
- boost_skill_cli-1.0.374/tests/unit/test_eval_corpus.py +0 -198
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.gitattributes +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.gitignore +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.vale.ini +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/LICENSE +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/Makefile +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/README.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/codecov.yml +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/chat.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/index.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/README.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/__init__.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/baseline.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/metrics.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/examples/README.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/index.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/noxfile.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/setup.cfg +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/sonar-project.properties +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/README.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/boost.css +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/boost.js +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/demo.html +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/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.375'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 375)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: eval-corpus-is-one-strangers-repo
|
|
3
|
+
board: code
|
|
4
|
+
section: internals
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Eval · Correctness
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: High
|
|
9
|
+
wow: 3
|
|
10
|
+
note: one third-party repo is 62% of the gate's corpus, and if it disappears every PR goes red
|
|
11
|
+
order: 84
|
|
12
|
+
owner: loop/eval-corpus-availability
|
|
13
|
+
pr: 428
|
|
14
|
+
title: 62% of the required gate's corpus is a single third-party repository
|
|
15
|
+
---
|
|
16
|
+
<b>Pinning the eval corpus to commit SHAs fixed drift. It did not fix concentration, and cannot fix
|
|
17
|
+
availability.</b> The twenty repositories in <code>tests/eval/taps.txt</code> resolve to 10,152
|
|
18
|
+
entries, wildly unevenly: <code>sickn33/antigravity-awesome-skills</code> is <b>6,309 of them
|
|
19
|
+
(62%)</b> and <code>affaan-m/ECC</code> another 1,616 (16%). Two strangers' repositories are
|
|
20
|
+
<b>78%</b> of what this project measures retrieval quality against.
|
|
21
|
+
|
|
22
|
+
<b>The failure mode is every open PR going red at once.</b>
|
|
23
|
+
<code>ensure_eval_corpus.sh</code> runs under <code>set -euo pipefail</code> and a failed clone takes
|
|
24
|
+
it with it — verified, not assumed: one unreachable repo in the list exits <b>1</b>, failing
|
|
25
|
+
CI's <code>lint</code> job, a required context. A pinned SHA does not help, because a commit still
|
|
26
|
+
has to be <em>fetchable</em>, and a repo that is deleted, renamed or made private takes its history
|
|
27
|
+
along. Not hypothetical for twenty personal repos: one was already missing from the machine that
|
|
28
|
+
measured this.
|
|
29
|
+
|
|
30
|
+
<b>It also biases the numbers while everything is up.</b> 62% of the corpus being one publisher's
|
|
31
|
+
house style is a sampling bias in every recall figure the project reports.
|
|
32
|
+
|
|
33
|
+
<b>Options, none obviously right.</b> <em>Vendor</em> the needed files into the repo — no
|
|
34
|
+
network, no third parties, but a corpus that no longer resembles a real tap. <em>Cache</em> the
|
|
35
|
+
clones in CI keyed on the taps file, so a disappearance degrades to a stale corpus rather than a red
|
|
36
|
+
gate, though a cold cache still fails. <em>Rebalance</em> so no single source exceeds some share,
|
|
37
|
+
costing corpus size and drawing an arbitrary line. <em>Fail soft</em> on N missing repos, which keeps
|
|
38
|
+
merges flowing but silently weakens the gate — the failure mode this line of work has been
|
|
39
|
+
removing. Not proposed: dropping or lowering the gate.
|
|
40
|
+
|
|
41
|
+
<b>Provenance.</b> The per-repo counts had to be printed to verify the pins in
|
|
42
|
+
[[eval-corpus-was-not-actually-pinned]]; the distribution was the surprise.
|
|
43
|
+
|
|
44
|
+
<b>Measured, and it eliminates one of the four options.</b> “Fail soft on N missing repos”
|
|
45
|
+
reads like the pragmatic choice. It is the dangerous one, because a corpus that loses a repo does not
|
|
46
|
+
get harder to pass — it gets easier. Same 91-query required set, one repo removed and everything
|
|
47
|
+
else identical: <code>all 20 → 10,152 entries, <b>0.852 / 0.473 / 0.605 / 0.657</b></code><br>
|
|
48
|
+
<code>minus sickn33 (62%) → 3,843, <b>0.885 / 0.593 / 0.711 / 0.746</b></code><br>
|
|
49
|
+
<code>minus that and ECC (78%) → 2,227, <b>0.967 / 0.659 / 0.769 / 0.814</b></code><br>
|
|
50
|
+
<code>minus LessUp (holds golden targets) → 9,682, <b>0.676 / 0.374 / 0.483 / 0.523</b></code><br>
|
|
51
|
+
<code>floors → 0.780 / 0.400 / 0.520 / 0.580</code>
|
|
52
|
+
|
|
53
|
+
So dropping a <em>scale</em> repo sails through all four floors having measured a third of the
|
|
54
|
+
intended corpus, and dropping a repo that carries golden targets fails all four in a way
|
|
55
|
+
indistinguishable from “this PR broke retrieval”. Fail-soft is unsafe in both directions.
|
|
56
|
+
The same table also kills <em>rebalancing by trimming</em>: cutting the big repo to fix the 62% would
|
|
57
|
+
inflate every published number. Diluting concentration means adding breadth, which is
|
|
58
|
+
[[eval-corpus-is-96x-smaller-than-a-real-install]]'s problem, not this one.
|
|
59
|
+
|
|
60
|
+
<b>What shipped.</b> The corpus is now <em>verifiable</em> and its unavailability
|
|
61
|
+
<em>distinguishable</em>. Each <code>taps.txt</code> row carries an entry count beside its SHA, and
|
|
62
|
+
<code>--ensure</code> refuses to leave a corpus that does not match — so the "quietly measured
|
|
63
|
+
3,843 entries" case above cannot reach the scorer. Unreachable repos exit <b>75</b> (EX_TEMPFAIL)
|
|
64
|
+
rather than 1, and every failing repo is named rather than just the first, so a third party's outage
|
|
65
|
+
stops reading as a regression here. CI restores the clones from a cache keyed on the tap list's
|
|
66
|
+
content, which is what actually stops one deleted repository reddening every open PR; only
|
|
67
|
+
third-party bytes are cached, never anything this repo derives, and there are no
|
|
68
|
+
<code>restore-keys</code> — a near-miss restore would carry taps this file no longer pins, and
|
|
69
|
+
the index is built from <em>every configured tap</em>. That last hazard is now checked directly:
|
|
70
|
+
a <code>BOOST_HOME</code> holding taps outside the list is a hard failure, which is exactly what
|
|
71
|
+
[[local-boost-install-is-not-the-eval-corpus]] walked into from the other side.
|
|
72
|
+
|
|
73
|
+
<b>A second, closer bug fell out of it.</b> The sentinel that makes a local <code>make eval</code>
|
|
74
|
+
fast was <em>empty</em> — it meant “some corpus was built here”. So editing
|
|
75
|
+
<code>taps.txt</code> (moving a pin, adding a repo) left the previous corpus in place and scored it
|
|
76
|
+
against the new file's baseline, silently, for as long as the sentinel survived. It now carries the
|
|
77
|
+
tap list's digest, so an edit is a cache miss.
|
|
78
|
+
|
|
79
|
+
<b>What did not ship, and why.</b> The 62% itself. There is no honest way to fix it by removing
|
|
80
|
+
anything, and adding breadth changes every published number and needs its own re-baselining. What is
|
|
81
|
+
enforced instead is a ratchet: <code>MAX_SHARE</code> fails the audit if any single publisher goes
|
|
82
|
+
above 65%, ~3 points over today's measured 62.1%. That stops it getting worse without pretending it
|
|
83
|
+
is fixed.
|
|
@@ -2646,8 +2646,9 @@ rank conventions. Measuring that is what exposed the name-collapse underneath it
|
|
|
2646
2646
|
</article>
|
|
2647
2647
|
|
|
2648
2648
|
<article class="cap rcard" id="eval-corpus-is-one-strangers-repo">
|
|
2649
|
-
<div class="head"><span class="pill
|
|
2649
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Eval · Correctness</span></div>
|
|
2650
2650
|
<h3>62% of the required gate's corpus is a single third-party repository</h3>
|
|
2651
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
2651
2652
|
<p><b>Pinning the eval corpus to commit SHAs fixed drift. It did not fix concentration, and cannot fix
|
|
2652
2653
|
availability.</b> The twenty repositories in <code>tests/eval/taps.txt</code> resolve to 10,152
|
|
2653
2654
|
entries, wildly unevenly: <code>sickn33/antigravity-awesome-skills</code> is <b>6,309 of them
|
|
@@ -2674,7 +2675,48 @@ merges flowing but silently weakens the gate — the failure mode this line
|
|
|
2674
2675
|
removing. Not proposed: dropping or lowering the gate.
|
|
2675
2676
|
|
|
2676
2677
|
<b>Provenance.</b> The per-repo counts had to be printed to verify the pins in
|
|
2677
|
-
[[eval-corpus-was-not-actually-pinned]]; the distribution was the surprise
|
|
2678
|
+
[[eval-corpus-was-not-actually-pinned]]; the distribution was the surprise.
|
|
2679
|
+
|
|
2680
|
+
<b>Measured, and it eliminates one of the four options.</b> “Fail soft on N missing repos”
|
|
2681
|
+
reads like the pragmatic choice. It is the dangerous one, because a corpus that loses a repo does not
|
|
2682
|
+
get harder to pass — it gets easier. Same 91-query required set, one repo removed and everything
|
|
2683
|
+
else identical: <code>all 20 → 10,152 entries, <b>0.852 / 0.473 / 0.605 / 0.657</b></code><br>
|
|
2684
|
+
<code>minus sickn33 (62%) → 3,843, <b>0.885 / 0.593 / 0.711 / 0.746</b></code><br>
|
|
2685
|
+
<code>minus that and ECC (78%) → 2,227, <b>0.967 / 0.659 / 0.769 / 0.814</b></code><br>
|
|
2686
|
+
<code>minus LessUp (holds golden targets) → 9,682, <b>0.676 / 0.374 / 0.483 / 0.523</b></code><br>
|
|
2687
|
+
<code>floors → 0.780 / 0.400 / 0.520 / 0.580</code>
|
|
2688
|
+
|
|
2689
|
+
So dropping a <em>scale</em> repo sails through all four floors having measured a third of the
|
|
2690
|
+
intended corpus, and dropping a repo that carries golden targets fails all four in a way
|
|
2691
|
+
indistinguishable from “this PR broke retrieval”. Fail-soft is unsafe in both directions.
|
|
2692
|
+
The same table also kills <em>rebalancing by trimming</em>: cutting the big repo to fix the 62% would
|
|
2693
|
+
inflate every published number. Diluting concentration means adding breadth, which is
|
|
2694
|
+
[[eval-corpus-is-96x-smaller-than-a-real-install]]'s problem, not this one.
|
|
2695
|
+
|
|
2696
|
+
<b>What shipped.</b> The corpus is now <em>verifiable</em> and its unavailability
|
|
2697
|
+
<em>distinguishable</em>. Each <code>taps.txt</code> row carries an entry count beside its SHA, and
|
|
2698
|
+
<code>--ensure</code> refuses to leave a corpus that does not match — so the "quietly measured
|
|
2699
|
+
3,843 entries" case above cannot reach the scorer. Unreachable repos exit <b>75</b> (EX_TEMPFAIL)
|
|
2700
|
+
rather than 1, and every failing repo is named rather than just the first, so a third party's outage
|
|
2701
|
+
stops reading as a regression here. CI restores the clones from a cache keyed on the tap list's
|
|
2702
|
+
content, which is what actually stops one deleted repository reddening every open PR; only
|
|
2703
|
+
third-party bytes are cached, never anything this repo derives, and there are no
|
|
2704
|
+
<code>restore-keys</code> — a near-miss restore would carry taps this file no longer pins, and
|
|
2705
|
+
the index is built from <em>every configured tap</em>. That last hazard is now checked directly:
|
|
2706
|
+
a <code>BOOST_HOME</code> holding taps outside the list is a hard failure, which is exactly what
|
|
2707
|
+
[[local-boost-install-is-not-the-eval-corpus]] walked into from the other side.
|
|
2708
|
+
|
|
2709
|
+
<b>A second, closer bug fell out of it.</b> The sentinel that makes a local <code>make eval</code>
|
|
2710
|
+
fast was <em>empty</em> — it meant “some corpus was built here”. So editing
|
|
2711
|
+
<code>taps.txt</code> (moving a pin, adding a repo) left the previous corpus in place and scored it
|
|
2712
|
+
against the new file's baseline, silently, for as long as the sentinel survived. It now carries the
|
|
2713
|
+
tap list's digest, so an edit is a cache miss.
|
|
2714
|
+
|
|
2715
|
+
<b>What did not ship, and why.</b> The 62% itself. There is no honest way to fix it by removing
|
|
2716
|
+
anything, and adding breadth changes every published number and needs its own re-baselining. What is
|
|
2717
|
+
enforced instead is a ratchet: <code>MAX_SHARE</code> fails the audit if any single publisher goes
|
|
2718
|
+
above 65%, ~3 points over today's measured 62.1%. That stops it getting worse without pretending it
|
|
2719
|
+
is fixed.</p></details>
|
|
2678
2720
|
<div class="meta">
|
|
2679
2721
|
<span class="m">Complexity <b>S</b></span>
|
|
2680
2722
|
<span class="m hi">Impact <b>High</b></span>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Tap the pinned Tier 1 eval corpus (tests/eval/taps.txt) into $BOOST_HOME so
|
|
3
|
+
# scripts/eval_retrieval.py has the repos its golden set grades against. Used by
|
|
4
|
+
# CI's lint job and by `make eval`.
|
|
5
|
+
#
|
|
6
|
+
# Idempotent: a sentinel skips re-tapping so a local `make check` stays fast (and
|
|
7
|
+
# offline) after the first run. Set FORCE=1 to re-tap; CI does, because a cached
|
|
8
|
+
# corpus must still be re-verified rather than trusted. Honors $PYTHON (defaults
|
|
9
|
+
# to python3) so make can pass its venv interpreter.
|
|
10
|
+
#
|
|
11
|
+
# THE SENTINEL CARRIES THE TAP LIST'S DIGEST, and that is not decoration. An
|
|
12
|
+
# empty sentinel said "some corpus has been built here", so editing taps.txt —
|
|
13
|
+
# moving a pin, adding a repo — left `make eval` scoring the OLD corpus against
|
|
14
|
+
# the NEW file's baseline, silently, for as long as the sentinel survived. That
|
|
15
|
+
# is the same class of bug as the unpinned list this whole area exists to fix,
|
|
16
|
+
# one directory further along. Keying on the digest makes an edit a cache miss.
|
|
17
|
+
#
|
|
18
|
+
# The tap list carries a commit SHA and an entry count per repo, and the loop
|
|
19
|
+
# that reads it lives in scripts/eval_corpus.py rather than here: the format
|
|
20
|
+
# needs parsing, the pin needs a fetch-then-checkout, and the count needs
|
|
21
|
+
# verifying — none of which a shell loop can be unit-tested on. This file keeps
|
|
22
|
+
# what it is good at, the sentinel and the environment.
|
|
23
|
+
set -euo pipefail
|
|
24
|
+
|
|
25
|
+
root=$(cd "$(dirname "$0")/.." && pwd)
|
|
26
|
+
py="${PYTHON:-python3}"
|
|
27
|
+
home="${BOOST_HOME:-$HOME/.boost}"
|
|
28
|
+
sentinel="$home/.eval-corpus-ready"
|
|
29
|
+
taps="$root/tests/eval/taps.txt"
|
|
30
|
+
|
|
31
|
+
digest=$("$py" -c 'import hashlib,sys
|
|
32
|
+
print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$taps")
|
|
33
|
+
|
|
34
|
+
if [ -z "${FORCE:-}" ] && [ -f "$sentinel" ] && [ "$(cat "$sentinel")" = "$digest" ]; then
|
|
35
|
+
echo "eval corpus already tapped for this taps.txt — skipping (FORCE=1 to re-tap)"
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
PYTHONPATH="$root" "$py" "$root/scripts/eval_corpus.py" --ensure
|
|
40
|
+
|
|
41
|
+
# Only after a clean --ensure: `set -e` means a corpus that could not be
|
|
42
|
+
# materialised, or that did not match its pinned counts, never gets a sentinel
|
|
43
|
+
# and so is never skipped on the next run.
|
|
44
|
+
mkdir -p "$home"
|
|
45
|
+
printf '%s\n' "$digest" > "$sentinel"
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Materialise the Tier 1 eval corpus at the exact commits it was measured on.
|
|
3
|
+
|
|
4
|
+
WHY THIS EXISTS. `tests/eval/taps.txt` used to pin repository NAMES. Tapping is
|
|
5
|
+
a shallow clone of whatever the default branch points at, so the corpus the
|
|
6
|
+
required `eval` gate scores against was a moving target: the list was written
|
|
7
|
+
recording **743** entries and the same 20 repos later resolved to **3,843**, a
|
|
8
|
+
5.2x growth nobody caused by editing a file. `affaan-m/ECC` alone is 1,616 of
|
|
9
|
+
them, so one third-party repository can move the gate's number by itself.
|
|
10
|
+
|
|
11
|
+
That is not academic. Measured on a clean 20-tap install, BM25 scores recall@10
|
|
12
|
+
**0.912** against a floor of **0.85** — a margin of +0.062. Unpinned growth
|
|
13
|
+
spends that margin quietly, and the first thing anyone would see is a required
|
|
14
|
+
gate failing on a pull request that touched nothing to do with retrieval.
|
|
15
|
+
|
|
16
|
+
So each row now carries a commit SHA, and this script checks each clone out at
|
|
17
|
+
it. `boost tap` still does the cloning (the corpus must be built the way a user
|
|
18
|
+
builds one); pinning is a step applied after, because the alternative — teaching
|
|
19
|
+
`boost tap` to pin — would add a CLI surface for a test-harness problem.
|
|
20
|
+
|
|
21
|
+
WHY A ROW ALSO CARRIES AN ENTRY COUNT. A SHA fixes the *tree*; it does not fix
|
|
22
|
+
what this project makes of that tree, and it does nothing at all when the tree
|
|
23
|
+
cannot be fetched. Both gaps end in the same place — the gate scoring a corpus
|
|
24
|
+
that is not the one its floors were set on — and the direction of the error is
|
|
25
|
+
the surprise. Measured over the 91-query required set, one repo removed and
|
|
26
|
+
everything else identical:
|
|
27
|
+
|
|
28
|
+
all 20 repos 10,152 entries 0.852 / 0.473 / 0.605 / 0.657
|
|
29
|
+
minus sickn33 (62%) 3,843 entries 0.885 / 0.593 / 0.711 / 0.746
|
|
30
|
+
minus that and ECC 2,227 entries 0.967 / 0.659 / 0.769 / 0.814
|
|
31
|
+
minus LessUp (targets) 9,682 entries 0.676 / 0.374 / 0.483 / 0.523
|
|
32
|
+
floors 0.780 / 0.400 / 0.520 / 0.580
|
|
33
|
+
|
|
34
|
+
Losing a *scale* repo makes the gate EASIER — all four metrics rise and the
|
|
35
|
+
check goes green having measured a third of the intended corpus. Losing a repo
|
|
36
|
+
that holds golden targets fails all four floors in a way indistinguishable from
|
|
37
|
+
"this pull request broke retrieval". So "skip whichever repos are missing today"
|
|
38
|
+
is unsafe in both directions, and the count is what makes the first case
|
|
39
|
+
detectable at all: a corpus that does not match its pins stops the run before
|
|
40
|
+
anything is scored.
|
|
41
|
+
|
|
42
|
+
WHY UNAVAILABILITY EXITS 75. `ensure_eval_corpus.sh` runs under `set -euo
|
|
43
|
+
pipefail` inside CI's `lint` job, a required context, so one deleted, renamed or
|
|
44
|
+
privatised repository reddens every open pull request at once. That is a real
|
|
45
|
+
risk for twenty personal repositories, not a hypothetical. Nothing here can keep
|
|
46
|
+
a vanished repository available — CI caches the materialised corpus for that —
|
|
47
|
+
but the failure can at least say what it is. EX_TEMPFAIL separates "a third
|
|
48
|
+
party took their repo down" from "your ranker regressed", which today arrive as
|
|
49
|
+
the same red check.
|
|
50
|
+
|
|
51
|
+
Usage:
|
|
52
|
+
python3 scripts/eval_corpus.py --ensure # tap, pin and verify every row
|
|
53
|
+
python3 scripts/eval_corpus.py --audit # static checks, no network
|
|
54
|
+
python3 scripts/eval_corpus.py --relock # re-measure the entry counts
|
|
55
|
+
python3 scripts/eval_corpus.py --list # print "repo sha count" rows
|
|
56
|
+
"""
|
|
57
|
+
from __future__ import annotations
|
|
58
|
+
|
|
59
|
+
import argparse
|
|
60
|
+
import re
|
|
61
|
+
import subprocess
|
|
62
|
+
import sys
|
|
63
|
+
from pathlib import Path
|
|
64
|
+
from typing import Dict, List, Optional, Sequence, Tuple
|
|
65
|
+
|
|
66
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
67
|
+
TAPS = ROOT / "tests" / "eval" / "taps.txt"
|
|
68
|
+
|
|
69
|
+
_SHA = re.compile(r"[0-9a-f]{40}")
|
|
70
|
+
|
|
71
|
+
#: ``(owner/repo, pinned commit or None, pinned entry count or None)``.
|
|
72
|
+
Row = Tuple[str, Optional[str], Optional[int]]
|
|
73
|
+
|
|
74
|
+
#: A repository, or the commit a row pins, could not be fetched.
|
|
75
|
+
UNAVAILABLE = "unavailable"
|
|
76
|
+
#: The repository materialised, but into a different number of entries.
|
|
77
|
+
DRIFT = "drift"
|
|
78
|
+
|
|
79
|
+
# 75 is EX_TEMPFAIL from sysexits.h, and the distinction is the point: an
|
|
80
|
+
# unreachable third-party repository is not a defect in the change under test,
|
|
81
|
+
# and it must not arrive looking like one.
|
|
82
|
+
EXIT_DRIFT = 1
|
|
83
|
+
EXIT_UNAVAILABLE = 75
|
|
84
|
+
|
|
85
|
+
# No single repository may hold more than this share of the corpus. Measured,
|
|
86
|
+
# not chosen: sickn33/antigravity-awesome-skills is 62.1% of the 10,152 entries
|
|
87
|
+
# today. So this is a ratchet against making the concentration worse — not a
|
|
88
|
+
# claim that 62% is a healthy number, which it is not. Diluting it means adding
|
|
89
|
+
# breadth, never dropping the big repo: the table above shows that dropping it
|
|
90
|
+
# raises every metric, so "rebalancing" by trimming would flatter the gate.
|
|
91
|
+
MAX_SHARE = 0.65
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class CorpusError(RuntimeError):
|
|
95
|
+
"""A corpus problem that carries which KIND of problem it is.
|
|
96
|
+
|
|
97
|
+
The kind is the whole reason this class exists. A corpus can fail to be the
|
|
98
|
+
one the floors were measured on in two unrelated ways — someone else's
|
|
99
|
+
repository went away, or the tree we did get scans into a different number
|
|
100
|
+
of entries — and only the second says anything about this project. Collapsed
|
|
101
|
+
into one exit status they are indistinguishable, which is how a third
|
|
102
|
+
party's force-push comes to look like a retrieval regression.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
def __init__(self, kind: str, repo: str, detail: str) -> None:
|
|
106
|
+
super().__init__("%s: %s" % (repo, detail))
|
|
107
|
+
self.kind = kind
|
|
108
|
+
self.repo = repo
|
|
109
|
+
self.detail = detail
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def parse_taps(text: str) -> List[Row]:
|
|
113
|
+
"""Rows of ``owner/repo [sha [count]]``, comments and blanks dropped.
|
|
114
|
+
|
|
115
|
+
An absent SHA parses as ``None`` rather than an error so the format stays
|
|
116
|
+
backward compatible, but a SHA that is *present and malformed* is fatal: a
|
|
117
|
+
typo silently degrading to "unpinned" would reintroduce the exact drift this
|
|
118
|
+
file exists to stop, while still looking pinned to a reader. A count is
|
|
119
|
+
fatal on the same grounds, and requires a SHA — a count beside an unpinned
|
|
120
|
+
repo describes a tree that is free to change underneath it.
|
|
121
|
+
"""
|
|
122
|
+
rows: List[Row] = []
|
|
123
|
+
for raw in text.splitlines():
|
|
124
|
+
line = raw.strip()
|
|
125
|
+
if not line or line.startswith("#"):
|
|
126
|
+
continue
|
|
127
|
+
parts = line.split()
|
|
128
|
+
repo = parts[0]
|
|
129
|
+
if len(parts) == 1:
|
|
130
|
+
rows.append((repo, None, None))
|
|
131
|
+
continue
|
|
132
|
+
sha = parts[1]
|
|
133
|
+
if not _SHA.fullmatch(sha):
|
|
134
|
+
raise SystemExit(
|
|
135
|
+
"tests/eval/taps.txt: %s is pinned to %r, which is not a "
|
|
136
|
+
"40-character commit SHA" % (repo, sha))
|
|
137
|
+
if len(parts) == 2:
|
|
138
|
+
rows.append((repo, sha, None))
|
|
139
|
+
continue
|
|
140
|
+
if len(parts) > 3:
|
|
141
|
+
raise SystemExit(
|
|
142
|
+
"tests/eval/taps.txt: %s has %d fields, expected at most 3 "
|
|
143
|
+
"(repo, sha, entry count)" % (repo, len(parts)))
|
|
144
|
+
count = parts[2]
|
|
145
|
+
if not count.isdigit():
|
|
146
|
+
raise SystemExit(
|
|
147
|
+
"tests/eval/taps.txt: %s records %r entries, which is not a "
|
|
148
|
+
"non-negative integer" % (repo, count))
|
|
149
|
+
rows.append((repo, sha, int(count)))
|
|
150
|
+
return rows
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def shares(rows: Sequence[Row]) -> List[Tuple[str, int, float]]:
|
|
154
|
+
"""``(repo, count, share)`` for every counted row, largest first.
|
|
155
|
+
|
|
156
|
+
Rows with no recorded count are omitted rather than treated as zero: a
|
|
157
|
+
partially counted list should report the concentration of what it knows,
|
|
158
|
+
not a share diluted by rows it cannot see.
|
|
159
|
+
"""
|
|
160
|
+
counted = [(repo, n) for repo, _sha, n in rows if n is not None]
|
|
161
|
+
total = sum(n for _repo, n in counted)
|
|
162
|
+
if not total:
|
|
163
|
+
return []
|
|
164
|
+
return sorted(((repo, n, n / total) for repo, n in counted),
|
|
165
|
+
key=lambda row: (-row[1], row[0]))
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def check_concentration(rows: Sequence[Row]) -> Optional[str]:
|
|
169
|
+
"""Return a message when one repository exceeds ``MAX_SHARE``, else ``None``.
|
|
170
|
+
|
|
171
|
+
Static — it reads the counts already in the file, so it costs no network and
|
|
172
|
+
runs anywhere. Concentration is a sampling bias in every recall figure this
|
|
173
|
+
project publishes, and the bias is invisible in a list of twenty names that
|
|
174
|
+
look equally weighted.
|
|
175
|
+
"""
|
|
176
|
+
ranked = shares(rows)
|
|
177
|
+
if not ranked:
|
|
178
|
+
return None
|
|
179
|
+
repo, count, share = ranked[0]
|
|
180
|
+
if share <= MAX_SHARE:
|
|
181
|
+
return None
|
|
182
|
+
return ("%s is %d of %d entries (%.1f%%), over the %.0f%% ceiling. The "
|
|
183
|
+
"corpus would be mostly one publisher's house style, which biases "
|
|
184
|
+
"every recall figure this project reports. Add breadth rather than "
|
|
185
|
+
"dropping the big repo: a smaller corpus scores HIGHER, so trimming "
|
|
186
|
+
"to rebalance would flatter the gate."
|
|
187
|
+
% (repo, count, sum(n for _r, n, _s in ranked), share * 100,
|
|
188
|
+
MAX_SHARE * 100))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def extra_taps(configured: Sequence[str], pinned: Sequence[str]) -> List[str]:
|
|
192
|
+
"""Configured taps that this list does not pin, sorted.
|
|
193
|
+
|
|
194
|
+
The third way to score a corpus that is not the pinned one, and the easiest
|
|
195
|
+
to walk into: the index is built from ``catalog.all_entries()``, which is
|
|
196
|
+
every configured tap, not the twenty in this file. Point BOOST_HOME at a
|
|
197
|
+
real install — 445 taps and 71,655 entries on the machine this was written
|
|
198
|
+
on — and `make eval` reports numbers for that catalogue while every comment
|
|
199
|
+
in the tree says it measured twenty repos.
|
|
200
|
+
"""
|
|
201
|
+
return sorted(set(configured) - set(pinned))
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _run(path: Path, *args: str) -> subprocess.CompletedProcess:
|
|
205
|
+
return subprocess.run(["git", "-C", str(path), *args],
|
|
206
|
+
capture_output=True, text=True)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def has_commit(path: Path, sha: str) -> bool:
|
|
210
|
+
"""True when ``sha`` names a commit already present in ``path``.
|
|
211
|
+
|
|
212
|
+
``^{commit}`` matters: `cat-file -e` succeeds for any object, so a tree or
|
|
213
|
+
blob SHA would otherwise report as present and then fail at checkout.
|
|
214
|
+
"""
|
|
215
|
+
return _run(path, "cat-file", "-e", "%s^{commit}" % sha).returncode == 0
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _fetch(path: Path, sha: str) -> subprocess.CompletedProcess:
|
|
219
|
+
# Shallow: the corpus needs the tree at one commit, not the history to it.
|
|
220
|
+
return _run(path, "fetch", "--quiet", "--depth", "1", "origin", sha)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def pin_clone(path: Path, sha: str) -> None:
|
|
224
|
+
"""Check ``path`` out at ``sha``, fetching the commit first if it is absent.
|
|
225
|
+
|
|
226
|
+
Raises ``CorpusError(UNAVAILABLE, ...)``, which is the same class of event as
|
|
227
|
+
the whole repository being gone: the tree the floors were measured on is not
|
|
228
|
+
obtainable here and now, and that is not a statement about this project.
|
|
229
|
+
"""
|
|
230
|
+
if not has_commit(path, sha):
|
|
231
|
+
_fetch(path, sha)
|
|
232
|
+
if not has_commit(path, sha):
|
|
233
|
+
raise CorpusError(
|
|
234
|
+
UNAVAILABLE, path.name,
|
|
235
|
+
"commit %s is not reachable — the pin in tests/eval/taps.txt is "
|
|
236
|
+
"stale, or the repository rewrote history" % sha)
|
|
237
|
+
res = _run(path, "checkout", "--quiet", "--detach", sha)
|
|
238
|
+
if res.returncode != 0:
|
|
239
|
+
raise CorpusError(UNAVAILABLE, path.name,
|
|
240
|
+
"could not check out %s: %s" % (sha, res.stderr.strip()))
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _materialise(rows: Sequence[Row], verify: bool = True
|
|
244
|
+
) -> Tuple[Dict[str, int], List[CorpusError]]:
|
|
245
|
+
"""Tap, pin and rescan every row. Returns ``(counts, failures)``.
|
|
246
|
+
|
|
247
|
+
Every row is attempted even after one fails. Stopping at the first would
|
|
248
|
+
report "one repository is unreachable" when five are, and the difference
|
|
249
|
+
decides whether the answer is "re-run it" or "the list needs work".
|
|
250
|
+
"""
|
|
251
|
+
sys.path.insert(0, str(ROOT))
|
|
252
|
+
from boost_cli.core import catalog, registry # deferred: repo-root import shim
|
|
253
|
+
|
|
254
|
+
counts: Dict[str, int] = {}
|
|
255
|
+
failures: List[CorpusError] = []
|
|
256
|
+
for repo, sha, want in rows:
|
|
257
|
+
try:
|
|
258
|
+
try:
|
|
259
|
+
tap = registry.get(repo)
|
|
260
|
+
except Exception: # not yet tapped; add it below
|
|
261
|
+
tap = registry.add(repo)
|
|
262
|
+
if sha:
|
|
263
|
+
pin_clone(tap.path, sha)
|
|
264
|
+
except CorpusError as exc:
|
|
265
|
+
# Re-name it: pin_clone only knows the clone directory, and the
|
|
266
|
+
# report has to say what taps.txt says so the reader can grep for it.
|
|
267
|
+
failures.append(CorpusError(exc.kind, repo, exc.detail))
|
|
268
|
+
print(" %-44s %s" % (repo, exc.detail))
|
|
269
|
+
continue
|
|
270
|
+
except Exception as exc: # any failure to obtain the tree at all
|
|
271
|
+
failures.append(CorpusError(UNAVAILABLE, repo, str(exc)))
|
|
272
|
+
print(" %-44s could not be tapped: %s" % (repo, exc))
|
|
273
|
+
continue
|
|
274
|
+
# Always after pinning: `boost tap` built the cache from the default
|
|
275
|
+
# branch, so an unrebuilt cache would describe a tree we just replaced.
|
|
276
|
+
entries = catalog.rebuild_tap(tap)
|
|
277
|
+
counts[repo] = len(entries)
|
|
278
|
+
note = ""
|
|
279
|
+
if verify and want is not None and len(entries) != want:
|
|
280
|
+
failures.append(CorpusError(
|
|
281
|
+
DRIFT, repo,
|
|
282
|
+
"taps.txt records %d entries, this tree scans into %d"
|
|
283
|
+
% (want, len(entries))))
|
|
284
|
+
note = " != %d pinned" % want
|
|
285
|
+
print(" %-44s %s %5d entries%s"
|
|
286
|
+
% (repo, (sha or "unpinned")[:7], len(entries), note))
|
|
287
|
+
|
|
288
|
+
extras = extra_taps([t.name for t in registry.list_taps()],
|
|
289
|
+
[r for r, _s, _n in rows])
|
|
290
|
+
if verify and extras:
|
|
291
|
+
failures.append(CorpusError(
|
|
292
|
+
DRIFT, "BOOST_HOME",
|
|
293
|
+
"%d tap(s) are configured here but not pinned by taps.txt, and the "
|
|
294
|
+
"index is built from ALL configured taps: %s"
|
|
295
|
+
% (len(extras), ", ".join(extras[:5])
|
|
296
|
+
+ (", ..." if len(extras) > 5 else ""))))
|
|
297
|
+
return counts, failures
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _report_failures(failures: Sequence[CorpusError], total_rows: int) -> int:
|
|
301
|
+
"""Print the failures grouped by kind and return the exit code to use."""
|
|
302
|
+
unavailable = [f for f in failures if f.kind == UNAVAILABLE]
|
|
303
|
+
drift = [f for f in failures if f.kind == DRIFT]
|
|
304
|
+
if unavailable:
|
|
305
|
+
print("\nCORPUS UNAVAILABLE — this is not a retrieval regression.")
|
|
306
|
+
print("%d of %d pinned repositories could not be materialised:"
|
|
307
|
+
% (len(unavailable), total_rows))
|
|
308
|
+
for f in unavailable:
|
|
309
|
+
print(" %s — %s" % (f.repo, f.detail))
|
|
310
|
+
print("The gate cannot run, and scoring the repos that ARE reachable is\n"
|
|
311
|
+
"not a fallback: measured, dropping the largest repo alone moves\n"
|
|
312
|
+
"BM25 recall@10 0.852 -> 0.885 and hit@1 0.473 -> 0.593, so a\n"
|
|
313
|
+
"partial corpus clears the floors MORE easily than the real one.")
|
|
314
|
+
if drift:
|
|
315
|
+
print("\nCORPUS DRIFT — what materialised is not what taps.txt pins.")
|
|
316
|
+
for f in drift:
|
|
317
|
+
print(" %s — %s" % (f.repo, f.detail))
|
|
318
|
+
print("A count mismatch means the scanner changed or a pin moved: "
|
|
319
|
+
"re-measure with\n`--relock`, then regenerate "
|
|
320
|
+
"tests/eval/baseline.json. An unpinned tap means\nBOOST_HOME is "
|
|
321
|
+
"not a corpus this file describes — point it at a scratch\n"
|
|
322
|
+
"directory (`make eval` uses ./.eval-home).")
|
|
323
|
+
# Drift wins when both happen: it is the one that says something about this
|
|
324
|
+
# repository, and it is not fixed by waiting or re-running.
|
|
325
|
+
return EXIT_DRIFT if drift else EXIT_UNAVAILABLE
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def relock_text(text: str, counts: Dict[str, int]) -> str:
|
|
329
|
+
"""Rewrite each pinned row's entry count, preserving everything else.
|
|
330
|
+
|
|
331
|
+
A whole-file rewrite would lose the header, which is where the reasoning
|
|
332
|
+
lives; this touches only rows it has a new count for. A row with no SHA is
|
|
333
|
+
left alone — a count beside an unpinned repo describes a tree free to change
|
|
334
|
+
underneath it, so it must never be written.
|
|
335
|
+
"""
|
|
336
|
+
width = max([len(r) for r in counts] or [1])
|
|
337
|
+
out = []
|
|
338
|
+
for raw in text.splitlines():
|
|
339
|
+
line = raw.strip()
|
|
340
|
+
parts = line.split()
|
|
341
|
+
if not line or line.startswith("#") or len(parts) < 2 \
|
|
342
|
+
or parts[0] not in counts or not _SHA.fullmatch(parts[1]):
|
|
343
|
+
out.append(raw)
|
|
344
|
+
continue
|
|
345
|
+
out.append("%-*s %s %5d" % (width, parts[0], parts[1], counts[parts[0]]))
|
|
346
|
+
return "\n".join(out) + ("\n" if text.endswith("\n") else "")
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def _print_concentration(rows: Sequence[Row]) -> None:
|
|
350
|
+
ranked = shares(rows)
|
|
351
|
+
if not ranked:
|
|
352
|
+
return
|
|
353
|
+
total = sum(n for _r, n, _s in ranked)
|
|
354
|
+
top = ranked[0]
|
|
355
|
+
print("corpus: %d entries across %d taps" % (total, len(ranked)))
|
|
356
|
+
line = "concentration: %s is %.1f%%" % (top[0], top[2] * 100)
|
|
357
|
+
if len(ranked) > 1:
|
|
358
|
+
line += "; top two are %.1f%%" % ((top[2] + ranked[1][2]) * 100)
|
|
359
|
+
print(line)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def _ensure(relock: bool = False) -> int:
|
|
363
|
+
rows = parse_taps(TAPS.read_text(encoding="utf-8"))
|
|
364
|
+
counts, failures = _materialise(rows, verify=not relock)
|
|
365
|
+
if failures:
|
|
366
|
+
return _report_failures(failures, len(rows))
|
|
367
|
+
if relock:
|
|
368
|
+
TAPS.write_text(relock_text(TAPS.read_text(encoding="utf-8"), counts),
|
|
369
|
+
encoding="utf-8")
|
|
370
|
+
print("relocked %d rows in tests/eval/taps.txt" % len(counts))
|
|
371
|
+
rows = parse_taps(TAPS.read_text(encoding="utf-8"))
|
|
372
|
+
_print_concentration(rows)
|
|
373
|
+
problem = check_concentration(rows)
|
|
374
|
+
if problem:
|
|
375
|
+
print("\nCORPUS CONCENTRATION — %s" % problem)
|
|
376
|
+
return EXIT_DRIFT
|
|
377
|
+
return 0
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def _audit() -> int:
|
|
381
|
+
"""Static checks over the shipped list — no network, no clones."""
|
|
382
|
+
rows = parse_taps(TAPS.read_text(encoding="utf-8"))
|
|
383
|
+
for repo, count, share in shares(rows):
|
|
384
|
+
print(" %-44s %5d entries %5.1f%%" % (repo, count, share * 100))
|
|
385
|
+
_print_concentration(rows)
|
|
386
|
+
uncounted = [r for r, _s, n in rows if n is None]
|
|
387
|
+
if uncounted:
|
|
388
|
+
print("\nuncounted rows (run --relock): %s" % ", ".join(uncounted))
|
|
389
|
+
return EXIT_DRIFT
|
|
390
|
+
problem = check_concentration(rows)
|
|
391
|
+
if problem:
|
|
392
|
+
print("\nCORPUS CONCENTRATION — %s" % problem)
|
|
393
|
+
return EXIT_DRIFT
|
|
394
|
+
return 0
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def main(argv: Optional[List[str]] = None) -> int:
|
|
398
|
+
p = argparse.ArgumentParser(prog="eval_corpus.py", description=__doc__)
|
|
399
|
+
p.add_argument("--ensure", action="store_true",
|
|
400
|
+
help="tap, pin and verify every row, then rebuild its cache")
|
|
401
|
+
p.add_argument("--relock", action="store_true",
|
|
402
|
+
help="re-measure entry counts and write them into taps.txt")
|
|
403
|
+
p.add_argument("--audit", action="store_true",
|
|
404
|
+
help="static concentration/count checks, no network")
|
|
405
|
+
p.add_argument("--list", action="store_true",
|
|
406
|
+
help="print the parsed rows and exit")
|
|
407
|
+
args = p.parse_args(argv)
|
|
408
|
+
if args.list:
|
|
409
|
+
for repo, sha, count in parse_taps(TAPS.read_text(encoding="utf-8")):
|
|
410
|
+
print("%s %s %s" % (repo, sha or "", "" if count is None else count))
|
|
411
|
+
return 0
|
|
412
|
+
if args.audit:
|
|
413
|
+
return _audit()
|
|
414
|
+
if args.relock:
|
|
415
|
+
return _ensure(relock=True)
|
|
416
|
+
if args.ensure:
|
|
417
|
+
return _ensure()
|
|
418
|
+
p.error("provide --ensure, --relock, --audit or --list")
|
|
419
|
+
return 2
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
if __name__ == "__main__":
|
|
423
|
+
raise SystemExit(main())
|