Skip to Content
PhasesPhase — locales subcommands (list / edit / dynamic / delete)

Phase — locales subcommands (list / edit / dynamic / delete)

Status: Active (CLI) — hub: active-phase.md. Roadmap order: CLI-ROADMAP-HANDOFF.md. First shippable slice: read-only locales list (no ADR 004). locales edit remains gated on ADR 004. key-sites continues in parallel where it does not block this track (key-sites.md).

When active again: two subcommands are usable today; two are stubs or placeholders until list/edit implementations land.

User docs: commands/locales (tracked).

This file is development-only (see repo .gitignore for docs/phases/).


Reality vs packages/cli/src/commands/locales/*

CommandImplementationNotes
i18nprune locales dynamicShippedRead-only: scanProjectDynamicKeySites, human output (capped), links to dynamic docs. No locale writes.
i18nprune locales deleteShippedRequires --target; confirmation (or global --yes); removes <target>.json and <target>.meta.json if present; blocks source locale.
i18nprune locales listStubOnly logs a “planned” line — no file enumeration or counts yet (intended to align with review-style summaries).
i18nprune locales editPartialResolves localesDir, lists targets, --target or interactive select; does not yet edit JSON or loader wiring — ends with a “planned” info line. Real editing depends on supported loader patterns and opt-in auto-patching (ADR 004).

Dependencies (ordering)

  1. locales list — can ship without ADR 004: implement using resolveContext, listJsonBasenamesInDir / existing locale helpers, and the same leaf-count ideas as review / validate (read-only).
  2. locales editstrongly gated on ADR 004 + documented patching recipes so “edit” means something safe and repeatable (not just opening a file path in the log).
  3. locales dynamic / delete — minor polish only (JSON output, report parity, tests) unless product scope expands.

Suggested sequence: list (complete stub)edit (minimal safe flows after auto-patch) → optional report / JSON parity for all four.


Goals

GoalCommandWhen
Real listinglistFirst — unblocks UX and docs examples.
Guided edit or patcheseditAfter ADR 004 surface is stable.
Parity with --json / report artifactsallWhen other commands reach report parity (see report.md).

Acceptance (close the phase)

  • locales list: enumerate locale JSON under localesDir, show useful counts (paths, optional English-identical hints), fail fast if localesDir missing.
  • locales edit: either documented no-op with exit 0 and pointer to manual flow, or a minimal safe action (e.g. open path, or one supported patch) — not a permanent “planned” string.
  • User docs and behavior / commands updated to match.
  • Tests: integration or unit for list; delete / dynamic as coverage allows.

Non-goals (this phase)

  • Replacing sync, fill, or generate — orchestration stays in missing-pipeline.md.
  • Full IDE integration — CLI scope only.

Planning — parity with generate / fill / validate (prompts, exit codes, --json)

This section is normative for future work: align locales * with the same integrator and agent expectations as commands that already ship CliJsonEnvelope output and predictable non-interactive behavior. See CLI --json parity and JSON output.

Prompt selection (interactive vs stable / non-interactive)

PrincipleBehavior
Context-drivenWhen the invocation is interactive (TTY, run.json === false, no “forced non-interactive” flag), subcommands may use stable, documented prompts: e.g. pick --target from a list, confirm destructive delete. Ordering and labels should match patterns used elsewhere (generate, fill, validate) so muscle memory and docs transfer.
No prompts when not allowedWhen --json is active or the command is registered as JSON-capable and the user expects automation, do not emit interactive prompts on stdout/stderr that block parsing. Prefer: require explicit --target, --yes for destructive actions, or fail with USAGE / structured issues[] — same family as prompts & CLI boundaries.
Observed gap (plan to fix)Example: locales delete --target fr --json still prompted for confirmation while --yes skipped it. Plan: --json must imply no interactive confirmation (or document that --yes is required for destructive --json — pick one rule and enforce it everywhere under locales).

Exit codes and failure rules

OutcomeExpected
SuccessOperation completed (including intentional no-op if documented). ok: true, issues[] may still carry warnings.
User error / missing argsNon-zero exit, ok: false, stable issues[] codes (e.g. missing --target when required).
Precondition failed (e.g. locales edit: no non-source locale files)Non-zero exit, one clear error (stderr in human mode; envelope + issues[] in JSON mode). Align wording with validate / generate “fail fast” style.
Idempotent / missing file (e.g. delete target already gone)Decide explicitly: either exit non-zero (“file not found”) for scripts, or exit 0 with issues[] / data explaining no-op — document the chosen contract per subcommand and keep it stable.

CliJsonEnvelope shape (per subcommand)

  • kind: use a stable command id (e.g. locales-delete, or nest under a shared locales payload with inner subcommand — follow whatever packages/cli/src/types adopts; must match commands that emit once locales is added to COMMANDS_WITH_JSON_OUTPUT).
  • data: include machine-useful fields: targets touched, paths, counts (deletedJson, deletedMeta, …), timings if other commands expose them.
  • issues[]: empty on pure success; populate for skips, parity warnings, or policy blocks — with docHref where applicable.
  • Stdout hygiene: JSON path prints only the primary envelope (no duplicate summary lines, no banners in machine mode) — cli-json-command-parity.

Acceptance for “locales CLI parity” (add to close criteria when implementing)

  • locales list / edit / delete / dynamic: documented matrix of prompts vs --json vs --yes.
  • Integration tests: --json produces a single parseable document; destructive flows never block on stdin when the documented non-interactive contract is met.
  • User docs (commands/locales) and behavior / commands updated.

See also