From 01a071f39602b858d284fbad9739c6fa624d6cdf Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Sat, 3 Oct 2026 06:56:12 +0000 Subject: [PATCH 1/2] docs(list): drop the stale-branch and dirty-tree skips from JSON help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `wt list --help` described three things the collector no longer does or never did: - `·` and JSON `null` blamed a branch "too stale for the expensive checks". The stale-branch skip was removed in #2098; nothing in `collect/` skips tasks by branch age now. - `default_branch.integration` was "null when a dirty tree skipped the checks". The probes run on the committed HEAD whatever the tree's state (json_v2.rs says so, and `test_integration_positive_match_ignores_cleanliness` pins a dirty `trees_match`); null comes from a timed-out or skipped probe. - "every reason renders as the same `⊂`" is false for `same_commit`, which the table shows as `_` or `–`. Also update the matching `JsonDefaultBranch::integration` docstring (which feeds the published list-v2 schema) and the internal comments in collect/execution.rs that still listed the stale-branch skip. --- docs/public/schema/list-v2.json | 2 +- docs/src/content/docs/list.md | 12 ++++---- .../skills/worktrunk/reference/list.md | 12 ++++---- skills/worktrunk/reference/list.md | 12 ++++---- src/cli/mod.rs | 12 ++++---- src/commands/list/collect/execution.rs | 12 ++++---- src/commands/list/json_v2.rs | 4 +-- ...tegration_tests__help__help_list_long.snap | 30 +++++++++---------- ...tion_tests__help__help_list_narrow_80.snap | 20 +++++++------ 9 files changed, 59 insertions(+), 57 deletions(-) diff --git a/docs/public/schema/list-v2.json b/docs/public/schema/list-v2.json index 3f338febb5..e0eb314449 100644 --- a/docs/public/schema/list-v2.json +++ b/docs/public/schema/list-v2.json @@ -217,7 +217,7 @@ }, "integration": { "$ref": "#/$defs/Nullable_JsonIntegration", - "description": "How committed content is integrated; absent when determined\nnot-integrated, null when undetermined (dirty trees skip the\nexpensive checks)." + "description": "How committed content is integrated; absent when determined\nnot-integrated, null when undetermined (a probe timed out or was\nskipped)." }, "merge_conflicts": { "description": "A merge into the default branch would conflict based on committed\ncontent and tracked worktree changes (local `merge-tree` simulation);\nnull while unresolved.", diff --git a/docs/src/content/docs/list.md b/docs/src/content/docs/list.md index bf0fb9b352..7d3d2ed099 100644 --- a/docs/src/content/docs/list.md +++ b/docs/src/content/docs/list.md @@ -221,7 +221,7 @@ These appear across all columns while the table is loading: | Symbol | Meaning | |--------|---------| -| `·` | Data is loading, or collection timed out / branch too stale | +| `·` | Data is loading, or collection timed out | --- @@ -269,9 +269,9 @@ How "no value" reads: - **Absent** — nothing to report: not applicable (`worktree` on a branch-only row), not requested this run (the envelope's `collected` records what was), or determined-empty (no PR, no lock, not integrated). -- **`null`** — requested but not determined: a task timed out, the branch was - too stale for the expensive checks, or a forge fetch failed. This is the - JSON form of the table's `·` placeholder. +- **`null`** — requested but not determined: a task timed out, a check was + skipped, or a forge fetch failed. This is the JSON form of the table's `·` + placeholder. jq treats absent and `null` identically in path expressions, so filters need no null checks; `has()` distinguishes the two when it matters. @@ -354,7 +354,7 @@ Independent facts; the table's priority-collapsed symbol is `display.state`. | `behind` | number/null | Commits behind the default branch (null for orphans) | | `diff` | object/null | Lines changed vs the default branch: `{added, deleted}` | | `orphan` | boolean/null | No common ancestor with the default branch | -| `integration` | object/null | `{reason}` — which check found the content [integrated](/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when a dirty tree skipped the checks | +| `integration` | object/null | `{reason}` — which check found the content [integrated](/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when undetermined (a check timed out or was skipped) | | `merge_conflicts` | boolean/null | Merging into the default branch would conflict, simulated locally with `git merge-tree` | ### upstream object @@ -426,7 +426,7 @@ The single highest-priority state describing the branch's relation to the defaul ### integration reasons -`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. JSON-only — every reason renders as the same `⊂`: +`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. The reason itself is JSON-only: the table shows `"same_commit"` as `_` (or `–` with uncommitted changes) and every other reason as `⊂` when the working tree is clean: | Value | Meaning | |-------|---------| diff --git a/plugins/worktrunk/skills/worktrunk/reference/list.md b/plugins/worktrunk/skills/worktrunk/reference/list.md index 3f2e56acce..93457d45a4 100644 --- a/plugins/worktrunk/skills/worktrunk/reference/list.md +++ b/plugins/worktrunk/skills/worktrunk/reference/list.md @@ -205,7 +205,7 @@ These appear across all columns while the table is loading: | Symbol | Meaning | |--------|---------| -| `·` | Data is loading, or collection timed out / branch too stale | +| `·` | Data is loading, or collection timed out | --- @@ -253,9 +253,9 @@ How "no value" reads: - **Absent** — nothing to report: not applicable (`worktree` on a branch-only row), not requested this run (the envelope's `collected` records what was), or determined-empty (no PR, no lock, not integrated). -- **`null`** — requested but not determined: a task timed out, the branch was - too stale for the expensive checks, or a forge fetch failed. This is the - JSON form of the table's `·` placeholder. +- **`null`** — requested but not determined: a task timed out, a check was + skipped, or a forge fetch failed. This is the JSON form of the table's `·` + placeholder. jq treats absent and `null` identically in path expressions, so filters need no null checks; `has()` distinguishes the two when it matters. @@ -338,7 +338,7 @@ Independent facts; the table's priority-collapsed symbol is `display.state`. | `behind` | number/null | Commits behind the default branch (null for orphans) | | `diff` | object/null | Lines changed vs the default branch: `{added, deleted}` | | `orphan` | boolean/null | No common ancestor with the default branch | -| `integration` | object/null | `{reason}` — which check found the content [integrated](https://worktrunk.dev/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when a dirty tree skipped the checks | +| `integration` | object/null | `{reason}` — which check found the content [integrated](https://worktrunk.dev/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when undetermined (a check timed out or was skipped) | | `merge_conflicts` | boolean/null | Merging into the default branch would conflict, simulated locally with `git merge-tree` | ### upstream object @@ -410,7 +410,7 @@ The single highest-priority state describing the branch's relation to the defaul ### integration reasons -`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. JSON-only — every reason renders as the same `⊂`: +`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. The reason itself is JSON-only: the table shows `"same_commit"` as `_` (or `–` with uncommitted changes) and every other reason as `⊂` when the working tree is clean: | Value | Meaning | |-------|---------| diff --git a/skills/worktrunk/reference/list.md b/skills/worktrunk/reference/list.md index 3f2e56acce..93457d45a4 100644 --- a/skills/worktrunk/reference/list.md +++ b/skills/worktrunk/reference/list.md @@ -205,7 +205,7 @@ These appear across all columns while the table is loading: | Symbol | Meaning | |--------|---------| -| `·` | Data is loading, or collection timed out / branch too stale | +| `·` | Data is loading, or collection timed out | --- @@ -253,9 +253,9 @@ How "no value" reads: - **Absent** — nothing to report: not applicable (`worktree` on a branch-only row), not requested this run (the envelope's `collected` records what was), or determined-empty (no PR, no lock, not integrated). -- **`null`** — requested but not determined: a task timed out, the branch was - too stale for the expensive checks, or a forge fetch failed. This is the - JSON form of the table's `·` placeholder. +- **`null`** — requested but not determined: a task timed out, a check was + skipped, or a forge fetch failed. This is the JSON form of the table's `·` + placeholder. jq treats absent and `null` identically in path expressions, so filters need no null checks; `has()` distinguishes the two when it matters. @@ -338,7 +338,7 @@ Independent facts; the table's priority-collapsed symbol is `display.state`. | `behind` | number/null | Commits behind the default branch (null for orphans) | | `diff` | object/null | Lines changed vs the default branch: `{added, deleted}` | | `orphan` | boolean/null | No common ancestor with the default branch | -| `integration` | object/null | `{reason}` — which check found the content [integrated](https://worktrunk.dev/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when a dirty tree skipped the checks | +| `integration` | object/null | `{reason}` — which check found the content [integrated](https://worktrunk.dev/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when undetermined (a check timed out or was skipped) | | `merge_conflicts` | boolean/null | Merging into the default branch would conflict, simulated locally with `git merge-tree` | ### upstream object @@ -410,7 +410,7 @@ The single highest-priority state describing the branch's relation to the defaul ### integration reasons -`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. JSON-only — every reason renders as the same `⊂`: +`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. The reason itself is JSON-only: the table shows `"same_commit"` as `_` (or `–` with uncommitted changes) and every other reason as `⊂` when the working tree is clean: | Value | Meaning | |-------|---------| diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 3f90a93589..ed3db53897 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1005,7 +1005,7 @@ These appear across all columns while the table is loading: | Symbol | Meaning | |--------|---------| -| `·` | Data is loading, or collection timed out / branch too stale | +| `·` | Data is loading, or collection timed out | --- @@ -1053,9 +1053,9 @@ How "no value" reads: - **Absent** — nothing to report: not applicable (`worktree` on a branch-only row), not requested this run (the envelope's `collected` records what was), or determined-empty (no PR, no lock, not integrated). -- **`null`** — requested but not determined: a task timed out, the branch was - too stale for the expensive checks, or a forge fetch failed. This is the - JSON form of the table's `·` placeholder. +- **`null`** — requested but not determined: a task timed out, a check was + skipped, or a forge fetch failed. This is the JSON form of the table's `·` + placeholder. jq treats absent and `null` identically in path expressions, so filters need no null checks; `has()` distinguishes the two when it matters. @@ -1138,7 +1138,7 @@ Independent facts; the table's priority-collapsed symbol is `display.state`. | `behind` | number/null | Commits behind the default branch (null for orphans) | | `diff` | object/null | Lines changed vs the default branch: `{added, deleted}` | | `orphan` | boolean/null | No common ancestor with the default branch | -| `integration` | object/null | `{reason}` — which check found the content [integrated](/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when a dirty tree skipped the checks | +| `integration` | object/null | `{reason}` — which check found the content [integrated](/remove/#branch-cleanup) (see [integration reasons](#integration-reasons)); absent when determined not-integrated, null when undetermined (a check timed out or was skipped) | | `merge_conflicts` | boolean/null | Merging into the default branch would conflict, simulated locally with `git merge-tree` | ### upstream object @@ -1210,7 +1210,7 @@ The single highest-priority state describing the branch's relation to the defaul ### integration reasons -`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. JSON-only — every reason renders as the same `⊂`: +`default_branch.integration.reason` records which check matched. Checks run cheapest-first and the first match wins. The reason itself is JSON-only: the table shows `"same_commit"` as `_` (or `–` with uncommitted changes) and every other reason as `⊂` when the working tree is clean: | Value | Meaning | |-------|---------| diff --git a/src/commands/list/collect/execution.rs b/src/commands/list/collect/execution.rs index 91be259062..6b9ff95cf8 100644 --- a/src/commands/list/collect/execution.rs +++ b/src/commands/list/collect/execution.rs @@ -12,9 +12,9 @@ //! `refresh_status_symbols` resolves each gate independently, reading that //! gate's required fields on `ListItem` / `WorktreeData` as they become //! `Some`. Tasks that *will* run are written by the drain as their results -//! arrive. Tasks that will *not* run (stale branches skip expensive tasks, -//! unborn branches skip commit-dependent tasks, the column plan excludes them, -//! branches with no worktree have no worktree-only tasks) have their fields +//! arrive. Tasks that will *not* run (unborn branches skip commit-dependent +//! tasks, the column plan excludes them, branches with no worktree have no +//! worktree-only tasks) have their fields //! seeded here via [`seed_skipped_task_defaults`] with conservative defaults //! — otherwise the fields would stay `None` forever and their gate would //! never resolve. @@ -126,7 +126,7 @@ impl ExpectedResults { /// /// `refresh_status_symbols` keeps gates at `None` while their inputs are /// unloaded, which renders as the `·` placeholder. For tasks that will -/// *never* run (stale branch, a task no rendered column needs, unborn item missing +/// *never* run (a task no rendered column needs, unborn item missing /// commit-dependent tasks, prunable worktree), seeding a conservative /// default up front lets the gate resolve normally instead of showing `·` /// forever. @@ -276,7 +276,7 @@ pub(super) fn seed_prunable_item(item: &mut ListItem) { /// /// **Side effects on `item`:** /// - Seeds conservative sentinels on fields corresponding to tasks that will -/// *not* run (stale/unborn/skipped). See module docstring. +/// *not* run (unborn/skipped). See module docstring. /// /// **Side effects on `tx`:** /// - Sends an immediate `TaskResult::UrlStatus { url: Some, active: None }` @@ -287,7 +287,7 @@ pub(super) fn seed_prunable_item(item: &mut ListItem) { /// directly here would leave it stuck behind whatever task happens to /// complete first. /// -/// Task preconditions (stale branch, unborn branch, missing llm_command) are +/// Task preconditions (unborn branch, missing llm_command) are /// enforced here — not in callers. This function is called from both /// `collect()` and `populate_item()`, so guards must live here to cover all /// entry points. diff --git a/src/commands/list/json_v2.rs b/src/commands/list/json_v2.rs index 4a4c265910..02a37a82c6 100644 --- a/src/commands/list/json_v2.rs +++ b/src/commands/list/json_v2.rs @@ -333,8 +333,8 @@ pub struct JsonDefaultBranch { pub orphan: Option, /// How committed content is integrated; absent when determined - /// not-integrated, null when undetermined (dirty trees skip the - /// expensive checks). + /// not-integrated, null when undetermined (a probe timed out or was + /// skipped). #[serde(skip_serializing_if = "Tri::is_absent")] pub integration: Tri, diff --git a/tests/snapshots/integration__integration_tests__help__help_list_long.snap b/tests/snapshots/integration__integration_tests__help__help_list_long.snap index 8ab8a20392..c9c1840ecb 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_long.snap @@ -281,9 +281,9 @@ field. These appear across all columns while the table is loading: - Symbol Meaning - ────── ─────────────────────────────────────────────────────────── - · Data is loading, or collection timed out / branch too stale + Symbol Meaning + ────── ──────────────────────────────────────── + · Data is loading, or collection timed out ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── @@ -329,9 +329,9 @@ How "no value" reads: - Absent — nothing to report: not applicable (worktree on a branch-only row), not requested this run (the envelope's collected records what was), or determined-empty (no PR, no lock, not integrated). -- null — requested but not determined: a task timed out, the branch was - too stale for the expensive checks, or a forge fetch failed. This is the - JSON form of the table's · placeholder. +- null — requested but not determined: a task timed out, a check was + skipped, or a forge fetch failed. This is the JSON form of the table's · + placeholder. jq treats absent and null identically in path expressions, so filters need no null checks; has() distinguishes the two when it matters. @@ -408,14 +408,14 @@ The five change flags map to the Working tree symbols (renamed and d Independent facts; the table's priority-collapsed symbol is display.state. - Field Type Description - ─────────────── ──────────── ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── - ahead number/null Commits ahead of the default branch (null for orphans) - behind number/null Commits behind the default branch (null for orphans) - diff object/null Lines changed vs the default branch: {added, deleted} - orphan boolean/null No common ancestor with the default branch - integration object/null {reason} — which check found the content integrated (see integration reasons); absent when determined not-integrated, null when a dirty tree skipped the checks - merge_conflicts boolean/null Merging into the default branch would conflict, simulated locally with git merge-tree + Field Type Description + ─────────────── ──────────── ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + ahead number/null Commits ahead of the default branch (null for orphans) + behind number/null Commits behind the default branch (null for orphans) + diff object/null Lines changed vs the default branch: {added, deleted} + orphan boolean/null No common ancestor with the default branch + integration object/null {reason} — which check found the content integrated (see integration reasons); absent when determined not-integrated, null when undetermined (a check timed out or was skipped) + merge_conflicts boolean/null Merging into the default branch would conflict, simulated locally with git merge-tree upstream object @@ -486,7 +486,7 @@ The single highest-priority state describing the branch's relation to the defaul integration reasons -default_branch.integration.reason records which check matched. Checks run cheapest-first and the first match wins. JSON-only — every reason renders as the same ⊂: +default_branch.integration.reason records which check matched. Checks run cheapest-first and the first match wins. The reason itself is JSON-only: the table shows "same_commit" as _ (or – with uncommitted changes) and every other reason as ⊂ when the working tree is clean: Value Meaning ──────────────────── ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap index 9198455e5e..db8e55156a 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap @@ -344,9 +344,9 @@ field. These appear across all columns while the table is loading: - Symbol Meaning - ────── ─────────────────────────────────────────────────────────── - · Data is loading, or collection timed out / branch too stale + Symbol Meaning + ────── ──────────────────────────────────────── + · Data is loading, or collection timed out ──────────────────────────────────────────────────────────────────────────────── @@ -396,9 +396,9 @@ How "no value" reads: - Absent — nothing to report: not applicable (worktree on a branch-only row), not requested this run (the envelope's collected records what was), or determined-empty (no PR, no lock, not integrated). -- null — requested but not determined: a task timed out, the branch was - too stale for the expensive checks, or a forge fetch failed. This is the - JSON form of the table's · placeholder. +- null — requested but not determined: a task timed out, a check was + skipped, or a forge fetch failed. This is the JSON form of the table's · + placeholder. jq treats absent and null identically in path expressions, so filters need no null checks; has() distinguishes the two when it matters. @@ -505,7 +505,8 @@ Independent facts; the table's priority-collapsed symbol is display.state[0 l integrat object/null {reason} — which check found the content integrated (see ion integration reasons); absent when determined - not-integrated, null when a dirty tree skipped the checks + not-integrated, null when undetermined (a check timed out + or was skipped) merge_co boolean/nul Merging into the default branch would conflict, simulated nflicts l locally with git merge-tree @@ -595,8 +596,9 @@ full meaning of each value ("is_main", "orphan", "empty" integration reasons default_branch.integration.reason records which check matched. Checks run -cheapest-first and the first match wins. JSON-only — every reason renders as the - same ⊂: +cheapest-first and the first match wins. The reason itself is JSON-only: the +table shows "same_commit" as _ (or – with uncommitted changes) and every other +reason as ⊂ when the working tree is clean: Value Meaning ────────────── ─────────────────────────────────────────────────────────────── From 2f5f863872737e4944be4cf3051c4a6986dcad7f Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Sat, 3 Oct 2026 07:12:57 +0000 Subject: [PATCH 2/2] docs(list): drop stale-branch exception from status_symbols module doc --- src/commands/list/model/status_symbols.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/list/model/status_symbols.rs b/src/commands/list/model/status_symbols.rs index 49f22b47b9..a416b1c27f 100644 --- a/src/commands/list/model/status_symbols.rs +++ b/src/commands/list/model/status_symbols.rs @@ -130,10 +130,10 @@ //! seeded, gate 3 resolves to `None` for unborn non-main items and the row //! still renders. //! -//! **Exception — stale branches and `--skip-tasks`:** fields for +//! **Exception — tasks the column plan skips:** fields for //! deliberately-skipped tasks are seeded at spawn time with conservative -//! defaults. Stale branches can render a less-specific main-state symbol -//! than fresh ones (e.g., `↕` instead of `⊂`). +//! defaults. Items with skipped integration tasks can render a less-specific +//! main-state symbol (e.g., `↕` instead of `⊂`). //! //! # Gate 4: Upstream divergence (position 5) //!