boost-skill-cli 1.0.78__tar.gz → 1.0.80__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.78 → boost_skill_cli-1.0.80}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/info.py +11 -10
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/catalog.py +20 -3
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/logs.py +10 -2
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/SOURCES.txt +2 -0
- boost_skill_cli-1.0.80/docs/roadmap/items/fork-safe-network-proxy-handler.md +26 -0
- boost_skill_cli-1.0.80/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +23 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/robust-tag-argument-parsing.md +3 -3
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +3 -3
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap.html +45 -4
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_info.py +24 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_catalog.py +34 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_logs.py +13 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/.gitattributes +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/.gitignore +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/LICENSE +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/Makefile +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/README.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/index.html +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/index.html +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/setup.cfg +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/style/README.md +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/style/boost.css +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/style/boost.js +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/style/demo.html +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/tests/unit/test_version.py +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
21
|
+
__version__ = version = '1.0.80'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 80)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -591,16 +591,17 @@ def cmd_tag(argv):
|
|
|
591
591
|
ap.add_argument("--json", action="store_true", help="machine-readable output")
|
|
592
592
|
ap.add_argument("name", nargs="?", help="installed skill")
|
|
593
593
|
ap.add_argument("mods", nargs="*", help="+tag to add, -tag to remove")
|
|
594
|
-
|
|
595
|
-
#
|
|
596
|
-
#
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
594
|
+
# A `-tag` removal looks like an option to argparse, which forced the old
|
|
595
|
+
# parse_known_args + argv re-walk. Instead split the literal option strings
|
|
596
|
+
# from operands ourselves: the skill name and its +tag/-tag operands keep
|
|
597
|
+
# their exact argv order with no re-walk, so `-x +x` still nets differently
|
|
598
|
+
# from `+x -x`.
|
|
599
|
+
flag_strings = {"--list", "--json", "-h", "--help"}
|
|
600
|
+
flags = [t for t in argv if t in flag_strings]
|
|
601
|
+
operands = [t for t in argv if t not in flag_strings]
|
|
602
|
+
args = ap.parse_args(flags)
|
|
603
|
+
args.name = operands[0] if operands else None
|
|
604
|
+
mods = operands[1:]
|
|
604
605
|
|
|
605
606
|
if args.list_all:
|
|
606
607
|
mapping = {}
|
|
@@ -67,10 +67,12 @@ def _description(meta: dict, body: str) -> str:
|
|
|
67
67
|
def _make_entry(root: Path, defining_file: Path, kind: str, default_name: str,
|
|
68
68
|
tap_name: str, curated: bool, meta: dict, body: str) -> dict:
|
|
69
69
|
name = str(meta.get("name") or "").strip() or default_name
|
|
70
|
+
slug = util.slugify(name) if " " in name else name
|
|
71
|
+
description = _description(meta, body)
|
|
70
72
|
item_dir = defining_file.parent
|
|
71
73
|
return {
|
|
72
|
-
"name":
|
|
73
|
-
"description":
|
|
74
|
+
"name": slug,
|
|
75
|
+
"description": description,
|
|
74
76
|
"version": str(meta.get("version") or "0.0.0"),
|
|
75
77
|
"tap": tap_name,
|
|
76
78
|
"curated": curated,
|
|
@@ -78,6 +80,9 @@ def _make_entry(root: Path, defining_file: Path, kind: str, default_name: str,
|
|
|
78
80
|
"rel_dir": str(item_dir.relative_to(root)) if item_dir != root else ".",
|
|
79
81
|
"skill_md": str(defining_file.relative_to(root)),
|
|
80
82
|
"meta": meta,
|
|
83
|
+
# Lowercased substring-search blob, flattened once at index time so
|
|
84
|
+
# search() never re-walks the frontmatter per query (see _search_blob).
|
|
85
|
+
"search_blob": _search_blob(slug, description, meta),
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
|
|
@@ -232,6 +237,13 @@ def _meta_text(meta) -> str:
|
|
|
232
237
|
return " ".join(parts).lower()
|
|
233
238
|
|
|
234
239
|
|
|
240
|
+
def _search_blob(name: str, description: str, meta) -> str:
|
|
241
|
+
"""The full lowercased substring-search text for an entry: its name,
|
|
242
|
+
description and flattened frontmatter. Built once at index time and cached
|
|
243
|
+
on the entry as ``search_blob`` so search() never rebuilds it per query."""
|
|
244
|
+
return " ".join([name.lower(), (description or "").lower(), _meta_text(meta)])
|
|
245
|
+
|
|
246
|
+
|
|
235
247
|
def search(query: str, entries: Optional[List[dict]] = None):
|
|
236
248
|
"""Rank entries against a query -> [(entry, score)] best-first."""
|
|
237
249
|
entries = all_entries() if entries is None else entries
|
|
@@ -241,7 +253,12 @@ def search(query: str, entries: Optional[List[dict]] = None):
|
|
|
241
253
|
for e in entries:
|
|
242
254
|
name = e["name"].lower()
|
|
243
255
|
desc = (e["description"] or "").lower()
|
|
244
|
-
|
|
256
|
+
# Precomputed at index time; fall back for older caches / entries
|
|
257
|
+
# constructed without a blob (e.g. tests passing raw dicts).
|
|
258
|
+
blob = e.get("search_blob")
|
|
259
|
+
if blob is None:
|
|
260
|
+
blob = _search_blob(e["name"], e.get("description", ""),
|
|
261
|
+
e.get("meta", {}))
|
|
245
262
|
score = 0
|
|
246
263
|
if q == name:
|
|
247
264
|
score += 100
|
|
@@ -170,8 +170,16 @@ def configure(verbose: bool = False, debug: bool = False,
|
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def log_invocation(argv: List[str]) -> None:
|
|
173
|
-
"""Record a command invocation at the head of the trail.
|
|
174
|
-
|
|
173
|
+
"""Record a command invocation at the head of the trail.
|
|
174
|
+
|
|
175
|
+
Includes ``pid``/``ppid`` and the interpreter path so a *native* crash —
|
|
176
|
+
which Python can't catch, so it never reaches :func:`write_crash_report` —
|
|
177
|
+
can still be correlated against an OS crash report by PID. If an OS report
|
|
178
|
+
names a PID that never appears here, boost is ruled out as that process.
|
|
179
|
+
"""
|
|
180
|
+
get_logger().info(
|
|
181
|
+
"invoke: boost %s [pid=%d ppid=%d py=%s]",
|
|
182
|
+
" ".join(argv), os.getpid(), os.getppid(), sys.executable)
|
|
175
183
|
|
|
176
184
|
|
|
177
185
|
def log_completion(argv: List[str], rc: int, elapsed_ms: float) -> None:
|
|
@@ -115,11 +115,13 @@ docs/roadmap/items/extension-free-tests-core-dense-py.md
|
|
|
115
115
|
docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md
|
|
116
116
|
docs/roadmap/items/finish-mutation-hardening-across-core.md
|
|
117
117
|
docs/roadmap/items/fix-self-update-version-detection-dead-branch.md
|
|
118
|
+
docs/roadmap/items/fork-safe-network-proxy-handler.md
|
|
118
119
|
docs/roadmap/items/frontmatter-scalar-over-coercion.md
|
|
119
120
|
docs/roadmap/items/github-pages-deploy-is-broken-every-push.md
|
|
120
121
|
docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md
|
|
121
122
|
docs/roadmap/items/html-validation-html-validate.md
|
|
122
123
|
docs/roadmap/items/integrity-verification-boost-verify.md
|
|
124
|
+
docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md
|
|
123
125
|
docs/roadmap/items/layering-guard-import-linter.md
|
|
124
126
|
docs/roadmap/items/lighthouse-ci-on-the-pages-site.md
|
|
125
127
|
docs/roadmap/items/localize-the-stored-bm25-snippet.md
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: fork-safe-network-proxy-handler
|
|
3
|
+
board: code
|
|
4
|
+
section: health
|
|
5
|
+
status: planned
|
|
6
|
+
category: Reliability · Network
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: Med
|
|
9
|
+
wow: 3
|
|
10
|
+
note: avoid macOS _scproxy Obj-C path
|
|
11
|
+
order: 9
|
|
12
|
+
owner:
|
|
13
|
+
pr:
|
|
14
|
+
title: Fork-safe network layer — explicit <code>ProxyHandler</code>
|
|
15
|
+
---
|
|
16
|
+
<code>core/ai.py</code> and <code>core/embed.py</code> call
|
|
17
|
+
<code>urllib.request.urlopen</code> with the default opener, which on
|
|
18
|
+
macOS runs <code>getproxies_macosx_sysconf()</code> →
|
|
19
|
+
<code>_scproxy</code> → SystemConfiguration/CoreFoundation — an
|
|
20
|
+
Obj-C path that is <strong>not fork-safe</strong> and aborts on the
|
|
21
|
+
child side of a <code>fork()</code>. Harmless in today's single-process
|
|
22
|
+
CLI, but fragile if boost ever runs post-fork (a future multiprocessing
|
|
23
|
+
worker, or an embedding host). Build the opener with an explicit
|
|
24
|
+
<code>ProxyHandler</code> honoring <code>HTTP(S)_PROXY</code>/<code>NO_PROXY</code>
|
|
25
|
+
so network calls never touch the Obj-C proxy machinery — deterministic
|
|
26
|
+
and fork-safe.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: invocation-pid-logging-for-crash-correlation
|
|
3
|
+
board: code
|
|
4
|
+
section: shipped
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Observability · Diagnostics
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: Med
|
|
9
|
+
wow: 3
|
|
10
|
+
note: rule boost in/out of OS crash reports
|
|
11
|
+
order: 9
|
|
12
|
+
owner:
|
|
13
|
+
pr:
|
|
14
|
+
title: Crash-correlation breadcrumbs in the invocation log
|
|
15
|
+
---
|
|
16
|
+
A native abort (e.g. a macOS Obj-C fork-safety <code>SIGABRT</code>) kills the
|
|
17
|
+
process outright, so it never reaches boost's Python crash recorder —
|
|
18
|
+
leaving no boost-side trace to confirm or clear boost when an OS crash
|
|
19
|
+
report appears. <code>log_invocation</code> now records
|
|
20
|
+
<code>pid</code>, <code>ppid</code> and the interpreter path on every
|
|
21
|
+
run, so any OS crash report can be cross-referenced by PID: if the
|
|
22
|
+
crashing PID never appears in <code>~/.boost/logs/boost.log</code>,
|
|
23
|
+
boost is definitively ruled out.
|
{boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/docs/roadmap/items/robust-tag-argument-parsing.md
RENAMED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
id: robust-tag-argument-parsing
|
|
3
3
|
board: code
|
|
4
4
|
section: internals
|
|
5
|
-
status:
|
|
5
|
+
status: shipped
|
|
6
6
|
category: Maintainability
|
|
7
7
|
complexity: M
|
|
8
8
|
impact: Med
|
|
9
9
|
wow: 2
|
|
10
10
|
note:
|
|
11
11
|
order: 16
|
|
12
|
-
owner:
|
|
13
|
-
pr:
|
|
12
|
+
owner: loop/robust-tag-parsing
|
|
13
|
+
pr: 94
|
|
14
14
|
title: Robust <code>tag</code> argument parsing
|
|
15
15
|
---
|
|
16
16
|
Because <code>-tag</code> looks like an option, <code>cmd_tag</code> calls <code>parse_known_args</code> then re-walks raw <code>argv</code> to reorder tokens (<code>info.py:575–584</code>) — fragile enough that the comment calls it "defensive". Replace with a positional-only sub-parser or an explicit <code>--add/--remove</code> design.
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
id: stop-re-serializing-entry-meta-on-every-search
|
|
3
3
|
board: code
|
|
4
4
|
section: internals
|
|
5
|
-
status:
|
|
5
|
+
status: shipped
|
|
6
6
|
category: Performance
|
|
7
7
|
complexity: S
|
|
8
8
|
impact: Med
|
|
9
9
|
wow: 2
|
|
10
10
|
note:
|
|
11
11
|
order: 11
|
|
12
|
-
owner:
|
|
13
|
-
pr:
|
|
12
|
+
owner: loop/precompute-search-blob
|
|
13
|
+
pr: 93
|
|
14
14
|
title: Stop re-serializing entry meta on every search
|
|
15
15
|
---
|
|
16
16
|
<code>catalog.search</code> computes <code>json.dumps(meta).lower()</code> for <b>every entry on every query</b> just to substring-match (<code>catalog.py:222</code>). Precompute a lowercased search blob at index time, or match structured fields directly.
|
|
@@ -115,10 +115,10 @@
|
|
|
115
115
|
<section class="block reveal">
|
|
116
116
|
<div class="stats">
|
|
117
117
|
<!-- ROADMAP:stats -->
|
|
118
|
-
<div class="stat"><b>
|
|
118
|
+
<div class="stat"><b>9</b><span>Shipped</span></div>
|
|
119
119
|
<div class="stat"><b>3</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>85</b><span>Loop finds</span></div>
|
|
122
122
|
<!-- /ROADMAP:stats -->
|
|
123
123
|
</div>
|
|
124
124
|
</section>
|
|
@@ -270,6 +270,25 @@
|
|
|
270
270
|
<span class="m">transport allow-list + -- guard</span>
|
|
271
271
|
</div>
|
|
272
272
|
</article>
|
|
273
|
+
|
|
274
|
+
<article class="cap rcard">
|
|
275
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Observability · Diagnostics</span></div>
|
|
276
|
+
<h3>Crash-correlation breadcrumbs in the invocation log</h3>
|
|
277
|
+
<p>A native abort (e.g. a macOS Obj-C fork-safety <code>SIGABRT</code>) kills the
|
|
278
|
+
process outright, so it never reaches boost's Python crash recorder —
|
|
279
|
+
leaving no boost-side trace to confirm or clear boost when an OS crash
|
|
280
|
+
report appears. <code>log_invocation</code> now records
|
|
281
|
+
<code>pid</code>, <code>ppid</code> and the interpreter path on every
|
|
282
|
+
run, so any OS crash report can be cross-referenced by PID: if the
|
|
283
|
+
crashing PID never appears in <code>~/.boost/logs/boost.log</code>,
|
|
284
|
+
boost is definitively ruled out.</p>
|
|
285
|
+
<div class="meta">
|
|
286
|
+
<span class="m">Complexity <b>S</b></span>
|
|
287
|
+
<span class="m">Impact <b>Med</b></span>
|
|
288
|
+
<span class="m">Wow <b class="wow">★★★</b></span>
|
|
289
|
+
<span class="m">rule boost in/out of OS crash reports</span>
|
|
290
|
+
</div>
|
|
291
|
+
</article>
|
|
273
292
|
<!-- /ROADMAP:cards -->
|
|
274
293
|
|
|
275
294
|
</div>
|
|
@@ -498,7 +517,7 @@
|
|
|
498
517
|
</article>
|
|
499
518
|
|
|
500
519
|
<article class="cap rcard">
|
|
501
|
-
<div class="head"><span class="pill
|
|
520
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Performance</span></div>
|
|
502
521
|
<h3>Stop re-serializing entry meta on every search</h3>
|
|
503
522
|
<p><code>catalog.search</code> computes <code>json.dumps(meta).lower()</code> for <b>every entry on every query</b> just to substring-match (<code>catalog.py:222</code>). Precompute a lowercased search blob at index time, or match structured fields directly.</p>
|
|
504
523
|
<div class="meta">
|
|
@@ -553,7 +572,7 @@
|
|
|
553
572
|
</article>
|
|
554
573
|
|
|
555
574
|
<article class="cap rcard">
|
|
556
|
-
<div class="head"><span class="pill
|
|
575
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Maintainability</span></div>
|
|
557
576
|
<h3>Robust <code>tag</code> argument parsing</h3>
|
|
558
577
|
<p>Because <code>-tag</code> looks like an option, <code>cmd_tag</code> calls <code>parse_known_args</code> then re-walks raw <code>argv</code> to reorder tokens (<code>info.py:575–584</code>) — fragile enough that the comment calls it "defensive". Replace with a positional-only sub-parser or an explicit <code>--add/--remove</code> design.</p>
|
|
559
578
|
<div class="meta">
|
|
@@ -742,6 +761,28 @@
|
|
|
742
761
|
<span class="m">stretch</span>
|
|
743
762
|
</div>
|
|
744
763
|
</article>
|
|
764
|
+
|
|
765
|
+
<article class="cap rcard">
|
|
766
|
+
<div class="head"><span class="pill planned">Planned</span><span class="cat">Reliability · Network</span></div>
|
|
767
|
+
<h3>Fork-safe network layer — explicit <code>ProxyHandler</code></h3>
|
|
768
|
+
<p><code>core/ai.py</code> and <code>core/embed.py</code> call
|
|
769
|
+
<code>urllib.request.urlopen</code> with the default opener, which on
|
|
770
|
+
macOS runs <code>getproxies_macosx_sysconf()</code> →
|
|
771
|
+
<code>_scproxy</code> → SystemConfiguration/CoreFoundation — an
|
|
772
|
+
Obj-C path that is <strong>not fork-safe</strong> and aborts on the
|
|
773
|
+
child side of a <code>fork()</code>. Harmless in today's single-process
|
|
774
|
+
CLI, but fragile if boost ever runs post-fork (a future multiprocessing
|
|
775
|
+
worker, or an embedding host). Build the opener with an explicit
|
|
776
|
+
<code>ProxyHandler</code> honoring <code>HTTP(S)_PROXY</code>/<code>NO_PROXY</code>
|
|
777
|
+
so network calls never touch the Obj-C proxy machinery — deterministic
|
|
778
|
+
and fork-safe.</p>
|
|
779
|
+
<div class="meta">
|
|
780
|
+
<span class="m">Complexity <b>S</b></span>
|
|
781
|
+
<span class="m">Impact <b>Med</b></span>
|
|
782
|
+
<span class="m">Wow <b class="wow">★★★</b></span>
|
|
783
|
+
<span class="m">avoid macOS _scproxy Obj-C path</span>
|
|
784
|
+
</div>
|
|
785
|
+
</article>
|
|
745
786
|
<!-- /ROADMAP:cards -->
|
|
746
787
|
|
|
747
788
|
</div>
|
|
@@ -330,3 +330,27 @@ class TestTag:
|
|
|
330
330
|
assert len(events) == 1
|
|
331
331
|
assert events[0]["subject"] == "brainstorming"
|
|
332
332
|
assert events[0]["tags"] == ["kept"]
|
|
333
|
+
|
|
334
|
+
def test_operand_order_preserved_add_then_remove(self, boost, installed):
|
|
335
|
+
# `+x -x` in argv order: add then remove -> nets to no tag.
|
|
336
|
+
boost("tag", "brainstorming", "+x", "-x")
|
|
337
|
+
assert _lock()["brainstorming"].get("tags", []) == []
|
|
338
|
+
|
|
339
|
+
def test_operand_order_preserved_remove_then_add(self, boost, installed):
|
|
340
|
+
# `-x +x`: remove (no-op on absent) then add -> nets to the tag present.
|
|
341
|
+
boost("tag", "brainstorming", "-x", "+x")
|
|
342
|
+
assert _lock()["brainstorming"]["tags"] == ["x"]
|
|
343
|
+
|
|
344
|
+
def test_removal_token_not_parsed_as_option(self, boost, installed):
|
|
345
|
+
# `-alpha` looks like an option but must be treated as a removal.
|
|
346
|
+
boost("tag", "brainstorming", "+alpha", "+beta")
|
|
347
|
+
r = boost("tag", "brainstorming", "-alpha")
|
|
348
|
+
assert "#beta" in r.out and "#alpha" not in r.out
|
|
349
|
+
assert _lock()["brainstorming"]["tags"] == ["beta"]
|
|
350
|
+
|
|
351
|
+
def test_list_flag_after_name_still_lists(self, boost, tapped):
|
|
352
|
+
# `--list` anywhere is a flag, not an operand.
|
|
353
|
+
boost("install", "brainstorming")
|
|
354
|
+
boost("tag", "brainstorming", "+shared")
|
|
355
|
+
r = boost("tag", "--list")
|
|
356
|
+
assert "#shared" in r.out
|
|
@@ -477,3 +477,37 @@ class TestMetaText:
|
|
|
477
477
|
def test_curated_entry_with_no_match_is_excluded(self):
|
|
478
478
|
res = catalog.search("xyzzy", entries=[_entry("unrelated", "t", curated=True)])
|
|
479
479
|
assert res == []
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
class TestSearchBlobPrecompute:
|
|
483
|
+
def test_search_blob_flattens_name_desc_meta_lowercased(self):
|
|
484
|
+
blob = catalog._search_blob(
|
|
485
|
+
"Foo-Bar", "Desc Here", {"tags": ["Alpha"], "x": "On"})
|
|
486
|
+
assert blob == "foo-bar desc here tags alpha x on"
|
|
487
|
+
|
|
488
|
+
def test_search_blob_tolerates_empty_description(self):
|
|
489
|
+
assert catalog._search_blob("name", "", {}) == "name "
|
|
490
|
+
assert catalog._search_blob("name", None, {}) == "name "
|
|
491
|
+
|
|
492
|
+
def test_make_entry_precomputes_blob(self, tmp_path):
|
|
493
|
+
f = tmp_path / "SKILL.md"
|
|
494
|
+
f.write_text("body")
|
|
495
|
+
e = catalog._make_entry(
|
|
496
|
+
tmp_path, f, "skill", "fallback-name", "tap", False,
|
|
497
|
+
{"tags": ["Kubernetes"]}, "Handles clusters")
|
|
498
|
+
assert e["search_blob"] == "fallback-name handles clusters tags kubernetes"
|
|
499
|
+
|
|
500
|
+
def test_search_reads_precomputed_blob_not_live_meta(self):
|
|
501
|
+
# Token lives only in search_blob, not in meta -> a match proves search
|
|
502
|
+
# consumed the precomputed blob rather than re-walking meta.
|
|
503
|
+
e = _entry("x", "t", meta={})
|
|
504
|
+
e["search_blob"] = "x zzsentinel"
|
|
505
|
+
res = catalog.search("zzsentinel", entries=[e])
|
|
506
|
+
assert [(m["name"], s) for m, s in res] == [("x", 2)]
|
|
507
|
+
|
|
508
|
+
def test_search_falls_back_when_blob_absent(self):
|
|
509
|
+
# Older caches / raw entries have no blob -> recompute from meta.
|
|
510
|
+
e = _entry("x", "t", meta={"tags": ["fallbackword"]})
|
|
511
|
+
assert "search_blob" not in e
|
|
512
|
+
res = catalog.search("fallbackword", entries=[e])
|
|
513
|
+
assert [(m["name"], s) for m, s in res] == [("x", 2)]
|
|
@@ -79,6 +79,19 @@ def test_invocation_is_logged(env):
|
|
|
79
79
|
assert "invoke: boost install foo" in logs.log_path().read_text()
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def test_invocation_records_pid_ppid_and_interpreter(env):
|
|
83
|
+
"""PID/PPID + interpreter are logged so a native crash can be correlated
|
|
84
|
+
against an OS crash report (and boost ruled in or out) by PID."""
|
|
85
|
+
import os
|
|
86
|
+
import sys
|
|
87
|
+
logs.configure()
|
|
88
|
+
logs.log_invocation(["mcp", "--stdio"])
|
|
89
|
+
line = logs.log_path().read_text()
|
|
90
|
+
assert ("pid=%d" % os.getpid()) in line
|
|
91
|
+
assert ("ppid=%d" % os.getppid()) in line
|
|
92
|
+
assert ("py=%s" % sys.executable) in line
|
|
93
|
+
|
|
94
|
+
|
|
82
95
|
def test_completion_logs_rc_and_duration(env):
|
|
83
96
|
logs.configure()
|
|
84
97
|
logs.log_completion(["count"], 0, 12.7)
|
|
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
|
{boost_skill_cli-1.0.78 → boost_skill_cli-1.0.80}/boost_skill_cli.egg-info/dependency_links.txt
RENAMED
|
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
|