Skip to content

feat(config): wt config update pins [list] json-schema while unset#3411

Merged
max-sixty merged 4 commits into
mainfrom
json-schema-update-hint
Jul 10, 2026
Merged

feat(config): wt config update pins [list] json-schema while unset#3411
max-sixty merged 4 commits into
mainfrom
json-schema-update-hint

Conversation

@max-sixty

@max-sixty max-sixty commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Wires the [list] json-schema nag into the standard config-update machinery, so the warning comes with the standard one-command fix.

wt config update now pins json-schema = 1 (the behavior-preserving choice) when the key is unset, via a new PendingDefault variant in DEPRECATION_RULES: applied on the update pass only — the load path must not pin, or an in-memory Some(1) would silence the nag — and scoped to user config through a ConfigFileKind enum threaded through detection in place of the old string labels. Two guards keep the pin honest: it stays inert when the system config layer already defines the key (a user-file pin would override a system-level = 2 and flip resolved output), and the nag's hint offers wt config update only when the same detection update runs would actually write the pin — a missing, unreadable, or malformed user config falls back to naming the manual setting.

The detection-equals-migration invariant holds with the warning relocated: the pin's warning fires at the JSON-emitting surface (resolve_json_schema) exactly when update would change the file, while config load stays quiet (DeprecationKind::is_pending_default filters it, and pin-only configs skip the warning-dedup machinery entirely), so wt switch users never see it. wt config show renders the pending pin's diff — including for empty config files — but keeps its TOML dump: a pin is additive, unlike a deprecation diff that supersedes the dump.

This departs from the plan reviewed in design/list-json-v2.md (#3357), which deferred the wt config update integration to the default flip. Deliberate tradeoff: users who run update during the window land pinned on schema 1 and will see the = 1 deprecation round after the flip; in exchange, the warning ships with its fixer.

Testing: unit tests pin the rule's iff (unset ⟺ update changes the file), kind scoping (System/Project inert, load pass inert), the PendingDefault-rule/kind coupling, and placement in existing or implicit [list] sections; integration tests cover both hint variants, the update flow end-to-end (pin applied, second run clean), --print, and the system-config deferral. The invariant battery runs with an explicit pin appended so each case exercises only its own rule. Full pre-merge gate green (4386 tests) plus --features shell-integration-tests clippy.

🤖 Generated with Claude Code

This was written by Claude Code on behalf of max

…system

The unset nag looks like a deprecation warning but wt config update can't
service it; record the rationale from design/list-json-v2.md (reviewed in
#3357) at the nag site: unset is a pending choice between two valid
schemas, so there's no behavior-preserving rewrite until the default
flips and = 1 becomes a real DEPRECATION_RULES row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewing as a draft — flagging anything that looks worth a quick fix. Mark ready for a full review.

The comment is accurate and reads well. One small pointer issue: design/list-json-v2.md won't resolve for a reader on any branch — design docs are removed from the net diff by repo convention, and #3357's own body pins this one to commit e1c9b72e0 ("it remains readable at e1c9b72"). As written, the bare path reads as a present file; a reader has to open #3357 to discover where it actually lives. Inline suggestion carries the SHA pin over so the reference is followable in one hop.

Comment thread src/commands/list/mod.rs Outdated
max-sixty and others added 3 commits July 10, 2026 00:45
The JSON-schema nag now comes with the standard fixer: a new
PendingDefault row in DEPRECATION_RULES inserts json-schema = 1 on the
update pass only, scoped to user config via a ConfigFileKind threaded
through detection (replacing the string labels). The nag's hint offers
wt config update when a user config file exists; config show renders
the pending pin without dropping its TOML dump.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Gate the pin on the system config layer not defining json-schema:
  a user-file pin would override a system-level = 2 and flip resolved
  JSON output, the opposite of behavior preservation.
- Decide the nag hint by the same detection update runs, so a missing,
  unreadable, or malformed user config falls back to the manual-setting
  hint instead of offering an update that would no-op.
- Skip the load-path dedup registry when an info carries only pins.
- Render the pending pin in wt config show for empty config files too
  (update would rewrite them), and mirror the user/project renderers.
- Collapse pin_json_schema_doc to one match; dedup the hint prefix;
  warn_unknown_fields takes ConfigFileKind instead of a label string.
- Pin the PendingDefault-rule/kind coupling and the implicit-[list]
  promotion with tests; add a system-config integration test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@max-sixty max-sixty changed the title docs(list): explain why the json-schema nag bypasses the deprecation system feat(config): wt config update pins [list] json-schema while unset Jul 10, 2026
@max-sixty max-sixty marked this pull request as ready for review July 10, 2026 10:42
@max-sixty max-sixty merged commit dac0f80 into main Jul 10, 2026
40 checks passed
@max-sixty max-sixty deleted the json-schema-update-hint branch July 10, 2026 10:56
@max-sixty max-sixty mentioned this pull request Jul 10, 2026
max-sixty added a commit that referenced this pull request Jul 10, 2026
Release v0.67.0: version bump and changelog.

Highlights since v0.66.0: experimental `wt remove --reap` (#3396), `wt
switch -x` opening the picker (#3394), the termimad panic containment in
the picker's PR-comments preview (#3408), the `wt config show` SIGTTOU
fix (#3327), the `GIT_*` discovery-var scrub for `wt step for-each` and
the `--execute` fallback (#3400), and the `wt list` prompt-reserve fix
(#3409).

Seven commits landed on `main` after the initial cut; `origin/main` is
merged back in and the two user-facing ones (#3394, #3411) plus the BY
CONTEXT profile table (#3403) are folded into the changelog.

Pre-release validation: local pre-merge gate green on the merged tree
(4389 tests); nightly cross-platform suite green on the initial cut
([run
29086956095](https://github.com/max-sixty/worktrunk/actions/runs/29086956095)),
with the seven post-cut commits each validated by their own PR CI;
`cargo semver-checks` reports no breaking changes; data-loss surface
review of the cumulative diff (including the drift commits) found one
new destructive capability (`--reap`, explicit opt-in, adjudicated
acceptable).

> _This was written by Claude Code on behalf of max_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants