boost-skill-cli 1.0.188__tar.gz → 1.0.190__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.190/.lighthouserc.json +29 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/scopes.py +24 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/store.py +19 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_skill_cli.egg-info/SOURCES.txt +2 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/index.html +11 -10
- boost_skill_cli-1.0.190/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +27 -0
- boost_skill_cli-1.0.190/docs/roadmap/items/project-scope-symlink-escape-on-write.md +33 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap.html +42 -6
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/style/boost.css +5 -2
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_scopes.py +38 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_store.py +25 -0
- boost_skill_cli-1.0.188/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -20
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.gitattributes +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.gitignore +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/.vale.ini +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/LICENSE +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/Makefile +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/README.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/examples/README.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/index.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/noxfile.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/setup.cfg +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/style/README.md +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/style/boost.js +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/style/demo.html +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.188 → boost_skill_cli-1.0.190}/tests/visual/visual_check.mjs +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ci": {
|
|
3
|
+
"collect": {
|
|
4
|
+
"startServerCommand": "python3 -m http.server 8099 --bind 127.0.0.1",
|
|
5
|
+
"startServerReadyPattern": "Serving HTTP",
|
|
6
|
+
"url": [
|
|
7
|
+
"http://127.0.0.1:8099/docs/index.html",
|
|
8
|
+
"http://127.0.0.1:8099/docs/roadmap.html"
|
|
9
|
+
],
|
|
10
|
+
"numberOfRuns": 3,
|
|
11
|
+
"settings": {
|
|
12
|
+
"chromeFlags": "--no-sandbox --headless=new"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"assert": {
|
|
16
|
+
"aggregationMethod": "median-run",
|
|
17
|
+
"assertions": {
|
|
18
|
+
"categories:performance": ["error", { "minScore": 0.85 }],
|
|
19
|
+
"categories:accessibility": ["error", { "minScore": 0.95 }],
|
|
20
|
+
"categories:best-practices": ["error", { "minScore": 0.9 }],
|
|
21
|
+
"categories:seo": ["error", { "minScore": 0.95 }]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"upload": {
|
|
25
|
+
"target": "filesystem",
|
|
26
|
+
"outputDir": ".lighthouseci"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -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.190'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 190)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -203,3 +203,27 @@ def contains(base, path) -> bool:
|
|
|
203
203
|
return os.path.commonpath([str(base_r), str(path_r)]) == str(base_r)
|
|
204
204
|
except (OSError, ValueError):
|
|
205
205
|
return False
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def ensure_in_base(base, path):
|
|
209
|
+
"""Raise if ``path`` would resolve outside ``base`` — the guard before any
|
|
210
|
+
project-scope WRITE, the mirror of :func:`contains` before every delete.
|
|
211
|
+
|
|
212
|
+
A project destination is built from directory names committed in the repo
|
|
213
|
+
(``.claude/skills`` and its per-agent siblings). A hostile repo can ship one
|
|
214
|
+
of those as a symlink pointing outside the tree — at ``~/.ssh``, say — and
|
|
215
|
+
the ``mkdir(parents=True)`` + ``os.replace`` that materializes a skill would
|
|
216
|
+
then run on the far side, escaping the project entirely. The squatter check
|
|
217
|
+
(refuse to overwrite a path boost did not create) does not stop this:
|
|
218
|
+
dropping a *new* name like ``authorized_keys`` collides with nothing, and
|
|
219
|
+
``--force`` waives it regardless. ``contains`` resolves symlinks on both
|
|
220
|
+
ends, so re-deriving containment here — before the write, independent of
|
|
221
|
+
existence or force — is the boundary that actually holds. Returns ``path``
|
|
222
|
+
so a caller can wrap the target inline.
|
|
223
|
+
"""
|
|
224
|
+
if not contains(base, path):
|
|
225
|
+
raise BoostError(
|
|
226
|
+
"refusing to install %s: it resolves outside this project" % path,
|
|
227
|
+
hint="a directory such as .claude/skills in this repo is a symlink "
|
|
228
|
+
"pointing outside it — remove or replace it, then reinstall")
|
|
229
|
+
return Path(path)
|
|
@@ -281,6 +281,15 @@ def _install_project_skill(entry: dict, force: bool = False,
|
|
|
281
281
|
for agent, skills_dir in agents.enabled_agents().items()
|
|
282
282
|
if not only_agents or agent in only_agents]
|
|
283
283
|
|
|
284
|
+
# Refuse to write through a symlink that leaves the repo. An agent dir like
|
|
285
|
+
# ``.claude/skills`` is committed, so a hostile clone can ship it as a
|
|
286
|
+
# symlink to ``~/.ssh`` and the copy below would land on the far side.
|
|
287
|
+
# Checked for every target up front — before existence, force, or any write
|
|
288
|
+
# — so a single escaping dir aborts the whole install rather than writing
|
|
289
|
+
# part of it outside the project first.
|
|
290
|
+
for _agent, dest in targets:
|
|
291
|
+
scopes.ensure_in_base(resolved_base, dest)
|
|
292
|
+
|
|
284
293
|
# Refuse to clobber a directory boost did not put there. In user scope the
|
|
285
294
|
# store is boost's alone, but here the destination is inside someone's repo
|
|
286
295
|
# — a same-named hand-written skill is a real possibility, and overwriting
|
|
@@ -492,6 +501,11 @@ def _install_rule(entry: dict, force: bool = False,
|
|
|
492
501
|
if only_agents and agent not in only_agents:
|
|
493
502
|
continue
|
|
494
503
|
mode, path = rules.rule_target(agent, skills_dir, name, base=resolved_base)
|
|
504
|
+
# Project scope writes into the repo, so a committed agent dir could be
|
|
505
|
+
# a symlink escaping it (see scopes.ensure_in_base). User scope writes
|
|
506
|
+
# into the user's own ~/.claude, which they control — nothing to guard.
|
|
507
|
+
if resolved_base is not None:
|
|
508
|
+
scopes.ensure_in_base(resolved_base, path)
|
|
495
509
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
496
510
|
if mode == rules.MODE_CLAUDE:
|
|
497
511
|
current = path.read_text(encoding="utf-8") if path.exists() else ""
|
|
@@ -591,6 +605,11 @@ def _install_workflow(entry: dict, force: bool = False,
|
|
|
591
605
|
if only_agents and agent not in only_agents:
|
|
592
606
|
continue
|
|
593
607
|
path = workflows.workflow_target(skills_dir, slot, name, base=resolved_base)
|
|
608
|
+
# Project scope writes into the repo; a committed agent dir could be a
|
|
609
|
+
# symlink escaping it (see scopes.ensure_in_base). User scope writes into
|
|
610
|
+
# the user's own ~/.claude, which they control — nothing to guard.
|
|
611
|
+
if resolved_base is not None:
|
|
612
|
+
scopes.ensure_in_base(resolved_base, path)
|
|
594
613
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
595
614
|
util.atomic_write_text(path, raw)
|
|
596
615
|
materializations.append({"agent": agent, "slot": slot, "path": str(path)})
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
.gitignore
|
|
3
3
|
.gitleaks.toml
|
|
4
4
|
.htmlvalidate.json
|
|
5
|
+
.lighthouserc.json
|
|
5
6
|
.lycheeignore
|
|
6
7
|
.markdownlint-cli2.jsonc
|
|
7
8
|
.pre-commit-config.yaml
|
|
@@ -184,6 +185,7 @@ docs/roadmap/items/performance-regression-gate-pytest-benchmark.md
|
|
|
184
185
|
docs/roadmap/items/post-deploy-smoke-headless-load-check.md
|
|
185
186
|
docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md
|
|
186
187
|
docs/roadmap/items/project-scope-across-every-command.md
|
|
188
|
+
docs/roadmap/items/project-scope-symlink-escape-on-write.md
|
|
187
189
|
docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md
|
|
188
190
|
docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md
|
|
189
191
|
docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<meta name="description" content="boost is a package manager for AI coding skills — find, install, and govern the SKILL.md, rule, and workflow files that Claude Code, Cursor, and Windsurf run on, wired into every agent in one pass.">
|
|
6
7
|
<title>boost — Homebrew for AI coding skills</title>
|
|
7
8
|
<!-- Canonical Aurora tokens + primitives (single source of truth). The
|
|
8
9
|
inline block below carries ONLY page-specific layout, and wins ties
|
|
@@ -184,8 +185,8 @@
|
|
|
184
185
|
font-family: var(--mono); font-size: 10.5px; font-weight: 700;
|
|
185
186
|
letter-spacing: .2em; text-transform: uppercase; color: var(--text-2);
|
|
186
187
|
}
|
|
187
|
-
.node
|
|
188
|
-
.node
|
|
188
|
+
.node h3 { font-size: 18px; font-weight: 750; margin-top: 8px; letter-spacing: -.01em; }
|
|
189
|
+
.node h3 code { font-size: 15.5px; color: var(--cyan); }
|
|
189
190
|
.node p { font-size: 13.5px; color: var(--text-2); margin-top: 6px; }
|
|
190
191
|
.node.src { border-color: rgba(96,165,250,.5); box-shadow: 0 0 32px rgba(96,165,250,.07); }
|
|
191
192
|
.node.mid { border-color: rgba(255,255,255,.14); }
|
|
@@ -473,7 +474,7 @@ facilitate structured divergent thinking:
|
|
|
473
474
|
<div class="flow-row one reveal">
|
|
474
475
|
<div class="node src">
|
|
475
476
|
<span class="tag">Source</span>
|
|
476
|
-
<
|
|
477
|
+
<h3>GitHub registries</h3>
|
|
477
478
|
<p>5 pre-tapped registries + a 10,000-skill discovery index</p>
|
|
478
479
|
</div>
|
|
479
480
|
</div>
|
|
@@ -484,12 +485,12 @@ facilitate structured divergent thinking:
|
|
|
484
485
|
<div class="flow-row two reveal">
|
|
485
486
|
<div class="node mid">
|
|
486
487
|
<span class="tag">Local Mirror</span>
|
|
487
|
-
<
|
|
488
|
+
<h3><code>~/.boost/repos/</code></h3>
|
|
488
489
|
<p>Shallow git clones</p>
|
|
489
490
|
</div>
|
|
490
491
|
<div class="node mid">
|
|
491
492
|
<span class="tag">Search Cache</span>
|
|
492
|
-
<
|
|
493
|
+
<h3><code>~/.boost/cache/</code></h3>
|
|
493
494
|
<p>JSON catalogs from SKILL.md frontmatter</p>
|
|
494
495
|
</div>
|
|
495
496
|
</div>
|
|
@@ -500,12 +501,12 @@ facilitate structured divergent thinking:
|
|
|
500
501
|
<div class="flow-row two reveal">
|
|
501
502
|
<div class="node store">
|
|
502
503
|
<span class="tag">Canonical Store</span>
|
|
503
|
-
<
|
|
504
|
+
<h3><code>~/.agents/skills/</code></h3>
|
|
504
505
|
<p>Single source of truth for installed skills</p>
|
|
505
506
|
</div>
|
|
506
507
|
<div class="node lock">
|
|
507
508
|
<span class="tag">Lock File</span>
|
|
508
|
-
<
|
|
509
|
+
<h3><code>.skill-lock.json</code></h3>
|
|
509
510
|
<p>v3 schema — pins version, commit & content hash</p>
|
|
510
511
|
</div>
|
|
511
512
|
</div>
|
|
@@ -516,17 +517,17 @@ facilitate structured divergent thinking:
|
|
|
516
517
|
<div class="flow-row three reveal">
|
|
517
518
|
<div class="node agent">
|
|
518
519
|
<span class="tag">Agent</span>
|
|
519
|
-
<
|
|
520
|
+
<h3>Claude Code</h3>
|
|
520
521
|
<p><code>~/.claude/skills/</code></p>
|
|
521
522
|
</div>
|
|
522
523
|
<div class="node agent">
|
|
523
524
|
<span class="tag">Agent</span>
|
|
524
|
-
<
|
|
525
|
+
<h3>Windsurf</h3>
|
|
525
526
|
<p><code>~/.windsurf/skills/</code></p>
|
|
526
527
|
</div>
|
|
527
528
|
<div class="node agent">
|
|
528
529
|
<span class="tag">Agent</span>
|
|
529
|
-
<
|
|
530
|
+
<h3>Cursor</h3>
|
|
530
531
|
<p><code>~/.cursor/skills/</code></p>
|
|
531
532
|
</div>
|
|
532
533
|
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: lighthouse-ci-on-the-pages-site
|
|
3
|
+
board: code
|
|
4
|
+
section: docsite
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Docs · Perf
|
|
7
|
+
complexity: M
|
|
8
|
+
impact: High
|
|
9
|
+
wow: 5
|
|
10
|
+
note: 4 budgets + 3 real a11y fixes
|
|
11
|
+
order: 2
|
|
12
|
+
owner: loop/lighthouse
|
|
13
|
+
pr: 214
|
|
14
|
+
title: Lighthouse CI on the Pages site
|
|
15
|
+
---
|
|
16
|
+
<code>treosh/lighthouse-ci-action</code> scores <code>index.html</code>
|
|
17
|
+
and <code>roadmap.html</code> on performance, accessibility,
|
|
18
|
+
best-practices and SEO on every deploy, and fails the build against
|
|
19
|
+
budgets. Turns the marketing surface's quality into four numbers that can't
|
|
20
|
+
silently regress as the Aurora theme evolves — four floors (a11y and
|
|
21
|
+
SEO 0.95, best-practices 0.90, the noisier performance 0.85) asserted
|
|
22
|
+
on the median of three runs, calibrated below the real scores with
|
|
23
|
+
margin the same way <code>perf_gate</code> sets its thresholds. And,
|
|
24
|
+
as every checker on this repo has, it found real defects on the
|
|
25
|
+
storefront: muted text at <code>3.9:1</code> contrast (below WCAG AA),
|
|
26
|
+
an <code>h2 → h4</code> heading skip, and colour-only footer links —
|
|
27
|
+
all fixed, so both pages now score <code>100</code> on accessibility.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: project-scope-symlink-escape-on-write
|
|
3
|
+
board: code
|
|
4
|
+
section: trust
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Security · Integrity
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: High
|
|
9
|
+
wow: 4
|
|
10
|
+
note: hostile repo could write outside itself
|
|
11
|
+
order: 6
|
|
12
|
+
owner: loop/writeguard
|
|
13
|
+
pr: 213
|
|
14
|
+
title: Project scope — refuse to write through an escaping symlink
|
|
15
|
+
---
|
|
16
|
+
Workspace scope (<a href="https://github.com/jonnyeclectic/boost/pull/212">#212</a>)
|
|
17
|
+
guarded the delete side — <code>uninstall --local</code> re-derives every
|
|
18
|
+
recorded path and refuses one that resolves outside the repo — but not
|
|
19
|
+
the <em>write</em> side. A project install builds its destination from
|
|
20
|
+
agent-dir names committed in the repo
|
|
21
|
+
(<code>.claude/skills</code> and its per-agent siblings), and a hostile
|
|
22
|
+
clone can ship one of those as a <strong>symlink pointing outside the
|
|
23
|
+
tree</strong> — at <code>~/.ssh</code>, say. Cloning that repo and
|
|
24
|
+
running <code>boost install <skill> --local</code> then writes on the
|
|
25
|
+
far side: confirmed by reproduction, a skill directory landed in a
|
|
26
|
+
sibling of the repo instead of inside it. The squatter check does not
|
|
27
|
+
stop it (a brand-new leaf name like <code>authorized_keys</code>
|
|
28
|
+
collides with nothing, and <code>--force</code> waives it anyway).
|
|
29
|
+
<code>scopes.ensure_in_base</code> is the write-side mirror of the
|
|
30
|
+
delete guard: it re-derives containment through symlinks for every
|
|
31
|
+
target up front, so one escaping directory aborts the whole install
|
|
32
|
+
before anything is written. Covers all three project-scope kinds —
|
|
33
|
+
skill, rule and workflow.
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
.legend .k { display: inline-flex; align-items: center; gap: 8px; }
|
|
74
74
|
|
|
75
75
|
footer { text-align: center; padding: 60px 0 48px; color: var(--text-3); font-size: 13px; }
|
|
76
|
-
footer a { color: var(--cyan); text-decoration:
|
|
76
|
+
footer a { color: var(--cyan); text-decoration: underline; }
|
|
77
77
|
|
|
78
78
|
@media (max-width: 560px) { .topbar nav { display: none; } }
|
|
79
79
|
</style>
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
<div class="stat"><b>16</b><span>Shipped</span></div>
|
|
119
119
|
<div class="stat"><b>1</b><span>Next up</span></div>
|
|
120
120
|
<div class="stat"><b>4</b><span>Planned</span></div>
|
|
121
|
-
<div class="stat"><b>
|
|
121
|
+
<div class="stat"><b>110</b><span>Loop finds</span></div>
|
|
122
122
|
<!-- /ROADMAP:stats -->
|
|
123
123
|
</div>
|
|
124
124
|
</section>
|
|
@@ -1560,18 +1560,25 @@ and the work stays visible.</p>
|
|
|
1560
1560
|
</article>
|
|
1561
1561
|
|
|
1562
1562
|
<article class="cap rcard">
|
|
1563
|
-
<div class="head"><span class="pill
|
|
1563
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Docs · Perf</span></div>
|
|
1564
1564
|
<h3>Lighthouse CI on the Pages site</h3>
|
|
1565
1565
|
<p><code>treosh/lighthouse-ci-action</code> scores <code>index.html</code>
|
|
1566
1566
|
and <code>roadmap.html</code> on performance, accessibility,
|
|
1567
1567
|
best-practices and SEO on every deploy, and fails the build against
|
|
1568
|
-
budgets. Turns the marketing surface's quality into
|
|
1569
|
-
silently regress as the Aurora theme evolves
|
|
1568
|
+
budgets. Turns the marketing surface's quality into four numbers that can't
|
|
1569
|
+
silently regress as the Aurora theme evolves — four floors (a11y and
|
|
1570
|
+
SEO 0.95, best-practices 0.90, the noisier performance 0.85) asserted
|
|
1571
|
+
on the median of three runs, calibrated below the real scores with
|
|
1572
|
+
margin the same way <code>perf_gate</code> sets its thresholds. And,
|
|
1573
|
+
as every checker on this repo has, it found real defects on the
|
|
1574
|
+
storefront: muted text at <code>3.9:1</code> contrast (below WCAG AA),
|
|
1575
|
+
an <code>h2 → h4</code> heading skip, and colour-only footer links —
|
|
1576
|
+
all fixed, so both pages now score <code>100</code> on accessibility.</p>
|
|
1570
1577
|
<div class="meta">
|
|
1571
1578
|
<span class="m">Complexity <b>M</b></span>
|
|
1572
1579
|
<span class="m hi">Impact <b>High</b></span>
|
|
1573
1580
|
<span class="m">Wow <b class="wow">★★★★★</b></span>
|
|
1574
|
-
<span class="m">4
|
|
1581
|
+
<span class="m">4 budgets + 3 real a11y fixes</span>
|
|
1575
1582
|
</div>
|
|
1576
1583
|
</article>
|
|
1577
1584
|
|
|
@@ -2082,6 +2089,35 @@ paths.</p>
|
|
|
2082
2089
|
</div>
|
|
2083
2090
|
</article>
|
|
2084
2091
|
|
|
2092
|
+
<article class="cap rcard">
|
|
2093
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Security · Integrity</span></div>
|
|
2094
|
+
<h3>Project scope — refuse to write through an escaping symlink</h3>
|
|
2095
|
+
<p>Workspace scope (<a href="https://github.com/jonnyeclectic/boost/pull/212">#212</a>)
|
|
2096
|
+
guarded the delete side — <code>uninstall --local</code> re-derives every
|
|
2097
|
+
recorded path and refuses one that resolves outside the repo — but not
|
|
2098
|
+
the <em>write</em> side. A project install builds its destination from
|
|
2099
|
+
agent-dir names committed in the repo
|
|
2100
|
+
(<code>.claude/skills</code> and its per-agent siblings), and a hostile
|
|
2101
|
+
clone can ship one of those as a <strong>symlink pointing outside the
|
|
2102
|
+
tree</strong> — at <code>~/.ssh</code>, say. Cloning that repo and
|
|
2103
|
+
running <code>boost install <skill> --local</code> then writes on the
|
|
2104
|
+
far side: confirmed by reproduction, a skill directory landed in a
|
|
2105
|
+
sibling of the repo instead of inside it. The squatter check does not
|
|
2106
|
+
stop it (a brand-new leaf name like <code>authorized_keys</code>
|
|
2107
|
+
collides with nothing, and <code>--force</code> waives it anyway).
|
|
2108
|
+
<code>scopes.ensure_in_base</code> is the write-side mirror of the
|
|
2109
|
+
delete guard: it re-derives containment through symlinks for every
|
|
2110
|
+
target up front, so one escaping directory aborts the whole install
|
|
2111
|
+
before anything is written. Covers all three project-scope kinds —
|
|
2112
|
+
skill, rule and workflow.</p>
|
|
2113
|
+
<div class="meta">
|
|
2114
|
+
<span class="m">Complexity <b>S</b></span>
|
|
2115
|
+
<span class="m hi">Impact <b>High</b></span>
|
|
2116
|
+
<span class="m">Wow <b class="wow">★★★★</b></span>
|
|
2117
|
+
<span class="m">hostile repo could write outside itself</span>
|
|
2118
|
+
</div>
|
|
2119
|
+
</article>
|
|
2120
|
+
|
|
2085
2121
|
<article class="cap rcard">
|
|
2086
2122
|
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Security · Secrets</span></div>
|
|
2087
2123
|
<h3>Secret & PII scanning of installed skills</h3>
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
--line-hi: rgb(255 255 255 / 22%);
|
|
27
27
|
--text: #e9ebf5;
|
|
28
28
|
--text-2: #9298b0;
|
|
29
|
-
--text-3: #676d86
|
|
29
|
+
--text-3: #767c96; /* muted; ≥4.5:1 on --bg (WCAG AA) — was #676d86 (3.9:1) */
|
|
30
30
|
|
|
31
31
|
/* --- the triad: the whole identity lives in these three --- */
|
|
32
32
|
--cyan: #22d3ee; /* primary accent */
|
|
@@ -385,7 +385,10 @@ footer {
|
|
|
385
385
|
border-top: 1px solid var(--line);
|
|
386
386
|
color: var(--text-3); font-size: 13px;
|
|
387
387
|
}
|
|
388
|
-
|
|
388
|
+
/* Underlined, not colour-only: a link inside footer prose must be
|
|
389
|
+
distinguishable without relying on colour (WCAG 1.4.1 / Lighthouse
|
|
390
|
+
link-in-text-block). */
|
|
391
|
+
footer a { color: var(--text-2); text-decoration: underline; }
|
|
389
392
|
footer a:hover { color: var(--text); }
|
|
390
393
|
|
|
391
394
|
@media (max-width: 720px) {
|
|
@@ -284,3 +284,41 @@ def test_contains_fails_closed_when_resolution_errors(tmp_path, monkeypatch):
|
|
|
284
284
|
|
|
285
285
|
monkeypatch.setattr(scopes, "Path", ExplodingPath)
|
|
286
286
|
assert scopes.contains(tmp_path, tmp_path / "x") is False
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
# ── ensure_in_base: the write guard ──────────────────────────────────────
|
|
290
|
+
|
|
291
|
+
def test_ensure_in_base_returns_the_path_when_inside(tmp_path):
|
|
292
|
+
dest = tmp_path / ".claude" / "skills" / "x"
|
|
293
|
+
assert scopes.ensure_in_base(tmp_path, dest) == Path(dest)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def test_ensure_in_base_raises_on_a_plain_escape(tmp_path):
|
|
297
|
+
(tmp_path / "repo").mkdir()
|
|
298
|
+
with pytest.raises(BoostError) as err:
|
|
299
|
+
scopes.ensure_in_base(tmp_path / "repo", tmp_path / "elsewhere" / "x")
|
|
300
|
+
assert "outside this project" in err.value.message
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def test_ensure_in_base_raises_when_a_symlinked_dir_escapes(tmp_path):
|
|
304
|
+
"""The write-side attack contains() is reused for: an agent dir committed as
|
|
305
|
+
a symlink pointing outside the repo, targeting a NEW leaf that does not yet
|
|
306
|
+
exist — so nothing but the containment check can catch it."""
|
|
307
|
+
repo = tmp_path / "repo"
|
|
308
|
+
(repo / ".git").mkdir(parents=True)
|
|
309
|
+
(repo / ".claude").mkdir()
|
|
310
|
+
outside = tmp_path / "outside"
|
|
311
|
+
outside.mkdir()
|
|
312
|
+
(repo / ".claude" / "skills").symlink_to(outside, target_is_directory=True)
|
|
313
|
+
# repo/.claude/skills/authorized_keys resolves to outside/authorized_keys.
|
|
314
|
+
dest = repo / ".claude" / "skills" / "authorized_keys"
|
|
315
|
+
with pytest.raises(BoostError):
|
|
316
|
+
scopes.ensure_in_base(repo, dest)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def test_ensure_in_base_allows_a_real_nested_dir(tmp_path):
|
|
320
|
+
# A legitimate project dir, even several levels deep, must pass untouched.
|
|
321
|
+
repo = tmp_path / "repo"
|
|
322
|
+
(repo / ".claude" / "skills").mkdir(parents=True)
|
|
323
|
+
dest = repo / ".claude" / "skills" / "ok"
|
|
324
|
+
assert scopes.ensure_in_base(repo, dest) == Path(dest)
|
|
@@ -860,6 +860,31 @@ class TestProjectSkills:
|
|
|
860
860
|
store.install(entry, scope="project", base=str(repo), force=True)
|
|
861
861
|
assert projectlock.get_skill(repo, "brainstorming")["installed_at"] == first
|
|
862
862
|
|
|
863
|
+
def test_symlinked_agent_dir_cannot_escape_the_repo(self, entry, tmp_path):
|
|
864
|
+
"""A committed ``.claude/skills`` symlink pointing outside the repo must
|
|
865
|
+
not let the install write on the far side.
|
|
866
|
+
|
|
867
|
+
The attack: a hostile clone ships an agent dir as a symlink to, say,
|
|
868
|
+
``~/.ssh``; ``_copy_skill`` would then ``mkdir``/``os.replace`` through
|
|
869
|
+
it and land outside the project. Guarded by ``scopes.ensure_in_base``
|
|
870
|
+
before any write. Uses a fresh skill name so the squatter check (which
|
|
871
|
+
only fires on an existing path) is not what does the blocking.
|
|
872
|
+
"""
|
|
873
|
+
repo = self._repo(tmp_path)
|
|
874
|
+
outside = tmp_path / "outside" # stands in for ~/.ssh
|
|
875
|
+
outside.mkdir()
|
|
876
|
+
(repo / ".claude").mkdir()
|
|
877
|
+
(repo / ".claude" / "skills").symlink_to(outside, target_is_directory=True)
|
|
878
|
+
|
|
879
|
+
with pytest.raises(BoostError) as err:
|
|
880
|
+
store.install(entry, scope="project", base=str(repo))
|
|
881
|
+
assert "outside this project" in err.value.message
|
|
882
|
+
# Nothing written through the symlink, and the all-or-nothing pre-check
|
|
883
|
+
# means the other agents' in-repo dirs stay untouched too.
|
|
884
|
+
assert list(outside.iterdir()) == []
|
|
885
|
+
assert not (repo / ".windsurf" / "skills" / "brainstorming").exists()
|
|
886
|
+
assert not (repo / ".cursor" / "skills" / "brainstorming").exists()
|
|
887
|
+
|
|
863
888
|
def test_policy_blocks_a_project_install_too(self, entry, tmp_path):
|
|
864
889
|
# Vendoring into a repo is not an escape hatch around policy.
|
|
865
890
|
policy.save({"blocked_skills": ["brainstorming"]})
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: lighthouse-ci-on-the-pages-site
|
|
3
|
-
board: code
|
|
4
|
-
section: docsite
|
|
5
|
-
status: planned
|
|
6
|
-
category: Docs · Perf
|
|
7
|
-
complexity: M
|
|
8
|
-
impact: High
|
|
9
|
-
wow: 5
|
|
10
|
-
note: 4 score budgets
|
|
11
|
-
order: 2
|
|
12
|
-
owner:
|
|
13
|
-
pr:
|
|
14
|
-
title: Lighthouse CI on the Pages site
|
|
15
|
-
---
|
|
16
|
-
<code>treosh/lighthouse-ci-action</code> scores <code>index.html</code>
|
|
17
|
-
and <code>roadmap.html</code> on performance, accessibility,
|
|
18
|
-
best-practices and SEO on every deploy, and fails the build against
|
|
19
|
-
budgets. Turns the marketing surface's quality into a number that can't
|
|
20
|
-
silently regress as the Aurora theme evolves.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|