Skip to content

discovery: repair the 20 rotted PROFILES entries and lint them - #355

Merged
maximelb merged 1 commit into
masterfrom
profiles-fix-stale-entries
Sep 2, 2026
Merged

discovery: repair the 20 rotted PROFILES entries and lint them#355
maximelb merged 1 commit into
masterfrom
profiles-fix-stale-entries

Conversation

@maximelb

@maximelb maximelb commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Stacked on #353 (mailsec-discovery-profiles). Base is that branch, not master, so the two do not conflict; GitHub will retarget this to master automatically when #353 merges. Review #353 first — the diff shown here is only this PR's changes.

What

limacharlie help discover prints each PROFILES entry verbatim as a limacharlie <entry> invocation. 20 entries named commands that no longer exist, so the CLI's own discovery surface was handing out advice that cannot be followed. This is a pure correction PR: it fixes rotted entries and pins them. It adds no new surfaces.

Every replacement was re-derived by walking the live click tree, not from the earlier inventory — which was wrong in two ways worth flagging: there are 10 rule * entries (not 11), and they map to dr *, not dr rule * (the dr group holds the verbs directly).

Per-entry disposition

Old entry Profile New entry Why
rule list detection_engineering dr list group renamed to dr
rule get detection_engineering dr get group renamed to dr
rule create detection_engineering dr set no create; dr set is create-or-update
rule update detection_engineering (collapsed into dr set) same command as rule create — two entries become one
rule delete detection_engineering dr delete group renamed to dr
rule test detection_engineering dr test group renamed to dr
rule replay detection_engineering dr replay group renamed to dr
rule validate detection_engineering dr validate group renamed to dr
rule export detection_engineering dr export group renamed to dr
rule import detection_engineering dr import group renamed to dr
fp create detection_engineering fp set no create; fp set is "Create or update a false positive rule"
org config get platform_admin org config-get hyphenated verb, never a config subgroup
org config set platform_admin org config-set hyphenated verb, never a config subgroup
search saved list historical_data search saved-list hyphenated verb, never a saved subgroup
search saved get historical_data search saved-get hyphenated verb
search saved create historical_data search saved-create hyphenated verb
search saved delete historical_data search saved-delete hyphenated verb
search interactive historical_data dropped no successor anywhere in the tree; genuinely gone
sensor online sensor_management dropped became a flag: sensor list --online. sensor list is already profiled
sync diff fleet_management dropped became a flag: sync push --dry-run. sync push is already profiled

Net: 17 corrected (16 entries, since rule create/rule update merge), 3 dropped.

dr convert-rules was already correct; it moved next to the other dr entries for readability.

Widened lint

TestProfileEntriesResolve now requires every entry in every profile to resolve against the live click tree. The mailsec both-directions pin from #353 is unchanged.

Deliberately one-directional: it does not require that every command be profiled. Which commands are worth surfacing is a curation call, and 32 top-level groups are unprofiled — that is curation debt, not a correctness bug, and forcing it here would be a different PR.

Verified by mechanism: stashing the discovery.py fix makes the new test fail listing exactly the 20 entries with actionable reasons (it prints the group's real subcommands); restoring makes it pass.

CLAUDE.md

The repo had none. Added a short one covering the thing that caused this rot: the command surface is described by three hand-maintained maps (_COMMAND_MODULE_MAP, PROFILES, doc/cli/) and none updates itself, so a rename must touch all three. It points at both lints and at the MCP-mirroring expectation, and says to look for a renamed command before deleting a profile entry — 17 of the 20 were renames, so "delete until the lint passes" would have been the wrong fix.

MCP reconciliation (NEW_CLI.md §1.1)

Not checkable in this repo — the profile list lives in the separate lc-mcp-server repo (configs/profiles.yaml), so nothing here can enforce it. Reconciled by hand for the record; the claim "matching MCP server profiles" is now only partly true:

  • Shared exactly (7): historical_data, live_investigation, threat_response, fleet_management, detection_engineering, platform_admin, ai_powered.
  • CLI name differs for the same concept (2): CLI sensor_management ≈ MCP core; CLI cases ≈ MCP investigation_management.
  • CLI-only (1): email_security (added in mailsec: make the command surface discoverable #353) — the MCP server has no email-security profile.
  • MCP-only (6): core, historical_data_readonly, investigation_management, api_access, cloud_security, cloud_security_readonly.

Renaming CLI profiles to converge would be a user-visible break to --profile, so it is not done here. Flagging it as a decision for a follow-up.

Remaining debt (not this PR)

  1. 32 of 58 top-level groups appear in no profile: ai-cost-model, ai-memory, ai-skill, app, arl, artifact, auth, cloud-adapter, cloudsec, completion, config, exfil, extension, external-adapter, feedback, help, hive, ingestion-key, integrity, job, logging, lookup, note, payload, playbook, schema, secret, sop, spotcheck, usp, vulnerability (+ mailsec, fixed in mailsec: make the command surface discoverable #353). Notably the MCP server does ship cloud_security profiles while the CLI has no cloudsec coverage at all.
  2. Unprofiled verbs inside already-profiled groups, found while fixing the above and left alone to keep this a correction: dr enable|disable, fp enable|disable, fp tag add|rm|set, search saved-run|queries|limits|checkpoints|checkpoint-show, and much of org.
  3. Doc drift in three filesdoc/cli/README.md, doc/cli/other-commands.md, doc/getting-started.md document limacharlie discover and limacharlie cheatsheet as top-level commands (they live under help), and reference a --profile incident_response that does not exist (it is threat_response).

Tests

Full CI suite (tests/unit/ tests/microbenchmarks/, matching cloudbuild_pr.yaml), clean venv: 4086 passed, 5 skipped — up from 4085 on #353 (+1 new test), and 4083 on master. The 5 skips are pre-existing and unrelated (3 platform-gated, 2 pre-existing-docstring gates).

🤖 Generated with Claude Code

lcbill
lcbill previously approved these changes Sep 2, 2026
Base automatically changed from mailsec-discovery-profiles to master September 2, 2026 16:15
@maximelb
maximelb dismissed lcbill’s stale review September 2, 2026 16:15

The base branch was changed.

@maximelb maximelb closed this Sep 2, 2026
@maximelb
maximelb force-pushed the profiles-fix-stale-entries branch from 20a9f21 to 0254238 Compare September 2, 2026 16:16
`limacharlie help discover` prints profile entries verbatim as
`limacharlie <entry>`, so an entry naming a command that no longer
exists is advice that cannot be followed. 20 of them were in that state.

Corrections, each re-derived by walking the live click tree rather than
by guessing: the 10 `rule *` entries are `dr *` (not `dr rule *`);
`rule create` and `rule update` both collapse into the single `dr set`,
which is create-or-update; `fp create` is likewise `fp set`;
`org config get|set` and the four `search saved *` are hyphenated, not
subgroups. Three are genuinely gone and are dropped: `sensor online` and
`sync diff` became flags (`sensor list --online`, `sync push --dry-run`)
and `search interactive` has no successor.

Widen the lint so every entry in every profile must resolve. This is
deliberately one-directional -- it does not demand that every command be
profiled, since which commands are worth surfacing is a curation call
and 32 top-level groups are still unprofiled.

Add a CLAUDE.md telling anyone changing the command surface to update
`_COMMAND_MODULE_MAP`, `PROFILES` and `doc/cli/` together, and to look
for a renamed command before deleting a profile entry -- most of the 20
were renames.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@maximelb maximelb reopened this Sep 2, 2026
@maximelb
maximelb marked this pull request as ready for review September 2, 2026 16:27
@maximelb
maximelb enabled auto-merge (squash) September 2, 2026 16:27
@maximelb
maximelb merged commit fe67856 into master Sep 2, 2026
6 checks passed
@maximelb
maximelb deleted the profiles-fix-stale-entries branch September 2, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants