taskchef 3.0.2 → 4.0.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.
- package/.codex-plugin/plugin.json +1 -1
- package/BACKLOG.md +15 -0
- package/README.md +48 -16
- package/SPEC.md +111 -44
- package/assets/taskchef-dispatcher-instructions.md +2 -0
- package/index.js +24 -0
- package/package.json +1 -1
- package/skills/taskchef-bootstrap/SKILL.md +29 -8
- package/skills/taskchef-delegate/SKILL.md +85 -14
- package/skills/taskchef-report/SKILL.md +20 -10
- package/src/cli.js +33 -5
- package/src/delegation.js +555 -0
- package/src/github.js +108 -0
- package/src/workspace.js +152 -240
package/BACKLOG.md
CHANGED
|
@@ -39,3 +39,18 @@ clear data model before implementation.
|
|
|
39
39
|
- Evaluate automatic project discovery rules and exclusions.
|
|
40
40
|
- Consider multiple executor threads for one logical assignment if a real
|
|
41
41
|
workflow requires it.
|
|
42
|
+
|
|
43
|
+
## Codex provisional thread lifecycle
|
|
44
|
+
|
|
45
|
+
- Track [openai/codex#26861](https://github.com/openai/codex/issues/26861),
|
|
46
|
+
where worktree creation can return only a provisional `clientThreadId` or
|
|
47
|
+
`pendingWorktreeId` with no supported mapping to the durable `threadId`.
|
|
48
|
+
- Prefer an official bounded operation such as
|
|
49
|
+
`wait_for_thread(clientThreadId, timeoutMs) -> { status, threadId? }` or
|
|
50
|
+
`resolve_client_thread(clientThreadId) -> { status, threadId? }`. Returning a
|
|
51
|
+
reserved durable ID from `create_thread`, or emitting a materialization event
|
|
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.
|
package/README.md
CHANGED
|
@@ -73,11 +73,13 @@ tasks.jsonl
|
|
|
73
73
|
TaskChef scans eligible local Codex projects during setup and adds them to the
|
|
74
74
|
managed project list in `taskchef.json`.
|
|
75
75
|
|
|
76
|
-
`taskchef.json` defines the available routes. A project name or GitHub
|
|
77
|
-
request URL in your request is usually enough for TaskChef to choose the
|
|
78
|
-
project.
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
`taskchef.json` defines the available routes. A project name or GitHub issue or
|
|
77
|
+
pull-request URL in your request is usually enough for TaskChef to choose the
|
|
78
|
+
right project. Each project's `githubRepos` field is a list. A managed
|
|
79
|
+
`*-workspace` project lists all child or sub-repositories there, so links into
|
|
80
|
+
any of them route to the workspace. If a project needs more context, extend its
|
|
81
|
+
optional `description` field with responsibilities and keywords that
|
|
82
|
+
distinguish it from nearby projects.
|
|
81
83
|
|
|
82
84
|
The generated `AGENTS.md` turns ordinary requests in this project into
|
|
83
85
|
delegated work. You do not need to name the delegate skill each time.
|
|
@@ -117,9 +119,18 @@ the same project.
|
|
|
117
119
|
Open an executor and prompt it like any other Codex task. Its thread is the
|
|
118
120
|
live source of truth for progress, questions, and results.
|
|
119
121
|
|
|
120
|
-
The dispatcher workspace keeps `tasks.jsonl`,
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
The dispatcher workspace keeps `tasks.jsonl`, a history of submitted
|
|
123
|
+
delegations. New tasks are appended; the only later change allowed is filling
|
|
124
|
+
an unresolved task's nullable thread ID. The log records what TaskChef sent,
|
|
125
|
+
when it sent it, which project it selected, and which Codex task received the
|
|
126
|
+
work.
|
|
127
|
+
|
|
128
|
+
Every delegated instruction includes a unique `# taskchef_id=<UUID>` marker.
|
|
129
|
+
If worktree creation does not return a thread ID immediately, TaskChef records
|
|
130
|
+
the marked delegation as unresolved, then waits briefly for the durable task.
|
|
131
|
+
It prefers a native Codex client-ID resolver when available and otherwise makes
|
|
132
|
+
two exact-marker checks during a short bounded window. If it still cannot
|
|
133
|
+
identify exactly one task, the recorded marker remains available for recovery.
|
|
123
134
|
|
|
124
135
|
### Ask for a live report
|
|
125
136
|
|
|
@@ -152,7 +163,8 @@ $taskchef-bootstrap Diagnose this TaskChef workspace and fix any repairable conf
|
|
|
152
163
|
Project paths must exist when you add or dispatch to them. Configure the
|
|
153
164
|
repository root for a Git project. TaskChef also accepts non-Git folders. It
|
|
154
165
|
detects Git status and the canonical GitHub `origin` when adding or importing
|
|
155
|
-
a project.
|
|
166
|
+
a project. Repeat `--github-repo` to configure several repositories, or place a
|
|
167
|
+
`githubRepos` array in an import. URLs are canonicalized and deduplicated.
|
|
156
168
|
|
|
157
169
|
Removing a project does not rewrite old task entries. Each entry keeps the
|
|
158
170
|
project metadata that TaskChef used when it delegated the work.
|
|
@@ -161,8 +173,9 @@ project metadata that TaskChef used when it delegated the work.
|
|
|
161
173
|
|
|
162
174
|
- TaskChef is an interactive dispatcher. It is not a scheduler, daemon, hook
|
|
163
175
|
service, or background worker.
|
|
164
|
-
- Executors are visible Codex tasks. The dispatcher
|
|
165
|
-
|
|
176
|
+
- Executors are visible Codex tasks. The dispatcher may wait briefly to resolve
|
|
177
|
+
a worktree task's thread ID, but it does not supervise executors or wait for
|
|
178
|
+
them to finish.
|
|
166
179
|
- TaskChef routes only to projects on the same local execution host.
|
|
167
180
|
- The task history contains successful delegations, not current task status or
|
|
168
181
|
task results.
|
|
@@ -213,6 +226,7 @@ taskchef project import [<file> | -]
|
|
|
213
226
|
taskchef project list
|
|
214
227
|
taskchef project remove <name>
|
|
215
228
|
taskchef task record
|
|
229
|
+
taskchef task resolve <task-id> --thread-id <thread-id>
|
|
216
230
|
taskchef task show <task-id>
|
|
217
231
|
taskchef task list
|
|
218
232
|
taskchef task summary
|
|
@@ -231,6 +245,8 @@ taskchef doctor --workspace <workspace>
|
|
|
231
245
|
taskchef project add /workspace/payments \
|
|
232
246
|
--name payments \
|
|
233
247
|
--description "Owns payment authorization, capture, and refunds." \
|
|
248
|
+
--github-repo https://github.com/example/payments-api \
|
|
249
|
+
--github-repo https://github.com/example/payments-sdk \
|
|
234
250
|
--workspace <workspace>
|
|
235
251
|
|
|
236
252
|
taskchef project list --workspace <workspace>
|
|
@@ -244,20 +260,36 @@ taskchef project import projects.json --workspace <workspace>
|
|
|
244
260
|
taskchef project import - --workspace <workspace> < projects.json
|
|
245
261
|
```
|
|
246
262
|
|
|
247
|
-
Import merges by canonical path
|
|
248
|
-
when the imported object omits it
|
|
249
|
-
set.
|
|
263
|
+
Import merges by canonical path, preserves an existing name or description
|
|
264
|
+
when the imported object omits it, and unions repository lists without
|
|
265
|
+
duplicates. `--replace` replaces the configured project set.
|
|
266
|
+
|
|
267
|
+
The current configuration schema is version 2. Version 1 remains readable:
|
|
268
|
+
legacy `githubRepo: null` normalizes to `githubRepos: []`, and a legacy string
|
|
269
|
+
normalizes to a one-item `githubRepos` list. `workspace init` persists this
|
|
270
|
+
migration atomically; other configuration writes also emit version 2. Legacy
|
|
271
|
+
task lines remain readable without an eager rewrite of the append-only history.
|
|
250
272
|
|
|
251
273
|
### Task history
|
|
252
274
|
|
|
253
|
-
`task record` reads one
|
|
275
|
+
`task record` reads one submitted delegation from standard input. The
|
|
254
276
|
`project` value is the exact configured project path:
|
|
255
277
|
|
|
256
278
|
```sh
|
|
257
|
-
printf '%s\n' '{"id":"
|
|
279
|
+
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\nAdd structured logs for failed retries and test them.","threadId":"019f..."}' |
|
|
258
280
|
taskchef task record --json --workspace <workspace>
|
|
259
281
|
```
|
|
260
282
|
|
|
283
|
+
If a task has `threadId: null`, Codex can later find its exact marker and pass
|
|
284
|
+
the verified durable ID to the CLI. Resolution is atomic and only permits the
|
|
285
|
+
one-way transition from null to one unique thread ID:
|
|
286
|
+
|
|
287
|
+
```sh
|
|
288
|
+
taskchef task resolve c0f010ff-84f2-4838-a69d-0ff1f5d721d7 \
|
|
289
|
+
--thread-id 019f9d46-f42c-7482-9707-3c107bf241ee \
|
|
290
|
+
--workspace <workspace>
|
|
291
|
+
```
|
|
292
|
+
|
|
261
293
|
Inspect the task history without querying Codex tasks:
|
|
262
294
|
|
|
263
295
|
```sh
|
package/SPEC.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
5
|
TaskChef is an interactive Codex dispatcher. It routes independent assignments
|
|
6
|
-
to real Codex tasks in configured local projects, records each
|
|
7
|
-
delegation in
|
|
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.
|
|
8
9
|
|
|
9
10
|
Codex tasks remain authoritative for their progress and results. TaskChef does
|
|
10
11
|
not maintain a second lifecycle database.
|
|
@@ -16,8 +17,10 @@ not maintain a second lifecycle database.
|
|
|
16
17
|
3. It selects each target using configured project metadata and validates the
|
|
17
18
|
selected local path.
|
|
18
19
|
4. It creates an independently openable Codex task in that project.
|
|
19
|
-
5.
|
|
20
|
-
|
|
20
|
+
5. It embeds a generated TaskChef UUID marker in the initial instruction before
|
|
21
|
+
creation. It appends one task entry as soon as creation returns, using
|
|
22
|
+
`threadId: null` while a provisional client ID is briefly resolved.
|
|
23
|
+
6. It returns without waiting for executor work to complete.
|
|
21
24
|
7. When requested, TaskChef can read task entries, query the relevant Codex
|
|
22
25
|
tasks once, and present a live report without persisting the fetched state.
|
|
23
26
|
|
|
@@ -38,15 +41,11 @@ live report requests to `$taskchef-report`. Bootstrap preserves unrelated
|
|
|
38
41
|
instructions and refreshes only the managed block.
|
|
39
42
|
|
|
40
43
|
`workspace init` is idempotent. It creates an empty configuration and task
|
|
41
|
-
log when missing, refreshes managed instructions, removes legacy TaskChef
|
|
42
|
-
symlinks
|
|
43
|
-
It stops on a legacy pending record with no thread ID rather than discarding
|
|
44
|
-
that record. If a legacy record refers to a project that was removed from the
|
|
45
|
-
configuration, migration reconstructs its project snapshot from the existing
|
|
46
|
-
local project path.
|
|
44
|
+
log when missing, refreshes managed instructions, and removes legacy TaskChef
|
|
45
|
+
skill symlinks.
|
|
47
46
|
|
|
48
47
|
`doctor` validates configuration, project paths, the JSONL log, managed
|
|
49
|
-
instructions, and the absence of legacy
|
|
48
|
+
instructions, and the absence of legacy TaskChef skill links without modifying
|
|
50
49
|
the workspace.
|
|
51
50
|
|
|
52
51
|
## Project configuration
|
|
@@ -55,20 +54,23 @@ the workspace.
|
|
|
55
54
|
|
|
56
55
|
```json
|
|
57
56
|
{
|
|
58
|
-
"schemaVersion":
|
|
57
|
+
"schemaVersion": 2,
|
|
59
58
|
"projects": [
|
|
60
59
|
{
|
|
61
60
|
"name": "payments-api",
|
|
62
61
|
"path": "/workspace/payments-api",
|
|
63
62
|
"isGitRepository": true,
|
|
64
|
-
"
|
|
63
|
+
"githubRepos": [
|
|
64
|
+
"https://github.com/example/payments-api",
|
|
65
|
+
"https://github.com/example/payments-sdk"
|
|
66
|
+
],
|
|
65
67
|
"description": "Owns payment authorization, capture, refunds, and provider integrations."
|
|
66
68
|
},
|
|
67
69
|
{
|
|
68
70
|
"name": "local-data-tools",
|
|
69
71
|
"path": "/workspace/local-data-tools",
|
|
70
72
|
"isGitRepository": false,
|
|
71
|
-
"
|
|
73
|
+
"githubRepos": []
|
|
72
74
|
}
|
|
73
75
|
]
|
|
74
76
|
}
|
|
@@ -80,18 +82,31 @@ the workspace.
|
|
|
80
82
|
- `path` is the normalized, canonical local directory. A Git project must use
|
|
81
83
|
its repository root.
|
|
82
84
|
- `isGitRepository` identifies Git and non-Git projects.
|
|
83
|
-
- `
|
|
85
|
+
- `githubRepos` is a deduplicated list of canonical GitHub repository URLs. Use
|
|
86
|
+
`[]` when the project advertises no repositories. A managed `*-workspace`
|
|
87
|
+
project lists each child or sub-repository that should route to it.
|
|
84
88
|
- `description` is optional routing context.
|
|
85
89
|
|
|
86
|
-
TaskChef classifies work against `name`, `
|
|
87
|
-
path identifies the checkout but is not a routing hint.
|
|
88
|
-
|
|
90
|
+
TaskChef classifies work against `name`, every URL in `githubRepos`, and
|
|
91
|
+
`description`. The path identifies the checkout but is not a routing hint. For
|
|
92
|
+
a GitHub issue or pull-request URL, TaskChef compares canonical,
|
|
93
|
+
case-insensitive owner/repository identities across every configured list. It
|
|
94
|
+
ignores the issue or PR suffix, `http` versus `https`, optional `www`, trailing
|
|
95
|
+
slashes, and trailing `.git`. It routes only when one configured project
|
|
96
|
+
matches; ambiguous and unmatched URLs are never guessed.
|
|
89
97
|
|
|
90
98
|
`project add` and `project import` detect Git status, exact Git roots, and
|
|
91
|
-
canonical GitHub origins. Import merges by
|
|
92
|
-
existing name or description when omitted
|
|
93
|
-
|
|
94
|
-
|
|
99
|
+
canonical GitHub origins. `--github-repo` is repeatable. Import merges by
|
|
100
|
+
canonical path, preserves an existing name or description when omitted, and
|
|
101
|
+
unions existing and imported repository lists without duplicates. `--replace`
|
|
102
|
+
replaces the configured set. Removing or replacing a project does not alter
|
|
103
|
+
historical task entries.
|
|
104
|
+
|
|
105
|
+
Schema version 2 replaces the string-or-null `githubRepo` field with the
|
|
106
|
+
list-valued `githubRepos` field. Schema-version-1 configurations remain
|
|
107
|
+
compatible: reads normalize a legacy string to one canonical list item and
|
|
108
|
+
legacy `null` to `[]`; `workspace init` persists the migration atomically, and
|
|
109
|
+
any later configuration write emits version 2.
|
|
95
110
|
|
|
96
111
|
The configuration does not store dispatcher identity, execution modes,
|
|
97
112
|
schedules, task status, results, host information, or the workspace path.
|
|
@@ -101,36 +116,81 @@ schedules, task status, results, host information, or the workspace path.
|
|
|
101
116
|
`tasks.jsonl` contains one compact JSON object per line, in append order:
|
|
102
117
|
|
|
103
118
|
```json
|
|
104
|
-
{"schemaVersion":
|
|
119
|
+
{"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\nAdd structured logs for failed payment retries and test them.","threadId":"019f9d46-f42c-7482-9707-3c107bf241ee","createdAt":"2026-08-08T10:00:00.000Z"}
|
|
105
120
|
```
|
|
106
121
|
|
|
107
122
|
- `schemaVersion` identifies the task entry format.
|
|
108
123
|
- `id` is a unique TaskChef task identifier.
|
|
109
124
|
- `project` is the complete configured project snapshot used for routing.
|
|
110
125
|
- `title` is a short task name.
|
|
111
|
-
- `instruction` is the complete executor instruction
|
|
112
|
-
|
|
126
|
+
- `instruction` is the complete executor instruction, including its first-line
|
|
127
|
+
`# taskchef_id=<full UUID>` correlation marker.
|
|
128
|
+
- `threadId` identifies the created Codex task, or is `null` when creation was
|
|
129
|
+
accepted but bounded marker resolution did not find one durable task ID.
|
|
113
130
|
- `createdAt` is the dispatch time as an ISO 8601 timestamp.
|
|
114
131
|
|
|
115
|
-
Every entry has exactly these fields. IDs and thread IDs must be
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
Every entry has exactly these fields. IDs and non-null thread IDs must be
|
|
133
|
+
unique; any number of unresolved entries may have `threadId: null`. The file is
|
|
134
|
+
empty or newline terminated, with no blank lines. TaskChef rejects a malformed
|
|
135
|
+
log instead of skipping bad entries. Writers replace the complete validated
|
|
136
|
+
file atomically under a workspace lock, so an interrupted write leaves either
|
|
137
|
+
the old history or the complete new history.
|
|
138
|
+
|
|
139
|
+
Task creation appends entries. The only permitted mutation is an atomic,
|
|
140
|
+
idempotent `task resolve` transition from `threadId: null` to one unique durable
|
|
141
|
+
thread ID. Resolution requires the stored instruction's exact marker to match
|
|
142
|
+
the task ID. A resolved or mismatched entry cannot be overwritten.
|
|
120
143
|
|
|
121
144
|
The project snapshot preserves the route even if the project is renamed,
|
|
122
145
|
moved, or removed later. Entries never contain status, result, transcript,
|
|
123
146
|
hidden reasoning, `hostId`, or update timestamps.
|
|
124
147
|
|
|
148
|
+
New task entries use schema version 2 and list-valued project snapshots.
|
|
149
|
+
Version 1 entries with string or null repository metadata remain readable and
|
|
150
|
+
normalize to version 2 in API and CLI output. TaskChef does not eagerly rewrite
|
|
151
|
+
legacy history solely for this migration.
|
|
152
|
+
|
|
125
153
|
## Dispatch workflow
|
|
126
154
|
|
|
127
155
|
For each assignment, `$taskchef-delegate`:
|
|
128
156
|
|
|
129
157
|
1. loads and validates configured projects
|
|
130
158
|
2. selects one unambiguous target
|
|
131
|
-
3.
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
3. generates a full UUID and prefixes the instruction with its exact
|
|
160
|
+
`# taskchef_id=<UUID>` marker
|
|
161
|
+
4. creates a real Codex task at the exact configured path
|
|
162
|
+
5. appends a task entry immediately when creation returns a durable thread ID
|
|
163
|
+
6. when creation returns only a provisional client ID, immediately appends the
|
|
164
|
+
marked entry with `threadId: null`, then prefers one native client-ID wait or
|
|
165
|
+
resolution call with a 30-second timeout when Codex exposes one
|
|
166
|
+
7. when no native operation is available, takes at most two recent-thread
|
|
167
|
+
snapshots near 10 and 30 seconds after the provisional result, filters
|
|
168
|
+
candidates by available host/project/time/worktree metadata, uses title only
|
|
169
|
+
as an advisory ordering hint, and accepts only one thread whose structured
|
|
170
|
+
delegated input starts with the exact marker
|
|
171
|
+
8. atomically fills the nullable thread ID after an exact match
|
|
172
|
+
9. returns after recording or after reporting that bounded resolution was
|
|
173
|
+
unresolved, without waiting for executor work completion.
|
|
174
|
+
|
|
175
|
+
The exact random marker makes a pre-creation thread snapshot unnecessary.
|
|
176
|
+
Creation-time filtering allows five seconds of clock skew. Candidate reads run
|
|
177
|
+
concurrently where the host permits and inspect only structured
|
|
178
|
+
`codexDelegation.input`, never untrusted title, summary, preview, or plain-text
|
|
179
|
+
marker echoes. A native resolver result is verified against the same structured
|
|
180
|
+
marker before persistence. Zero exact matches time out unresolved; multiple
|
|
181
|
+
exact matches are ambiguous. Snapshot, candidate-read, native-resolution, or
|
|
182
|
+
task-resolution errors leave the already-recorded nullable entry intact. No
|
|
183
|
+
snapshot, candidate read, marker verification, or task-resolution write starts
|
|
184
|
+
after the 30-second deadline, so tool latency can reduce the number of attempts.
|
|
185
|
+
A `clientThreadId`, `pendingWorktreeId`, or ID in the documented provisional
|
|
186
|
+
`local:` namespace remains diagnostic context and is rejected from every path
|
|
187
|
+
that could persist the canonical `threadId` field.
|
|
188
|
+
|
|
189
|
+
Desktop thread tools are available to the Codex skill, not to the standalone
|
|
190
|
+
Node CLI. The package therefore exposes testable marker/filter/orchestration
|
|
191
|
+
helpers with injected thread-tool callbacks, while the skill owns the actual
|
|
192
|
+
desktop-tool calls and the CLI remains responsible only for validated data
|
|
193
|
+
operations.
|
|
134
194
|
|
|
135
195
|
A failed executor creation produces no entry. If executor creation succeeds but
|
|
136
196
|
the append fails, the executor remains valid and TaskChef tells the user that
|
|
@@ -144,19 +204,23 @@ The CLI reads persisted history without contacting Codex:
|
|
|
144
204
|
- `task list` returns entries in append order, optionally filtered by
|
|
145
205
|
historical project name or exact path.
|
|
146
206
|
- `task summary` returns the total and per-project counts.
|
|
207
|
+
- `task resolve <id> --thread-id <thread-id>` atomically fills one nullable
|
|
208
|
+
thread ID after Codex verifies the exact structured marker match.
|
|
147
209
|
|
|
148
|
-
When the user requests current state or outcomes, `$taskchef-report`
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
210
|
+
When the user requests current state or outcomes, `$taskchef-report` makes one
|
|
211
|
+
marker-based discovery pass for nullable entries and uses `task resolve` only
|
|
212
|
+
for a single exact match. It reports unmatched entries as unresolved and
|
|
213
|
+
queries every durable thread ID exactly once, in batches of no more than eight.
|
|
214
|
+
The report does not poll, wait, persist status or results, or create a scheduled
|
|
215
|
+
job.
|
|
152
216
|
|
|
153
217
|
## Boundaries
|
|
154
218
|
|
|
155
219
|
TaskChef does not include:
|
|
156
220
|
|
|
157
221
|
- lifecycle status or result persistence
|
|
158
|
-
- task callbacks, hooks, polling, daemons, heartbeats, or schedules
|
|
159
|
-
- arbitrary Codex task discovery
|
|
222
|
+
- task callbacks, hooks, indefinite polling, daemons, heartbeats, or schedules
|
|
223
|
+
- arbitrary Codex task discovery beyond bounded marker-based creation recovery
|
|
160
224
|
- remote hosts or `hostId` storage
|
|
161
225
|
- transcript or hidden-reasoning collection
|
|
162
226
|
- one-active-task-per-project restrictions
|
|
@@ -170,10 +234,13 @@ TaskChef does not include:
|
|
|
170
234
|
2. Project metadata routes an unambiguous request to the correct local project.
|
|
171
235
|
3. A successful delegation creates a visible Codex task and appends its thread
|
|
172
236
|
ID with a project snapshot.
|
|
173
|
-
4.
|
|
174
|
-
|
|
237
|
+
4. A provisional creation with one exact marker match records its durable
|
|
238
|
+
thread ID; zero or multiple matches record `threadId: null` for later
|
|
239
|
+
recovery.
|
|
240
|
+
5. The dispatcher returns without waiting for execution.
|
|
241
|
+
6. Several independent assignments can create several entries, including
|
|
175
242
|
multiple entries for the same project.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
243
|
+
7. Task history commands return deterministic entries and project counts.
|
|
244
|
+
8. A live report queries each relevant task once and writes nothing.
|
|
245
|
+
9. Malformed JSONL, duplicate IDs, duplicate thread IDs, and symlinked managed
|
|
179
246
|
files fail safely.
|
|
@@ -9,6 +9,8 @@ This repository is a TaskChef dispatcher workspace.
|
|
|
9
9
|
- For every actionable work request, use `$taskchef-delegate`
|
|
10
10
|
automatically, even when the user does not explicitly say "delegate" or
|
|
11
11
|
mention TaskChef.
|
|
12
|
+
- GitHub issue and pull-request URLs may identify any repository advertised by
|
|
13
|
+
a configured project, including child repositories of managed workspaces.
|
|
12
14
|
- Do not perform delegated work directly in the dispatcher thread.
|
|
13
15
|
- Return immediately after dispatch, as required by `$taskchef-delegate`.
|
|
14
16
|
- Answer directly only when the user explicitly asks about TaskChef itself or
|
package/index.js
CHANGED
|
@@ -14,7 +14,31 @@ export {
|
|
|
14
14
|
listTasks,
|
|
15
15
|
readTask,
|
|
16
16
|
recordTask,
|
|
17
|
+
resolveTask,
|
|
17
18
|
requireSafeId,
|
|
18
19
|
removeProject,
|
|
19
20
|
validateConfig,
|
|
20
21
|
} from "./src/workspace.js";
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
canonicalGithubRepository,
|
|
25
|
+
matchProjectForGithubUrl,
|
|
26
|
+
normalizeGithubRepositories,
|
|
27
|
+
} from "./src/github.js";
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
THREAD_RESOLUTION_CHECKPOINTS_MS,
|
|
31
|
+
THREAD_RESOLUTION_CLOCK_SKEW_MS,
|
|
32
|
+
THREAD_RESOLUTION_RECENT_LIMIT,
|
|
33
|
+
THREAD_RESOLUTION_TIMEOUT_MS,
|
|
34
|
+
createAndRecordDelegation,
|
|
35
|
+
filterThreadCandidates,
|
|
36
|
+
hasExactTaskChefMarker,
|
|
37
|
+
listThreadEntries,
|
|
38
|
+
isProvisionalThreadId,
|
|
39
|
+
normalizeDurableThreadId,
|
|
40
|
+
parseTaskChefMarker,
|
|
41
|
+
prepareDelegation,
|
|
42
|
+
structuredDelegatedInputs,
|
|
43
|
+
taskChefMarker,
|
|
44
|
+
} from "./src/delegation.js";
|
package/package.json
CHANGED
|
@@ -24,9 +24,8 @@ all deterministic workspace operations.
|
|
|
24
24
|
|
|
25
25
|
1. Run `workspace init --json`. It takes no stdin, creates an empty
|
|
26
26
|
configuration when missing, creates the append-only task log, refreshes
|
|
27
|
-
managed instructions, and
|
|
28
|
-
|
|
29
|
-
the dispatcher workspace.
|
|
27
|
+
managed instructions, and removes legacy TaskChef skill links. The installed
|
|
28
|
+
plugin provides all three TaskChef skills outside the dispatcher workspace.
|
|
30
29
|
2. Run `doctor --json` after setup or when the user asks to diagnose the
|
|
31
30
|
workspace. Doctor is read-only. Rerun `workspace init --json` to repair the
|
|
32
31
|
managed scaffold.
|
|
@@ -40,12 +39,34 @@ all deterministic workspace operations.
|
|
|
40
39
|
projects are outside the v1 contract.
|
|
41
40
|
2. Add one project with `project add <path>`, normally supplying `--name` and a
|
|
42
41
|
curated `--description`. The CLI detects Git status, exact Git root, and a
|
|
43
|
-
canonical GitHub `origin`.
|
|
44
|
-
|
|
42
|
+
canonical GitHub `origin`. Repeat `--github-repo <url>` to advertise several
|
|
43
|
+
repositories, or use `--no-github` for an empty list. A managed
|
|
44
|
+
`*-workspace` project must list all of its child or sub-repositories so issue
|
|
45
|
+
and pull-request URLs route to that workspace.
|
|
45
46
|
3. Bulk import with `project import <file|-> --json`. Input is a JSON array of
|
|
46
47
|
objects containing `path` plus optional `name`, `description`, and
|
|
47
|
-
`
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
`githubRepos`, which is always a JSON array of GitHub repository URLs. Import
|
|
49
|
+
merges by canonical path, preserves an existing name or description when
|
|
50
|
+
omitted, and unions existing and imported repository lists without
|
|
51
|
+
duplicates. Use `--replace` only when the user explicitly requests
|
|
52
|
+
replacement.
|
|
50
53
|
4. Inspect configured projects with `project list --json`. Remove by name with
|
|
51
54
|
`project remove`. Existing task entries keep their project snapshots.
|
|
55
|
+
|
|
56
|
+
Example managed-workspace import entry:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"name": "skills-workspace",
|
|
61
|
+
"path": "/workspace/skills-workspace",
|
|
62
|
+
"githubRepos": [
|
|
63
|
+
"https://github.com/example/skill-one",
|
|
64
|
+
"https://github.com/example/skill-two"
|
|
65
|
+
],
|
|
66
|
+
"description": "Manages the listed child skill repositories."
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`workspace init` safely migrates schema-version-1 configuration: a string
|
|
71
|
+
`githubRepo` becomes a one-item `githubRepos` list and `null` becomes
|
|
72
|
+
`githubRepos: []`. All subsequent configuration writes use schema version 2.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: taskchef-delegate
|
|
3
|
-
description: "Dispatch actionable requests from an initialized TaskChef workspace into independently openable Codex project tasks. Use for ordinary work requests in a TaskChef workspace, explicit delegation, or splitting independent work across projects.
|
|
3
|
+
description: "Dispatch actionable requests from an initialized TaskChef workspace into independently openable Codex project tasks. Use for ordinary work requests in a TaskChef workspace, explicit delegation, or splitting independent work across projects. Preserve unresolved delegations for later marker-based recovery, and never use subagents, hooks, schedules, daemons, or executor-completion waiting."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TaskChef Delegate
|
|
@@ -17,7 +17,10 @@ for all deterministic workspace and task-record operations.
|
|
|
17
17
|
- Keep only `AGENTS.md`, `taskchef.json`, and `tasks.jsonl` in a dispatcher
|
|
18
18
|
workspace.
|
|
19
19
|
- Use real Codex tasks, never collaboration or subagent tools.
|
|
20
|
-
- Never use hooks, callbacks, schedules, polling, or
|
|
20
|
+
- Never use hooks, callbacks, schedules, daemons, indefinite polling, or
|
|
21
|
+
background monitors.
|
|
22
|
+
- Use only bounded provisional-ID resolution after `create_thread` returns a
|
|
23
|
+
provisional client ID. Prefer a native Codex wait or resolver when available.
|
|
21
24
|
- Never wait for delegated work after executor creation.
|
|
22
25
|
- Never collect transcripts or hidden reasoning.
|
|
23
26
|
|
|
@@ -29,20 +32,88 @@ for all deterministic workspace and task-record operations.
|
|
|
29
32
|
`$taskchef-bootstrap` if the workspace is missing or unhealthy.
|
|
30
33
|
2. Split the request into the smallest independently useful outcomes. Include
|
|
31
34
|
constraints, expected testing, and reporting in every instruction.
|
|
32
|
-
3. Classify against configured `name`,
|
|
33
|
-
`path` only as checkout identity.
|
|
34
|
-
|
|
35
|
+
3. Classify against configured `name`, every URL in the `githubRepos` list, and
|
|
36
|
+
`description`. Use `path` only as checkout identity. Managed `*-workspace`
|
|
37
|
+
projects advertise their child or sub-repositories in this list.
|
|
38
|
+
When the prompt contains a GitHub issue or pull-request URL, canonicalize
|
|
39
|
+
its case-insensitive owner/repository identity, ignoring `http` versus
|
|
40
|
+
`https`, an optional `www`, a trailing slash or `.git`, and the issue or PR
|
|
41
|
+
suffix. Check that identity against every repository URL of every configured
|
|
42
|
+
project. Route on this evidence only when exactly one configured project
|
|
43
|
+
matches. Ask instead of guessing when no project or several projects match.
|
|
35
44
|
4. Resolve native projects once and require the exact configured path.
|
|
36
|
-
5.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
5. Generate a lowercase full UUID task ID before creation. Prefix the complete
|
|
46
|
+
executor instruction with exactly `# taskchef_id=<full UUID>`, followed by a
|
|
47
|
+
blank line and the instruction body. Preserve this marked instruction for
|
|
48
|
+
recording, and note the creation time. Do not take a pre-creation thread
|
|
49
|
+
snapshot; the exact random marker is the correlation key.
|
|
50
|
+
6. Create one real Codex task using the exact configured project, a local
|
|
51
|
+
environment on its executor host, the marked instruction, and a short title.
|
|
52
|
+
7. When `create_thread` returns a durable `threadId`, immediately run
|
|
40
53
|
`<plugin-root>/bin/taskchef.js task record --json --workspace <workspace>`.
|
|
41
54
|
Send exactly `id`, `project`, `title`, `instruction`, and `threadId` as JSON
|
|
42
|
-
on stdin. Use the configured project path for `project
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
on stdin. Use the configured project path for `project`, and send the marked
|
|
56
|
+
instruction unchanged. Never persist a provisional `clientThreadId` or
|
|
57
|
+
`pendingWorktreeId` as `threadId`. Never persist `hostId`, status, results,
|
|
58
|
+
transcripts, or hidden reasoning.
|
|
59
|
+
8. When creation returns only `clientThreadId` or `pendingWorktreeId`, keep it
|
|
60
|
+
only for the created-thread directive and diagnostic reporting. It is not a
|
|
61
|
+
durable ID and cannot be passed to thread tools or converted directly.
|
|
62
|
+
Immediately record the marked instruction with `threadId: null` using the
|
|
63
|
+
command from step 7, then resolve the durable ID with this bounded workflow:
|
|
64
|
+
|
|
65
|
+
- If the current Codex tool surface provides a dedicated operation that
|
|
66
|
+
accepts the provisional ID and waits for or resolves its durable thread
|
|
67
|
+
ID, call it exactly once with a timeout of at most 30 seconds. Do not invent
|
|
68
|
+
an operation or pass the provisional ID to tools that require `threadId`.
|
|
69
|
+
- When no native operation is available, take at most two `list_threads`
|
|
70
|
+
snapshots with limit 50, near 10 and 30 seconds after the provisional
|
|
71
|
+
result. Count tool latency against the 30-second deadline. Do not start a
|
|
72
|
+
snapshot, candidate read, marker verification, or task-resolution write
|
|
73
|
+
after it.
|
|
74
|
+
- Filter Codex candidates by the expected host, project, creation time
|
|
75
|
+
(allow five seconds of clock skew), and worktree environment whenever
|
|
76
|
+
those fields are present. Use the title only to prioritize reads; Codex
|
|
77
|
+
may normalize it, so never exclude a candidate because its title differs.
|
|
78
|
+
- Read every remaining candidate with `read_thread`, requesting one turn and
|
|
79
|
+
no command output. Read candidates concurrently when the tool surface
|
|
80
|
+
permits. Inspect only the structured
|
|
81
|
+
`userMessage.content[].codexDelegation.input`; do not trust titles,
|
|
82
|
+
summaries, previews, plain-text echoes, or assistant output as proof.
|
|
83
|
+
- Accept a candidate only when the structured input's first line is exactly
|
|
84
|
+
the task's `# taskchef_id=<full UUID>` marker and exactly one candidate
|
|
85
|
+
matches. Apply the same marker verification to a thread ID returned by a
|
|
86
|
+
native resolver. Reject any returned or discovered thread ID equal to the
|
|
87
|
+
provisional identifier or in its `local:` namespace. Then use
|
|
88
|
+
the task-resolution command under **Later resolution** to atomically fill
|
|
89
|
+
the nullable field.
|
|
90
|
+
- Treat native-resolution, snapshot, candidate-read, wait, and task-resolution
|
|
91
|
+
failures as indeterminate. If the workflow ends with zero exact matches,
|
|
92
|
+
multiple matches, or errors, leave the already-recorded `threadId: null`,
|
|
93
|
+
clearly report the unresolved reason and provisional diagnostic ID, and
|
|
94
|
+
never guess.
|
|
95
|
+
|
|
96
|
+
9. If executor creation fails, do not record a task. If recording fails
|
|
45
97
|
after creation, still return the created task and clearly say that it is not
|
|
46
98
|
in the task log. Do not delete the executor.
|
|
47
|
-
|
|
48
|
-
|
|
99
|
+
10. Return immediately after immediate recording or the bounded ID-resolution
|
|
100
|
+
workflow. Emit the appropriate created-thread directive, but label a
|
|
101
|
+
client-thread directive as provisional when resolution failed. Treat a
|
|
102
|
+
nullable record as preserved but unresolved, not as a durable task link. Do
|
|
103
|
+
not read an executor for progress and never wait for executor work
|
|
104
|
+
completion.
|
|
105
|
+
|
|
106
|
+
The package exports pure repository canonicalization and unique URL matching
|
|
107
|
+
helpers from `src/github.js`, plus marker, candidate-filtering, and
|
|
108
|
+
injected-adapter orchestration helpers from `src/delegation.js`, for
|
|
109
|
+
deterministic tests and hosts that can supply thread-tool callbacks. The
|
|
110
|
+
standalone Node CLI cannot call desktop thread tools; perform the tool calls in
|
|
111
|
+
Codex and use the CLI only for validated workspace data operations.
|
|
112
|
+
|
|
113
|
+
## Later resolution
|
|
114
|
+
|
|
115
|
+
When a later Codex workflow finds exactly one durable thread whose structured
|
|
116
|
+
delegated input contains an unresolved task's exact marker, run
|
|
117
|
+
`<plugin-root>/bin/taskchef.js task resolve <task-id> --thread-id <thread-id> --json --workspace <workspace>`.
|
|
118
|
+
Never edit `tasks.jsonl` directly. The CLI permits only an idempotent one-way
|
|
119
|
+
transition from `threadId: null` to one unique durable thread ID.
|