Repository navigation
Move advanced Settings to a TOML-backed config with separate docs #3
Description
Activity
- addedtriage/ai-reviewedReviewed by the cautious issue triage workflow.Reviewed by the cautious issue triage workflow.triage/human-neededHuman maintainer review is needed.Human maintainer review is needed.
on Jul 3, 2026 First execution milestone landed in 7b77258.
What changed:
- Added dependency-free TOML config parsing for the known TSRS sections.
- Added
relay config path,relay config show,relay config validate, andrelay config reload. relay config shownow gives a 1.1.2 SQLite-settings upgrade preview when no config file exists, without writing a new persistence file or switching runtime playback to TOML.- Added tests for config commands, invalid placeholders, 1.1.2-style settings preview, and preserving an existing config file.
- Added AGENTS.md guidance plus
.github/skills/settings-ui-verificationfor the issue Add accessibility-backed Settings UI smoke tests and screenshot capture #2 Accessibility/screenshot workflow.
Important remaining checkpoint: before TSRS reads voice/combiner/retention from TOML at runtime, we still need the explicit fail-quiet contract for malformed/invalid config so the app surfaces errors without unexpectedly speaking or falling back to a command path.
Added the release-upgrade gate in 0a1bd5e:
scripts/test-112-upgrade.sh.What it covers now:
- Builds the tagged
v1.1.2CLI in a temporary git worktree. - Uses that real 1.1.2 CLI to create a SQLite database with queue data, active line, live mode, mute, first-start completion, speech command, and combiner command.
- Runs the current bundled
relayagainst the same database. - Verifies
relay config showandrelay config validateproduce the TOML upgrade preview, preserve runtime state, keep the queued relay, and do not createconfig.tomlbefore the write migration exists.
Remaining for 2.0.0: once the TOML write/source-of-truth migration is implemented, extend this same harness to assert the file is created exactly once, existing TOML is not overwritten, invalid TOML fails quiet, and runtime voice/combiner/retention reads come from TOML safely.
- Builds the tagged
TOML source-of-truth migration landed in 4b91ff8.
What changed:
config.tomlis created once from existing SQLite settings and preserved if already user-edited.- TOML is now the source of truth for advanced voice command, inactive-line combiner command, and cleanup retention.
- SQLite remains the source for runtime/user state: mode, mute, active line, queue, first-start completion, shortcut, voice selection, diagnostics, and usage.
- Invalid TOML now fails quiet: status/settings expose
configError, Settings Voice diagnostics show the config error, playback reports blocked/muted, andapp-claim-nextreturnsnullso queued relays are not spoken. scripts/test-112-upgrade.shnow covers real v1.1.2 database upgrade, one-time TOML creation, existing-TOML preservation, invalid-config fail-quiet behavior, and queue/runtime state preservation.
Validated with focused XCTest, full XCTest, direct build, app restart, Settings screenshot/interaction smoke capture, and the v1.1.2 upgrade harness.
Settings UX and persistence smoke milestone landed in deba948.
What changed:
- Redesigned the Voice Settings panel around the TOML config file with Open Config, Reveal in Finder, Validate, and Reload controls.
- Added explicit Save buttons for voice command and inactive-line combiner command instead of relying only on save-on-close.
- Kept the compact Advanced and Combiner panels visible in screenshots.
- Added an app-owned
relay debug settings-roundtrippath for UI smoke testing. The screenshot workflow can now modify Voice, Combiner, and cleanup retention through the real Settings controller, verify the bundled CLI sees the modified values, restore the original TOML, and verify restore. - Updated docs/AGENTS with the
TSRS_SETTINGS_UI_ROUNDTRIP=1 TSRS_SETTINGS_UI_REQUIRE_INTERACTIONS=1 scripts/capture-settings-ui.shrelease gate.
Validated with focused XCTest, full XCTest, direct build/restart, v1.1.2 upgrade harness, and strict Settings capture/roundtrip artifacts in
.artifacts/settings-ui/settings-ux-roundtrip/.Final closeout: all requirements in this issue have been satisfied on
main.What is now covered:
config.tomlis the source of truth for advanced voice command, inactive-line combiner command, variable values when present, and cleanup retention.- Existing 1.1.2 SQLite settings upgrade into TOML once, while queue/runtime state remains in SQLite.
- Invalid TOML/config fails quiet and leaves queued relays unclaimed for speech.
- Settings uses the same config model and provides Open, Reveal, Validate, Reload, and explicit Save controls.
- The duplicate advanced CLI surfaces were consolidated under
relay config set, with existing compatibility/errors covered. - Docs and release-upgrade/UI verification gates have been updated.
Follow-up refinements after the main milestone also landed: generated config no longer emits empty variable tables, and Provider line voices stay TOML-only instead of stretching the Voice Settings panel.
Problem
Voice command templates, inactive-line combiner command templates, and local cleanup retention are now split across CLI settings and text-heavy Settings panels. That is hard to maintain, awkward in the GUI, and not ideal for the likely configuration path: a user asking an agent to update local TSRS settings. TSRS should make the advanced configuration file-first while preserving the Settings UI for visibility, validation, and safe edits.
Goals
${...}shell-looking placeholders; continue from the current<text-file>,<output-file>,<voice-id>,<app-bin>,<input>, and<system>style unless a migration explicitly preserves compatibility.docs/and any generated public-site docs source if this repo owns one.Proposed config shape
Use a sectioned TOML file that preserves existing placeholder semantics, for example:
Placeholder syntax should be explicit, allowlisted, and substituted as argv-safe values, not shell-expanded strings. Unknown placeholders should fail validation. If file-backed placeholders such as
<input-file>or<system-file>are added later, keep<input>and<system>compatibility or provide a clear migration path.Proposed approach
RelayCore.swiftor a dedicated shared core file.relay config path,relay config validate,relay config reload, andrelay config edit.settingsfrom the existing SQLite database, create the TOML config only if it is missing, and do not overwrite a user-edited TOML file without an explicit command. Mapinactive_line_combiner_commandinto[combiner].command, explicitly decide whether compatiblespeech_commandvalues can become[voice].command, and leave runtime/user-state keys such asmode,muted,active_line,first_start_setup_complete,command_palette_shortcut,speech_voice_identifier,last_spoken_line, and live-batch bookkeeping in SQLite.voice_command,voice_command_last_error, orcleanup_retention_minutes, mapping only stable config values into TOML and preserving diagnostic/runtime state in SQLite.speech-commandsetting. Either migrate compatible values into the app-ownedvoice.commandmodel or deprecate it with clear CLI output and docs; do not reintroduce CLI-owned speech.docs/user-guide.md,docs/inactive-line-combination.md,docs/development.md, and any public-site generated docs source if present. If jonmagic.com docs are not generated from this repo, note the external follow-up instead of adding a fake path.Acceptance criteria
combiner,settings --voice-command, and cleanup-retention workflows continue to work or emit clear migration guidance.speech-commandpath has an explicit migration/deprecation decision with tests.Out of scope