ShippedPerformance
Memoize config.load() in-process
Every config.get() re-reads config.json and runs a recursive deepcopy of DEFAULTS (core/config.py:80–102). It's called all over hot paths — ai.enabled, per-skill enabled_agents in sync loops, log-level and policy checks — so one command triggers dozens of full reads + deep-copies. Cache the load, invalidate on save.
Complexity S
Impact Med-High
Wow ★★★
ShippedRobustness
Atomic skill install (temp-dir swap)
Already shipped: core/store.py's _copy_skill stages the
full copy in a temp dir on the same filesystem, then swaps it in with
two atomic os.replace renames and rolls back to the original
on any failure — the old rmtree-then-copytree window is gone. Covered by
test_copytree_failure_preserves_existing and the flaky
os.replace test in tests/unit/test_store.py.
Complexity M
Impact Med
Wow ★★★
ShippedRobustness
One shared atomic-write helper
journal._maybe_rotate is a racy read-modify-write that concurrent appends can truncate mid-line; rag._save and config.save repeat the non-atomic pattern (journal.py:63 · rag.py:252 · config.py:93). Factor a single atomic_write into core and route all four through it.
Complexity S
Impact Med
Wow ★★
ShippedCorrectness
Unify _tilde() — two copies have a boundary bug
Eight command modules each define _tilde; the quality and intelligence versions use startswith(home) with no separator check (quality.py:78), so /Users/bob-backup wrongly contracts to ~-backup. Collapse to one helper in core/paths.
Complexity S
Impact Med
Wow ★★
ShippedPerformance
Cache the catalog entry-set across RAG queries
rag.retrieve() calls all_entries(), which reads & json.loads every tap cache on every search to build the live map (rag.py:323 · catalog.py:166–181) — the BM25 index is mtime-cached, the entry set is not. Memoize the entry set on cache mtime the same way.
Complexity M
Impact Med
Wow ★★★
ShippedPerformance
Stop re-serializing entry meta on every search
catalog.search computes json.dumps(meta).lower() for every entry on every query just to substring-match (catalog.py:222). Precompute a lowercased search blob at index time, or match structured fields directly.
Complexity S
Impact Med
Wow ★★
ShippedPerformance
Prune ignored dirs during scan_dir walk
Two full rglob passes descend into .git/node_modules and only filter afterward, and the skill-dir membership test is O(files × skill_dirs) (catalog.py:106,119–123). Switch to an os.walk that prunes ignored dirs in place; index skill dirs in a set.
Complexity M
Impact Low-Med
Wow ★★
ShippedTech-debt
Single tech-stack prober
Shipped in #140. The canonical detect_stack prober — a
~75-line pure function that lived in the command module
commands/discovery.py yet was imported across the command layer by
both intelligence and quality — now lives in one place:
a new pure core module core/stackprobe.py (with its private
_SKIP_DIRS/_EXT_LANGS/_read_text helpers,
used nowhere else). Every consumer imports the single core prober;
discovery re-exports it for compatibility, and the now-dead helpers
+ unused os import were removed from it. Covered by 16 new
mutation-gated unit tests. The consumer-local enrichment fallbacks
(_local_stack, _STACK_MARKERS) are intentionally kept —
they add coarse filesystem signal the language-only prober doesn't.
Complexity M
Impact Med
Wow ★★
prober moved to core
ShippedMaintainability
Split oversized command modules
quality.py (15 cmds / 1,264 lines) mixes audit regexes, conflict NLP, decay scoring, fingerprinting, a health dashboard and tap-provenance; intelligence.py and configuration.py are similarly overloaded. Split along cohesive seams to shrink blast radius. First seam (this PR): lift the installed-skill safety & integrity commands — audit, verify, attest, quarantine — into commands/safety.py, with the two shared helpers in commands/_common.py; quality.py drops from 1,264 to ~955 lines. Tap-side trust and the health/diagnostics set stay put.
Complexity L
Impact Med
Wow ★★
ShippedMaintainability
Robust tag argument parsing
Because -tag looks like an option, cmd_tag calls parse_known_args then re-walks raw argv to reorder tokens (info.py:575–584) — fragile enough that the comment calls it "defensive". Replace with a positional-only sub-parser or an explicit --add/--remove design.
Complexity M
Impact Med
Wow ★★
ShippedTech-debt · RAG
Localize the stored BM25 snippet
_make_docs stored piece[:200] — the head of the best
chunk — and retrieve surfaced it verbatim, yet the docstrings
promised the "best-matching passage": when the matched terms sat past the
chunk's first 200 chars, the shown snippet (and the rerank context fed to the
LLM) missed them entirely. Now the index stores a larger head of the matched
chunk (SNIP_STORE) and retrieve windows a
SNIP_WIDTH-char passage centered on the first query term,
with ellipsis markers on trimmed edges (_passage). Ranking is
untouched — the eval harness confirms recall@10 holds at
0.919 — and the index grows a bounded ~34% (an
INDEX_VERSION bump forces the one-time reindex); storing whole
chunks instead cost ~70%.
Complexity M
Impact Low
Wow ★★★
query-centered snippets
ShippedCorrectness
Frontmatter scalar over-coercion
Already shipped: core/frontmatter._scalar coerces only the YAML 1.2
core keywords (true/false/null/~);
the 1.1 aliases yes/no/on/off/none stay strings, so a skill
named none or tagged on keeps the right type.
Guarded by test_scalar_leaves_yaml11_aliases_as_strings.
Complexity S
Impact Low
Wow ★★
ShippedInstall engine · Rules
Rule install — materialize rules into each agent's native format
Today store.install refuses every non-skill kind
("rules and workflows show up in boost search/boost taps
for now"), so rules are indexed for discovery but land nowhere —
there is no boost install path for a rule. Add one that
writes each rule into the form the target agent actually reads, since
there is no single cross-agent "rules folder": Cursor/Windsurf/Cline
consume a rules directory (.cursorrules /
.windsurfrules / .clinerules / .mdc),
but Claude Code has no rules folder — its standing
rules are CLAUDE.md. So installing a rule for Claude means
merging it into CLAUDE.md (a managed, idempotent block),
while for the others it means dropping the file into their rules dir.
Needs a store/lock model for rules (uninstall must cleanly remove the
merged block), mirroring how skills symlink into enabled_agents().
Complexity L
Impact High
Wow ★★★★
rules are indexed but never installed
ShippedInstall engine · Workflows
Workflow install — drop commands/subagents into each agent's native dir
After rules landed (#141), store.install still refused
kind == "workflow", so slash commands and subagents were
indexed for discovery but installed nowhere — browse could
surface a workflow but not install it. Add the install path. Unlike
rules (no cross-agent rules folder, so Claude needs a
CLAUDE.md merge), workflows are a clean file drop: a
command markdown lands in the agent's commands/ dir and a
subagent in its agents/ dir, with the slot derived from the
source path (commands//workflows/ →
commands, agents//subagents/ →
agents). Mirrors the rule store/lock model so uninstall
removes exactly what install wrote.
Complexity M
Impact High
Wow ★★★
rules install (#141); workflows were still tap-only
ShippedInstall engine · Scope
Workspace scope — boost install --local into the project
boost was user-global by construction: one store at
~/.agents/skills, symlinked into every home-level agent
dir. Right for the skills you use everywhere, wrong for the
ones a team agrees on. Shipped the npm
--save half: boost install <skill> --local
(= --scope project) writes into the repo's own
.claude/skills/, .cursor/skills/, … and
records a committable per-repo lock at
.boost/skill-lock.json. Real directories, never
symlinks — a link into the author's ~/.agents/skills
arrives dangling on a teammate's machine, which is the exact problem
committing skills is meant to solve. Two separate locks, because
~40 call sites resolve a locked skill to
~/.agents/skills/<name>, which a project skill does
not have. Scope resolution walks up for the nearest project root, so
installing from src/deep/nested lands in the repo instead
of scattering a .claude/ three levels down;
list --local, uninstall --local and
sync all understand both scopes, and sync
re-materializes what a fresh clone is missing while never deleting a
directory boost did not write.
Complexity L
Impact High
Wow ★★★★
--local, committable repo lock
ShippedInstall engine · UX
boost list shows installed rules and workflows
Rule (#141) and workflow (#150) install landed, but
boost list still read only the lock file's
skills section — so a rule or workflow installed from
browse showed up nowhere, and worse, the empty-state
("no skills installed") fired whenever no skill was
present even if rules/workflows were, hiding them entirely. Extend
list to render an installed rules and
installed workflows table (agents drawn from each item's
recorded materializations, workflows also showing their slot), gate
the empty state on all three kinds being empty, and move
--json to a {skills, rules, workflows} shape.
--tag stays skill-only.
Complexity S
Impact Med
Wow ★★
list was skill-only after rule/workflow install landed
ShippedInstall engine · Scope
Teach the rest of the CLI about project scope
Workspace scope shipped in #212
— install --local, list --local,
uninstall --local, info and
sync all understand the per-repo lock. The other ~70
commands still read the user lock alone, and an adversarial review
of that PR named the consequences: boost update and
outdated can't see a vendored skill (the workaround is
install --local --force), and the governance
commands — audit, verify,
drift, doctor, health,
fingerprint, attest — report a clean bill
of health while N third-party skills sit in the repo being loaded by
every agent on the team. That last one is the real prize: vendored
skills are exactly the ones a security review should be looking at,
because they arrive by PR and run on everyone's machine. Shipped the governance slice — the real prize — via a shared
integrity.project_skills() / project_status() pair: verify and
doctor now check project-scoped skills' committed digests the same
way they do user-scope ones, so a drifted vendored skill is flagged
instead of silently trusted.
Complexity M
Impact Med
Wow ★★
update/audit/doctor are user-scope only
ShippedInstall engine · UX
boost update refreshes installed rules and workflows
After rule (#141) and workflow (#150) install landed,
boost update still upgraded only skills — a rule or
workflow stayed frozen at its install-time content even after its tap
moved. Extend the update pass: for each installed rule/workflow from a
refreshed tap, re-materialize (force reinstall) when the source
version bumped or its file content sha changed, mirroring the skill
upgrade loop. Rules/workflows carry no pin/quarantine flags and their
source is a single file, so there is no risky-diff gate — re-applying
a file drop or a CLAUDE.md managed block is cheap and the
refresh is reported per item.
Complexity S
Impact Med
Wow ★★
update was skill-only after rule/workflow install
ShippedInstall engine · Safety
Scan and sync rules/workflows like skills
Two skill-only gaps remained after rule (#141) / workflow
(#150) install: the install-time injection + secret scan
read res.dest/SKILL.md, which doesn't exist for a
rule/workflow (a single file / merged block), so their executable
Markdown went unscanned; and boost sync only reconciled
skills, so a deleted rule/workflow materialization couldn't be
repaired. Fix both: carry the raw source on the install result
(scan_text) so injectscan/secretscan see exactly what was
installed, and extend sync_plan/sync_apply
with a missing_materializations pass that re-materializes
a rule/workflow from its tap when a drop file or CLAUDE.md block is
gone — mirroring the missing-store-dir repair for skills.
Complexity M
Impact Med
Wow ★★
close the last skill-only gaps for rules/workflows
ShippedInstall engine · UX
boost install --scope user|project for rules/workflows
Rule and workflow install always materialized into user-global agent config
(~/.claude/CLAUDE.md, ~/.cursor/rules, …), so a
rule meant for one repo leaked into every session. Add
--scope project: materialize into the current repo instead —
<repo>/.cursor/rules/, <repo>/.claude/commands|agents/,
and, since Claude reads per-repo memory from the root and has no rules
folder, <repo>/CLAUDE.local.md (the personal, git-ignored
file). The chosen scope + base dir are recorded in the lock so
update/sync re-materialize back into the same
repo rather than wherever they happen to run. Default stays
--scope user (unchanged behavior). Uninstall already reverses
by recorded path, so it works for either scope.
Complexity M
Impact High
Wow ★★★
rules/workflows were user-global only
PlannedBug
Ambiguous tap short-name resolution silently picks the wrong tap
registry.get(name) matches on full name, safe-name, or trailing path segment and returns
the first hit with no ambiguity check — unlike catalog.resolve_one, which
explicitly errors on a multi-tap ambiguous match. Three of the five default taps end in
/skills, so after boost tap --defaults, boost untap skills or
boost update skills silently resolves to whichever tap sorts first and the others
become unreachable by short name. Raise on an ambiguous short-name match, mirroring
resolve_one.
Complexity S
Impact High
Wow ★★★
PlannedBug
sync --apply deletes any broken symlink, not just boost's own
sync_plan flags every broken symlink under an enabled agent dir as stale regardless of
whether it points into boost's store — the points_into_store check only runs on the
live-link branch — and sync_apply unconditionally unlinks everything in
stale_links. A user's own unrelated broken symlink sitting in
~/.claude/skills gets deleted by boost sync --apply with no ownership
check. Only treat a broken symlink as boost-managed if its raw readlink() target
resolves under the store dir.
Complexity S
Impact Med
Wow ★★
PlannedBug
Dense search's empty result skips the BM25 fallback
_retrieve_any treats any non-None dense result as final, but
dense.retrieve() returns [] (not None) whenever every KNN
neighbor gets filtered by kind mismatch or staleness — silently short-circuiting the documented
"everything degrades to BM25" contract. Compounding it, dense.build()'s incremental
path only prunes chunks for taps still present in the current entry set, so a tap removed via
boost tap remove leaves ghost vectors in rag_vectors.sqlite forever,
crowding the KNN pool on every future query. Distinguish "dense unavailable" from "dense had zero
live hits," and prune removed taps on every build, not just changed ones.
Complexity M
Impact Med
Wow ★★
PlannedConcurrency · Bug
Journal rotation has a lost-update race between concurrent processes
_maybe_rotate reads the whole pulse file and atomically replaces it with a truncated
snapshot — but two concurrent boost processes (explicitly expected per this repo's parallel-loop
model) can both read, then both write their own snapshot, and whichever writes last silently
discards any event the other appended in between. rotation_healthy() also opens the
file with a bare p.open() and never closes it, relying on GC instead of a
with block like every other open in the module. Rotate under a lock (or an
append-only rename scheme), and close the handle explicitly.
Complexity M
Impact Med
Wow ★★
PlannedUX · Bug
boost uninstall has no confirmation prompt
boost uninstall deletes a skill's store directory and lock entry straight through
shutil.rmtree() with zero confirmation — every other destructive command
(snapshot restore, cohort delete, profile delete,
untap, replay rollback, bmad uninstall) gates on
out.confirm() first. Add the same out.confirm() (bypassable via the
existing BOOST_ASSUME_YES/--yes convention) before the rmtree.
Complexity S
Impact High
Wow ★★★
PlannedBug
update/reinstall silently widen a skill's agent scope
A skill installed with --agent narrowing (e.g. boost install foo --agent
claude-code) records that subset in the lock, but boost update/
boost reinstall force-reinstall via store.install(entry, force=True)
without passing only_agents — so link_agents relinks into every currently
enabled agent and silently overwrites the lock's narrower agent list. Pass
only_agents=lk.get("agents") on both force-reinstall paths, matching what the
rule/workflow update path already does for scope.
Complexity S
Impact Med
Wow ★★
PlannedBug
lint --tap mis-scores rule/workflow entries as broken
boost lint --tap builds its target list without filtering by kind, so rule/workflow
catalog entries (which have no SKILL.md) always report "missing SKILL.md," and
repo-root items get scored against the entire tap directory instead of their actual file. Running
it against any tap that mixes rules/workflows with skills makes every rule/workflow entry show a
bogus error and a garbage score. Skip or special-case non-skill kinds, mirroring the kind-branching
already used elsewhere in pkg.py.
Complexity S
Impact Med
Wow ★★
PlannedUX · Bug
boost onboard silently overwrites existing generated files
boost onboard writes .boost/telemetry.json, a GitHub Actions workflow, and
.skill-lock.json via a bare write_text() with no existence check,
confirmation, or diff — unlike the sibling "write a generated file" helper elsewhere in the
codebase, which always confirms before overwriting. Re-running it on a repo with its own tracked
lock file silently clobbers it and still reports "created," even though it overwrote. Check
dest.exists() and route through out.confirm() first.
Complexity S
Impact Med
Wow ★★
PlannedCLI ergonomics
Negative -n silently inverts log/pulse output
boost log/boost pulse accept -n/--limit as a bare
type=int with no positivity check, and the slicing does
out[:n] if n else out — a negative n becomes a Python negative slice, so
-n -1 silently returns everything except the most recent event instead of erroring.
discovery.py's --limit flags already share a _positive_int
validator that rejects values below 1; reuse it here.
Complexity S
Impact Low
Wow ★
PlannedTesting · Bug
boost log --crashes listing branch has no non-empty test
_show_crashes has an empty-state branch and a listing branch that reads each
crash-*.log, extracts its summary line, and swallows OSError on an
unreadable report — only the empty-state message is exercised by any test. A regression in the glob
sort, the summary-extraction regex, or the OSError fallback would ship undetected. Add
a test that seeds one or more crash logs and asserts on the rendered listing.
Complexity S
Impact Low
Wow ★
PlannedTesting · Security
boost serve's own path-traversal guards are untested
serve.py's defenses against a malicious catalog skill_md path
(_is_within, _safe_join_within, the ".." in rel.parts check)
and its HTTP-handler failure modes are the least-covered lines in core/ — 84.5% file
coverage, the lowest of any module — and no test actually feeds a ..-containing path
through skill_text() to prove the guard fires. Add adversarial tests for the traversal
guards and for _CatalogHandler's error paths.
Complexity S
Impact Med
Wow ★★
lowest coverage in core/
PlannedObservability
Diagnostic log has no structured/JSON output mode
core/logs.py uses stdlib logging with rotation and crash reports, but its
file formatter only ever emits fixed plain-text lines — unlike core/journal.py, which
already writes one JSON object per line for the pulse feed. A BOOST_LOG_FORMAT=json
option emitting the same fields as structured records would let
~/.boost/logs/boost.log feed straight into jq or a log aggregator instead
of needing regex parsing.
Complexity M
Impact Med
Wow ★★
PlannedObservability
AI bridge swallows failures with zero diagnostic trail
core/ai.py's CLI and API call paths both catch their failure modes (timeout, OS error,
URL error, bad JSON) and return None — but neither ever calls into the logger, unlike
the rest of boost. A user whose expired key or flaky network silently degrades every AI-assisted
command to its heuristic fallback has no trail to diagnose why, even with --debug. Add
a one-line logger.debug(...) in each except branch.
Complexity S
Impact Med
Wow ★★