Files
dotfiles/.config/dot/.claude/tasks/0001-kde-schema-backed-save.md
alexion 0614e0ebe6 dotcli: Add dot kde save with schema-backed defaults and completion.
Introduces the dot kde subcommand family (fish dispatcher plus a Python
helper under commands/kde/), a flat identifier=value manifest, and
dot kde save in both its explicit-identifier and no-argument refresh
modes. Settings resolve to KDE's KConfigXT schema-backed mechanism via a
(rcfile -> [kcfg files]) mapping table auto-derived by scanning the
system schema directory (overridable via DOT_KDE_KCFG_DIR), plus a
hand-maintained exceptions list for schemas that only declare their
target rc file at runtime. Also wires tab-completion for dot kde save
identifiers, sourced live from that same mapping table.
2026-07-05 18:33:55 -04:00

5.5 KiB

spec, blocked-by
spec blocked-by
dot-kde 0000-nested-subcommand-discovery

What to build

Stand up dot kde itself: the fish dispatcher plus its Python helper, living together under commands/kde/ per the nested-subcommand layout from the prior task. Establish the manifest file (flat text file directly under ~/.config/dot/, one identifier=value line each, split on the first = only; identifier split on the first two .s into file.group.key, leaving the key free to contain further dots or spaces).

Implement the KConfigXT schema-backed mechanism: reads and writes go through kreadconfig6/kwriteconfig6, and the "default" value for a setting comes from its .kcfg schema. Build the (rcfile → [kcfg files]) mapping table by scanning the system's KConfigXT schema directory for files that statically declare their target rc file (<kcfgfile name="...">), plus a small hand-maintained list for the exceptions that only declare their target file at runtime (<kcfgfile arg="true">kwin.kcfg is a known example). The schema directory location must be overridable (e.g. via an environment variable), defaulting to the real system path, so tests can point it at a fixture directory of synthetic .kcfg files instead.

Structure identifier resolution as a dispatchable decision (rc file is kglobalshortcutsrc → shortcuts; else resolves via the mapping table → schema-backed; else → freeform) even though only the schema-backed branch is implemented yet — later tasks add the other two branches without restructuring this.

Implement dot kde save for schema-backed settings, in both modes: run with no arguments, refresh every already-declared manifest entry's value from the live system; run with an explicit identifier, read its current live value and add it to the manifest as a new declared entry. Add dot kde help and dot kde save help, following the project's check-for-help-before-argparse convention at each dispatch level.

Add README rows for dot kde help, dot kde save <identifier>, and dot kde save (no arguments).

Acceptance criteria

  • dot kde and dot kde save are discoverable via dot help and dispatch correctly
  • Manifest parsing splits correctly on the first = (values may contain =) and the first two .s of the identifier (keys may contain dots/spaces)
  • The (rcfile → [kcfg files]) mapping table is derived by scanning a schema directory for <kcfgfile name="...">, plus the hand-maintained exceptions list for arg="true"> schemas
  • The schema directory is overridable via an environment variable, defaulting to the real system path
  • dot kde save <identifier> reads the current live value via kreadconfig6 and adds a new declared entry to the manifest
  • dot kde save with no arguments refreshes every already-declared manifest entry's stored value from the live system, leaving undeclared settings untouched
  • dot kde help and dot kde save help print usage without touching the manifest or invoking kreadconfig6/kwriteconfig6
  • Tests run against a scratch $HOME and a fixture .kcfg schema directory, exercising manifest read/write, identifier parsing, and mapping-table-driven default lookup, per the project's scratch-$HOME-plus-fishtape convention
  • README has rows for dot kde help, dot kde save <identifier>, and dot kde save

Implementation Notes

  • File layout: commands/kde/kde.fish (thin dispatcher: help-before-dispatch at the dot kde level, then hands off to the Python helper) plus commands/kde/kde.py (manifest parsing, mapping-table derivation, mechanism resolution, kreadconfig6 invocation, and save's own help-before-work check).
  • Manifest location: ~/.config/dot/kde-manifest, a flat file directly under ~/.config/dot/ as specified.
  • Mechanism dispatch (resolve_mechanism) implements all three branches described in the parent spec (shortcuts / schema / freeform) even though only schema is wired to real behavior; shortcuts and freeform both currently raise a clear "not yet supported" error from save_one, so later tasks can fill them in without restructuring the dispatch.
  • Test fixtures added under tests/fixtures/kcfg/: testrc.kcfg (a plain <kcfgfile name="..."> schema, including an entry whose ini key= differs from its schema name=, and one entry whose key contains dots and spaces), kwin.kcfg (an arg="true" schema resolved only via the hand-maintained exceptions list), and unmapped.kcfg (an arg="true" schema absent from that list, proving it's never guessed at from its own filename).
  • Per the project's testing convention, kreadconfig6 is never mocked for the tests exercising actual save behavior — it runs for real against fixture rc files under a scratch $HOME. It's faked (via a $PATH-prepended logging stub) only for the two tests asserting that dot kde help / dot kde save help never invoke it.
  • Applied two small cleanups surfaced by /review-uncommitted's Standards pass before closing out: extracted a shared _parse_kcfg helper (was duplicated between build_kcfg_map and find_schema_default), and introduced a Setting = namedtuple("Setting", ["file", "group", "key"]) to stop threading those three strings as separate parameters across resolve_mechanism/find_schema_default/read_live_value/save_one.
  • The Spec pass caught that the unmapped.kcfg fixture was created but never actually exercised by a test; added a case asserting dot kde save unmapped.Whatever.Setting resolves to freeform rather than schema-backed.