ace-git-worktree 0.26.1 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.ace-defaults/nav/protocols/skill-sources/ace-git-worktree.yml +0 -0
  3. data/.ace-defaults/nav/protocols/wfi-sources/ace-git-worktree.yml +0 -0
  4. data/CHANGELOG.md +62 -0
  5. data/LICENSE +0 -0
  6. data/README.md +0 -0
  7. data/Rakefile +0 -0
  8. data/docs/demo/ace-git-worktree-getting-started.gif +0 -0
  9. data/docs/demo/ace-git-worktree-getting-started.tape.yml +0 -0
  10. data/docs/demo/fixtures/README.md +0 -0
  11. data/docs/demo/fixtures/sample.txt +0 -0
  12. data/docs/getting-started.md +7 -4
  13. data/docs/handbook.md +0 -0
  14. data/docs/usage.md +153 -24
  15. data/handbook/agents/worktree.ag.md +10 -6
  16. data/handbook/skills/as-git-worktree/SKILL.md +0 -0
  17. data/handbook/skills/as-git-worktree-cleanup/SKILL.md +0 -0
  18. data/handbook/skills/as-git-worktree-create/SKILL.md +0 -0
  19. data/handbook/skills/as-git-worktree-manage/SKILL.md +0 -0
  20. data/handbook/workflow-instructions/git/worktree-create.wf.md +3 -3
  21. data/handbook/workflow-instructions/git/worktree-manage.wf.md +6 -6
  22. data/handbook/workflow-instructions/git/worktree.wf.md +2 -2
  23. data/lib/ace/git/worktree/atoms/duration_parser.rb +81 -0
  24. data/lib/ace/git/worktree/atoms/git_command.rb +0 -0
  25. data/lib/ace/git/worktree/atoms/path_expander.rb +0 -0
  26. data/lib/ace/git/worktree/atoms/relative_age_formatter.rb +59 -0
  27. data/lib/ace/git/worktree/atoms/slug_generator.rb +0 -0
  28. data/lib/ace/git/worktree/atoms/task_id_extractor.rb +20 -1
  29. data/lib/ace/git/worktree/atoms/text_truncator.rb +67 -0
  30. data/lib/ace/git/worktree/cli/commands/bootstrap.rb +0 -0
  31. data/lib/ace/git/worktree/cli/commands/cleanup.rb +0 -0
  32. data/lib/ace/git/worktree/cli/commands/config.rb +0 -0
  33. data/lib/ace/git/worktree/cli/commands/create.rb +0 -0
  34. data/lib/ace/git/worktree/cli/commands/list.rb +29 -8
  35. data/lib/ace/git/worktree/cli/commands/prune.rb +0 -0
  36. data/lib/ace/git/worktree/cli/commands/remove.rb +0 -0
  37. data/lib/ace/git/worktree/cli/commands/shared_helpers.rb +0 -0
  38. data/lib/ace/git/worktree/cli/commands/switch.rb +0 -0
  39. data/lib/ace/git/worktree/cli.rb +1 -1
  40. data/lib/ace/git/worktree/commands/bootstrap_command.rb +0 -0
  41. data/lib/ace/git/worktree/commands/list_command.rb +90 -94
  42. data/lib/ace/git/worktree/commands/prune_command.rb +0 -0
  43. data/lib/ace/git/worktree/commands/remove_command.rb +0 -0
  44. data/lib/ace/git/worktree/commands/switch_command.rb +0 -0
  45. data/lib/ace/git/worktree/configuration.rb +0 -0
  46. data/lib/ace/git/worktree/models/task_index.rb +186 -0
  47. data/lib/ace/git/worktree/models/worktree_info.rb +52 -3
  48. data/lib/ace/git/worktree/models/worktree_metadata.rb +0 -0
  49. data/lib/ace/git/worktree/molecules/bootstrap_executor.rb +0 -0
  50. data/lib/ace/git/worktree/molecules/cleanup_applier.rb +0 -0
  51. data/lib/ace/git/worktree/molecules/config_loader.rb +0 -0
  52. data/lib/ace/git/worktree/molecules/current_task_linker.rb +0 -0
  53. data/lib/ace/git/worktree/molecules/hook_executor.rb +0 -0
  54. data/lib/ace/git/worktree/molecules/parent_task_resolver.rb +0 -0
  55. data/lib/ace/git/worktree/molecules/pr_status_resolver.rb +172 -0
  56. data/lib/ace/git/worktree/molecules/recent_branch_counter.rb +70 -0
  57. data/lib/ace/git/worktree/molecules/task_association_resolver.rb +121 -0
  58. data/lib/ace/git/worktree/molecules/task_fetcher.rb +0 -0
  59. data/lib/ace/git/worktree/molecules/task_index_builder.rb +121 -0
  60. data/lib/ace/git/worktree/molecules/task_pusher.rb +0 -0
  61. data/lib/ace/git/worktree/molecules/task_status_updater.rb +0 -0
  62. data/lib/ace/git/worktree/molecules/toolchain_truster.rb +0 -0
  63. data/lib/ace/git/worktree/molecules/worktree_footer_formatter.rb +43 -0
  64. data/lib/ace/git/worktree/molecules/worktree_lister.rb +22 -93
  65. data/lib/ace/git/worktree/molecules/worktree_probe.rb +196 -0
  66. data/lib/ace/git/worktree/molecules/worktree_remover.rb +0 -0
  67. data/lib/ace/git/worktree/molecules/worktree_table_formatter.rb +241 -0
  68. data/lib/ace/git/worktree/organisms/worktree_list_report.rb +315 -0
  69. data/lib/ace/git/worktree/organisms/worktree_manager.rb +22 -20
  70. data/lib/ace/git/worktree/organisms/worktree_probe_runner.rb +320 -0
  71. data/lib/ace/git/worktree/version.rb +1 -1
  72. data/lib/ace/git/worktree.rb +14 -0
  73. metadata +15 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a51dd94ea8eeadcabd99be5d79ee88d9c536114637c58781d8ac8c8089243587
4
- data.tar.gz: a8389cc335baa6559bf8ee4f88b167ceb90ca2c0669341f72f632f0c81968f40
3
+ metadata.gz: 3fbcf3673de821e4ed42fd7415a7cc0fa88fca4176d2d3cfbf7cff65e6d50332
4
+ data.tar.gz: ec88eedd7b9f6d3822835b70777e235a5581cacf3a413a98ee4a4bdd66eb5ae1
5
5
  SHA512:
6
- metadata.gz: 8a65769172a854d95a44dd5d268ed14fd73a259b652978955139c7a5ac1f0653e7d78d47e5149dd17a90c9835f3281bf2fcf13111d67561e7458d5324b75f933
7
- data.tar.gz: 7412edb73d8944f55c50b4fecb7fa8ca6e977cdcd59f2b4377fa5f823d5207bae36becfba4cc2d1a5305184d6d8acd526c530710e50fee2e507c5b114d85290c
6
+ metadata.gz: 8e3038cf6f5465be9074866bd6c174da7c79839fa94eb0e6abc902ea1f7300dc4fb511e6132a55841e92de594b0b9c89f9a8401de08020a37f7ae0baec512bf0
7
+ data.tar.gz: 73ee36beff2acc5bcda6d456db1715b95b3dc580193ce07acaab7e9ec89a591674756a456036d179b2ee30b4f054bd5a2d007e99c24b7f54e2b9f6423fac503a
data/CHANGELOG.md CHANGED
@@ -7,6 +7,68 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.27.1] - 2026-10-18
11
+
12
+ ### Changed
13
+
14
+ - `list` table rows now print the full, never-truncated worktree path on its
15
+ own line under the row (indented to the `Commit` column) followed by a blank
16
+ separator line, replacing the truncated `Path` column. Every displayed path
17
+ is directly usable (`cd`, copy/paste); `--full` prints absolute paths.
18
+ - `Changes` counts staged + unstaged + untracked files under `.ace-tasks/`;
19
+ untracked files outside the task tree are no longer scanned or counted.
20
+
21
+ ### Fixed
22
+
23
+ - Large-repository listing performance: the deep untracked walk
24
+ (`--untracked-files=all`) dominated runtime and degraded further under
25
+ parallel probing (88 worktrees: ~18s). Probes now read tracked-only status
26
+ and run the deep `.ace-tasks/` untracked scan as a selective second round
27
+ for worktrees the cheap association tiers cannot resolve (~7s).
28
+ - Task index lookups no longer re-`realpath` every task directory on every
29
+ lookup; canonical paths are resolved once per index.
30
+
31
+ ## [0.27.0] - 2026-10-17
32
+
33
+ ### Added
34
+
35
+ - `ace-git-worktree list` now defaults to a compact active-worktree table: one
36
+ enriched row per worktree whose last commit or uncommitted changes fall inside
37
+ the activity window (`--active-within`, default `18h`), plus a two-line count
38
+ footer. Columns: Task, Branch, Age, Commit, Changes, PR, Path.
39
+ - `--full` lists every worktree in the same columns with absolute, untruncated
40
+ paths; `--compact` is the explicit default and is mutually exclusive with
41
+ `--full`.
42
+ - Name-independent task association with provenance: recorded task metadata,
43
+ the `_current` symlink, validated path/branch names, then task files modified
44
+ in the worktree (uncommitted first, then commits vs the primary branch
45
+ merge-base). Ambiguous inference renders `<id>+N` and exposes all candidates.
46
+ - PR resolution through one bounded forge query per run: branch match, then HEAD
47
+ commit sha, then a unique task reference in the PR title/body.
48
+ - Per-worktree probing in isolated forked children: at most 16 live children,
49
+ 5 second per-probe budget, process-group kill on timeout, deterministic
50
+ `git worktree list` order, and a sequential fallback where `fork` is
51
+ unavailable. Probe failures render `?` without failing the command.
52
+ - Width-aware table layout driven by `COLUMNS`/the terminal size: columns shrink
53
+ in priority order (Path, Commit, Branch) and Path/Commit drop on narrow
54
+ terminals; compact output never exceeds the detected width.
55
+ - `--format json` additions per selected worktree: `task_id_source`, `task_ids`,
56
+ `active_within_window`, `last_commit`, `uncommitted`, and `pr` with `state`,
57
+ `draft`, and `matched_by`. Existing keys are unchanged.
58
+
59
+ ### Changed
60
+
61
+ - `ace-git-worktree list` output is now the active-worktree table; the legacy
62
+ plain Task/Branch/Path/Status table and the `Summary:` block are gone.
63
+ - Invalid `--active-within` values, mutually exclusive detail flags, and removed
64
+ flags fail with actionable one-line errors and a non-zero exit.
65
+
66
+ ### Removed
67
+
68
+ - `--show-tasks`: the Task column is always present and association is always
69
+ inferred. Passing `--show-tasks` now fails as an unknown option (ADR-024, no
70
+ compatibility layer).
71
+
10
72
  ## [0.26.1] - 2026-10-10
11
73
 
12
74
  ### Fixed
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
File without changes
data/Rakefile CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -53,10 +53,13 @@ This keeps your shell history simple while avoiding hard-coded worktree paths.
53
53
  List worktrees with task context when you want a quick overview:
54
54
 
55
55
  ```bash
56
- ace-git-worktree list --show-tasks
56
+ ace-git-worktree list
57
57
  ```
58
58
 
59
- Use `--search auth` or `--format json` later when you want filtering or machine-readable output.
59
+ The default view shows only worktrees active in the last 18 hours, with task,
60
+ age, last commit, uncommitted changes, and PR context. Use `--full` for an
61
+ exhaustive listing, `--active-within 3d` for a wider window, `--search auth` to
62
+ filter, or `--format json` for machine-readable output.
60
63
 
61
64
  ## 4. Create a PR Worktree
62
65
 
@@ -102,7 +105,7 @@ Add hooks, auto-push, terminal launch, or PR automation only after the basic cre
102
105
  | Create a task worktree | `ace-git-worktree create --task 081` |
103
106
  | Create a PR worktree | `ace-git-worktree create --pr 26` |
104
107
  | Switch into a worktree | `cd "$(ace-git-worktree switch 081)"` |
105
- | List worktrees with task info | `ace-git-worktree list --show-tasks` |
108
+ | List active worktrees with task info | `ace-git-worktree list` |
106
109
  | Remove a task worktree | `ace-git-worktree remove --task 081` |
107
110
  | Preview stale cleanup | `ace-git-worktree prune --dry-run` |
108
111
 
@@ -128,7 +131,7 @@ ace-git-worktree list
128
131
  ### Task filtering behavior
129
132
 
130
133
  ```bash
131
- ace-git-worktree list --show-tasks
134
+ ace-git-worktree list
132
135
  ace-git-worktree list --task-associated
133
136
  ace-git-worktree list --no-task-associated
134
137
  ```
data/docs/handbook.md CHANGED
File without changes
data/docs/usage.md CHANGED
@@ -3,8 +3,8 @@ doc-type: user
3
3
  title: ace-git-worktree CLI Usage Reference
4
4
  purpose: Command reference for ace-git-worktree
5
5
  ace-docs:
6
- last-updated: 2026-04-14
7
- last-checked: 2026-03-22
6
+ last-updated: 2026-10-17
7
+ last-checked: 2026-10-17
8
8
  ---
9
9
 
10
10
  # ace-git-worktree CLI Usage Reference
@@ -38,7 +38,7 @@ Create a task worktree, list active worktrees, and resolve the path for shell na
38
38
 
39
39
  ```bash
40
40
  ace-git-worktree create --task 081
41
- ace-git-worktree list --show-tasks
41
+ ace-git-worktree list
42
42
  ace-git-worktree switch 081
43
43
  ```
44
44
 
@@ -62,14 +62,14 @@ Success looks like a new worktree directory exists and `switch` returns a path y
62
62
 
63
63
  ```bash
64
64
  ace-git-worktree create --task 081
65
- ace-git-worktree list --show-tasks
65
+ ace-git-worktree list
66
66
  ```
67
67
 
68
68
  **Expected output:**
69
69
 
70
70
  ```text
71
71
  Created task worktree and branch for 081
72
- ... task.081 appears in the worktree list ...
72
+ ... task 081 appears in the active worktree table ...
73
73
  ```
74
74
 
75
75
  **Next steps:** Run `cd "$(ace-git-worktree switch 081)"` to move into the new worktree.
@@ -143,7 +143,7 @@ ace-git-worktree cleanup --target main --apply --approved-digest <sha256-digest>
143
143
  **Commands:**
144
144
 
145
145
  ```bash
146
- ace-git-worktree list --show-tasks
146
+ ace-git-worktree list
147
147
  ace-git-worktree list --task-associated
148
148
  ace-git-worktree list --no-task-associated
149
149
  ```
@@ -151,9 +151,50 @@ ace-git-worktree list --no-task-associated
151
151
  **Expected output:**
152
152
 
153
153
  ```text
154
- ... --show-tasks includes task metadata ...
155
- ... --task-associated excludes the main worktree ...
156
- ... --no-task-associated shows main/non-task entries only ...
154
+ ... the default view lists only worktrees active in the last 18h ...
155
+ ... --task-associated keeps only worktrees with a resolved task id ...
156
+ ... --no-task-associated shows only worktrees without a task id ...
157
+ ```
158
+
159
+ ### Scenario 4: Find Work Without Meaningful Worktree Names
160
+
161
+ **Goal:** A worktree created by another tool has a path/branch that names no
162
+ task. Still identify its task and PR.
163
+
164
+ **Commands:**
165
+
166
+ ```bash
167
+ ace-git-worktree list
168
+ ace-git-worktree list --format json
169
+ ```
170
+
171
+ **Expected output:**
172
+
173
+ ```text
174
+ ... the Task cell shows the task whose .ace-tasks files were modified there ...
175
+ ... `ace-git-worktree list --format json` reports task_id_source=task_files ...
176
+ ```
177
+
178
+ The PR cell resolves by branch name, then by HEAD commit, then by a unique task
179
+ reference in the PR title/body; `null`/`-` means no match. The JSON entry exposes
180
+ `pr.matched_by` (`branch`, `head_sha`, or `task_reference`).
181
+
182
+ ### Scenario 5: Exhaustive Listing and Custom Window
183
+
184
+ **Goal:** Inspect every worktree, or widen the activity window after a weekend.
185
+
186
+ **Commands:**
187
+
188
+ ```bash
189
+ ace-git-worktree list --full
190
+ ace-git-worktree list --active-within 3d
191
+ ```
192
+
193
+ **Expected output:**
194
+
195
+ ```text
196
+ ... --full lists every worktree with absolute paths ...
197
+ ... --active-within 3d reads "Active worktrees (last 3d) -- N of M:" ...
157
198
  ```
158
199
 
159
200
  ### Scenario 5: Remove by Task and Delete Branch
@@ -216,33 +257,121 @@ ace-git-worktree create --task 081 --dry-run
216
257
 
217
258
  ### `ace-git-worktree list`
218
259
 
219
- List active worktrees with optional task metadata and filters.
260
+ List worktrees as an active-worktree table with task, activity, dirty-state, and
261
+ PR context. By default only worktrees active inside the activity window are
262
+ rows; everything else is collapsed into counts.
220
263
 
221
264
  ```bash
222
265
  ace-git-worktree list
223
- ace-git-worktree list --show-tasks
266
+ ace-git-worktree list --full
267
+ ace-git-worktree list --active-within 3d
224
268
  ace-git-worktree list --format json
269
+ ace-git-worktree list --task-associated
225
270
  ace-git-worktree list --search auth
226
271
  ```
227
272
 
228
273
  **Options:**
229
274
 
230
- * `--format` - Output format: `table`, `json`, or `simple`
231
- * `--show-tasks` - Include task associations
232
- * `--task-associated` - Show only task-associated worktrees
233
- * `--no-task-associated` - Show only non-task worktrees
234
- * `--usable` - Show only usable worktrees
235
- * `--search` - Filter by branch-name pattern
236
- * `-q`, `--quiet` - Suppress non-essential output
275
+ * `--compact` - Active worktrees only (the default; mutually exclusive with `--full`)
276
+ * `--full` - List every worktree in the same columns with absolute paths
277
+ * `--active-within <duration>` - Activity window: `30m`, `18h`, `2d`, or a bare
278
+ integer (hours). Default `18h`. Invalid, empty, zero, or negative values fail
279
+ with a non-zero exit.
280
+ * `--format` - Output format: `table` (default), `json`, or `simple`
281
+ * `--task-associated` / `--no-task-associated` - Filter by resolved task id
282
+ * `--usable` / `--no-usable` - Filter by usable (not bare/detached) state
283
+ * `--search <pattern>` - Filter by branch-name pattern
284
+ * `-q`, `--quiet` - Suppress the count footer
237
285
  * `-v`, `--verbose` - Show verbose output
238
286
  * `-d`, `--debug` - Show debug output
239
287
 
240
- **Minimal JSON contract (`--format json`):**
288
+ There is no `--show-tasks` flag: the Task column is always present and task
289
+ association is always inferred.
290
+
291
+ **Default output shape:**
292
+
293
+ ```text
294
+ Active worktrees (last 18h) -- 3 of 88:
295
+ Task Branch Age Commit Changes PR
296
+ ---------------------------------------------------------------------------------------
297
+ k9y codex/r3-bounded-convergence 17h feat(review): define bo… 2 #142 draft
298
+ ~/Ps/ace/.ace-wt/codex-r3-bounded-convergence
299
+
300
+ - codex/ei9-campaign-join 8m feat(ace-assign): compl… - -
301
+ ~/Ps/ace/.ace-wt/ei9-campaign-composition-join
302
+
303
+ Inactive: 85 (use --full to list all)
304
+ Task-associated: 14 Usable: 71 Recent branches without worktrees: 4
305
+ ```
241
306
 
242
- - Output is valid JSON (`array` or object containing worktree entries).
243
- - Each entry includes a stable path/identity surface usable by scripts (`path` and `branch` fields).
244
- - Task-associated entries expose `task_id`.
245
- - Non-task entries either omit `task_id` or set it to `null`.
307
+ Each worktree renders as three lines: the aligned columns, the
308
+ never-truncated path (indented to the `Commit` column, `$HOME` shortened to
309
+ `~` in compact mode, absolute with `--full`), and a blank separator line, so
310
+ every displayed path is directly usable (`cd`, copy/paste).
311
+
312
+ **Activity:** a worktree is active when the last commit reachable from its
313
+ checked-out HEAD is inside the window **or** it has uncommitted changes
314
+ (staged, unstaged, or untracked under `.ace-tasks/`). Bare worktrees are never
315
+ active. Filters apply before the active/inactive split, so the header and
316
+ footer counts always describe the filtered set. `Recent branches without
317
+ worktrees` is branch-based and is not affected by worktree filters.
318
+
319
+ **Columns:**
320
+
321
+ * `Task` - resolved short task id; `<id>+N` when N additional candidate tasks
322
+ were inferred from modified task files; `-` when unresolved.
323
+ * `Branch` - checked-out branch (middle-elided when truncated); `detached`.
324
+ * `Age` - last commit age in one unit (`8m`, `3h`, `9d`, `3w`, `2mo`, `1y`);
325
+ `never` when the branch has no commits; future timestamps render `0m`.
326
+ * `Commit` - last commit subject, right-truncated with `…`.
327
+ * `Changes` - uncommitted file count (staged + unstaged + untracked files
328
+ under `.ace-tasks/`); `-` when clean. Untracked files outside the task tree
329
+ are not scanned: the deep untracked walk dominates listing time on large
330
+ repositories, and stray artifacts are not an activity signal.
331
+ * `PR` - `#N` (open), `#N draft`, `#N merged`, `#N closed`, or `-`.
332
+
333
+ **Task association (name-independent), in precedence order:**
334
+
335
+ 1. recorded task metadata (`worktree.path` / `worktree.branch`);
336
+ 2. the `_current` symlink resolving under `.ace-tasks/`;
337
+ 3. a validated path/branch name extraction (rejected when it names no task);
338
+ 4. task files modified in the worktree (uncommitted first, then commits relative
339
+ to the merge-base with the primary worktree's branch). The dominant task wins
340
+ (most changed task files; lexicographic tie-break), rendered `<id>+N`.
341
+
342
+ **PR resolution:** one bounded forge query per run. A PR is matched by branch
343
+ name, then by HEAD commit sha, then by a unique task reference in the PR
344
+ title/body. Unconfigured/offline forges render `-` and never fail the command.
345
+
346
+ **Width behavior:** the table targets `120` columns, shrinks `Commit`, then
347
+ `Branch` down to their minimums, and drops `Commit` on very narrow terminals.
348
+ Width comes from `COLUMNS`, else the terminal size, else `120`. Path lines are
349
+ never truncated; `--full` is exempt from truncation entirely.
350
+
351
+ **Probe isolation and performance:** each worktree is probed in its own forked
352
+ child process (one child per worktree, at most 16 alive, hard 5 second budget
353
+ per probe). The probe reads only cheap signals: HEAD metadata, tracked changes
354
+ (`git status --untracked-files=no`), committed task-file diffs, and the
355
+ `_current` symlink. The expensive deep untracked scan of `.ace-tasks/` runs as
356
+ a selective second round, only for worktrees the cheap association tiers could
357
+ not resolve. Probe results are ordered by `git worktree list` order, so output
358
+ is deterministic; a failed or timed-out probe renders `?` in `Age`/`Commit`/
359
+ `Changes` while the rest of the table renders and the command exits 0. Where
360
+ `fork` is unavailable, probes run sequentially with the same timeouts.
361
+
362
+ **JSON contract (`--format json`):**
363
+
364
+ - Output is a top-level array of every selected (post-filter) worktree.
365
+ - Existing keys stay unchanged (`path`, `branch`, `commit`, `task_id`, `bare`,
366
+ `detached`, `created_at`, `usable`, `task_associated`, `exists`, `empty`).
367
+ - Added keys: `task_id_source` (`metadata|symlink|path|branch|task_files|null`),
368
+ `task_ids` (all candidates), `active_within_window` (boolean),
369
+ `last_commit` (`sha`, `age_hours`, `committed_at`, `subject`), `uncommitted`
370
+ (`staged`, `unstaged`, `untracked`, `total`), and `pr` (`number`, `state` in
371
+ `open|merged|closed`, `draft`, `matched_by` in
372
+ `branch|head_sha|task_reference`).
373
+ - Absent sub-objects are `null` rather than omitted. Detail flags do not change
374
+ JSON output.
246
375
 
247
376
  ### `ace-git-worktree switch [IDENTIFIER]`
248
377
 
@@ -477,7 +606,7 @@ fall back to another provider.
477
606
  **Solution:**
478
607
 
479
608
  ```bash
480
- ace-git-worktree list --show-tasks
609
+ ace-git-worktree list --full
481
610
  ```
482
611
 
483
612
  Confirm the identifier matches a task ID, branch name, directory name, or path shown in the current worktree list.
@@ -50,8 +50,8 @@ A specialized agent for managing git worktrees with task-aware automation. Handl
50
50
  # Create worktree for feature branch
51
51
  @worktree create feature-branch
52
52
 
53
- # List all worktrees
54
- @worktree list --show-tasks
53
+ # List active worktrees (last 18h) with task context
54
+ @worktree list
55
55
 
56
56
  # Switch to worktree
57
57
  @worktree switch feature-branch
@@ -106,10 +106,14 @@ The worktree agent accepts standard CLI parameters:
106
106
  - `--no-commit`: Skip committing task changes
107
107
 
108
108
  ### list
109
+ - `--compact`: Active worktrees only (default)
110
+ - `--full`: List every worktree (including inactive) with absolute paths
111
+ - `--active-within <duration>`: Activity window (`30m`, `18h`, `2d`, or bare hours; default 18h)
109
112
  - `--format <format>`: Output format (table, json, simple)
110
- - `--show-tasks`: Include task associations
111
- - `--task-associated`: Filter by task association
112
- - `--search <pattern>`: Filter by search pattern
113
+ - `--task-associated` / `--no-task-associated`: Filter by resolved task id
114
+ - `--usable` / `--no-usable`: Filter by usability
115
+ - `--search <pattern>`: Filter by branch-name pattern
116
+ - `-q`, `--quiet`: Suppress the count footer
113
117
 
114
118
  ### switch
115
119
  - `identifier`: Worktree identifier (task ID, branch name, directory, path)
@@ -179,7 +183,7 @@ The worktree agent provides deterministic output suitable for AI automation:
179
183
  WORKTREE_PATH=$(ace-git-worktree switch 081)
180
184
 
181
185
  # Get worktree status as JSON
182
- STATUS=$(ace-git-worktree list --format json --show-tasks)
186
+ STATUS=$(ace-git-worktree list --format json)
183
187
 
184
188
  # Create worktree and verify creation
185
189
  RESULT=$(ace-git-worktree create --task 081 --dry-run --format json)
File without changes
File without changes
File without changes
File without changes
@@ -86,7 +86,7 @@ ace-git-worktree create feature-branch --path ~/dev-work
86
86
 
87
87
  ```bash
88
88
  # List all worktrees
89
- ace-git-worktree list --show-tasks
89
+ ace-git-worktree list
90
90
 
91
91
  # Switch to the worktree
92
92
  cd $(ace-git-worktree switch 081)
@@ -218,7 +218,7 @@ ace-git-worktree list --task-associated
218
218
  ace-git-worktree prune --cleanup-directories
219
219
 
220
220
  # Get status in JSON for scripts
221
- ace-git-worktree list --format json --show-tasks
221
+ ace-git-worktree list --format json
222
222
  ```
223
223
 
224
224
  ## Error Handling
@@ -244,7 +244,7 @@ RESULT=$(ace-git-worktree create --task 081 --dry-run --format json)
244
244
  echo "$RESULT" | jq '.worktree_path'
245
245
 
246
246
  # List worktrees with task associations
247
- STATUS=$(ace-git-worktree list --format json --show-tasks)
247
+ STATUS=$(ace-git-worktree list --format json)
248
248
  echo "$STATUS" | jq '.worktrees[] | select(.task_associated == true)'
249
249
  ```
250
250
 
@@ -35,7 +35,7 @@ $action: Management action (list, switch, remove, prune)
35
35
  ace-git-worktree list
36
36
 
37
37
  # List with task associations
38
- ace-git-worktree list --show-tasks
38
+ ace-git-worktree list
39
39
 
40
40
  # List in different formats
41
41
  ace-git-worktree list --format json
@@ -158,10 +158,10 @@ ace-git-worktree config --show
158
158
 
159
159
  ```bash
160
160
  # Get worktree status for all tasks
161
- ace-git-worktree list --format json --show-tasks | jq '.worktrees'
161
+ ace-git-worktree list --format json | jq '.[]'
162
162
 
163
163
  # Count worktrees by type
164
- ace-git-worktree list --show-tasks | grep "Task" | wc -l
164
+ ace-git-worktree list --full | grep -c "Task"
165
165
 
166
166
  # Find worktrees with specific patterns
167
167
  ace-git-worktree list --search "bug" --format simple
@@ -184,7 +184,7 @@ ace-git-worktree list | grep -v "bare\|detached"
184
184
 
185
185
  ```bash
186
186
  # Get comprehensive status
187
- ace-git-worktree list --show-tasks --format json
187
+ ace-git-worktree list --format json
188
188
 
189
189
  # Check specific worktree
190
190
  ace-git-worktree switch 081 --verbose
@@ -199,7 +199,7 @@ ace-git-worktree config --validate
199
199
 
200
200
  ```bash
201
201
  # Get all worktrees as JSON
202
- WORKTREES=$(ace-git-worktree list --format json --show-tasks)
202
+ WORKTREES=$(ace-git-worktree list --format json)
203
203
 
204
204
  # Extract specific information
205
205
  echo "$WORKTREES" | jq '.worktrees[] | select(.task_id == "081")'
@@ -311,7 +311,7 @@ fi
311
311
 
312
312
  # 1. Check current worktree status
313
313
  echo "=== Current Worktree Status ==="
314
- ace-git-worktree list --show-tasks --format simple
314
+ ace-git-worktree list --format simple
315
315
 
316
316
  # 2. Clean up if needed
317
317
  echo "=== Cleanup Check ==="
@@ -72,7 +72,7 @@ ace-git-worktree create feature-branch --no-mise-trust
72
72
  ace-git-worktree list
73
73
 
74
74
  # Show task associations
75
- ace-git-worktree list --show-tasks
75
+ ace-git-worktree list
76
76
 
77
77
  # Filter by task association
78
78
  ace-git-worktree list --task-associated
@@ -170,7 +170,7 @@ git:
170
170
 
171
171
  ### list
172
172
  - `--format <format>`: Output format (table, json, simple)
173
- - `--show-tasks`: Include task associations
173
+ - `--full`: List every worktree (including inactive) with absolute paths
174
174
  - `--task-associated`: Filter by task association
175
175
  - `--search <pattern>`: Filter by search pattern
176
176
 
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ace
4
+ module Git
5
+ module Worktree
6
+ module Atoms
7
+ # Parses the `--active-within` activity window into hours.
8
+ #
9
+ # Accepted forms: `Nm` (minutes), `Nh` (hours), `Nd` (days), and bare
10
+ # integers (interpreted as hours). The canonical label echoes the
11
+ # operator's unit so the table header reads the way it was requested
12
+ # (`3d` -> "3d", `5` -> "5h").
13
+ #
14
+ # @example Parse a window
15
+ # DurationParser.parse("18h") # => {hours: 18.0, label: "18h"}
16
+ # DurationParser.parse("90m") # => {hours: 1.5, label: "90m"}
17
+ # DurationParser.parse("5") # => {hours: 5.0, label: "5h"}
18
+ #
19
+ # @example Invalid window
20
+ # DurationParser.parse("abc") # raises ArgumentError
21
+ module DurationParser
22
+ # Default activity window label
23
+ DEFAULT_LABEL = "18h"
24
+
25
+ # Accepted duration shape: positive integer + optional unit
26
+ PATTERN = /\A(\d+)([mhd])?\z/
27
+
28
+ class << self
29
+ # Default activity window in hours (no unit = hours follows).
30
+ # @return [Hash] parsed default window
31
+ def default
32
+ parse(DEFAULT_LABEL)
33
+ end
34
+
35
+ # Parse a duration string into hours.
36
+ #
37
+ # @param value [String, nil] raw CLI value
38
+ # @return [Hash] `{hours: Float, label: String}`
39
+ # @raise [ArgumentError] when the value is empty, zero, negative, or
40
+ # not one of the accepted forms
41
+ def parse(value)
42
+ raw = value.to_s.strip
43
+ raise invalid_duration(value) if raw.empty?
44
+
45
+ match = PATTERN.match(raw)
46
+ raise invalid_duration(value) unless match
47
+
48
+ amount = Integer(match[1], 10)
49
+ unit = match[2]
50
+ raise invalid_duration(value) if amount <= 0
51
+
52
+ {hours: hours_for(amount, unit), label: "#{amount}#{display_unit(unit)}"}
53
+ end
54
+
55
+ private
56
+
57
+ # @return [Float] duration expressed in hours
58
+ def hours_for(amount, unit)
59
+ case unit
60
+ when "m" then amount / 60.0
61
+ when "d" then amount * 24.0
62
+ else amount.to_f # "h" or bare integer
63
+ end
64
+ end
65
+
66
+ # @return [String] unit to echo back (bare integers render as hours)
67
+ def display_unit(unit)
68
+ unit || "h"
69
+ end
70
+
71
+ def invalid_duration(value)
72
+ ArgumentError.new(
73
+ "invalid duration '#{value}'. Use forms like 30m, 18h, 2d, or bare hours."
74
+ )
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
File without changes
File without changes