feat(config): refresh rig config --help keys list + 0.3.1 release notes

V0.3.1 slice 08 settings-config-validation. Light verification + docs
pass; one drift fix surfaced during the audit.

What this slice ships:

(1) HG-6 drift fix — `rig config --help` text was missing several key
namespaces relative to the actual VALID_KEYS list (the help still
enumerated only the original-5 + a partial workspace.* + recovery.*
shape; missing ui.preview.*, agents.*, feed.subscriptions.*,
runtime.codex.*, transcripts.lines, transcripts.poll_interval_seconds,
workspace.dogfood_evidence_root, workspace.operator_seat_name).
Refreshed the "Keys:" section in
`packages/cli/src/commands/config.ts` to enumerate every top-level
namespace currently in VALID_KEYS.

(2) HG-6 regression guard — new test in
`packages/cli/test/config.test.ts` extracts every top-level dotted-
prefix from VALID_KEYS and asserts each appears in the rendered help
output (captured via Commander outputHelp() through a custom writer
so the after-help text is included). Guards against silent help-text
drift when new keys are added.

(3) 0.3.1 release notes section drafted in CHANGELOG.md — adds an
`[0.3.1] - unreleased` section with a "Config + settings" subsection
documenting: VALID_KEYS / SETTINGS_VALID_KEYS lockstep, the
OPENRIG_<KEY> > config-file > default precedence, the original-5
RIGGED_<KEY> legacy aliases, the help-text refresh, and the no-new-
SC-29 posture for this slice.

Verification (no other code changed):

- HG-1: every VALID_KEYS entry round-trips through
  `resolveAllWithSource`. Existing `resolveAllWithSource returns every
  valid key with source + default` test in config-store-extended.test.ts
  covers this.
- HG-2: CLI `VALID_KEYS` and daemon `SETTINGS_VALID_KEYS` are byte-
  identical sets (29 keys each; diff returned empty). ENV_MAP entries
  are byte-identical between CLI and daemon (29 entries each).
- HG-3: env > file > default discriminator with distinct values per
  layer. Covered in CLI (`env > file > default for new keys`) and
  daemon (`env > file > default for daemon.port`) test files; no new
  test needed.
- HG-4: 5 RIGGED_<KEY> legacy aliases (PORT, HOST, DB,
  TRANSCRIPTS_ENABLED, TRANSCRIPTS_PATH) — verified pre-rename via
  `git log -S "RIGGED_<KEY>"` first-occurrence check. All 5 first
  appear pre-rename-merge. No cargo-culted post-rename entries. Zero
  findings to surface to backlog slice 01-rigged-legacy-env-vars-
  cleanup.
- HG-5: slice 05 already shipped; `workspace.operator_seat_name`
  end-to-end roundtrip is covered by existing tests in
  config-store-extended.test.ts and user-settings-store.test.ts.
- HG-6: see (1) + (2) above.
- HG-7: CLI suite 922 passed / 3 failed (3 pre-existing failures on
  main 2b5b86b; verified by cross-checking the same tests against
  origin/main; not introduced by this slice). Daemon
  user-settings-store: 16/16 PASS. No new typecheck or build errors.
- HG-8: CHANGELOG.md section drafted; see (3).

SC-29 EXCEPTION declared: NONE.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
mvschwarzandClaude Opus 4.7 committed 2026-05-11 19:46:27 -07:00
1 parent e2f58fbd1e
commit b252137a2e
3 files changed
+92 -3

No files matched your search

+30
View File
@@ -8,6 +8,36 @@ deprecations, and behavioral changes. Breaking changes are called out explicitly
---
## [0.3.1] - unreleased
**Status**: in-flight; draft notes accumulate per shipped slice.
### Config + settings
- `rig config get/set/reset/list` continues to be the canonical CLI surface
for the typed config keys. No new keys added in 0.3.1; no breaking changes.
- 29 allowlisted keys total. CLI `VALID_KEYS` and daemon `SETTINGS_VALID_KEYS`
are byte-identical sets (verified in slice 08; lockstep contract holds).
- Env override precedence is `OPENRIG_<KEY>` env var > `~/.openrig/config.json`
> derived default. The 5 original runtime keys (`daemon.port`, `daemon.host`,
`db.path`, `transcripts.enabled`, `transcripts.path`) additionally accept
their `RIGGED_<KEY>` legacy alias for upgrade compatibility from pre-rename
installs; new typed keys are `OPENRIG_<KEY>` only.
- `rig config --help` text refreshed to enumerate every top-level key
namespace: `daemon.*`, `db.path`, `transcripts.*` (including the
rotation-tuning keys `lines` + `poll_interval_seconds`), `workspace.*`
(including `dogfood_evidence_root` + `operator_seat_name`), `files.allowlist`,
`progress.scan_roots`, `ui.preview.*`, `recovery.*`, `agents.*`,
`feed.subscriptions.*`, `runtime.codex.*`. A regression test asserts the
help text continues to enumerate every namespace as new keys land.
- No new SC-29 EXCEPTIONs introduced by the slice 08 validation pass.
### Other slices
(slice notes accumulate here as each slice ships.)
---
## [0.3.0] - 2026-05-10
**Status**: release candidate for public publish. This entry documents the
+7 -2
View File
@@ -33,11 +33,16 @@ Examples:
Keys:
daemon.* port, host
db.path
transcripts.* enabled, path
workspace.* root, slices_root, steering_path, field_notes_root, specs_root
transcripts.* enabled, path, lines, poll_interval_seconds
workspace.* root, slices_root, steering_path, field_notes_root,
specs_root, dogfood_evidence_root, operator_seat_name
files.allowlist name:/abs/path,name:/abs/path
progress.scan_roots name:/abs/path,name:/abs/path
ui.preview.* refresh_interval_seconds, max_pins, default_lines
recovery.* auto_drive_provider_prompts, provider_auth_env_allowlist
agents.* advisor_session, operator_session
feed.subscriptions.* action_required, approvals, shipped, progress, audit_log
runtime.codex.* hooks_enabled
Precedence: CLI flag > environment variable > config file > default`)
.action((opts: { json?: boolean; withSource?: boolean }) => {
+55 -1
View File
@@ -4,7 +4,7 @@ import { join } from "node:path";
import { tmpdir } from "node:os";
import http from "node:http";
import { Command } from "commander";
import { ConfigStore } from "../src/config-store.js";
import { ConfigStore, VALID_KEYS } from "../src/config-store.js";
import { configCommand } from "../src/commands/config.js";
import { DaemonClient } from "../src/client.js";
import { STATE_FILE, type DaemonState } from "../src/daemon-lifecycle.js";
@@ -281,4 +281,58 @@ describe("Config CLI", () => {
// by checking description and options contain the essential info
expect(coreHelp).toContain("config");
});
// V0.3.1 slice 08 — HG-6: rig config --help text must enumerate every
// top-level dotted-prefix used in VALID_KEYS. The slice 08 verification
// pass caught a drift where ui.preview.* / agents.* / feed.subscriptions.* /
// runtime.codex.* + workspace.dogfood_evidence_root +
// workspace.operator_seat_name + transcripts.lines +
// transcripts.poll_interval_seconds were missing from the help "Keys:"
// section. This regression test extracts every top-level prefix from
// VALID_KEYS and asserts each appears (or its parent group appears) in
// the addHelpText after-text — guards against silent drift when new
// keys are added without updating help text.
it("HG-6: rig config --help enumerates every VALID_KEYS top-level prefix", () => {
const cmd = configCommand(join(tmpDir, "config.json"));
// Commander's `addHelpText("after", ...)` text is NOT included by
// `helpInformation()` — it's emitted via lifecycle hooks at help
// display time. Capture the full displayed help by routing
// `outputHelp()` through a custom writer.
let combined = "";
cmd.configureOutput({
writeOut: (text) => {
combined += text;
},
writeErr: () => {},
});
cmd.outputHelp();
// Top-level prefixes are the first dotted segment OR first-two
// segments for grouped namespaces like `ui.preview.*`,
// `feed.subscriptions.*`, `runtime.codex.*`.
const prefixes = new Set<string>();
for (const key of VALID_KEYS) {
const parts = key.split(".");
// Group sub-namespaces under their second segment when there are
// 3+ segments (e.g. ui.preview.refresh_interval_seconds → "ui.preview").
if (parts.length >= 3) {
prefixes.add(`${parts[0]}.${parts[1]}`);
} else {
prefixes.add(parts[0]!);
}
}
// Single-segment leaves (db.path, files.allowlist, progress.scan_roots)
// also appear in the help; the test allows either bare prefix OR
// the full leaf to satisfy the assertion.
const knownLeaves: Record<string, string[]> = {
"db": ["db.path"],
"files": ["files.allowlist"],
"progress": ["progress.scan_roots"],
};
for (const prefix of prefixes) {
const accepted = [prefix, ...(knownLeaves[prefix] ?? [])];
const found = accepted.some((needle) => combined.includes(needle));
expect(found, `rig config --help text must mention "${prefix}" (or one of ${accepted.join(", ")})`).toBe(true);
}
});
});