taskchef 5.5.0 → 5.5.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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +7 -1
- package/docs/delegation-design.md +268 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -32,6 +32,10 @@ TaskChef does not copy executor results into its workspace. When you ask for a
|
|
|
32
32
|
report, it reads the recorded task IDs, checks those Codex tasks once, and
|
|
33
33
|
shows their current state without saving another snapshot.
|
|
34
34
|
|
|
35
|
+
See [Delegation design](docs/delegation-design.md) for the complete illustrated
|
|
36
|
+
workflow, durable and provisional-ID examples, safety invariants, and measured
|
|
37
|
+
CLI-versus-MCP latency comparison.
|
|
38
|
+
|
|
35
39
|
## Quickstart
|
|
36
40
|
|
|
37
41
|
### 1. Install the plugin
|
|
@@ -378,7 +382,9 @@ TITLE PROJECT CREATED ID THREAD ID
|
|
|
378
382
|
Add retry logs payments 2026-08-12T10:00:00.000Z c0f010ff 019f9d46
|
|
379
383
|
```
|
|
380
384
|
|
|
381
|
-
The complete data contract is in [SPEC.md](SPEC.md).
|
|
385
|
+
The complete data contract is in [SPEC.md](SPEC.md). The illustrated runtime
|
|
386
|
+
workflow and latency analysis are in
|
|
387
|
+
[Delegation design](docs/delegation-design.md). Deferred ideas are in
|
|
382
388
|
[BACKLOG.md](BACKLOG.md).
|
|
383
389
|
|
|
384
390
|
## Development and release
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Delegation design
|
|
2
|
+
|
|
3
|
+
This document explains how TaskChef 5.5 delegates a request, records the new
|
|
4
|
+
Codex task, and safely recovers a durable task ID when creation initially
|
|
5
|
+
returns only a provisional ID.
|
|
6
|
+
|
|
7
|
+
## Mental model
|
|
8
|
+
|
|
9
|
+
TaskChef is the dispatcher and Codex tasks are the executors. TaskChef chooses
|
|
10
|
+
where work belongs, creates a normal Codex task there, and appends one entry to
|
|
11
|
+
the canonical `~/.agents/taskchef/tasks.jsonl` history. It returns after the
|
|
12
|
+
task is recorded; it does not wait for executor completion.
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
flowchart LR
|
|
16
|
+
U["User request"] --> D["TaskChef dispatcher"]
|
|
17
|
+
D --> P["Choose configured project"]
|
|
18
|
+
P --> C["Create Codex executor"]
|
|
19
|
+
C --> R["Record task atomically"]
|
|
20
|
+
R --> U2["Return executor link"]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Three focused local tools handle TaskChef-owned data operations:
|
|
24
|
+
|
|
25
|
+
| Tool | Responsibility | Mutates history? |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `prepare_dispatch` | Load routes and generate the UUID, timestamp, and exact marker | No |
|
|
28
|
+
| `record_task` | Append the created task with a durable ID or `null` | Yes, one atomic append |
|
|
29
|
+
| `resolve_task` | Fill a recorded `null` ID after one exact marker match | Yes, one-way and atomic |
|
|
30
|
+
|
|
31
|
+
The tools never create Codex tasks. Task creation and thread discovery remain
|
|
32
|
+
native Codex operations.
|
|
33
|
+
|
|
34
|
+
## Before and after structured tools
|
|
35
|
+
|
|
36
|
+
The following values come from separate real traces. The MCP record calls used
|
|
37
|
+
an existing record and therefore measured duplicate validation, locking, tool
|
|
38
|
+
transport, and permission overhead rather than a new append. The resolve calls
|
|
39
|
+
were idempotent. Treat the operation comparison as strong evidence about
|
|
40
|
+
orchestration overhead, not as a complete post-release delegation benchmark.
|
|
41
|
+
|
|
42
|
+
| Stage | Earlier CLI path | TaskChef 5.5 MCP path | What changed |
|
|
43
|
+
| --- | ---: | ---: | --- |
|
|
44
|
+
| Prepare routing data and correlation values | Several operations; roughly 0.4–1.0 s in the original trace | `prepare_dispatch`: 79 ms | One call now loads routes and generates UUID, timestamp, and marker internally |
|
|
45
|
+
| Native Codex project list | About 0.6–0.7 s | Still about 0.6–0.7 s | Runs concurrently with preparation |
|
|
46
|
+
| Create Codex task | About 0.3 s | Fundamentally unchanged | Still a native Codex operation |
|
|
47
|
+
| Record permission-aware operation | 7.167 s | 62 ms, then 58 ms | Removed shell, stdin, temporary-file, sandbox-failure, and approval paths |
|
|
48
|
+
| Resolve permission-aware operation | 8.982 s | 11 ms, then 8 ms | Uses a structured atomic call instead of a new shell command |
|
|
49
|
+
| Approval prompts | Required in the failing trace | None in the MCP benchmark | The installed local tool process has the appropriate tool authorization |
|
|
50
|
+
|
|
51
|
+
Combining measurements from different runs suggests a durable fast path near
|
|
52
|
+
1.0–1.2 seconds, compared with roughly 8–9 seconds for the later CLI benchmark.
|
|
53
|
+
This is an estimate until another full post-release delegation benchmark
|
|
54
|
+
measures every stage in one run.
|
|
55
|
+
|
|
56
|
+
### Where the time was saved
|
|
57
|
+
|
|
58
|
+
MCP is not inherently thousands of times faster than invoking a CLI. Both
|
|
59
|
+
paths ultimately call the same TaskChef validation, lock, and atomic-write
|
|
60
|
+
code. The large difference came from work surrounding that code:
|
|
61
|
+
|
|
62
|
+
| Removed overhead | Evidence from the original trace |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| Interactive stdin and EOF handling | The first TTY attempt consumed several tool round trips and did not terminate cleanly |
|
|
65
|
+
| Temporary-file/redirection orchestration | A second invocation was needed to pass one exact JSON value non-interactively |
|
|
66
|
+
| Late sandbox failure | The redirected attempt waited about 7.3 seconds before `EPERM` on the canonical workspace lock |
|
|
67
|
+
| Approval and retry | The escalated retry took about 11 seconds including review and then succeeded |
|
|
68
|
+
| Separate UUID/timestamp shell work | Those values are now generated inside `prepare_dispatch` |
|
|
69
|
+
| Repeated process/tool boundaries | Preparation and both writes are focused structured calls with validated schemas |
|
|
70
|
+
|
|
71
|
+
The actual TaskChef write is small. The MCP benchmark reached duplicate-record
|
|
72
|
+
validation in tens of milliseconds. The improvement comes mainly from avoiding
|
|
73
|
+
a known-to-fail sandboxed command followed by an approved retry, not from
|
|
74
|
+
weakening locking, atomicity, or validation.
|
|
75
|
+
|
|
76
|
+
## Durable-ID fast path
|
|
77
|
+
|
|
78
|
+
```mermaid
|
|
79
|
+
sequenceDiagram
|
|
80
|
+
participant U as User
|
|
81
|
+
participant S as Delegate skill
|
|
82
|
+
participant M as TaskChef MCP
|
|
83
|
+
participant C as Codex
|
|
84
|
+
participant W as Canonical workspace
|
|
85
|
+
|
|
86
|
+
U->>S: Delegate request
|
|
87
|
+
par Independent preparation
|
|
88
|
+
S->>M: prepare_dispatch()
|
|
89
|
+
M->>W: Load and validate routes
|
|
90
|
+
M-->>S: UUID, timestamp, marker, projects
|
|
91
|
+
and
|
|
92
|
+
S->>C: List native projects once
|
|
93
|
+
C-->>S: Native projects
|
|
94
|
+
end
|
|
95
|
+
S->>S: Select one exact configured project
|
|
96
|
+
S->>C: Create task with marked instruction
|
|
97
|
+
C-->>S: durable threadId
|
|
98
|
+
S->>M: record_task(..., threadId)
|
|
99
|
+
M->>W: Lock, validate, append atomically
|
|
100
|
+
M-->>S: Recorded task
|
|
101
|
+
S-->>U: Return created task immediately
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Example
|
|
105
|
+
|
|
106
|
+
Preparation returns:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"schemaVersion": 1,
|
|
111
|
+
"workspace": "/home/example/.agents/taskchef",
|
|
112
|
+
"taskId": "c0f010ff-84f2-4838-a69d-0ff1f5d721d7",
|
|
113
|
+
"preparedAt": "2026-08-14T09:30:00.000Z",
|
|
114
|
+
"marker": "<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->",
|
|
115
|
+
"projectCount": 1,
|
|
116
|
+
"projects": [
|
|
117
|
+
{
|
|
118
|
+
"name": "t2",
|
|
119
|
+
"path": "/projects/t2",
|
|
120
|
+
"isGitRepository": true,
|
|
121
|
+
"githubRepos": [],
|
|
122
|
+
"description": "Small Python fixture project"
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The exact executor instruction becomes:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->
|
|
132
|
+
|
|
133
|
+
Return exactly the integers 1 through 10, one per line.
|
|
134
|
+
Do not modify files.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
If Codex returns a durable ID such as
|
|
138
|
+
`019ffbd4-5d96-79c0-9364-130d58156b76`, TaskChef sends the same marked
|
|
139
|
+
instruction and durable ID to `record_task`. The tool rejects a mismatched
|
|
140
|
+
marker, duplicate task ID, or duplicate durable thread ID before appending.
|
|
141
|
+
|
|
142
|
+
## Provisional-ID recovery path
|
|
143
|
+
|
|
144
|
+
Codex can sometimes return a `clientThreadId` or `pendingWorktreeId` before the
|
|
145
|
+
durable task is discoverable. TaskChef never writes that provisional value into
|
|
146
|
+
the canonical `threadId` field.
|
|
147
|
+
|
|
148
|
+
```mermaid
|
|
149
|
+
flowchart TD
|
|
150
|
+
C["Creation returns provisional ID"] --> N["Record task with threadId: null"]
|
|
151
|
+
N --> S1["First recent-task snapshot around 10 seconds"]
|
|
152
|
+
S1 --> B1["Filter candidates and batch-read structured inputs"]
|
|
153
|
+
B1 --> M1{"Exactly one exact marker match?"}
|
|
154
|
+
M1 -->|Yes| R["resolve_task: null to durable ID"]
|
|
155
|
+
M1 -->|No| S2["Second snapshot at least 20 seconds after first start"]
|
|
156
|
+
S2 --> B2["Filter candidates and batch-read structured inputs"]
|
|
157
|
+
B2 --> M2{"Exactly one exact marker match?"}
|
|
158
|
+
M2 -->|Yes| R
|
|
159
|
+
M2 -->|Zero, multiple, or error| U["Keep null and report unresolved"]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The nominal snapshot starts are 10 and 30 seconds after the provisional
|
|
163
|
+
result. They are catch-up checkpoints rather than expiration deadlines. If
|
|
164
|
+
mandatory recording finishes at 14 seconds, the first snapshot starts
|
|
165
|
+
immediately at 14 seconds, and the second cannot start before 34 seconds. Work
|
|
166
|
+
spent filtering and reading candidates counts toward that 20-second interval.
|
|
167
|
+
TaskChef never takes a third snapshot.
|
|
168
|
+
|
|
169
|
+
### Example
|
|
170
|
+
|
|
171
|
+
Suppose task creation initially returns only:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"clientThreadId": "local:pending-123"
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
TaskChef keeps that value for diagnostics only and records the complete task
|
|
180
|
+
with `threadId: null`:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"id": "c0f010ff-84f2-4838-a69d-0ff1f5d721d7",
|
|
185
|
+
"project": "/projects/t2",
|
|
186
|
+
"title": "Count from 1 to 10",
|
|
187
|
+
"instruction": "<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->\n\nReturn exactly the integers 1 through 10, one per line.\nDo not modify files.",
|
|
188
|
+
"threadId": null
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
A later candidate read might contain this structured delegated input:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"userMessage": {
|
|
197
|
+
"content": [
|
|
198
|
+
{
|
|
199
|
+
"codexDelegation": {
|
|
200
|
+
"input": "<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->\n\nReturn exactly the integers 1 through 10, one per line.\nDo not modify files."
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
"threadId": "019ffbd4-5d96-79c0-9364-130d58156b76"
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
If this is the only exact marker match, TaskChef calls:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"tool": "resolve_task",
|
|
214
|
+
"arguments": {
|
|
215
|
+
"taskId": "c0f010ff-84f2-4838-a69d-0ff1f5d721d7",
|
|
216
|
+
"threadId": "019ffbd4-5d96-79c0-9364-130d58156b76"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The stored value changes atomically from `null` to that durable ID. If neither
|
|
222
|
+
snapshot finds exactly one match, the stored value remains `null`; TaskChef
|
|
223
|
+
reports `local:pending-123` only as provisional diagnostic context.
|
|
224
|
+
|
|
225
|
+
For each snapshot TaskChef:
|
|
226
|
+
|
|
227
|
+
1. Lists at most 50 recent tasks.
|
|
228
|
+
2. Filters by available host, project, creation time, and worktree metadata.
|
|
229
|
+
3. Uses title only to prioritize reads, never as correlation proof.
|
|
230
|
+
4. Reads every remaining candidate together in one programmatic batch.
|
|
231
|
+
5. Examines only structured `codexDelegation.input`.
|
|
232
|
+
6. Accepts only one input beginning with the exact marker and blank line.
|
|
233
|
+
7. Calls `resolve_task` once to atomically change `null` to the durable ID.
|
|
234
|
+
|
|
235
|
+
Zero matches, multiple matches, read errors, or resolution-write errors leave
|
|
236
|
+
the existing nullable record intact. TaskChef reports that state and never
|
|
237
|
+
guesses.
|
|
238
|
+
|
|
239
|
+
## Correctness and safety invariants
|
|
240
|
+
|
|
241
|
+
| Invariant | Enforcement |
|
|
242
|
+
| --- | --- |
|
|
243
|
+
| Canonical workspace | The MCP server resolves `TASKCHEF_WORKSPACE` or `~/.agents/taskchef`; the model cannot pass a workspace path |
|
|
244
|
+
| Exact marked instruction | The full UUID marker is generated before creation and must be the first line followed by a blank line |
|
|
245
|
+
| Durable correlation | Only the exact marker inside structured delegated input proves a discovery match |
|
|
246
|
+
| No provisional persistence | A provisional ID is diagnostic only; the record receives `null` |
|
|
247
|
+
| Atomic history | Record and resolve reuse TaskChef's existing locks and atomic file replacement |
|
|
248
|
+
| One-way resolution | Resolution permits only `null` to one unique durable ID and is idempotent for that same ID |
|
|
249
|
+
| Bounded discovery | At most two snapshots, with at least 20 seconds between their actual start times |
|
|
250
|
+
| Immediate handoff | The dispatcher returns after recording or bounded recovery and never waits for executor completion |
|
|
251
|
+
|
|
252
|
+
## Stable capability assumptions
|
|
253
|
+
|
|
254
|
+
TaskChef 5.5 does not probe the tool surface after creation. The supported Codex
|
|
255
|
+
surface has no native provisional-ID resolver, so the skill always uses the
|
|
256
|
+
fixed two-snapshot recovery workflow when creation is provisional. A future
|
|
257
|
+
native resolver should be adopted through a versioned TaskChef change and
|
|
258
|
+
tests, rather than adding capability-detection latency and variable behavior to
|
|
259
|
+
every dispatch.
|
|
260
|
+
|
|
261
|
+
## Validation references
|
|
262
|
+
|
|
263
|
+
- The normative data and workflow contract is in [`../SPEC.md`](../SPEC.md).
|
|
264
|
+
- The executable skill instructions are in
|
|
265
|
+
[`../skills/taskchef-delegate/SKILL.md`](../skills/taskchef-delegate/SKILL.md).
|
|
266
|
+
- Structured tool definitions are in [`../src/mcp.js`](../src/mcp.js).
|
|
267
|
+
- Timestamped local benchmark artifacts are written under
|
|
268
|
+
`reports/e2e-benchmarks/` and intentionally remain outside release packages.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taskchef",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "A non-blocking interactive dispatcher for visible Codex tasks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Favo Yang",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"assets",
|
|
24
24
|
"BACKLOG.md",
|
|
25
25
|
"bin",
|
|
26
|
+
"docs/delegation-design.md",
|
|
26
27
|
"index.js",
|
|
27
28
|
"mcp",
|
|
28
29
|
"SPEC.md",
|