taskchef 5.7.2 → 5.8.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "5.7.2",
3
+ "version": "5.8.0",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
@@ -20,7 +20,7 @@
20
20
  "interface": {
21
21
  "displayName": "TaskChef",
22
22
  "shortDescription": "Dispatch work to the right Codex project task.",
23
- "longDescription": "Route actionable requests to independently openable Codex project tasks, keep an append-only task history, and query live reports on demand.",
23
+ "longDescription": "Route work to visible Codex project tasks, cache their latest semantic result, and query fresh reports on demand.",
24
24
  "developerName": "Favo Yang",
25
25
  "category": "Productivity",
26
26
  "capabilities": [
package/BACKLOG.md CHANGED
@@ -50,7 +50,7 @@ clear data model before implementation.
50
50
  `resolve_client_thread(clientThreadId) -> { status, threadId? }`. Returning a
51
51
  reserved durable ID from `create_thread`, or emitting a materialization event
52
52
  containing it, would also close the lifecycle gap.
53
- - Re-evaluate TaskChef's sparse marker-discovery fallback when Codex exposes
54
- one of these APIs. Keep exact marker verification before persisting the
55
- returned durable ID unless the official contract provides equivalent
56
- correlation guarantees.
53
+ - Re-evaluate whether the initial-hook identity link and exact-marker manual
54
+ recovery can be simplified when Codex exposes one of these APIs. Keep exact
55
+ correlation verification before persisting the returned durable ID unless
56
+ the official contract provides equivalent guarantees.
package/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Bring work for all your local Codex projects to one inbox. TaskChef reads each
4
4
  request, chooses the right project, and opens a normal Codex task there. It
5
- keeps a task history so you can find the work later. The created Codex tasks
6
- remain the source of truth for progress and results.
5
+ keeps a task history plus the executor's latest semantic result so you can find
6
+ the work later. Codex task state remains authoritative for current activity.
7
7
 
8
8
  If a request contains independent work for different projects, TaskChef can
9
9
  open several tasks. It returns as soon as they are created, so you can send the
@@ -28,13 +28,15 @@ request in dispatcher
28
28
  +-- task entry --> executor in project B
29
29
  ```
30
30
 
31
- TaskChef does not copy executor results into its workspace. When you ask for a
32
- report, it reads the recorded task IDs, checks those Codex tasks once, and
33
- shows their current state without saving another snapshot.
31
+ Executors report a compact `completed`, `needs_input`, or `failed` result into
32
+ their existing task entry. When you ask for a report, TaskChef filters old
33
+ terminal work and checks cheap live metadata once for every selected task.
34
+ Active or approval-waiting metadata overrides the cache immediately; idle MCP
35
+ results are trusted by default, with detailed reads reserved for anomalies. It
36
+ never infers completion from hook events.
34
37
 
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
+ See [Delegation design](docs/delegation-design.md) for the illustrated workflow,
39
+ writer boundaries, locking, trust model, freshness rules, and follow-up example.
38
40
 
39
41
  ## Quickstart
40
42
 
@@ -50,6 +52,12 @@ codex plugin marketplace add favoyang/codex-plugins
50
52
  codex plugin add taskchef@favoyang-plugins
51
53
  ```
52
54
 
55
+ In a new Codex task, run `/hooks`, review the TaskChef hook, and trust it. Codex
56
+ skips new or changed plugin hooks until you approve their current definition,
57
+ so repeat this review after an update changes the hook. TaskChef uses this hook
58
+ to link the marked initial executor prompt and to provide read-only current-turn
59
+ identity on later prompts in that same executor. It never writes task outcomes.
60
+
53
61
  ### 2. Bootstrap the dispatcher workspace
54
62
 
55
63
  Invoke the bootstrap skill from any Codex project:
@@ -122,21 +130,19 @@ the same project.
122
130
  Open an executor and prompt it like any other Codex task. Its thread is the
123
131
  live source of truth for progress, questions, and results.
124
132
 
125
- The dispatcher workspace keeps `tasks.jsonl`, a history of submitted
126
- delegations. New tasks are appended; the only later change allowed is filling
127
- an unresolved task's nullable thread ID. The log records what TaskChef sent,
128
- when it sent it, which project it selected, and which Codex task received the
129
- work.
133
+ The dispatcher workspace keeps `tasks.jsonl`, one line per submitted
134
+ delegation. New tasks are appended. Later locked atomic updates may fill the
135
+ nullable thread ID and replace the task's latest status, summary, turn ID,
136
+ timestamp, and writer. There is no transition-event log.
130
137
 
131
138
  Every delegated instruction begins with a unique
132
139
  `<!-- taskchef_id=<UUID> -->` marker followed by a blank line, an
133
- executor-ownership paragraph, another blank line, and the assignment. The
140
+ executor-ownership paragraph, a result-callback paragraph, and the assignment. The
134
141
  valid HTML comment stays invisible in rendered Markdown.
135
- If worktree creation does not return a thread ID immediately, TaskChef records
136
- the marked delegation as unresolved, then makes at most two exact-marker checks
137
- during a short bounded window. Candidate reads use one programmatic batch per
138
- check. If the batch cannot execute or TaskChef cannot identify exactly one
139
- task, the recorded marker remains available for recovery.
142
+ TaskChef records the marked delegation before executor creation. If creation
143
+ does not return a durable thread ID, the trusted initial-prompt hook receives
144
+ the root session ID and atomically links it to the existing entry. Delegation
145
+ does not wait, poll, list tasks, or retry discovery.
140
146
 
141
147
  ### Ask for a live report
142
148
 
@@ -146,9 +152,15 @@ Ask the dispatcher when you want a current overview:
146
152
  Report on the work TaskChef has dispatched.
147
153
  ```
148
154
 
149
- This runs `$taskchef-report`. It reads the task history, checks the relevant
150
- Codex tasks once, and reports their current states and outcomes. Nothing is
151
- written back to the log, and TaskChef does not keep polling after the report.
155
+ This runs `$taskchef-report`. Overviews always consider working, needs-input,
156
+ unresolved, legacy, and terminal tasks changed in the last seven days. Older
157
+ terminal tasks are skipped unless requested or live metadata shows that they
158
+ are active or awaiting approval. Cached MCP results are trusted for idle tasks
159
+ in broad overviews. Active or approval-waiting tasks are reported directly from
160
+ the one broad metadata snapshot. Focused reports read a selected idle task once
161
+ when its metadata is newer than the callback; missing callbacks and other
162
+ anomalies also receive at most one targeted read. Reporting writes nothing and
163
+ never polls.
152
164
 
153
165
  ### Manage configured projects
154
166
 
@@ -177,17 +189,19 @@ project metadata that TaskChef used when it delegated the work.
177
189
 
178
190
  ## Important boundaries
179
191
 
180
- - TaskChef is an interactive dispatcher. It is not a scheduler, daemon, hook
181
- service, or background worker.
182
- - Executors are visible Codex tasks. The dispatcher may wait briefly to resolve
183
- a worktree task's thread ID, but it does not supervise executors or wait for
184
- them to finish.
192
+ - TaskChef is an interactive dispatcher, not a scheduler, daemon, or background
193
+ worker. Its single lifecycle hook writes initial executor identity, then only
194
+ provides read-only current-turn context on follow-up prompts.
195
+ - Executors are visible Codex tasks. The dispatcher does not supervise them or
196
+ wait for them to finish.
185
197
  - TaskChef routes only to projects on the same local execution host.
186
- - The task history contains successful delegations, not current task status or
187
- task results.
198
+ - Each task line contains the latest reported semantic result, not a complete
199
+ lifecycle or event history.
188
200
  - TaskChef does not store executor transcripts, hidden reasoning, or `hostId`.
189
- - A live report is a one-time read of recorded Codex tasks. TaskChef discards
190
- the fetched state after presenting it.
201
+ - A live report uses one metadata snapshot for all selected tasks and
202
+ immediately overrides active or approval-waiting state. Broad overviews stay
203
+ cache-first; focused reports read selected idle tasks once when metadata is
204
+ newer than the callback. Reporting never persists inferred live state.
191
205
 
192
206
  ## Updating
193
207
 
@@ -245,7 +259,9 @@ taskchef task summary
245
259
 
246
260
  Workspace resolution is deterministic: `--workspace <path>`, then the
247
261
  `TASKCHEF_WORKSPACE` environment variable, then `~/.agents/taskchef`. The
248
- current directory is never an implicit workspace. Data commands use concise
262
+ environment override must be absolute (or start with `~/`) so plugin processes
263
+ with different working directories resolve the same workspace. The current
264
+ directory is never an implicit workspace. Data commands use concise
249
265
  human-readable output by default and accept `--json` for machine-readable
250
266
  output. Run `taskchef help` for every option.
251
267
 
@@ -345,7 +361,7 @@ The current configuration schema is version 2. Version 1 remains readable:
345
361
  legacy `githubRepo: null` normalizes to `githubRepos: []`, and a legacy string
346
362
  normalizes to a one-item `githubRepos` list. `workspace init` persists this
347
363
  migration atomically; other configuration writes also emit version 2. Legacy
348
- task lines remain readable without an eager rewrite of the append-only history.
364
+ task lines remain readable without an eager rewrite of the JSONL history.
349
365
 
350
366
  ### Task history
351
367
 
@@ -353,16 +369,15 @@ task lines remain readable without an eager rewrite of the append-only history.
353
369
  `project` value is the exact configured project path:
354
370
 
355
371
  ```sh
356
- printf '%s\n' '{"id":"c0f010ff-84f2-4838-a69d-0ff1f5d721d7","project":"/workspace/payments","title":"Add retry logs","instruction":"<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->\n\nThis task owns the delegated assignment. Execute it in this task; do not re-dispatch it merely because it concerns TaskChef or a configured project. Explicit requests to delegate separate work remain valid.\n\nAdd structured logs for failed retries and test them.","threadId":"019f..."}' |
372
+ printf '%s\n' '{"id":"c0f010ff-84f2-4838-a69d-0ff1f5d721d7","project":"/workspace/payments","title":"Add retry logs","instruction":"<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->\n\nThis task owns the delegated assignment. Execute it in this task; do not re-dispatch it merely because it concerns TaskChef or a configured project. Explicit requests to delegate separate work remain valid.\n\nBefore ending, call the TaskChef report_result MCP tool with completed, needs_input, or failed and a concise summary. Use needs_input only for a semantic decision or information the user must provide; a native approval prompt is live Codex state, not a TaskChef result. Do not include secrets, transcripts, or raw command output.\n\nAdd structured logs for failed retries and test them.","threadId":"019f..."}' |
357
373
  taskchef task record --json
358
374
  ```
359
375
 
360
- If a task has `threadId: null`, a later Codex workflow can find its exact
361
- marker and pass the verified durable ID through its prescribed interface. The
362
- delegate skill uses the MCP `resolve_task` tool during bounded post-creation
363
- recovery; the report skill and direct manual recovery use the equivalent CLI
364
- operation below. Both reach the same atomic logic, which permits only the
365
- one-way transition from null to one unique thread ID:
376
+ If a task has `threadId: null`, the initial plugin hook normally resolves its
377
+ exact marker to the root session ID. Direct manual recovery may use the
378
+ equivalent CLI operation below after verifying one exact structured marker
379
+ match. Both hook and CLI reach the same locked atomic logic, which permits only
380
+ the one-way transition from null to one unique thread ID:
366
381
 
367
382
  ```sh
368
383
  taskchef task resolve c0f010ff-84f2-4838-a69d-0ff1f5d721d7 \
@@ -392,8 +407,8 @@ the complete values in `--json` output, and the selected order applies to its
392
407
  `task show` accepts either the full task ID or the exact eight-character task
393
408
  ID printed by the default human-readable list. A short ID must identify exactly
394
409
  one recorded task; use `task list --full-id` when a short ID is missing or
395
- ambiguous. Its default output labels the title, project name and path, creation
396
- time, full task and thread IDs, and instruction. A null thread ID appears as
410
+ ambiguous. Its default output labels the title, project, latest result fields,
411
+ creation and update times, task/thread/turn IDs, and instruction. A null thread ID appears as
397
412
  `-`. Line breaks in labeled values are escaped as `\\r` and `\\n`, while
398
413
  multiline instructions retain their original line breaks and indentation. Pass
399
414
  `--json` to receive the unchanged complete task object.
@@ -401,32 +416,50 @@ multiline instructions retain their original line breaks and indentation. Pass
401
416
  ```text
402
417
  Title: Add retry logs
403
418
  Project: payments
419
+ Status: completed
420
+ Summary: Added structured retry logs and regression coverage.
404
421
  Project path: /workspace/payments
405
422
  Created: 2026-08-12T10:00:00.000Z
423
+ Updated: 2026-08-12T10:08:00.000Z
424
+ Updated by: mcp
406
425
  Task ID: c0f010ff-84f2-4838-a69d-0ff1f5d721d7
407
426
  Thread ID: 019f9d46-f42c-7482-9707-3c107bf241ee
427
+ Turn ID: 019f9d47-result-turn
408
428
  Instruction:
409
429
  <!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->
410
430
 
411
431
  This task owns the delegated assignment. Execute it in this task; do not re-dispatch it merely because it concerns TaskChef or a configured project. Explicit requests to delegate separate work remain valid.
412
432
 
433
+ Before ending, call the TaskChef report_result MCP tool with completed, needs_input, or failed and a concise summary. Use needs_input only for a semantic decision or information the user must provide; a native approval prompt is live Codex state, not a TaskChef result. Do not include secrets, transcripts, or raw command output.
434
+
413
435
  Add structured logs for failed payment retries and test them.
414
436
  ```
415
437
 
416
438
  The list remains a compact table:
417
439
 
418
440
  ```text
419
- TITLE PROJECT CREATED ID THREAD ID
420
- Add retry logs payments 2026-08-12T10:00:00.000Z c0f010ff 019f9d46
441
+ TITLE PROJECT STATUS UPDATED ID THREAD ID
442
+ Add retry logs payments completed 2026-08-12T10:08:00.000Z c0f010ff 019f9d46
421
443
  ```
422
444
 
423
445
  The complete data contract is in [SPEC.md](SPEC.md). The illustrated runtime
424
- workflow and latency analysis are in
446
+ workflow, writer boundaries, and freshness rules are in
425
447
  [Delegation design](docs/delegation-design.md). Deferred ideas are in
426
448
  [BACKLOG.md](BACKLOG.md).
427
449
 
428
450
  ## Development and release
429
451
 
452
+ This result-callback redesign changes the public
453
+ `createAndRecordDelegation` contract from post-creation thread discovery to
454
+ record-before-create plus hook resolution. Release it as a new major version.
455
+ Library callers migrating from TaskChef 5.x should remove `listThreads`,
456
+ `readThread`, checkpoint, and timeout arguments; provide `recordTask` before
457
+ creation and optional `resolveRecordedTask` and `reportRecordedResult`
458
+ callbacks instead. The old pure thread-inspection exports remain temporarily
459
+ available as deprecated compatibility helpers, but TaskChef no longer calls
460
+ them. Creation errors expose `taskChefTaskId` and `taskChefResultReporting` so
461
+ library callers can recover a record when the failure callback was unavailable.
462
+
430
463
  ```sh
431
464
  npm test
432
465
  npm pack --dry-run
package/SPEC.md CHANGED
@@ -4,11 +4,11 @@
4
4
 
5
5
  TaskChef is an interactive Codex dispatcher. It routes independent assignments
6
6
  to real Codex tasks in configured local projects, records each submitted
7
- delegation in a task history, and returns immediately. New tasks append; only a
8
- nullable thread ID may later transition to its durable value.
7
+ delegation in a task history, and returns immediately. New tasks append; locked
8
+ atomic updates may later resolve identity and replace the latest semantic result.
9
9
 
10
- Codex tasks remain authoritative for their progress and results. TaskChef does
11
- not maintain a second lifecycle database.
10
+ Codex tasks remain authoritative for current activity. TaskChef stores only the
11
+ latest useful semantic result, not a second lifecycle or event database.
12
12
 
13
13
  ## Core behavior
14
14
 
@@ -19,14 +19,15 @@ not maintain a second lifecycle database.
19
19
  2. TaskChef separates only outcomes that can proceed independently.
20
20
  3. It selects each target using configured project metadata and validates the
21
21
  selected local path.
22
- 4. It creates an independently openable Codex task in that project.
23
- 5. It embeds a generated TaskChef UUID marker in the initial instruction before
24
- creation, followed by an executor-ownership sentence and the assignment. It
25
- appends one task entry as soon as creation returns, using `threadId: null`
26
- while a provisional client ID is briefly resolved.
22
+ 4. It embeds a generated TaskChef UUID marker, executor-ownership sentence, and
23
+ result-callback instruction, then records the task with `threadId: null`.
24
+ 5. It creates an independently openable Codex task. A durable returned ID is
25
+ resolved immediately; otherwise the initial-prompt hook links the root
26
+ session ID without polling.
27
27
  6. It returns without waiting for executor work to complete.
28
- 7. When requested, TaskChef can read task entries, query the relevant Codex
29
- tasks once, and present a live report without persisting the fetched state.
28
+ 7. Executors report `completed`, `needs_input`, or `failed` through MCP. Reports
29
+ filter old terminal entries, use one live metadata snapshot, and read only
30
+ tasks whose cached result may be stale.
30
31
 
31
32
  A task created by TaskChef owns its delegated initial assignment. It executes
32
33
  that assignment in the current task and does not re-dispatch it merely because
@@ -60,7 +61,10 @@ Every command resolves one workspace in this precedence order:
60
61
  2. `TASKCHEF_WORKSPACE`
61
62
  3. `~/.agents/taskchef`
62
63
 
63
- The current directory is never an implicit workspace. `workspace path` exposes
64
+ `TASKCHEF_WORKSPACE` must be absolute or start with `~/`; this prevents the
65
+ hook, MCP server, and CLI from resolving one relative override against
66
+ different process directories. The current directory is never an implicit
67
+ workspace. `workspace path` exposes
64
68
  the resolved absolute path and its source. Bootstrap compares this canonical
65
69
  path with native Codex projects, and when absent invokes the validated
66
70
  `codex app <path>` command before verifying the native list again. It never
@@ -136,14 +140,14 @@ legacy `null` to `[]`; `workspace init` persists the migration atomically, and
136
140
  any later configuration write emits version 2.
137
141
 
138
142
  The configuration does not store dispatcher identity, execution modes,
139
- schedules, task status, results, host information, or the workspace path.
143
+ schedules, task state, host information, or the workspace path.
140
144
 
141
145
  ## Task entry
142
146
 
143
147
  `tasks.jsonl` contains one compact JSON object per line, in append order:
144
148
 
145
149
  ```json
146
- {"schemaVersion":2,"id":"c0f010ff-84f2-4838-a69d-0ff1f5d721d7","project":{"name":"payments-api","path":"/workspace/payments-api","isGitRepository":true,"githubRepos":["https://github.com/example/payments-api","https://github.com/example/payments-sdk"],"description":"Owns payment authorization, capture, refunds, and provider integrations."},"title":"Add payment retry logs","instruction":"<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->\n\nThis task owns the delegated assignment. Execute it in this task; do not re-dispatch it merely because it concerns TaskChef or a configured project. Explicit requests to delegate separate work remain valid.\n\nAdd structured logs for failed payment retries and test them.","threadId":"019f9d46-f42c-7482-9707-3c107bf241ee","createdAt":"2026-08-08T10:00:00.000Z"}
150
+ {"schemaVersion":3,"id":"c0f010ff-84f2-4838-a69d-0ff1f5d721d7","project":{"name":"payments-api","path":"/workspace/payments-api","isGitRepository":true,"githubRepos":["https://github.com/example/payments-api","https://github.com/example/payments-sdk"],"description":"Owns payment authorization, capture, refunds, and provider integrations."},"title":"Add payment retry logs","instruction":"<!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->\n\nThis task owns the delegated assignment. Execute it in this task; do not re-dispatch it merely because it concerns TaskChef or a configured project. Explicit requests to delegate separate work remain valid.\n\nBefore ending, call the TaskChef report_result MCP tool with completed, needs_input, or failed and a concise summary. Use needs_input only for a semantic decision or information the user must provide; a native approval prompt is live Codex state, not a TaskChef result. Do not include secrets, transcripts, or raw command output.\n\nAdd structured logs for failed payment retries and test them.","threadId":"019f9d46-f42c-7482-9707-3c107bf241ee","createdAt":"2026-08-08T10:00:00.000Z","status":"completed","summary":"Added structured retry logs and regression coverage.","turnId":"019f9d47-result-turn","updatedAt":"2026-08-08T10:08:00.000Z","updatedBy":"mcp"}
147
151
  ```
148
152
 
149
153
  - `schemaVersion` identifies the task entry format.
@@ -154,28 +158,38 @@ schedules, task status, results, host information, or the workspace path.
154
158
  `<!-- taskchef_id=<full UUID> -->` correlation marker, executor-ownership
155
159
  paragraph, and assignment body.
156
160
  - `threadId` identifies the created Codex task, or is `null` when creation was
157
- accepted but bounded marker resolution did not find one durable task ID.
161
+ accepted but its initial identity has not yet been linked.
158
162
  - `createdAt` is the dispatch time as an ISO 8601 timestamp.
159
-
160
- Every entry has exactly these fields. IDs and non-null thread IDs must be
163
+ - `status` is `working`, `needs_input`, `completed`, or `failed`; legacy
164
+ entries normalize it to `null`.
165
+ - `summary` is a nullable, bounded latest-result summary.
166
+ - `turnId` identifies the initial hook turn or latest reported result turn. An
167
+ MCP result for a linked executor requires it; null is allowed only for a
168
+ failed creation before any durable thread exists.
169
+ - `updatedAt` is the server-side update time.
170
+ - `updatedBy` is `dispatcher`, `hook`, or `mcp`.
171
+
172
+ Schema-version-3 entries have exactly these fields. IDs and non-null thread IDs must be
161
173
  unique; any number of unresolved entries may have `threadId: null`. The file is
162
174
  empty or newline terminated, with no blank lines. TaskChef rejects a malformed
163
175
  log instead of skipping bad entries. Writers replace the complete validated
164
176
  file atomically under a workspace lock, so an interrupted write leaves either
165
177
  the old history or the complete new history.
166
178
 
167
- Task creation appends entries. The only permitted mutation is an atomic,
168
- idempotent `task resolve` transition from `threadId: null` to one unique durable
169
- thread ID. Resolution requires the stored instruction's exact marker to match
170
- the task ID. A resolved or mismatched entry cannot be overwritten.
179
+ Task creation appends entries. Identity resolution and result callbacks acquire
180
+ the same cross-process lock, reread and validate the complete log, patch one
181
+ matching entry, and atomically replace the file. Resolution is idempotent and
182
+ one-way from null to one unique durable thread ID. Result callbacks must match
183
+ the recorded task/thread and replace only the latest result snapshot; they do
184
+ not append events.
171
185
 
172
186
  The project snapshot preserves the route even if the project is renamed,
173
- moved, or removed later. Entries never contain status, result, transcript,
174
- hidden reasoning, `hostId`, or update timestamps.
187
+ moved, or removed later. Entries never contain transcripts, hidden reasoning,
188
+ `hostId`, or an event history.
175
189
 
176
- New task entries use schema version 2 and list-valued project snapshots.
177
- Version 1 entries with string or null repository metadata remain readable and
178
- normalize to version 2 in API and CLI output. Historical task entries with the
190
+ New task entries use schema version 3. Version 1 and 2 entries remain readable
191
+ and normalize to version 3 in API and CLI output with nullable result fields.
192
+ Historical task entries with the
179
193
  old heading-style marker also remain readable. New nullable records, candidate
180
194
  matching, and resolution require the exact HTML-comment marker; TaskChef never
181
195
  uses an old marker to correlate a thread. Direct records that already have a
@@ -197,49 +211,29 @@ For each assignment, `$taskchef-delegate`:
197
211
  the already-loaded native projects
198
212
  3. prefixes the instruction with the prepared exact
199
213
  `<!-- taskchef_id=<UUID> -->` marker as the first line, followed by a blank
200
- line, the executor-ownership sentence, another blank line, and the
214
+ line, the executor-ownership sentence, result-callback sentence, and
201
215
  assignment body
202
- 4. creates a real Codex task at the exact configured path
203
- 5. appends a task entry immediately through the structured `record_task` tool
204
- when creation returns a durable thread ID; it never opens a shell, parses
205
- stdin, writes a temporary record file, or probes command-sandbox permission
206
- 6. when creation returns only a provisional client ID, immediately appends the
207
- marked entry with `threadId: null`; the current supported Codex surface has
208
- no provisional-ID resolver, so the skill performs no post-creation tool
209
- availability inspection
210
- 7. takes at most two recent-thread
211
- snapshots on a nominal 10- and 30-second schedule after the provisional
212
- result; a late first checkpoint runs immediately, and the second starts at
213
- least 20 seconds after the first actually started. It filters candidates by
214
- available host/project/time/worktree metadata, uses title only as an advisory
215
- ordering hint, issues all independent candidate reads in exactly one
216
- programmatic batch per snapshot, and accepts only one thread whose structured
217
- delegated input starts with the exact marker; inability to execute that
218
- required batch leaves the nullable record unresolved instead of switching to
219
- serial reads
220
- 8. atomically fills the nullable thread ID with `resolve_task` after an exact
221
- match
222
- 9. returns after recording or after reporting that bounded resolution was
223
- unresolved, without waiting for executor work completion.
224
-
225
- The exact random marker remains the sole correlation proof. Creation-time
226
- filtering allows five seconds of clock skew. Candidate reads use exactly one
227
- programmatic batch per snapshot and inspect only
228
- structured `codexDelegation.input`, never untrusted title, summary, preview, or
229
- plain-text marker echoes. Zero exact matches remain unresolved; multiple exact
230
- matches are ambiguous. Snapshot, candidate-read, or task-resolution errors
231
- leave the already-recorded nullable entry intact. The workflow is bounded by
232
- two snapshots rather than an absolute wall-clock cutoff:
233
- mandatory recording or tool latency can shift both attempts later, but cannot
234
- erase an attempt or reduce the minimum 20-second interval between their start
235
- times.
236
- A `clientThreadId`, `pendingWorktreeId`, or ID in the documented provisional
237
- `local:` namespace remains diagnostic context and is rejected from every path
238
- that could persist the canonical `threadId` field.
216
+ 4. appends a `working` task entry with `threadId: null` through `record_task`
217
+ before executor creation
218
+ 5. creates a real Codex task at the exact configured path
219
+ 6. calls `resolve_task` when creation returns a durable thread ID; otherwise it
220
+ returns immediately and the initial `UserPromptSubmit` hook resolves the root
221
+ session ID against the exact marker
222
+ 7. records executor-creation failure as a `failed` semantic result on the
223
+ already-existing entry
224
+ 8. never lists, reads, waits for, or polls threads during delegation.
225
+
226
+ Recording first closes the creation/hook race. On the exact marked prompt, the
227
+ hook receives the root session ID and initial turn ID and writes only identity
228
+ plus `working`. On later prompts whose session ID matches a recorded executor,
229
+ the same `UserPromptSubmit` hook reads the task history and supplies the current
230
+ turn ID as callback context without writing. No permission, tool, stop,
231
+ notification, or session hook writes task lifecycle state. A provisional
232
+ `local:` ID is diagnostic only and can never be persisted as `threadId`.
239
233
 
240
234
  The plugin bundles a local stdio MCP server with focused `prepare_dispatch`,
241
- `record_task`, and `resolve_task` tools. It accepts no workspace path from the
242
- model and resolves only `TASKCHEF_WORKSPACE` or the canonical
235
+ `record_task`, `resolve_task`, and `report_result` tools. It accepts no workspace path from the
236
+ model and resolves only an absolute (or `~/`-prefixed) `TASKCHEF_WORKSPACE` or the canonical
243
237
  `~/.agents/taskchef` default. The write tools reuse the public workspace APIs,
244
238
  so structured calls cannot bypass exact-field validation, locking, atomic
245
239
  replacement, unique IDs, or one-way nullable resolution. They are closed-world
@@ -247,7 +241,11 @@ local mutations and never create Codex tasks. Desktop thread tools remain
247
241
  available only to the Codex skill; the standalone CLI remains available for
248
242
  bootstrap, manual inspection, and recovery.
249
243
 
250
- ### End-to-end benchmark results
244
+ ### Legacy end-to-end benchmark results
245
+
246
+ Schema-v1 benchmark fixtures below validate historical bounded-resolver
247
+ artifacts only. New benchmarks must measure record-before-create, initial-hook
248
+ identity, and result callbacks without using the removed snapshot resolver.
251
249
 
252
250
  An explicitly requested live benchmark writes one ignored, timestamped JSON
253
251
  artifact through `scripts/e2e-benchmark.js`. Schema version 1 contains:
@@ -298,17 +296,20 @@ up to seven seconds, while permanent permission failures such as `EPERM` or
298
296
  `EACCES` fail immediately so the caller can request the required permission
299
297
  without paying the contention retry budget.
300
298
 
301
- A failed executor creation produces no entry. If executor creation succeeds but
302
- the append fails, the executor remains valid and TaskChef tells the user that
303
- it was not recorded.
299
+ A failed executor creation normally leaves its pre-created entry with `failed`.
300
+ The exported orchestration helper attaches `taskChefTaskId` and
301
+ `taskChefResultReporting` (`recorded`, `failed`, or `unavailable`) to a thrown
302
+ creation error so callers can recover the entry if failure reporting itself was
303
+ not available. A failed pre-creation record stops before executor creation, so
304
+ there is no untracked executor.
304
305
 
305
306
  ## Task history and live reports
306
307
 
307
308
  The CLI reads persisted history without contacting Codex:
308
309
 
309
310
  - `task show <id-or-8-character-prefix>` returns one entry. By default it emits
310
- labeled human-readable lines for title, project name and path, creation time,
311
- full task ID, thread ID, and instruction. A null thread ID renders as `-`.
311
+ labeled human-readable lines for title, project, status, summary, creation and
312
+ update metadata, task/thread/turn IDs, and instruction. A null ID renders as `-`.
312
313
  Carriage returns and newlines in labeled values render as `\\r` and `\\n`.
313
314
  The instruction starts on the line after `Instruction:` and retains its stored
314
315
  line breaks and indentation. `--json` returns the unchanged complete task
@@ -318,7 +319,7 @@ The CLI reads persisted history without contacting Codex:
318
319
  wrong-case prefixes fail without selecting a task.
319
320
  - `task list` returns entries newest-first by creation time, optionally filtered
320
321
  by historical project name or exact path. `--ascending` returns oldest-first.
321
- Human rows include task and thread ID columns, abbreviating UUID-shaped IDs
322
+ Human rows include status, update time, task ID, and thread ID, abbreviating UUID-shaped IDs
322
323
  to their first eight-character section unless `--full-id` is passed. Null
323
324
  thread IDs display as `-`. ID formatting does not alter JSON values, and the
324
325
  selected order applies to both human rows and the JSON `tasks` array.
@@ -326,20 +327,35 @@ The CLI reads persisted history without contacting Codex:
326
327
  - `task resolve <id> --thread-id <thread-id>` atomically fills one nullable
327
328
  thread ID after Codex verifies the exact structured marker match.
328
329
 
329
- When the user requests current state or outcomes, `$taskchef-report` makes one
330
- marker-based discovery pass for nullable entries and uses `task resolve` only
331
- for a single exact match. It reports unmatched entries as unresolved and
332
- queries every durable thread ID exactly once, in batches of no more than eight.
333
- The report does not poll, wait, persist status or results, or create a scheduled
334
- job.
330
+ When the user requests an overview, `$taskchef-report` includes working,
331
+ needs-input, unresolved, legacy, and terminal tasks updated during the last
332
+ seven days. It omits older terminal entries unless explicitly requested or a
333
+ single recent-thread metadata snapshot shows that they are active or awaiting
334
+ approval. That one snapshot is a broad contradiction check: active or awaiting-
335
+ approval metadata overrides a cached result immediately, without one detailed
336
+ read per task. An inactive state does not prove semantic completion; in a broad
337
+ overview it permits an `updatedBy: mcp` result to stand by default.
338
+ Dispatcher- or hook-written `working` snapshots have no semantic callback and
339
+ trigger a live read when selected; an inactive task without an MCP callback has
340
+ an unknown outcome. An MCP-written `failed` snapshot with null thread/turn IDs
341
+ is a fresh executor-creation failure and requires no live lookup. For a focused
342
+ task, title, or project report, any newer matched metadata timestamp triggers at
343
+ most one targeted read per selected inactive task. This distinguishes normal
344
+ same-turn finalization from a quick newer turn by comparing structured turn IDs
345
+ and native turn state. Missing callbacks, uncertain or contradictory identity
346
+ or metadata, and explicitly fully-live requests also trigger one targeted read.
347
+ Reads are batched in groups of eight. Broad overviews do not fan out reads over
348
+ idle terminal tasks solely because their timestamps are newer. Reporting never
349
+ persists inferred live state and does not poll, wait, or schedule work.
335
350
 
336
351
  ## Boundaries
337
352
 
338
353
  TaskChef does not include:
339
354
 
340
- - lifecycle status or result persistence
341
- - task callbacks, hooks, indefinite polling, daemons, heartbeats, or schedules
342
- - arbitrary Codex task discovery beyond bounded marker-based creation recovery
355
+ - lifecycle event history or hook-inferred completion
356
+ - lifecycle event types beyond `UserPromptSubmit`
357
+ - indefinite polling, daemons, heartbeats, dispatcher wakeups, or schedules
358
+ - arbitrary Codex task discovery
343
359
  - remote hosts or `hostId` storage
344
360
  - transcript or hidden-reasoning collection
345
361
  - one-active-task-per-project restrictions
@@ -351,15 +367,16 @@ TaskChef does not include:
351
367
  1. Bootstrap creates `AGENTS.md`, `taskchef.json`, and `tasks.jsonl`, then
352
368
  remains idempotent.
353
369
  2. Project metadata routes an unambiguous request to the correct local project.
354
- 3. A successful delegation creates a visible Codex task and appends its thread
355
- ID with a project snapshot.
356
- 4. A provisional creation with one exact marker match records its durable
357
- thread ID; zero or multiple matches record `threadId: null` for later
358
- recovery.
370
+ 3. A delegation records `working` before creating a visible Codex task.
371
+ 4. A durable creation resolves immediately; a provisional creation is linked
372
+ by the initial exact-marker hook without polling.
359
373
  5. The dispatcher returns without waiting for execution.
360
374
  6. Several independent assignments can create several entries, including
361
375
  multiple entries for the same project.
362
376
  7. Task history commands return deterministic entries and project counts.
363
- 8. A live report queries each relevant task once and writes nothing.
364
- 9. Malformed JSONL, duplicate IDs, duplicate thread IDs, and symlinked managed
377
+ 8. MCP callbacks replace the latest needs-input, completed, or failed snapshot.
378
+ 9. A report skips old terminal tasks by default, checks live metadata once,
379
+ overrides active or approval-waiting tasks directly, and reads only anomalous
380
+ candidates without writing inferred state.
381
+ 10. Malformed JSONL, duplicate IDs, duplicate thread IDs, and symlinked managed
365
382
  files fail safely.