hiiro 0.1.365 → 0.1.366
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -343
- data/README.md +73 -14
- data/bin/t +526 -0
- data/bin/tt +20 -0
- data/docs/h-task.md +120 -56
- data/docs/t.md +427 -0
- data/docs/why-t.md +306 -0
- data/lib/hiiro/task_scope.rb +92 -0
- data/lib/hiiro/task_sessions.rb +51 -0
- data/lib/hiiro/version.rb +1 -1
- metadata +8 -2
data/docs/why-t.md
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# Why t belongs in your daily workflow
|
|
2
|
+
|
|
3
|
+
The best reason to use `t` is the time between deciding to return to a task and actually doing useful work.
|
|
4
|
+
|
|
5
|
+
You already have the code, the issue, the PR, the notes, and a terminal somewhere. The hard part is remembering which ones belong together and what you meant to do next. That gets harder when you switch between projects, wait for reviews, or hand work to an agent.
|
|
6
|
+
|
|
7
|
+
**`t` gives each task a named record you can return to.** It keeps the next action and supporting references together, and connects that record to a Herdr workspace when you need terminals.
|
|
8
|
+
|
|
9
|
+
This is the case for using the current tool, with examples of what it already does. For every command and option, see the [complete t reference](t.md).
|
|
10
|
+
|
|
11
|
+
## Your next action survives an interruption
|
|
12
|
+
|
|
13
|
+
A task name tells you the subject. A useful next action tells you how to resume.
|
|
14
|
+
|
|
15
|
+
Compare these two descriptions of the same work:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
// Enough to remember that work exists.
|
|
19
|
+
{ task: "fix-checkout" }
|
|
20
|
+
|
|
21
|
+
// Enough to start doing something useful.
|
|
22
|
+
{
|
|
23
|
+
task: "fix-checkout",
|
|
24
|
+
status: "active",
|
|
25
|
+
next: "Reproduce the timeout with the saved checkout payload"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The second version takes one command:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
t fix-checkout next 'Reproduce the timeout with the saved checkout payload'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
When a meeting interrupts you, or another bug takes priority, that instruction stays with the task. Tomorrow, `t fix-checkout` tells you where to pick up.
|
|
36
|
+
|
|
37
|
+
**The habit that makes this useful is updating `next` before you switch away.** It can be one sentence. It does not need to become a project plan.
|
|
38
|
+
|
|
39
|
+
`next` is one current action, not an accumulating checklist. Replace it as you make progress. Separate todos can hold the other steps without replacing that next action:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
t fix-checkout todo add Compare the retry settings
|
|
43
|
+
tt fix-checkout add Inspect --help output
|
|
44
|
+
t fix-checkout todo
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Task display and todo listing show every todo with its ID, status, and text. To remove one, use its displayed ID, such as `t fix-checkout todo rm 42`. The ID must belong to that scope. Adding or removing todos does not change the task's next action or status, and `t` does not choose the next todo for you.
|
|
48
|
+
|
|
49
|
+
Task references prefer an exact name, then a unique case-sensitive prefix. Ambiguous prefixes fail. If `todo add` finds no task, it creates one with the usual name and notes-home rules before adding the item. Other commands never create unknown tasks except explicit `t NAME new`, which creates that exact name rather than resolving a prefix.
|
|
50
|
+
|
|
51
|
+
`tt TASK ...` delegates to `t TASK todo ...`. Bare `tt` lists current-task todos, and `tt help` shows todo help. Use `t - todo` or `tt -` to list orphan todos, with `add` and `rm` in that scope. `-` is not a task and works only for todos.
|
|
52
|
+
|
|
53
|
+
Every word after `add` is literal text, including flags and `--`, except that leading `add -h` or `add --help` shows help. Empty text fails before any task is created.
|
|
54
|
+
|
|
55
|
+
Todos share the existing database table with `h todo`. `t` does not rewrite `todo.yml` or change `h task` behavior. Keep the longer investigation in a document.
|
|
56
|
+
|
|
57
|
+
## Waiting becomes visible instead of forgotten
|
|
58
|
+
|
|
59
|
+
Some unfinished work is actionable. Some is waiting on someone else. Treating both as the same pile makes it harder to decide what deserves your attention.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
t fix-checkout waiting 'Payments team to confirm the retry behavior'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
That saves the explanation and changes the task's status to `waiting`. The next action remains available, so you can retain what you intend to do after the blocker clears.
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
{
|
|
69
|
+
task: "fix-checkout",
|
|
70
|
+
status: "waiting",
|
|
71
|
+
waiting_on: "Payments team to confirm the retry behavior",
|
|
72
|
+
next: "Add a regression case once the expected behavior is confirmed"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Bare `t` lists every task and status, including done and archived work. Active and waiting rows show their next-action and blocker text, so you can review what needs attention without opening every terminal.
|
|
77
|
+
|
|
78
|
+
When the answer arrives:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
t fix-checkout waiting --clear
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A waiting task becomes active again. There is no automatic reminder or follow-up scheduler; the benefit is having the blocker written down where you review the work.
|
|
85
|
+
|
|
86
|
+
## The issue, PR, code, and notes stay together
|
|
87
|
+
|
|
88
|
+
You should not need to remember whether the useful link is in a browser tab, a chat message, or a terminal's scrollback.
|
|
89
|
+
|
|
90
|
+
A task can hold references to each of those pieces:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
{
|
|
94
|
+
task: "fix-checkout",
|
|
95
|
+
code: "the existing store checkout directory",
|
|
96
|
+
issue: "the original failure report",
|
|
97
|
+
pr: "the proposed fix",
|
|
98
|
+
notes: "what we tried and what we learned"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For example, using an existing local directory and illustrative URLs:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
t fix-checkout directory add ~/proj/store --primary --label code
|
|
106
|
+
t fix-checkout link add https://example.com/issues/123 --kind issue --label ticket
|
|
107
|
+
t fix-checkout pr add https://example.com/pulls/456 --label implementation
|
|
108
|
+
t fix-checkout doc new investigation 'Checkout investigation'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
You can then return directly to a named resource:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
t fix-checkout link open ticket
|
|
115
|
+
t fix-checkout pr open implementation
|
|
116
|
+
t fix-checkout doc open investigation
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The primary directory also becomes the default code location for terminals you create through `t`.
|
|
120
|
+
|
|
121
|
+
Directory and file attachments are references. Your files stay where they already live. Links are saved URLs, not a second issue tracker that needs to be kept in sync. `t` does not fetch PR review status or infer whether the linked issue is complete.
|
|
122
|
+
|
|
123
|
+
## Your working notes remain ordinary files
|
|
124
|
+
|
|
125
|
+
Each task has a home under `~/notes/work/`. Documents created through `t` are ordinary Markdown files, and existing Markdown documents placed in that home are discoverable without registration.
|
|
126
|
+
|
|
127
|
+
A task home might look like this:
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
~/notes/work/fix-checkout/
|
|
131
|
+
task-42-investigation.md
|
|
132
|
+
task-42-handoff.md
|
|
133
|
+
failing-payload.json
|
|
134
|
+
screenshot.png
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The task ID in generated filenames helps keep document names distinct when `mdoc` renders them.
|
|
138
|
+
|
|
139
|
+
This gives you room for the details that do not belong in a one-line next action:
|
|
140
|
+
|
|
141
|
+
- A reproduction and the exact inputs that trigger it.
|
|
142
|
+
- Approaches you ruled out, with the reason each one failed.
|
|
143
|
+
- A decision and the evidence behind it.
|
|
144
|
+
- A handoff note for your next session or another agent.
|
|
145
|
+
|
|
146
|
+
`t fix-checkout file list` discovers files in the task home. `t fix-checkout doc open` uses `mdoc`, so you can read the notes through the same rendered-document workflow.
|
|
147
|
+
|
|
148
|
+
The database holds the task metadata and resource references; the notes remain files you can read and edit with your existing tools.
|
|
149
|
+
|
|
150
|
+
## You can return to the task's terminals by name
|
|
151
|
+
|
|
152
|
+
Herdr makes terminal work persistent. `t` gives that workspace a relationship to the task you are trying to finish.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
t fix-checkout switch
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If the task's workspace is already open, this focuses it. If it is missing, `t` creates one using the task's starting-directory rules. Only after the explicit switch succeeds does `t` save the task as your fallback.
|
|
159
|
+
|
|
160
|
+
`t fix-checkout workspace` is the same operation. Add `--show` to either command to inspect without creating a workspace, focusing it, or changing the saved task. These are direct commands, not groups. Native command abbreviations remain available inside the task scope, such as `t fix-checkout wor`.
|
|
161
|
+
|
|
162
|
+
Within that workspace, you can create a labelled tab for a particular activity:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
t fix-checkout tab new tests --command 'bundle exec rake test'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Later:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
t fix-checkout tab open tests
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
You can also list panes, read their output, split one, or submit a command to an existing pane. That is useful when an agent needs to inspect the same working context rather than start an unrelated terminal elsewhere.
|
|
175
|
+
|
|
176
|
+
There are important limits. `t` does not restore a closed workspace's old layout or restart all its former processes. Creating a tab creates another terminal; it does not reuse one merely because the label matches. Terminals remain open after their commands finish.
|
|
177
|
+
|
|
178
|
+
The useful guarantee is narrower: **you can find or open the workspace associated with a task without remembering its position in the sidebar.**
|
|
179
|
+
|
|
180
|
+
## AI sessions start fresh unless you ask to resume
|
|
181
|
+
|
|
182
|
+
The tool commands open a new focused tab in the task workspace:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
t fix-checkout omp
|
|
186
|
+
t fix-checkout codex
|
|
187
|
+
t fix-checkout claude
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`cdx` is an alias for `codex`, and `cld` is an alias for `claude`. Each command runs its native executable. Claude runs `claude`, never `omp`.
|
|
191
|
+
|
|
192
|
+
Only the first tool argument can switch to resume mode. It must be a nonempty prefix of `resume`, such as `r`, `res`, or `resume`:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
t fix-checkout cdx r
|
|
196
|
+
t fix-checkout cld resume SESSION_ID
|
|
197
|
+
t fix-checkout omp resume --help
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
With nothing after the resume selector, `t` focuses the unique running instance of that tool in the task workspace. It checks Herdr's agent metadata, not the tab name. Multiple matches produce an error with IDs. If none is running, a new tab opens the native resume picker.
|
|
201
|
+
|
|
202
|
+
With a session ID or any other arguments after the selector, `t` always creates a tab and passes those arguments to the native resume command. OMP and Claude receive `--resume`; Codex receives `resume`. All other arguments pass unchanged, including `--help`, `--`, and native tool options. There is no wrapper `--new` or automatic last-session resume.
|
|
203
|
+
|
|
204
|
+
The workspace identifies running terminals, not a separate persisted-session store. If tasks share a directory, native resume discovery is not necessarily task-isolated. The launcher does not inject model or permission settings or make auth/API requests.
|
|
205
|
+
|
|
206
|
+
## Context can save typing without making scripts guess
|
|
207
|
+
|
|
208
|
+
The first argument is always the task reference. `t TASK` shows the task, and `t TASK COMMAND...` runs a command in that task's scope. Only exact root `t help` is special: it prints usage and native scoped help without task lookup. Names such as `new`, `show`, `edit`, and `he` remain task names at the root.
|
|
209
|
+
|
|
210
|
+
Use `.` when the calling Herdr workspace, directory, or saved fallback identifies the task:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
t . current
|
|
214
|
+
t .
|
|
215
|
+
t . next
|
|
216
|
+
t . next 'Check the new test against the original failing payload'
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
A named reference bypasses context lookup. For `.`, the calling Herdr workspace wins over a conflicting current directory. The directory is next, followed by the saved task. Ambiguous matches and invalid, stale, or conflicting Herdr IDs are errors.
|
|
220
|
+
|
|
221
|
+
You can set that fallback without moving terminal focus:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
t fix-checkout current
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`t . current` only prints the selected name. Reads and workspace opens through `.` leave the saved fallback unchanged. A deleted saved task causes an error if selection reaches it. Bare `t` always lists all tasks rather than selecting one.
|
|
228
|
+
|
|
229
|
+
## An agent can leave you a useful place to resume
|
|
230
|
+
|
|
231
|
+
An agent's final chat message can be hard to find later. A task's next action and document home are predictable places to leave the result.
|
|
232
|
+
|
|
233
|
+
For example, an agent working on a selected task can create a handoff document and update what remains:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
t fix-checkout doc new handoff 'Checkout handoff'
|
|
237
|
+
t fix-checkout next 'Review the retry test and decide whether to merge'
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The agent still needs to write its findings into the document. `doc new` creates the file and heading; it does not generate the handoff content.
|
|
241
|
+
|
|
242
|
+
This is a shared convention, not an agent orchestration system. `t` does not launch an autonomous workflow, merge competing updates, or guarantee that an agent's claims are correct. It gives you both the same named task and the same place to record the result.
|
|
243
|
+
|
|
244
|
+
## Organization does not require changing your checkout
|
|
245
|
+
|
|
246
|
+
You can start tracking work immediately:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
t fix-checkout new
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
That creates a record and notes directory. It does not create a worktree, switch branches, modify sparse checkout, or open Herdr.
|
|
253
|
+
|
|
254
|
+
You can attach an existing repository or worktree afterward. If that directory already uses sparse checkout, `t` leaves the configuration alone.
|
|
255
|
+
|
|
256
|
+
This matters for small investigations and noncoding tasks. You can track an invoice review or a design decision without pretending it needs a branch and a terminal workspace.
|
|
257
|
+
|
|
258
|
+
The separate `h task` commands still own their coding-worktree operations. The [reference explains that boundary](t.md#worktrees-branches-and-sparse-checkout), including the different behavior of `h task start` and `h task switch`.
|
|
259
|
+
|
|
260
|
+
## Completing work preserves its context
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
t fix-checkout done
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Completed work stays in bare `t` output with its `done` status. Its record, todos, notes, links, and directory references remain available. Archiving also preserves those resources.
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
t
|
|
270
|
+
t fix-checkout
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
If the problem returns, you can reopen the task:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
t fix-checkout status active
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Completion does not close terminals or clean up Git worktrees. It means the task is complete, not that every resource associated with it should be destroyed.
|
|
280
|
+
|
|
281
|
+
## The smallest routine worth adopting
|
|
282
|
+
|
|
283
|
+
You do not need to use every command for this to pay off.
|
|
284
|
+
|
|
285
|
+
| Moment | Useful command | What it gives you |
|
|
286
|
+
|---|---|---|
|
|
287
|
+
| You capture a new piece of work | `t TASK new` | An exact named record and notes home |
|
|
288
|
+
| You capture another step | `tt TASK add 'Compare the retry settings'` | A todo without replacing the next action; creates a task if no name or prefix matches |
|
|
289
|
+
| You decide what to work on | `t` | Every task and status, with next-action and blocker text |
|
|
290
|
+
| You resume a task | `t TASK` | The context you recorded for it |
|
|
291
|
+
| You want a fallback outside task directories and Herdr | `t TASK current` | Saved selection without moving terminal focus |
|
|
292
|
+
| You need its terminals | `t TASK switch` | The associated workspace and a saved fallback after success |
|
|
293
|
+
| You want a fresh AI session | `t TASK omp` | A new focused tab running the native tool |
|
|
294
|
+
| You are about to switch away | `t TASK next 'The next concrete action'` | An instruction for your next session |
|
|
295
|
+
| Someone else is blocking progress | `t TASK waiting 'Who or what I need'` | A waiting state and explanation |
|
|
296
|
+
| The work is complete | `t TASK done` | A done status without deleting the supporting context |
|
|
297
|
+
|
|
298
|
+
Start with task names and useful next actions. Add documents, links, and terminal organization when they make a particular task easier to resume.
|
|
299
|
+
|
|
300
|
+
`t` will not choose your priorities or keep itself accurate. Its value comes from making a small update at the moment you know the answer, so you do not have to reconstruct it later.
|
|
301
|
+
|
|
302
|
+
**The strongest feature is the combination: a named task, a concrete next action, and direct access to the material you need to act on it.**
|
|
303
|
+
|
|
304
|
+
## Read next
|
|
305
|
+
|
|
306
|
+
[The complete t command reference](t.md) covers every subcommand, option, alias, state transition, storage location, and Herdr/worktree side effect. The canonical implementation is the repository's `bin/t`, with `~/bin/t` as its symlink. Gem installation does not install the launcher.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
class Hiiro
|
|
2
|
+
class TaskScope
|
|
3
|
+
class Error < StandardError; end
|
|
4
|
+
|
|
5
|
+
attr_reader :reference
|
|
6
|
+
|
|
7
|
+
def initialize(reference, herdr:)
|
|
8
|
+
@reference = reference.to_s
|
|
9
|
+
raise Error, 'Task reference cannot be empty' if @reference.empty?
|
|
10
|
+
|
|
11
|
+
@herdr = herdr
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def explicit?
|
|
15
|
+
!%w[. -].include?(reference)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def orphan?
|
|
19
|
+
reference == '-'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def task
|
|
23
|
+
return @task if defined?(@task)
|
|
24
|
+
|
|
25
|
+
@task = if orphan?
|
|
26
|
+
nil
|
|
27
|
+
elsif explicit?
|
|
28
|
+
result = Matcher.new(TaskRecord.all_as_list, :name).by_prefix(reference)
|
|
29
|
+
match = result.resolved
|
|
30
|
+
if !match && result.ambiguous?
|
|
31
|
+
raise Error, "Ambiguous task #{reference}: #{result.matches.map { |item| item.item.name }.join(', ')}"
|
|
32
|
+
end
|
|
33
|
+
match&.item
|
|
34
|
+
else
|
|
35
|
+
current_task
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def task!
|
|
40
|
+
raise Error, "Use t - todo for orphan todos; '-' does not select a task" if orphan?
|
|
41
|
+
|
|
42
|
+
task || raise(Error, "Task not found: #{reference}")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def current_task
|
|
48
|
+
tasks = TaskRecord.all_as_list
|
|
49
|
+
if ENV['HERDR_WORKSPACE_ID'] || ENV['HERDR_PANE_ID'] || ENV['HERDR_ENV'] == '1'
|
|
50
|
+
herdr = @herdr.call
|
|
51
|
+
unless herdr.server_running?
|
|
52
|
+
raise Error, 'Herdr is not running; start Herdr for workspace/tab/pane commands, or supply a task name for task data'
|
|
53
|
+
end
|
|
54
|
+
pane = herdr.get_pane(ENV['HERDR_PANE_ID']) if ENV['HERDR_PANE_ID']
|
|
55
|
+
if ENV['HERDR_PANE_ID'] && !pane
|
|
56
|
+
raise Error, 'Cannot resolve the current Herdr pane; supply a task name'
|
|
57
|
+
end
|
|
58
|
+
workspace_id = ENV['HERDR_WORKSPACE_ID'] || pane&.workspace_id
|
|
59
|
+
if pane && workspace_id != pane.workspace_id
|
|
60
|
+
raise Error, 'Conflicting Herdr pane/workspace context; supply a task name'
|
|
61
|
+
end
|
|
62
|
+
workspace = workspace_id ? herdr.get_workspace(workspace_id) : herdr.current_workspace
|
|
63
|
+
raise Error, 'Cannot resolve the current Herdr workspace; supply a task name' unless workspace
|
|
64
|
+
|
|
65
|
+
matches = tasks.select { |task| (task.session || task.name).tr('.', '_') == workspace.name }
|
|
66
|
+
raise Error, "Ambiguous workspace task: #{matches.map(&:name).join(', ')}" if matches.length > 1
|
|
67
|
+
return matches.first if matches.one?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
cwd = File.realpath(Dir.pwd)
|
|
71
|
+
matches = tasks.select do |task|
|
|
72
|
+
directory = task.primary_directory || (task.tree && (task.tree.start_with?('/') ? task.tree : File.join(Hiiro::WORK_DIR, task.tree)))
|
|
73
|
+
paths = [task.home, directory, *task.resources.where(kind: 'directory').select_map(:target)].compact
|
|
74
|
+
paths.any? { |path| inside?(cwd, path) }
|
|
75
|
+
end
|
|
76
|
+
raise Error, "Ambiguous directory task: #{matches.map(&:name).join(', ')}" if matches.length > 1
|
|
77
|
+
return matches.first if matches.one?
|
|
78
|
+
|
|
79
|
+
saved = PinRecord.find_key('t', 'current_task')
|
|
80
|
+
raise Error, 'No current task; supply a task name or run t TASK current' unless saved
|
|
81
|
+
|
|
82
|
+
TaskRecord[saved.value] || raise(Error, 'Saved task no longer exists; run t TASK current')
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def inside?(path, directory)
|
|
86
|
+
return false unless Dir.exist?(directory)
|
|
87
|
+
|
|
88
|
+
root = File.realpath(directory)
|
|
89
|
+
path == root || path.start_with?(root == File::SEPARATOR ? root : root + File::SEPARATOR)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'shellwords'
|
|
2
|
+
|
|
3
|
+
class Hiiro
|
|
4
|
+
class TaskSessions
|
|
5
|
+
class Error < StandardError; end
|
|
6
|
+
|
|
7
|
+
def initialize(client, workspace:, directory:)
|
|
8
|
+
@client = client
|
|
9
|
+
@workspace = workspace
|
|
10
|
+
@directory = directory
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(tool, argv)
|
|
14
|
+
raise Error, "Unknown AI tool: #{tool}" unless %w[omp codex claude].include?(tool)
|
|
15
|
+
|
|
16
|
+
first = argv.first
|
|
17
|
+
resume = first && !first.empty? && 'resume'.start_with?(first)
|
|
18
|
+
args = resume ? argv.drop(1) : argv
|
|
19
|
+
if resume && args.empty?
|
|
20
|
+
panes = @client.panes(workspace: @workspace).select { |pane| pane.agent == tool }
|
|
21
|
+
if panes.length > 1
|
|
22
|
+
raise Error, "Multiple running #{tool} panes: #{panes.map(&:id).join(', ')}; choose a pane or pass native resume arguments"
|
|
23
|
+
end
|
|
24
|
+
if (pane = panes.first)
|
|
25
|
+
raise Error, "Could not focus pane #{pane.id}" unless @client.focus_pane(pane.id)
|
|
26
|
+
|
|
27
|
+
return pane.id
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
command = [tool]
|
|
32
|
+
command << (tool == 'codex' ? 'resume' : '--resume') if resume
|
|
33
|
+
command.concat(args)
|
|
34
|
+
result = @client.new_tab(
|
|
35
|
+
name: tool,
|
|
36
|
+
workspace: @workspace,
|
|
37
|
+
start_directory: @directory,
|
|
38
|
+
focus: true,
|
|
39
|
+
)
|
|
40
|
+
tab_id = result.is_a?(Hash) && result.dig('tab', 'tab_id')
|
|
41
|
+
raise Error, "Could not create #{tool} tab" unless tab_id.is_a?(String) && !tab_id.empty?
|
|
42
|
+
pane_id = result.dig('root_pane', 'pane_id')
|
|
43
|
+
raise Error, "Created #{tool} tab has no root pane" unless pane_id.is_a?(String) && !pane_id.empty?
|
|
44
|
+
unless @client.run_in_pane(pane_id, Shellwords.join(command))
|
|
45
|
+
raise Error, "Could not start #{tool} in pane #{pane_id}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
tab_id
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/hiiro/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hiiro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.366
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Toyota
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pry
|
|
@@ -175,6 +175,8 @@ files:
|
|
|
175
175
|
- bin/h-todo
|
|
176
176
|
- bin/h-window
|
|
177
177
|
- bin/h-wtree
|
|
178
|
+
- bin/t
|
|
179
|
+
- bin/tt
|
|
178
180
|
- bkup..ruby-version
|
|
179
181
|
- demo.sh
|
|
180
182
|
- demo.typescript
|
|
@@ -325,6 +327,8 @@ files:
|
|
|
325
327
|
- docs/h-window.md
|
|
326
328
|
- docs/h-wtree.md
|
|
327
329
|
- docs/h.md
|
|
330
|
+
- docs/t.md
|
|
331
|
+
- docs/why-t.md
|
|
328
332
|
- editboth
|
|
329
333
|
- examples/bin-with-proposed-options
|
|
330
334
|
- examples/services.sleepers.yml
|
|
@@ -380,6 +384,8 @@ files:
|
|
|
380
384
|
- lib/hiiro/shell.rb
|
|
381
385
|
- lib/hiiro/tags.rb
|
|
382
386
|
- lib/hiiro/task_record.rb
|
|
387
|
+
- lib/hiiro/task_scope.rb
|
|
388
|
+
- lib/hiiro/task_sessions.rb
|
|
383
389
|
- lib/hiiro/tasks.rb
|
|
384
390
|
- lib/hiiro/todo.rb
|
|
385
391
|
- lib/hiiro/tui.rb
|