Skip to content

Add fourth pillar (Data) to working-with-state.md — program-managed working state #33

@rianjs

Description

@rianjs

Adds a fourth state pillar — Data — to cli-common/docs/working-with-state.md, between the existing Config, Cache, and Secrets pillars. Driver: the new cr (codereview) CLI needs to persist a SQLite run ledger, findings JSON, log streams, and agent outputs that must survive config clear --all. Cache doesn't fit (loss tolerated by definition); config doesn't fit (user didn't author it); there was no slot.

Pillar shape

  • Definition: program-managed working state. The program owns the lifecycle; the user shouldn't poke at it directly. Defined negatively as not config, not secret, not cache, with the tiebreaker default to cache when on the fence (drift-prevention without a strict positive criterion).
  • Backing (Path A — STATE-flavored, decided over XDG_DATA_HOME):
    • Linux: XDG_STATE_HOME~/.local/state/<dir>
    • macOS: ~/Library/Application Support/<dir>/data/
    • Windows: %LOCALAPPDATA%\<dir> (explicitly not %APPDATA% — Roaming would sync SQLite + logs + agent outputs over the network for users on roaming profiles)
  • Naming rule: per-binary (matches cache §4.1, not config §3) — derived program-managed state has program-specific lifecycle, not credential-scope ownership.
  • Format invariants: dir 0700 / file 0600; no atomic-write mandate (open-ended formats — SQLite has its own durability, logs/streams don't want temp-rename); schema migration is fail-loud + migrate (not cache's "version mismatch = miss" — data loss is not tolerated).
  • Lifecycle invariants:
    • The dir as a whole survives config clear --all. Pillars have separate lifecycles.
    • Whole-dir nuke is explicit and user-invoked (the purge verb).
    • Individual records may be removed by the program under a documented retention policy.
  • Command surface: nuclear required, maintenance optional; suggested verb pair <tool> data purge (nuclear) / <tool> data prune (maintenance). Severity encoded in the verb, not a flag. Both verbs support --dry-run; nuclear's dry-run reports paths-that-would-be-scrubbed. Nuclear obeys the §7.6 cleanup-command recovery contract (must scrub even if data unreadable). User-invoked, not uninstall-triggered.
  • Retention (guidance, not mandate): if the dir can grow unboundedly in normal use, the CLI SHOULD declare a size/age/count cap with automatic enforcement at write-time. Generous-but-finite defaults beat unbounded.
  • Test isolation: statedirtest.Hermetic grows from 7 to 8 env vars — XDG_STATE_HOME joins the existing set so an XDG-aware dev env can't bleed into a Linux test run.

Cross-doc

  • working-with-secrets.md §1.7.2 reframed: no longer "factory reset of the active profile" — now "config + credentials + cache reset". Data pillar is explicitly excluded; users compose config clear --all AND <tool> data purge for the historical full reset.
  • working-with-state.md §1, §1.1, §2, §5 (new), §6a, §7 (rollout item 7), §8 all updated.

Pressure-test history

  • Round 6 Codex pressure-test (2026-05-28): blockers=1 majors=3 minors=2. All findings disposed in the same revision — Path A backing shift, per-binary naming, retention guidance, secrets-doc cross-update, --dry-run extension, code-comment cleanup. Full disposition table in working-with-state.md §8.
  • Round 6 cleanup pass (2026-05-28): post-application re-read surfaced 5 cleanup items (lifecycle invariant contradiction, sticky factory-reset framing, 8-var propagation, resolver overclaim, stale primer). All applied.
  • Round 7 confirmation pass recommended before merge — single-round-with-corrections is not the same as the 5-round convergence that the existing three pillars went through.

Scope

  • Forward-looking pattern doc — cr is the first consumer.
  • No existing CLI ports to the data pillar; it's additive to the §7 rollout.
  • cli-common/statedir resolver does not yet expose a Data() method — that lands when the first data-holding CLI does (§7 rollout step 7); the package doc reflects this as not-yet-implemented.
  • data-pillar-primer.md retained as the "how the decision was reached" companion; superseded banner at top with deltas.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions