ace-git-worktree 0.27.1 → 0.27.3

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.
data/README.md CHANGED
@@ -14,6 +14,10 @@
14
14
 
15
15
  > Works with: Claude Code, Codex CLI, OpenCode, Gemini CLI, pi-agent, and more.
16
16
 
17
+ > **State owner:** `.ace-wt/` -- one worktree per project task, owning only the
18
+ > Git checkout and branch. Task metadata stays in `.ace-tasks/`; assignment
19
+ > plans stay in `.ace-local/assign/`. See [docs/lab-flow.md](../docs/lab-flow.md).
20
+
17
21
  [Getting Started](docs/getting-started.md) | [Usage Guide](docs/usage.md) | [Handbook - Skills, Agents, Templates](docs/handbook.md)
18
22
 
19
23
  ![ace-git-worktree demo](docs/demo/ace-git-worktree-getting-started.gif)
@@ -36,6 +40,9 @@
36
40
 
37
41
  **Orchestrate parallel task work with ace-overseer** - pair with [ace-overseer](../ace-overseer) to spin up worktrees per task, drive agents in parallel, and prune finished worktrees automatically.
38
42
 
43
+ > **Planned (L6):** the private overseer queue that hands one worktree between
44
+ > worker, reviewer, and integrator -- not available yet.
45
+
39
46
  ## Testing Contract
40
47
 
41
48
  Run package tests with the restarted deterministic + scenario split:
data/docs/usage.md CHANGED
@@ -74,6 +74,11 @@ Created task worktree and branch for 081
74
74
 
75
75
  **Next steps:** Run `cd "$(ace-git-worktree switch 081)"` to move into the new worktree.
76
76
 
77
+ Worktree creation is role- and folder-name-agnostic: it does not inspect
78
+ `.gitignore` and does not classify management tasks. If a requested worktree
79
+ does not contain the named task, the executor reports the missing task;
80
+ preparing a correct delegation is the requester's responsibility.
81
+
77
82
  ### Scenario 2: Review a Pull Request in Its Own Worktree
78
83
 
79
84
  **Goal:** Create a dedicated workspace for PR review or patching, on any
@@ -15,13 +15,24 @@ module Ace
15
15
  # TaskIDExtractor.extract({id: "v.0.9.0+task.121"}) # => "121"
16
16
  # TaskIDExtractor.extract({id: "v.0.9.0+ace-t.121.01"}) # => "121.01"
17
17
  # TaskIDExtractor.extract({id: "v.0.9.0+t.121"}) # => "121"
18
+ # TaskIDExtractor.extract({id: "8xh.t.ddd.0.0"}) # => "ddd.0.0"
18
19
  #
19
20
  # @example Normalize a task reference string
20
21
  # TaskIDExtractor.normalize("v.0.9.0+task.121.01") # => "121.01"
21
22
  # TaskIDExtractor.normalize("task.121") # => "121"
22
23
  # TaskIDExtractor.normalize("ace-t.121") # => "121"
23
24
  # TaskIDExtractor.normalize("121.01") # => "121.01"
25
+ # TaskIDExtractor.normalize("8xh.t.ddd.0.0") # => "ddd.0.0"
24
26
  class TaskIDExtractor
27
+ # B36TS full id with an arbitrary chain of subtask segments:
28
+ # "8xh.t.ddd" -> "ddd", "8xh.t.ddd.0" -> "ddd.0",
29
+ # "8xh.t.ddd.0.0" -> "ddd.0.0". Every task/subtask segment is
30
+ # preserved so the derived branch/worktree name is deterministic
31
+ # and reversible (the segment chain maps 1:1 onto the id).
32
+ B36TS_FULL_ID = /\A[0-9a-z]{3}\.[a-z]\.([0-9a-z]{3}(?:\.[0-9a-z]+)*)\z/
33
+ # Short form of the same chain, optionally inside a longer path
34
+ # (matched at the end): "t.ddd.0.0", "task.hy4", "/x/ace-task.121/".
35
+ SHORT_TASK_ID = /(?:ace-)?(?:task|t)\.([0-9a-z]{3}(?:\.[0-9a-z]+)*)\/?\z/
25
36
  # Extract task ID from task data hash
26
37
  #
27
38
  # @param task_data [Hash] Task data with :id and/or :task_number
@@ -31,8 +42,9 @@ module Ace
31
42
 
32
43
  # Regex with subtask support
33
44
  if task_data[:id]
34
- # B36TS full ID: "8pp.t.hy4" -> "hy4", or subtask "8pp.t.hy4.a" -> "hy4.a"
35
- if match = task_data[:id].match(/\A[0-9a-z]{3}\.[a-z]\.([0-9a-z]{3}(?:\.[a-z0-9])?)\z/)
45
+ # B36TS full ID: "8pp.t.hy4" -> "hy4", subtasks keep every
46
+ # segment: "8pp.t.hy4.a" -> "hy4.a", "8xh.t.ddd.0.0" -> "ddd.0.0"
47
+ if (match = task_data[:id].match(B36TS_FULL_ID))
36
48
  return match[1]
37
49
  end
38
50
  # Try subtask pattern first (e.g., "v.0.9.0+task.121.01" -> "121.01")
@@ -55,18 +67,17 @@ module Ace
55
67
 
56
68
  # Derive the short form of a full Base36 task id.
57
69
  #
58
- # The short form is the three-character suffix plus an optional
59
- # subtask segment (numeric or single character).
70
+ # The short form is the three-character suffix plus the complete
71
+ # subtask segment chain (each segment numeric or alphanumeric,
72
+ # any depth): "8xh.t.ddd.0.0" -> "ddd.0.0".
60
73
  #
61
74
  # @param full_id [String, nil] formatted task id (e.g. "8xg.t.k9y",
62
- # "8wr.t.qk0.3")
63
- # @return [String, nil] short id (e.g. "k9y", "qk0.3") or nil when the
64
- # argument is not a full task id
75
+ # "8wr.t.qk0.3", "8xh.t.ddd.0.0")
76
+ # @return [String, nil] short id (e.g. "k9y", "qk0.3", "ddd.0.0")
77
+ # or nil when the argument is not a full task id
65
78
  def self.short_id(full_id)
66
- match = full_id.to_s.strip.match(/\A[0-9a-z]{3}\.[a-z]\.([0-9a-z]{3})(?:\.([0-9a-z]+))?\z/)
67
- return nil unless match
68
-
69
- match[2] ? "#{match[1]}.#{match[2]}" : match[1]
79
+ match = full_id.to_s.strip.match(B36TS_FULL_ID)
80
+ match && match[1]
70
81
  end
71
82
 
72
83
  # Normalize a task reference string to simple ID format
@@ -78,8 +89,9 @@ module Ace
78
89
  return nil if ref.empty?
79
90
 
80
91
  # Regex patterns for recognized ACE task ID formats
81
- # B36TS full ID: "8pp.t.hy4" -> "hy4", or subtask "8pp.t.hy4.a" -> "hy4.a"
82
- if match = ref.match(/\A[0-9a-z]{3}\.[a-z]\.([0-9a-z]{3}(?:\.[0-9a-z]+)?)\z/)
92
+ # B36TS full ID: "8pp.t.hy4" -> "hy4", subtasks keep every
93
+ # segment: "8pp.t.hy4.a" -> "hy4.a", "8xh.t.ddd.0.0" -> "ddd.0.0"
94
+ if (match = ref.match(B36TS_FULL_ID))
83
95
  match[1]
84
96
  # B36TS short ref: exactly 3 lowercase alphanumeric chars (e.g., "hy4")
85
97
  elsif match = ref.match(/\A([0-9a-z]{3})\z/)
@@ -88,11 +100,14 @@ module Ace
88
100
  # Try hierarchical pattern first (e.g., "121.01", "task.121.01")
89
101
  elsif match = ref.match(/(\d{3})\.(\d{2})(?:\b|$)/)
90
102
  "#{match[1]}.#{match[2]}"
91
- # B36TS short ref with subtask segment (e.g., "qk0.3", "hy4.a")
92
- elsif match = ref.match(/\A([0-9a-z]{3})\.([0-9a-z]+)\z/)
93
- "#{match[1]}.#{match[2]}"
94
- # Try ace-task/ace-t or task/t directory at end of path (e.g., "ace-task.hy4", "/path/to/task.121")
95
- elsif match = ref.match(/(?:ace-)?(?:task|t)\.([0-9a-z]{3})\/?$/)
103
+ # B36TS short ref with the whole subtask segment chain
104
+ # (e.g., "qk0.3", "hy4.a", "ddd.0.0")
105
+ elsif match = ref.match(/\A([0-9a-z]{3}(?:\.[0-9a-z]+)*)\z/)
106
+ match[1]
107
+ # Try task./t. (or ace-task./ace-t.) prefix, keeping the whole
108
+ # subtask segment chain (e.g. "t.ddd.0.0", "task.hy4.a",
109
+ # "/path/to/task.121", "ace-task.hy4/")
110
+ elsif (match = ref.match(SHORT_TASK_ID))
96
111
  match[1]
97
112
  # Try task./t. prefix in middle of path (e.g., ".cache/test/task.121")
98
113
  # Use negative lookbehind to skip ace-task.XXX / ace-t.XXX parent directories
@@ -272,8 +272,8 @@ module Ace
272
272
  # result = manager.list_all
273
273
  # result = manager.list_all(format: :json)
274
274
  #
275
- # Programmatic inventory for internal consumers (overseer, prune,
276
- # switch/remove hints). The user-facing enriched table is rendered by
275
+ # Programmatic inventory for internal consumers (prune, switch/remove
276
+ # hints). The user-facing enriched table is rendered by
277
277
  # {WorktreeListReport}, not here.
278
278
  #
279
279
  # @option options [Symbol] :format Optional formatting (:simple, :json)
@@ -3,7 +3,7 @@
3
3
  module Ace
4
4
  module Git
5
5
  module Worktree
6
- VERSION = "0.27.1"
6
+ VERSION = "0.27.3"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-git-worktree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.1
4
+ version: 0.27.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-10-17 00:00:00.000000000 Z
10
+ date: 2026-10-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-support-cli