boost-skill-cli 1.0.121__tar.gz → 1.0.122__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.121 → boost_skill_cli-1.0.122}/.gitignore +3 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/CLAUDE.md +16 -2
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/Makefile +17 -8
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/discovery.py +2 -91
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/intelligence.py +1 -1
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/quality.py +1 -1
- boost_skill_cli-1.0.122/boost_cli/core/stackprobe.py +108 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_skill_cli.egg-info/SOURCES.txt +4 -0
- boost_skill_cli-1.0.122/docs/roadmap/items/single-tech-stack-prober.md +27 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap.html +14 -2
- boost_skill_cli-1.0.122/scripts/ensure_eval_corpus.sh +29 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/scripts/eval_retrieval.py +5 -2
- boost_skill_cli-1.0.122/tests/eval/baseline.json +17 -0
- boost_skill_cli-1.0.122/tests/eval/taps.txt +23 -0
- boost_skill_cli-1.0.122/tests/unit/test_stackprobe.py +115 -0
- boost_skill_cli-1.0.121/docs/roadmap/items/single-tech-stack-prober.md +0 -16
- boost_skill_cli-1.0.121/tests/eval/baseline.json +0 -17
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/.gitattributes +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/LICENSE +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/README.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/index.html +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/index.html +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/setup.cfg +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/style/README.md +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/style/boost.css +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/style/boost.js +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/style/demo.html +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.121 → boost_skill_cli-1.0.122}/tests/unit/test_version.py +0 -0
|
@@ -9,18 +9,32 @@ Package name on PyPI is `boost-skill-cli`; the command is `boost`.
|
|
|
9
9
|
Before calling any change done, run the full gate:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
make check # == lint test smoke mutation
|
|
12
|
+
make check # == lint eval test smoke mutation
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
It is
|
|
15
|
+
It is five gates and **all must pass**:
|
|
16
16
|
|
|
17
17
|
| Gate | Command | Threshold |
|
|
18
18
|
|------------|------------------------------------------------|-----------|
|
|
19
19
|
| `lint` | `ruff check boost_cli tests` + `mypy` | zero errors |
|
|
20
|
+
| `eval` | `ensure_eval_corpus.sh` + `eval_retrieval.py --build -k 10 --fail-under 0.85` | BM25 recall@k **≥ 0.85** over the pinned corpus |
|
|
20
21
|
| `test` | `pytest tests/unit tests/functional --cov` | **80%** coverage (`fail_under = 80`) |
|
|
21
22
|
| `smoke` | `bash tests/smoke.sh` | 0 failed |
|
|
22
23
|
| `mutation` | `python3 scripts/mutation_gate.py --run --min 80` | **80%** of `boost_cli/core` mutants killed |
|
|
23
24
|
|
|
25
|
+
The `eval` gate is the Tier 1 retrieval-quality check: it runs boost's RAG
|
|
26
|
+
engines over the golden set (`tests/eval/golden.jsonl`) and floors BM25
|
|
27
|
+
recall@k. The golden set grades real catalog items **by name**, so it needs a
|
|
28
|
+
corpus: `scripts/ensure_eval_corpus.sh` first taps the pinned repo list in
|
|
29
|
+
`tests/eval/taps.txt` (the minimal set covering all golden targets — `boost tap
|
|
30
|
+
--defaults` is NOT enough, it omits every rule/workflow repo). Over that corpus
|
|
31
|
+
BM25 recall is 1.000, so the 0.85 floor has wide margin; regression-vs-baseline
|
|
32
|
+
is relaxed in the gate (`--regression-eps 1`) so upstream repo drift can't flake
|
|
33
|
+
it. Edit `taps.txt` → regenerate `tests/eval/baseline.json`. It runs in CI's
|
|
34
|
+
`lint` job (pure-stdlib BM25, no `ANTHROPIC_API_KEY`; needs network to tap). The
|
|
35
|
+
opt-in Tier 2a/2b evals (`make eval-ai` / `eval-rec`) are key-gated and stay out
|
|
36
|
+
of `check`.
|
|
37
|
+
|
|
24
38
|
New/changed core logic needs tests that both cover it *and* kill mutants —
|
|
25
39
|
untested code counts as unkilled mutants, so the mutation gate fails even at 80%
|
|
26
40
|
line coverage. Target `boost_cli/core` behavior with assertions, not just imports.
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# boost — test & quality gates
|
|
2
2
|
# `make check` is the full production gate: unit + functional with >=80%
|
|
3
|
-
# coverage, the shell-level smoke suite,
|
|
3
|
+
# coverage, the shell-level smoke suite, >=80% mutation strength, and the
|
|
4
|
+
# Tier 1 retrieval-quality gate (golden-set recall@k).
|
|
4
5
|
|
|
5
|
-
VENV
|
|
6
|
-
PY
|
|
7
|
-
PYTEST
|
|
6
|
+
VENV := .venv
|
|
7
|
+
PY := $(VENV)/bin/python
|
|
8
|
+
PYTEST := $(VENV)/bin/pytest
|
|
9
|
+
# Sandboxed boost home for the Tier 1 eval corpus (gitignored) — keeps the
|
|
10
|
+
# pinned taps out of the developer's real ~/.boost.
|
|
11
|
+
EVAL_HOME := $(CURDIR)/.eval-home
|
|
8
12
|
|
|
9
13
|
.PHONY: venv test unit functional smoke coverage mutation lint check demo clean-test eval eval-ai eval-rec audit dist-check
|
|
10
14
|
|
|
@@ -54,10 +58,15 @@ dist-check:
|
|
|
54
58
|
$(VENV)/bin/check-wheel-contents dist/*.whl
|
|
55
59
|
$(VENV)/bin/pyroma --min 8 dist/*.tar.gz
|
|
56
60
|
|
|
57
|
-
# Tier 1 retrieval quality gate: golden-set recall@k over
|
|
58
|
-
#
|
|
61
|
+
# Tier 1 retrieval quality gate: golden-set recall@k over a pinned corpus
|
|
62
|
+
# (tests/eval/taps.txt). Part of `check` and required in CI (the lint job).
|
|
63
|
+
# Taps the pinned repos into a sandboxed $(EVAL_HOME) first (network on the
|
|
64
|
+
# first run; a sentinel skips re-tapping after), then floors BM25 recall@k at
|
|
65
|
+
# 0.85. Regression-vs-baseline is relaxed here (drift tolerance); the absolute
|
|
66
|
+
# floor is the gate.
|
|
59
67
|
eval:
|
|
60
|
-
|
|
68
|
+
PYTHON=$(PY) BOOST_HOME=$(EVAL_HOME) bash scripts/ensure_eval_corpus.sh
|
|
69
|
+
BOOST_HOME=$(EVAL_HOME) $(PY) scripts/eval_retrieval.py --build -k 10 --fail-under 0.85 --regression-eps 1
|
|
61
70
|
|
|
62
71
|
# Tier 2a: LLM rerank lift over BM25 on the same golden set. Opt-in and
|
|
63
72
|
# key-gated — needs the `claude` CLI on PATH or ANTHROPIC_API_KEY; skips
|
|
@@ -80,7 +89,7 @@ generate:
|
|
|
80
89
|
demo:
|
|
81
90
|
vhs docs/demo.tape
|
|
82
91
|
|
|
83
|
-
check: lint test smoke mutation
|
|
92
|
+
check: lint eval test smoke mutation
|
|
84
93
|
@echo "== all gates passed =="
|
|
85
94
|
|
|
86
95
|
clean-test:
|
|
@@ -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.122'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 122)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -7,7 +7,6 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import argparse
|
|
9
9
|
import json
|
|
10
|
-
import os
|
|
11
10
|
import re
|
|
12
11
|
import shutil
|
|
13
12
|
import subprocess
|
|
@@ -19,15 +18,10 @@ from pathlib import Path
|
|
|
19
18
|
from .. import cliparse, spin
|
|
20
19
|
from ..core import agents, ai, catalog, dense, embed, gitutil, journal, lockfile, paths, rag, registry, store, util
|
|
21
20
|
from ..core import output as out
|
|
21
|
+
from ..core.stackprobe import detect_stack # re-exported: shared with Quality
|
|
22
22
|
from ..errors import BoostError
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
"dist", "build", "target", "vendor"}
|
|
26
|
-
|
|
27
|
-
_EXT_LANGS = {".py": "python", ".ts": "typescript", ".tsx": "typescript",
|
|
28
|
-
".js": "javascript", ".jsx": "javascript", ".go": "go",
|
|
29
|
-
".rs": "rust", ".java": "java", ".rb": "ruby", ".kt": "kotlin",
|
|
30
|
-
".swift": "swift", ".php": "php", ".cs": "csharp"}
|
|
24
|
+
__all__ = ["detect_stack"]
|
|
31
25
|
|
|
32
26
|
|
|
33
27
|
def _positive_int(s: str) -> int:
|
|
@@ -44,13 +38,6 @@ def _positive_int(s: str) -> int:
|
|
|
44
38
|
_tilde = paths.tilde
|
|
45
39
|
|
|
46
40
|
|
|
47
|
-
def _read_text(p: Path) -> str:
|
|
48
|
-
try:
|
|
49
|
-
return p.read_text(encoding="utf-8", errors="replace")
|
|
50
|
-
except OSError:
|
|
51
|
-
return ""
|
|
52
|
-
|
|
53
|
-
|
|
54
41
|
def _json_array(text):
|
|
55
42
|
"""Best-effort extraction of the first JSON array in an AI reply."""
|
|
56
43
|
m = re.search(r"\[.*\]", text or "", re.S)
|
|
@@ -67,82 +54,6 @@ def _discovery_path() -> Path:
|
|
|
67
54
|
return paths.cache_dir() / "discovery.json"
|
|
68
55
|
|
|
69
56
|
|
|
70
|
-
def detect_stack(path) -> dict:
|
|
71
|
-
"""Detect a project's tech stack from files on disk.
|
|
72
|
-
|
|
73
|
-
Walks at most two directory levels (skipping .git/node_modules etc.) and
|
|
74
|
-
returns {"languages": [...], "frameworks": [...], "keywords": [...]}.
|
|
75
|
-
Shared with the Quality commands.
|
|
76
|
-
"""
|
|
77
|
-
root = Path(path)
|
|
78
|
-
langs, frameworks, extras = set(), set(), set()
|
|
79
|
-
markers: dict = {}
|
|
80
|
-
ext_counts: dict = {}
|
|
81
|
-
for dirpath, dirnames, filenames in os.walk(str(root)):
|
|
82
|
-
rel = os.path.relpath(dirpath, str(root))
|
|
83
|
-
depth = 0 if rel == "." else rel.count(os.sep) + 1
|
|
84
|
-
dirnames[:] = [] if depth >= 2 else [d for d in dirnames
|
|
85
|
-
if d not in _SKIP_DIRS]
|
|
86
|
-
for fn in filenames:
|
|
87
|
-
markers.setdefault(fn.lower(), Path(dirpath) / fn)
|
|
88
|
-
ext = os.path.splitext(fn)[1].lower()
|
|
89
|
-
if ext:
|
|
90
|
-
ext_counts[ext] = ext_counts.get(ext, 0) + 1
|
|
91
|
-
|
|
92
|
-
def read(*names) -> str:
|
|
93
|
-
return "\n".join(_read_text(markers[n]) for n in names
|
|
94
|
-
if n in markers).lower()
|
|
95
|
-
|
|
96
|
-
if "package.json" in markers:
|
|
97
|
-
langs.add("javascript")
|
|
98
|
-
try:
|
|
99
|
-
pkg = json.loads(_read_text(markers["package.json"]))
|
|
100
|
-
except json.JSONDecodeError:
|
|
101
|
-
pkg = {}
|
|
102
|
-
if not isinstance(pkg, dict):
|
|
103
|
-
pkg = {}
|
|
104
|
-
deps: set[str] = set()
|
|
105
|
-
for section in ("dependencies", "devDependencies", "peerDependencies"):
|
|
106
|
-
deps.update(pkg.get(section) or {})
|
|
107
|
-
for dep in ("react", "vue", "next", "express"):
|
|
108
|
-
if any(d == dep or d.startswith((dep + "/", "@" + dep + "/"))
|
|
109
|
-
for d in deps):
|
|
110
|
-
frameworks.add(dep)
|
|
111
|
-
if "typescript" in deps:
|
|
112
|
-
langs.add("typescript")
|
|
113
|
-
if "pyproject.toml" in markers or "requirements.txt" in markers:
|
|
114
|
-
langs.add("python")
|
|
115
|
-
blob = read("pyproject.toml", "requirements.txt")
|
|
116
|
-
for fw in ("django", "flask", "fastapi", "pytest"):
|
|
117
|
-
if fw in blob:
|
|
118
|
-
frameworks.add(fw)
|
|
119
|
-
if "go.mod" in markers:
|
|
120
|
-
langs.add("go")
|
|
121
|
-
if "cargo.toml" in markers:
|
|
122
|
-
langs.add("rust")
|
|
123
|
-
if any(n in markers for n in ("pom.xml", "build.gradle", "build.gradle.kts")):
|
|
124
|
-
langs.add("java")
|
|
125
|
-
if "spring" in read("pom.xml", "build.gradle", "build.gradle.kts"):
|
|
126
|
-
frameworks.add("spring")
|
|
127
|
-
if "gemfile" in markers:
|
|
128
|
-
langs.add("ruby")
|
|
129
|
-
if "rails" in read("gemfile"):
|
|
130
|
-
frameworks.add("rails")
|
|
131
|
-
if "tsconfig.json" in markers:
|
|
132
|
-
langs.add("typescript")
|
|
133
|
-
if "dockerfile" in markers:
|
|
134
|
-
extras.add("docker")
|
|
135
|
-
if (root / ".github" / "workflows").is_dir():
|
|
136
|
-
extras.add("ci")
|
|
137
|
-
if ext_counts.get(".tf"):
|
|
138
|
-
extras.add("terraform")
|
|
139
|
-
for ext, n in ext_counts.items():
|
|
140
|
-
if n >= 2 and ext in _EXT_LANGS:
|
|
141
|
-
langs.add(_EXT_LANGS[ext])
|
|
142
|
-
return {"languages": sorted(langs), "frameworks": sorted(frameworks),
|
|
143
|
-
"keywords": sorted(langs | frameworks | extras)}
|
|
144
|
-
|
|
145
|
-
|
|
146
57
|
def _ai_rank(query: str, scored):
|
|
147
58
|
"""Ask Claude to reorder the top hits. Returns a new scored list or None."""
|
|
148
59
|
top = scored[:15]
|
|
@@ -327,7 +327,7 @@ def _probe_repo(root: Path) -> dict:
|
|
|
327
327
|
def _stack_from_discovery(root: Path) -> Optional[Tuple[List[str], List[str]]]:
|
|
328
328
|
"""Use discovery's shared stack prober when present; normalize its shape."""
|
|
329
329
|
try:
|
|
330
|
-
from .
|
|
330
|
+
from ..core.stackprobe import detect_stack
|
|
331
331
|
result = detect_stack(root)
|
|
332
332
|
except Exception:
|
|
333
333
|
return None
|
|
@@ -185,7 +185,7 @@ def _stack_keywords(cwd: Path) -> set:
|
|
|
185
185
|
like `testing` or `git` can match even when detect_stack is language-only)."""
|
|
186
186
|
kws: List[str] = []
|
|
187
187
|
try:
|
|
188
|
-
from .
|
|
188
|
+
from ..core.stackprobe import detect_stack
|
|
189
189
|
stack = detect_stack(cwd)
|
|
190
190
|
if isinstance(stack, dict):
|
|
191
191
|
kws.extend(str(k) for k in (stack.get("keywords") or []))
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Tech-stack probing: read a project tree and name its languages/frameworks.
|
|
2
|
+
|
|
3
|
+
``detect_stack`` used to live in ``commands/discovery.py`` even though the
|
|
4
|
+
Intelligence and Quality command modules both imported it — engine logic
|
|
5
|
+
stranded in a command module, reached across the command layer. It belongs in
|
|
6
|
+
``core``: a pure, filesystem-only prober with no command dependencies, so every
|
|
7
|
+
consumer shares one implementation instead of a copy plus a fallback table.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Dict
|
|
15
|
+
|
|
16
|
+
# Directories that never describe the project's own stack — skip them so a
|
|
17
|
+
# vendored dependency can't masquerade as a first-party language.
|
|
18
|
+
_SKIP_DIRS = {".git", "node_modules", "__pycache__", ".venv", "venv",
|
|
19
|
+
"dist", "build", "target", "vendor"}
|
|
20
|
+
|
|
21
|
+
# A file extension seen ``>= 2`` times is treated as a language signal even
|
|
22
|
+
# without a manifest — enough to catch a script-only repo.
|
|
23
|
+
_EXT_LANGS = {".py": "python", ".ts": "typescript", ".tsx": "typescript",
|
|
24
|
+
".js": "javascript", ".jsx": "javascript", ".go": "go",
|
|
25
|
+
".rs": "rust", ".java": "java", ".rb": "ruby", ".kt": "kotlin",
|
|
26
|
+
".swift": "swift", ".php": "php", ".cs": "csharp"}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _read_text(p: Path) -> str:
|
|
30
|
+
try:
|
|
31
|
+
return p.read_text(encoding="utf-8", errors="replace")
|
|
32
|
+
except OSError:
|
|
33
|
+
return ""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def detect_stack(path) -> Dict[str, list]:
|
|
37
|
+
"""Detect a project's tech stack from files on disk.
|
|
38
|
+
|
|
39
|
+
Walks at most two directory levels (skipping .git/node_modules etc.) and
|
|
40
|
+
returns ``{"languages": [...], "frameworks": [...], "keywords": [...]}``.
|
|
41
|
+
"""
|
|
42
|
+
root = Path(path)
|
|
43
|
+
langs, frameworks, extras = set(), set(), set()
|
|
44
|
+
markers: dict = {}
|
|
45
|
+
ext_counts: dict = {}
|
|
46
|
+
for dirpath, dirnames, filenames in os.walk(str(root)):
|
|
47
|
+
rel = os.path.relpath(dirpath, str(root))
|
|
48
|
+
depth = 0 if rel == "." else rel.count(os.sep) + 1
|
|
49
|
+
dirnames[:] = [] if depth >= 2 else [d for d in dirnames
|
|
50
|
+
if d not in _SKIP_DIRS]
|
|
51
|
+
for fn in filenames:
|
|
52
|
+
markers.setdefault(fn.lower(), Path(dirpath) / fn)
|
|
53
|
+
ext = os.path.splitext(fn)[1].lower()
|
|
54
|
+
if ext:
|
|
55
|
+
ext_counts[ext] = ext_counts.get(ext, 0) + 1
|
|
56
|
+
|
|
57
|
+
def read(*names) -> str:
|
|
58
|
+
return "\n".join(_read_text(markers[n]) for n in names
|
|
59
|
+
if n in markers).lower()
|
|
60
|
+
|
|
61
|
+
if "package.json" in markers:
|
|
62
|
+
langs.add("javascript")
|
|
63
|
+
try:
|
|
64
|
+
pkg = json.loads(_read_text(markers["package.json"]))
|
|
65
|
+
except json.JSONDecodeError:
|
|
66
|
+
pkg = {}
|
|
67
|
+
if not isinstance(pkg, dict):
|
|
68
|
+
pkg = {}
|
|
69
|
+
deps: set = set()
|
|
70
|
+
for section in ("dependencies", "devDependencies", "peerDependencies"):
|
|
71
|
+
deps.update(pkg.get(section) or {})
|
|
72
|
+
for dep in ("react", "vue", "next", "express"):
|
|
73
|
+
if any(d == dep or d.startswith((dep + "/", "@" + dep + "/"))
|
|
74
|
+
for d in deps):
|
|
75
|
+
frameworks.add(dep)
|
|
76
|
+
if "typescript" in deps:
|
|
77
|
+
langs.add("typescript")
|
|
78
|
+
if "pyproject.toml" in markers or "requirements.txt" in markers:
|
|
79
|
+
langs.add("python")
|
|
80
|
+
blob = read("pyproject.toml", "requirements.txt")
|
|
81
|
+
for fw in ("django", "flask", "fastapi", "pytest"):
|
|
82
|
+
if fw in blob:
|
|
83
|
+
frameworks.add(fw)
|
|
84
|
+
if "go.mod" in markers:
|
|
85
|
+
langs.add("go")
|
|
86
|
+
if "cargo.toml" in markers:
|
|
87
|
+
langs.add("rust")
|
|
88
|
+
if any(n in markers for n in ("pom.xml", "build.gradle", "build.gradle.kts")):
|
|
89
|
+
langs.add("java")
|
|
90
|
+
if "spring" in read("pom.xml", "build.gradle", "build.gradle.kts"):
|
|
91
|
+
frameworks.add("spring")
|
|
92
|
+
if "gemfile" in markers:
|
|
93
|
+
langs.add("ruby")
|
|
94
|
+
if "rails" in read("gemfile"):
|
|
95
|
+
frameworks.add("rails")
|
|
96
|
+
if "tsconfig.json" in markers:
|
|
97
|
+
langs.add("typescript")
|
|
98
|
+
if "dockerfile" in markers:
|
|
99
|
+
extras.add("docker")
|
|
100
|
+
if (root / ".github" / "workflows").is_dir():
|
|
101
|
+
extras.add("ci")
|
|
102
|
+
if ext_counts.get(".tf"):
|
|
103
|
+
extras.add("terraform")
|
|
104
|
+
for ext, n in ext_counts.items():
|
|
105
|
+
if n >= 2 and ext in _EXT_LANGS:
|
|
106
|
+
langs.add(_EXT_LANGS[ext])
|
|
107
|
+
return {"languages": sorted(langs), "frameworks": sorted(frameworks),
|
|
108
|
+
"keywords": sorted(langs | frameworks | extras)}
|
|
@@ -52,6 +52,7 @@ boost_cli/core/rag.py
|
|
|
52
52
|
boost_cli/core/registry.py
|
|
53
53
|
boost_cli/core/secretscan.py
|
|
54
54
|
boost_cli/core/serve.py
|
|
55
|
+
boost_cli/core/stackprobe.py
|
|
55
56
|
boost_cli/core/staleness.py
|
|
56
57
|
boost_cli/core/store.py
|
|
57
58
|
boost_cli/core/typosquat.py
|
|
@@ -194,6 +195,7 @@ docs/roadmap/items/workflow-sast-zizmor.md
|
|
|
194
195
|
docs/roadmap/items/workspace-scope-install.md
|
|
195
196
|
scripts/build_registries.py
|
|
196
197
|
scripts/build_roadmap.py
|
|
198
|
+
scripts/ensure_eval_corpus.sh
|
|
197
199
|
scripts/eval_recommend.py
|
|
198
200
|
scripts/eval_retrieval.py
|
|
199
201
|
scripts/mutation_gate.py
|
|
@@ -207,6 +209,7 @@ tests/smoke.sh
|
|
|
207
209
|
tests/eval/baseline.json
|
|
208
210
|
tests/eval/golden.jsonl
|
|
209
211
|
tests/eval/recommend.jsonl
|
|
212
|
+
tests/eval/taps.txt
|
|
210
213
|
tests/functional/test_cli_bmad.py
|
|
211
214
|
tests/functional/test_cli_configuration.py
|
|
212
215
|
tests/functional/test_cli_discovery.py
|
|
@@ -251,6 +254,7 @@ tests/unit/test_roadmap_fresh.py
|
|
|
251
254
|
tests/unit/test_secretscan.py
|
|
252
255
|
tests/unit/test_serve.py
|
|
253
256
|
tests/unit/test_spin.py
|
|
257
|
+
tests/unit/test_stackprobe.py
|
|
254
258
|
tests/unit/test_staleness.py
|
|
255
259
|
tests/unit/test_store.py
|
|
256
260
|
tests/unit/test_token_parity.py
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: single-tech-stack-prober
|
|
3
|
+
board: code
|
|
4
|
+
section: internals
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Tech-debt
|
|
7
|
+
complexity: M
|
|
8
|
+
impact: Med
|
|
9
|
+
wow: 2
|
|
10
|
+
note: prober moved to core
|
|
11
|
+
order: 13
|
|
12
|
+
owner: loop/core-stack-prober
|
|
13
|
+
pr: 140
|
|
14
|
+
title: Single tech-stack prober
|
|
15
|
+
---
|
|
16
|
+
Shipped in <b>#140</b>. The canonical <code>detect_stack</code> prober — a
|
|
17
|
+
~75-line pure function that lived in the <b>command</b> module
|
|
18
|
+
<code>commands/discovery.py</code> yet was imported across the command layer by
|
|
19
|
+
both <code>intelligence</code> and <code>quality</code> — now lives in one place:
|
|
20
|
+
a new pure core module <code>core/stackprobe.py</code> (with its private
|
|
21
|
+
<code>_SKIP_DIRS</code>/<code>_EXT_LANGS</code>/<code>_read_text</code> helpers,
|
|
22
|
+
used nowhere else). Every consumer imports the single core prober;
|
|
23
|
+
<code>discovery</code> re-exports it for compatibility, and the now-dead helpers
|
|
24
|
+
+ unused <code>os</code> import were removed from it. Covered by 16 new
|
|
25
|
+
mutation-gated unit tests. The consumer-local enrichment fallbacks
|
|
26
|
+
(<code>_local_stack</code>, <code>_STACK_MARKERS</code>) are intentionally kept —
|
|
27
|
+
they add coarse filesystem signal the language-only prober doesn't.
|
|
@@ -603,13 +603,25 @@ message, so routing it through the helper would change user-facing errors.</p>
|
|
|
603
603
|
</article>
|
|
604
604
|
|
|
605
605
|
<article class="cap rcard">
|
|
606
|
-
<div class="head"><span class="pill
|
|
606
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Tech-debt</span></div>
|
|
607
607
|
<h3>Single tech-stack prober</h3>
|
|
608
|
-
<p>
|
|
608
|
+
<p>Shipped in <b>#140</b>. The canonical <code>detect_stack</code> prober — a
|
|
609
|
+
~75-line pure function that lived in the <b>command</b> module
|
|
610
|
+
<code>commands/discovery.py</code> yet was imported across the command layer by
|
|
611
|
+
both <code>intelligence</code> and <code>quality</code> — now lives in one place:
|
|
612
|
+
a new pure core module <code>core/stackprobe.py</code> (with its private
|
|
613
|
+
<code>_SKIP_DIRS</code>/<code>_EXT_LANGS</code>/<code>_read_text</code> helpers,
|
|
614
|
+
used nowhere else). Every consumer imports the single core prober;
|
|
615
|
+
<code>discovery</code> re-exports it for compatibility, and the now-dead helpers
|
|
616
|
+
+ unused <code>os</code> import were removed from it. Covered by 16 new
|
|
617
|
+
mutation-gated unit tests. The consumer-local enrichment fallbacks
|
|
618
|
+
(<code>_local_stack</code>, <code>_STACK_MARKERS</code>) are intentionally kept —
|
|
619
|
+
they add coarse filesystem signal the language-only prober doesn't.</p>
|
|
609
620
|
<div class="meta">
|
|
610
621
|
<span class="m">Complexity <b>M</b></span>
|
|
611
622
|
<span class="m">Impact <b>Med</b></span>
|
|
612
623
|
<span class="m">Wow <b class="wow">★★</b></span>
|
|
624
|
+
<span class="m">prober moved to core</span>
|
|
613
625
|
</div>
|
|
614
626
|
</article>
|
|
615
627
|
|
|
@@ -0,0 +1,29 @@
|
|
|
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. CI runs on a fresh $HOME and always taps. Set
|
|
8
|
+
# FORCE=1 to re-tap. Honors $PYTHON (defaults to python3) so make can pass its
|
|
9
|
+
# venv interpreter.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
root=$(cd "$(dirname "$0")/.." && pwd)
|
|
13
|
+
py="${PYTHON:-python3}"
|
|
14
|
+
home="${BOOST_HOME:-$HOME/.boost}"
|
|
15
|
+
sentinel="$home/.eval-corpus-ready"
|
|
16
|
+
|
|
17
|
+
if [ -z "${FORCE:-}" ] && [ -f "$sentinel" ]; then
|
|
18
|
+
echo "eval corpus already tapped ($sentinel) — skipping (FORCE=1 to re-tap)"
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
while IFS= read -r repo || [ -n "$repo" ]; do
|
|
23
|
+
case "$repo" in ''|\#*) continue ;; esac
|
|
24
|
+
echo "tap $repo"
|
|
25
|
+
PYTHONPATH="$root" "$py" -m boost_cli tap "$repo"
|
|
26
|
+
done < "$root/tests/eval/taps.txt"
|
|
27
|
+
|
|
28
|
+
mkdir -p "$home"
|
|
29
|
+
: > "$sentinel"
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Golden-set retrieval eval for boost's RAG engines.
|
|
3
3
|
|
|
4
|
-
Tier 1 (deterministic
|
|
5
|
-
fixed set of query -> expected-skill judgments.
|
|
4
|
+
Tier 1 (deterministic given a pinned corpus): grades the always-on retrieval
|
|
5
|
+
stack against a fixed set of query -> expected-skill judgments. The judgments
|
|
6
|
+
name real catalog items, so the corpus must contain them — CI and `make eval`
|
|
7
|
+
first tap the pinned repo list (tests/eval/taps.txt) via
|
|
8
|
+
scripts/ensure_eval_corpus.sh. It is the semantic-quality gate
|
|
6
9
|
the exact-arithmetic unit tests in tests/unit/test_rag.py cannot be — those pin
|
|
7
10
|
the math, this asks "does the right skill actually come back for a real question."
|
|
8
11
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"k": 10,
|
|
3
|
+
"engines": {
|
|
4
|
+
"catalog.search": {
|
|
5
|
+
"recall@k": 0.9651162790697675,
|
|
6
|
+
"hit@1": 0.7906976744186046,
|
|
7
|
+
"MRR": 0.8565715292459479,
|
|
8
|
+
"nDCG@k": 0.8753239696644998
|
|
9
|
+
},
|
|
10
|
+
"BM25 full-content": {
|
|
11
|
+
"recall@k": 1.0,
|
|
12
|
+
"hit@1": 0.8604651162790697,
|
|
13
|
+
"MRR": 0.9186046511627907,
|
|
14
|
+
"nDCG@k": 0.9390680511952059
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Pinned corpus for the Tier 1 retrieval-quality gate (scripts/eval_retrieval.py).
|
|
2
|
+
#
|
|
3
|
+
# The golden set (golden.jsonl) grades real catalog items by NAME, so the gate
|
|
4
|
+
# needs the repos that actually contain those items tapped before it can score.
|
|
5
|
+
# This is the minimal set of repos that covers all 44 golden targets across the
|
|
6
|
+
# skill / rule / workflow kinds. Over it, BM25 recall@10 == 1.000, so the 0.85
|
|
7
|
+
# floor gate has a wide margin and tolerates upstream drift.
|
|
8
|
+
#
|
|
9
|
+
# NOTE: `boost tap --defaults` is NOT sufficient — it taps only skill repos and
|
|
10
|
+
# scores 0.000 on every rule and workflow query (overall recall ~0.33). That is
|
|
11
|
+
# why this explicit list exists.
|
|
12
|
+
#
|
|
13
|
+
# If you edit this list, regenerate the baseline:
|
|
14
|
+
# BOOST_HOME=/tmp/evalhome bash scripts/ensure_eval_corpus.sh
|
|
15
|
+
# BOOST_HOME=/tmp/evalhome python3 scripts/eval_retrieval.py --build --save-baseline
|
|
16
|
+
#
|
|
17
|
+
# Future hardening: pin each repo to a commit SHA for full reproducibility.
|
|
18
|
+
anthropics/skills
|
|
19
|
+
0xfurai/claude-code-subagents
|
|
20
|
+
NeoLabHQ/context-engineering-kit
|
|
21
|
+
Aaronontheweb/dotnet-cursor-rules
|
|
22
|
+
ChrisWiles/claude-code-showcase
|
|
23
|
+
LessUp/awesome-cursorrules-zh
|