Context
During PR #11815 review, operator feedback surfaced a recurring friction pattern: new AI/operator scripts keep adding bespoke parseArgs() implementations even though commander is already present in package.json and used by multiple repo CLIs.
The immediate #11815 blocker is PR-local and should be fixed there. This ticket captures the broader substrate improvement so future scripts do not reintroduce the same hand-rolled parsing drift.
The Problem
Hand-rolled CLI parsers repeatedly miss failure semantics that an established parser gives for free: unknown-flag rejection, missing option-value handling, consistent help text, and predictable option defaults.
Fresh evidence from the #11815 review:
package.json lists commander as a direct devDependency.
- Existing repo CLIs use Commander patterns such as
new Command() / program.option().
ai/scripts/revalidationSweep.mjs introduced a manual parseArgs() switch where unknown flags are silently ignored; for example, a typo like --aply with a valid --family stays in dry-run mode instead of failing fast.
- Synced issue-content sweep found prior parseArgs-heavy work and a recent Commander conversion (#11743), but no existing ticket that standardizes the pattern for AI scripts.
The Architectural Reality
The affected substrate is the right-hemisphere AI/build CLI layer, not the browser/runtime Body layer.
Observed parser surfaces include:
- Commander-backed examples:
buildScripts/ai/kbPushClient.mjs, buildScripts/ai/mcpHealthcheck.mjs, buildScripts/ai/defragChromaDB.mjs.
- Bespoke
parseArgs() examples: ai/scripts/lint-agents.mjs, ai/scripts/lint-skill-manifest.mjs, ai/scripts/migrateWakeSubscriptions.mjs, ai/scripts/normalizeGraphIdentities.mjs, ai/scripts/backfillChromaSharedUserId.mjs, buildScripts/ai/ingestTenant.mjs, buildScripts/ai/restore.mjs.
The goal is not to churn every legacy parser blindly. The goal is to establish a default for new and actively touched AI/operator scripts, with targeted conversion where friction is already observed.
The Fix
Define and implement a Commander-backed CLI parsing standard for AI/operator scripts:
- Convert the active friction point from PR #11815 to Commander as part of that PR's review response.
- Add a short documented convention in an appropriate low-load substrate, or extend existing script/testing documentation if a suitable owner already exists.
- Add targeted tests for at least one converted script proving:
- valid defaults,
- valid option values,
- unknown flags reject,
- missing option values reject,
- help path remains deterministic.
- Optionally add a lightweight lint/check guard for newly touched
ai/scripts/*.mjs parser surfaces if it can be done without noisy false positives.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| AI/operator CLI parser convention |
package.json Commander dependency + existing Commander-backed scripts |
New or actively touched AI/operator CLIs use Commander-backed parsing by default |
A bespoke parser is allowed only with explicit rationale and tests for unknown/missing option failure semantics |
Add/extend the lowest-load relevant docs surface; avoid always-loaded substrate unless necessary |
Unit tests for converted parser behavior + grep/audit showing no new unguarded parser added in the touched scope |
| PR review friction from #11815 |
PR #11815 review PRR_kwDODSospM8AAAABA0E6oQ |
revalidationSweep parsing moves from manual switch to Commander-backed semantics |
Keep current behavior only if Commander cannot support the required exported/testable parser shape, with rationale |
PR body explains the chosen shape |
Focused revalidationSweep tests include unknown/missing option rejection |
Decision Record Impact
none. This aligns with existing dependency and script practice; it does not amend or supersede an ADR.
Acceptance Criteria
Out of Scope
- Rewriting every historical
parseArgs() implementation in one pass.
- Changing CLI business logic unrelated to parser semantics.
- Introducing a new dependency; Commander already exists.
- Adding always-loaded agent substrate unless the chosen documentation location requires it and the PR justifies the loaded-byte cost.
Avoided Traps / Gold Standards Rejected
- Blind mass migration rejected: legacy parsers with stable behavior can remain until touched; this keeps the ticket ROI-positive.
- Convention-only rejected: the pattern needs tests and either documentation or a guard, otherwise the next script can reintroduce the same parser drift.
- Always-loaded rule rejected by default: this is script/tooling discipline, not a core per-turn invariant.
Related
Handoff Retrieval Hint: query_raw_memories("PR #11815 Commander parseArgs friction") or query_raw_memories("hand-rolled parseArgs commander package.json").
Context
During PR #11815 review, operator feedback surfaced a recurring friction pattern: new AI/operator scripts keep adding bespoke
parseArgs()implementations even thoughcommanderis already present inpackage.jsonand used by multiple repo CLIs.The immediate #11815 blocker is PR-local and should be fixed there. This ticket captures the broader substrate improvement so future scripts do not reintroduce the same hand-rolled parsing drift.
The Problem
Hand-rolled CLI parsers repeatedly miss failure semantics that an established parser gives for free: unknown-flag rejection, missing option-value handling, consistent help text, and predictable option defaults.
Fresh evidence from the #11815 review:
package.jsonlistscommanderas a direct devDependency.new Command()/program.option().ai/scripts/revalidationSweep.mjsintroduced a manualparseArgs()switch where unknown flags are silently ignored; for example, a typo like--aplywith a valid--familystays in dry-run mode instead of failing fast.The Architectural Reality
The affected substrate is the right-hemisphere AI/build CLI layer, not the browser/runtime Body layer.
Observed parser surfaces include:
buildScripts/ai/kbPushClient.mjs,buildScripts/ai/mcpHealthcheck.mjs,buildScripts/ai/defragChromaDB.mjs.parseArgs()examples:ai/scripts/lint-agents.mjs,ai/scripts/lint-skill-manifest.mjs,ai/scripts/migrateWakeSubscriptions.mjs,ai/scripts/normalizeGraphIdentities.mjs,ai/scripts/backfillChromaSharedUserId.mjs,buildScripts/ai/ingestTenant.mjs,buildScripts/ai/restore.mjs.The goal is not to churn every legacy parser blindly. The goal is to establish a default for new and actively touched AI/operator scripts, with targeted conversion where friction is already observed.
The Fix
Define and implement a Commander-backed CLI parsing standard for AI/operator scripts:
ai/scripts/*.mjsparser surfaces if it can be done without noisy false positives.Contract Ledger Matrix
package.jsonCommander dependency + existing Commander-backed scriptsPRR_kwDODSospM8AAAABA0E6oQrevalidationSweepparsing moves from manual switch to Commander-backed semanticsrevalidationSweeptests include unknown/missing option rejectionDecision Record Impact
none. This aligns with existing dependency and script practice; it does not amend or supersede an ADR.
Acceptance Criteria
revalidationSweepparser to Commander-backed parsing, or link the already-landed PR that did so.converted now,legacy tolerated, orfuture-touch conversion target; do not churn legacy scripts without evidence of friction.Out of Scope
parseArgs()implementation in one pass.Avoided Traps / Gold Standards Rejected
Related
package.jsoncommanderdevDependencyHandoff Retrieval Hint:
query_raw_memories("PR #11815 Commander parseArgs friction")orquery_raw_memories("hand-rolled parseArgs commander package.json").