CLI: inactive bundled plugin command reports unavailable + repair, not unknown (LLP 0098)#296
Conversation
Dual-agent review -
|
neutral PR-review round - PR #296 (own neutral PR, not adopted)Path: dual-review (Codex + Claude, both ran). Verdict: Findings1. [minor] Repair line is wrong for a present-but-disabled plugin entry -
Verified clean (independent Claude scan)
Nothing pushed; head unchanged at |
Round 2 review (independent second pass) — verdict: approve with one deferred minorIndependent read of the diff on head Confirmations:
Confirmed round-1 minor (real, non-blocking, deferred)
Non-blocking because: (a) it is outside #294's scope (absent plugin, not disabled entry); (b) the advised duplicate entry would still re-enable the plugin (the merge adds on the New findingsNone actionable. Recording |
|
Round 3 (light confirmation review, per maxReviewRounds=4). Head is byte-identical to rounds 1-2 (9e2332b) — no new commits to re-review. Confirmed: the diff to The one known minor still stands (unresolved, deliberately deferred, non-blocking):
No other findings. |
Round 4 review (final round, maxReviewRounds=4) — verdict: approve with one deferred non-blocking minorIndependent final read of the full diff on head Confirmed correct and safe for issue #294's scope (absent plugin):
Known non-blocking minor (unchanged, deferred by design): a plugin present in config but disabled ( No new findings. Review rounds now exhausted (4/4) with only the one non-blocking, out-of-scope minor open → the PR ships; triage files the follow-up. Nothing pushed; head unchanged at |
|
Triage (rounds exhausted 4/4): ships. The one residual review finding was independently classified non-blocking (judgment-tier) — a misleading-but-not-broken repair hint on the dispatch-miss error path, out of issue #294's scope, blocked from an in-PR fix by immutable LLP 0098. No production risk (no crash, data loss, security, or perf; no boot path hard-fails). Deferred to follow-up issue #297 (labelled |
…099, issue #297) (#298) * Dispatch miss on inactive bundled plugin command: report unavailable + repair, not unknown (LLP 0098) Fixes #294 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix JSDoc @param after collectPluginHelpCommands refactor (fix-ci for #296) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Dispatch-miss repair line branches on why a plugin is inactive (LLP 0099, issue #297) The dispatch-miss availability hint (LLP 0098) always advised `add {"name": "<plugin>"} to plugins[]`. That is correct only when the plugin is absent from plugins[]. When the effective config already contains `{"name": "<plugin>", "enabled": false}` the entry lands in the boot pool but not the selected set, so the miss path fires and told the user to add an entry that already exists (issue #297, deferred from PR #296). Classify the inactive plugin into absent / disabled-local / disabled-central (the disabled entry belongs to central iff central declares its name, per the additive merge model in LLP 0031) and emit a case-appropriate repair: - absent: unchanged, byte-identical to LLP 0098. - disabled-local: set "enabled": true on the existing entry. - disabled-central: the fleet config disables it; it cannot be enabled locally. computeBootSelection now also returns the resolved layered config so the miss path can read the effective + central documents it already resolved (no extra I/O). Mint LLP 0099 extending LLP 0098's repair wording; add an Extended-by forward-ref on 0098. Regression tests (fail on the old single-line output, pass now) cover the disabled-local and disabled-central cases alongside the existing absent case. @ref LLP 0099, LLP 0098 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * PR #298 review: inline InactiveState union (drop @typedef), byte-exact absent-case test assertion CLAUDE.md forbids @typedef in JSDoc; inline the 'absent'|'disabled-local'| 'disabled-central' union literal at each of its three use sites in dispatch.js instead of naming it. Also tighten the absent-plugin repair-line assertion in dispatch-inactive-plugin.test.js to a byte-exact full-line equality check, so any drift in the LLP-0098-pinned wording (issue #294) fails the test instead of slipping past a prefix/regex match. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
When
hyp <cmd>names a command that a bundled/installed plugin declares in its manifest but the effective config does not activate, the dispatcher used to print the generichyp: unknown command '<cmd>'. The command is not unknown, it is unavailable: the process already knows which plugin provides it (the same manifest catalog--helpsynthesis reads) and knows it was left inactive.This adds
findInactivePluginForCommandtosrc/core/cli/dispatch.jsso a dispatch miss on a known-but-inactive plugin command reports anunavailablestate naming the providing plugin, plus a repair line, instead ofunknown command. A genuine typo still gets the generic unknown-command message, and commands whose plugin is active are unaffected. Rationale is captured inllp/0098-inactive-not-unknown-dispatch-miss.decision.md(annotated via@ref LLP 0098#decision [implements]).Test
test/core/dispatch-inactive-plugin.test.jsgates the fix. Verified under ground-truth discipline: with the source change stashed the test FAILS (asserts on the oldunknown command 'graph'output); with the fix in place it PASSES. Fullnpm testis green (2146 pass, 0 fail, 1 skipped).Fixes #294
🤖 Generated with Claude Code