taskchef 7.3.0 → 7.5.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/README.md +58 -15
- package/assets/taskchef-dispatcher-instructions.md +9 -0
- package/docs/images/result-history-dashboard.jpg +0 -0
- package/docs/spec.md +99 -17
- package/docs/workflows.md +75 -17
- package/index.js +10 -0
- package/mcp/server.js +12 -0
- package/package.json +2 -1
- package/skills/taskchef-bootstrap/SKILL.md +4 -2
- package/skills/taskchef-report/SKILL.md +8 -6
- package/src/cli.js +40 -6
- package/src/dashboard/app.js +63 -5
- package/src/dashboard/index.html +2 -2
- package/src/dashboard/styles.css +8 -0
- package/src/dashboard-manager.js +183 -0
- package/src/dashboard.js +57 -1
- package/src/mcp.js +56 -2
- package/src/version.js +7 -0
- package/src/workspace.js +164 -68
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
TaskChef is a local dispatch desk for Codex. Give one dispatcher a request and
|
|
4
4
|
it records each independently useful outcome, creates a normal Codex task in
|
|
5
5
|
the right project, and returns immediately. The executor task is where live
|
|
6
|
-
work, approvals, and follow-ups happen; TaskChef keeps
|
|
7
|
-
|
|
6
|
+
work, approvals, and follow-ups happen; TaskChef keeps every semantic result
|
|
7
|
+
while projecting the latest one for compact navigation and reporting.
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
-
request -> recorded TaskChef task -> Codex executor -> current state +
|
|
10
|
+
request -> recorded TaskChef task -> Codex executor -> current state + result history
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Which document should I read?
|
|
@@ -33,7 +33,8 @@ npm install --global taskchef
|
|
|
33
33
|
|
|
34
34
|
The plugin provides four skills and a local MCP server. The npm installation
|
|
35
35
|
puts the `taskchef` CLI on `PATH`. TaskChef installs no hooks, schedules,
|
|
36
|
-
daemons, or background identity search
|
|
36
|
+
daemons, login items, system services, or background identity search and needs
|
|
37
|
+
no elevated permissions.
|
|
37
38
|
|
|
38
39
|
## Bootstrap and configure
|
|
39
40
|
|
|
@@ -48,7 +49,7 @@ The canonical workspace is `~/.agents/taskchef`. TaskChef owns only:
|
|
|
48
49
|
```text
|
|
49
50
|
AGENTS.md managed dispatcher instructions plus user additions
|
|
50
51
|
taskchef.json schema-2 configured projects and routing metadata
|
|
51
|
-
tasks.jsonl one
|
|
52
|
+
tasks.jsonl one task snapshot per line (schema 6; schema 4/5 migration supported)
|
|
52
53
|
```
|
|
53
54
|
|
|
54
55
|
List or change routing targets conversationally:
|
|
@@ -93,6 +94,12 @@ reads the executor's own `CODEX_THREAD_ID`, self-links, and reports lifecycle
|
|
|
93
94
|
state. Independent outcomes may become separate executors; dependent work
|
|
94
95
|
should stay together.
|
|
95
96
|
|
|
97
|
+
At the start of every dispatcher turn, the managed workspace instructions ask
|
|
98
|
+
the MCP server to best-effort ensure the dashboard. A startup failure never
|
|
99
|
+
blocks an answer, report, or delegation. Every dispatcher response ends with
|
|
100
|
+
the stable [TaskChef Dashboard](http://127.0.0.1:3210/) link; a created-task
|
|
101
|
+
directive remains on the preceding line so dispatch still returns immediately.
|
|
102
|
+
|
|
96
103
|
For example, TaskChef generates this shape:
|
|
97
104
|
|
|
98
105
|
```text
|
|
@@ -112,10 +119,12 @@ when a turn starts and one semantic outcome before that same turn ends:
|
|
|
112
119
|
- `failed`: the executor or creation attempt ended unsuccessfully.
|
|
113
120
|
|
|
114
121
|
A native approval prompt is live Codex state, not `needs_input`.
|
|
115
|
-
TaskChef stores the current reported execution state and
|
|
116
|
-
|
|
117
|
-
immediately without erasing
|
|
118
|
-
|
|
122
|
+
TaskChef stores the current reported execution state and appends every concise
|
|
123
|
+
semantic result to `results`. A follow-up therefore appears as `working`
|
|
124
|
+
immediately without erasing any prior outcome. The final entry is exposed as a
|
|
125
|
+
derived `lastResult` compatibility alias; it is not persisted independently and
|
|
126
|
+
is planned for removal in the next major version after callers move to
|
|
127
|
+
`results.at(-1)`. TaskChef does not store transcripts or non-semantic events.
|
|
119
128
|
|
|
120
129
|
Delegated tasks created by earlier TaskChef versions remain compatible: their
|
|
121
130
|
inline executor protocol still parses, self-links, and may use the deprecated
|
|
@@ -146,12 +155,39 @@ an unambiguous eight-character prefix.
|
|
|
146
155
|
|
|
147
156
|
## Dashboard
|
|
148
157
|
|
|
158
|
+
Dispatcher turns call the input-free `ensure_dashboard` MCP tool. It starts at
|
|
159
|
+
most one dashboard inside the existing TaskChef MCP process on
|
|
160
|
+
`127.0.0.1:3210`, or reuses a listener only when its bounded `/api/health`
|
|
161
|
+
identity proves the exact TaskChef/dashboard-server version and the same
|
|
162
|
+
canonical workspace. The response says `started` or `reused` and includes the
|
|
163
|
+
stable URL, canonical workspace, and versions.
|
|
164
|
+
|
|
165
|
+
The in-process dashboard closes with the MCP process. Closing Codex or reloading
|
|
166
|
+
the plugin may therefore stop the dashboard; the next dispatcher turn restores
|
|
167
|
+
it. TaskChef adds no OS-persistent component.
|
|
168
|
+
|
|
169
|
+
For manual development, run the foreground CLI:
|
|
170
|
+
|
|
149
171
|
```sh
|
|
150
172
|
taskchef dashboard
|
|
173
|
+
taskchef dashboard --port 3211
|
|
151
174
|
```
|
|
152
175
|
|
|
153
176
|
The loopback dashboard watches `tasks.jsonl`, groups current states, and opens
|
|
154
|
-
linked Codex tasks.
|
|
177
|
+
linked Codex tasks. List snapshots and SSE events carry only the latest-result
|
|
178
|
+
projection; opening task details fetches the full newest-first result history.
|
|
179
|
+
It does not mutate TaskChef data and prints its local URL.
|
|
180
|
+
When a compatible foreground dashboard already owns port 3210,
|
|
181
|
+
`ensure_dashboard` reuses it but does not take ownership. If an unknown,
|
|
182
|
+
different-workspace, or stale-version process owns the port, TaskChef reports a
|
|
183
|
+
concise conflict and never kills or replaces that process. The foreground CLI
|
|
184
|
+
similarly asks you to stop the listener or choose another `--port`.
|
|
185
|
+
|
|
186
|
+
The health endpoint contains only a fixed service marker, health schema,
|
|
187
|
+
TaskChef version, dashboard-server version, and canonical workspace. It exposes
|
|
188
|
+
no task data, credentials, environment variables, process control, or secrets.
|
|
189
|
+
|
|
190
|
+

|
|
155
191
|
|
|
156
192
|
## Common recovery
|
|
157
193
|
|
|
@@ -160,20 +196,27 @@ Check the managed workspace:
|
|
|
160
196
|
```sh
|
|
161
197
|
taskchef doctor
|
|
162
198
|
taskchef workspace init
|
|
199
|
+
taskchef workspace migrate
|
|
163
200
|
taskchef doctor
|
|
164
201
|
```
|
|
165
202
|
|
|
166
|
-
`doctor` is read-only. `workspace init` creates missing
|
|
167
|
-
|
|
168
|
-
|
|
203
|
+
`doctor` is read-only. `workspace init` creates missing files and refreshes
|
|
204
|
+
managed instructions. `workspace migrate` explicitly upgrades supported schema
|
|
205
|
+
4/5 task lines to schema 6 under the workspace lock. It validates the complete
|
|
206
|
+
source and converted log before writing, creates an exclusive `tasks.jsonl.pre-v6-*.bak`
|
|
207
|
+
backup, atomically replaces the log, validates the result, and becomes an
|
|
208
|
+
idempotent no-op after migration. If replacement fails, the original remains
|
|
209
|
+
or the reported backup can be restored; unsupported or invalid input is rejected
|
|
210
|
+
before a backup or rewrite.
|
|
169
211
|
|
|
170
212
|
If a new record has no thread ID, the executor is link-pending. Reopen that
|
|
171
213
|
executor so its first action can retry `link_task`. Do not guess an identity
|
|
172
214
|
or edit `tasks.jsonl`. If native task creation failed, the record is retained
|
|
173
215
|
as `failed` with null thread and turn IDs.
|
|
174
216
|
|
|
175
|
-
|
|
176
|
-
|
|
217
|
+
Schemas other than 4, 5, and 6 remain unsupported. Retain such a workspace
|
|
218
|
+
unchanged and create a current workspace; the migration command deliberately
|
|
219
|
+
does not guess how to convert unknown formats.
|
|
177
220
|
|
|
178
221
|
## Boundaries
|
|
179
222
|
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
This folder is the canonical per-user TaskChef dispatcher workspace.
|
|
5
5
|
|
|
6
|
+
- Early in every dispatcher turn, best-effort call the TaskChef
|
|
7
|
+
`ensure_dashboard` MCP tool. Dashboard startup failure must not block direct
|
|
8
|
+
TaskChef answers, reporting, or delegation.
|
|
6
9
|
- Use `$taskchef-bootstrap` when initializing or refreshing this workspace,
|
|
7
10
|
changing or listing its configured projects, running TaskChef doctor,
|
|
8
11
|
or repairing its managed instructions.
|
|
@@ -20,4 +23,10 @@ This folder is the canonical per-user TaskChef dispatcher workspace.
|
|
|
20
23
|
write status or results to this workspace.
|
|
21
24
|
- Explicit invocations of TaskChef skills from other Codex projects use this
|
|
22
25
|
same workspace and task history through TaskChef's global resolution rules.
|
|
26
|
+
- Every final response in this dispatcher workspace must end with this exact
|
|
27
|
+
clickable link on its final non-empty line:
|
|
28
|
+
`[TaskChef Dashboard](http://127.0.0.1:3210/)`. Keep any
|
|
29
|
+
`::created-thread{...}` directive required by delegation on its own line
|
|
30
|
+
immediately before the dashboard link so the immediate-return contract still
|
|
31
|
+
holds. Include the link even when `ensure_dashboard` failed.
|
|
23
32
|
<!-- taskchef:dispatcher-instructions:end -->
|
|
Binary file
|
package/docs/spec.md
CHANGED
|
@@ -23,7 +23,8 @@ is dated research, not contract.
|
|
|
23
23
|
| **Self-linking** | The executor's one-way registration of its own canonical Codex UUIDv7 from `CODEX_THREAD_ID`. |
|
|
24
24
|
| **Link-pending** | A working task whose `threadId` is null and `updatedBy` is `dispatcher`. |
|
|
25
25
|
| **Current execution state** | The latest reported executor turn and its `working`, `needs_input`, `completed`, or `failed` status. |
|
|
26
|
-
| **
|
|
26
|
+
| **Result history** | The ordered collection of every accepted `completed`, `needs_input`, or `failed` per-turn outcome. |
|
|
27
|
+
| **Last semantic result** | The final result-history entry, exposed through the derived `lastResult` compatibility alias. |
|
|
27
28
|
| **Current turn ID** | The canonical Codex UUIDv7 returned by an exact native read of the linked executor for the turn being reported. |
|
|
28
29
|
| **Dashboard** | The loopback, read-only UI derived from validated workspace snapshots and bounded native actions. |
|
|
29
30
|
| **Skill** | One packaged agent procedure: `taskchef-bootstrap`, `taskchef-delegate`, `taskchef-executor`, or `taskchef-report`. |
|
|
@@ -39,8 +40,8 @@ is dated research, not contract.
|
|
|
39
40
|
privacy, and idempotency. It MUST NOT dispatch the owned assignment again.
|
|
40
41
|
- `taskchef-report` MUST own on-demand reporting. It MUST NOT poll or persist
|
|
41
42
|
inferred state.
|
|
42
|
-
- The MCP server MUST expose four primary lifecycle tools
|
|
43
|
-
`report_result` compatibility alias specified below.
|
|
43
|
+
- The MCP server MUST expose `ensure_dashboard`, four primary lifecycle tools,
|
|
44
|
+
and the deprecated `report_result` compatibility alias specified below.
|
|
44
45
|
- The CLI MAY administer and inspect the workspace, but MUST NOT provide a
|
|
45
46
|
second agent lifecycle protocol.
|
|
46
47
|
- The dashboard MUST be read-only with respect to dispatcher files.
|
|
@@ -67,10 +68,10 @@ Names and paths MUST be unique. Git projects MUST be exact Git roots.
|
|
|
67
68
|
Repository URLs MUST canonicalize to `https://github.com/<owner>/<repository>`
|
|
68
69
|
and be case-insensitively deduplicated.
|
|
69
70
|
|
|
70
|
-
`tasks.jsonl` MUST contain zero or more newline-terminated schema-4
|
|
71
|
-
records, one per line.
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
`tasks.jsonl` MUST contain zero or more newline-terminated schema-4, schema-5,
|
|
72
|
+
or schema-6 records, one per line. Schemas 4 and 5 are supported migration/read
|
|
73
|
+
formats; every new record and state mutation MUST write schema 6. Other schemas
|
|
74
|
+
or unsupported fields MUST be rejected without conversion.
|
|
74
75
|
Reads and writes MUST reject symlinked managed files. Mutations
|
|
75
76
|
MUST hold the shared workspace lock and replace state atomically; read-only
|
|
76
77
|
operations MUST NOT require write permission.
|
|
@@ -81,7 +82,7 @@ Every record MUST contain exactly these fields:
|
|
|
81
82
|
|
|
82
83
|
| Field | Contract |
|
|
83
84
|
| --- | --- |
|
|
84
|
-
| `schemaVersion` | Integer `
|
|
85
|
+
| `schemaVersion` | Integer `6`; schema-4/5 records remain readable until explicit migration or their next mutation. |
|
|
85
86
|
| `id` | Unique safe TaskChef ID; delegation uses a lowercase full UUID. |
|
|
86
87
|
| `project` | Immutable configured-project snapshot. |
|
|
87
88
|
| `title` | Non-empty display title. |
|
|
@@ -93,13 +94,26 @@ Every record MUST contain exactly these fields:
|
|
|
93
94
|
| `turnId` | Null before turn reporting; otherwise the current reported turn. Linked MCP journeys use a canonical Codex UUIDv7. |
|
|
94
95
|
| `updatedAt` | ISO 8601 timestamp not earlier than `createdAt` or the prior `updatedAt`; clock rollback cannot backdate a transition. |
|
|
95
96
|
| `updatedBy` | `dispatcher` or `mcp`. |
|
|
96
|
-
| `
|
|
97
|
+
| `results` | Ordered oldest-first array of `{status, summary, turnId, updatedAt}` semantic results, with unique turn IDs and nondecreasing timestamps. |
|
|
98
|
+
|
|
99
|
+
Returned Task objects MUST additionally expose `lastResult` as null for an empty
|
|
100
|
+
history or the final `results` entry. `lastResult` MUST be derived and MUST NOT
|
|
101
|
+
be persisted in schema 6. It is a compatibility alias for schema-4/5, CLI,
|
|
102
|
+
MCP, reporting-skill, and dashboard-list callers, with removal planned for the
|
|
103
|
+
next major version after callers migrate to `results.at(-1)`.
|
|
97
104
|
|
|
98
105
|
Task IDs and non-null thread identities MUST be unique. The immutable intent
|
|
99
106
|
fields MUST NOT change after recording.
|
|
100
107
|
|
|
101
108
|
## Required lifecycle
|
|
102
109
|
|
|
110
|
+
At the start of every dispatcher turn, the dispatcher SHOULD call
|
|
111
|
+
`ensure_dashboard` best-effort. Failure MUST NOT block direct TaskChef answers,
|
|
112
|
+
reporting, or delegation. Every dispatcher final response MUST end with the
|
|
113
|
+
exact clickable `[TaskChef Dashboard](http://127.0.0.1:3210/)` link even when
|
|
114
|
+
ensure failed. A created-thread directive MUST remain on its own line before
|
|
115
|
+
the final link, preserving the delegate skill's immediate-return contract.
|
|
116
|
+
|
|
103
117
|
1. The dispatcher MUST call `prepare_dispatch` once per outcome.
|
|
104
118
|
2. It MUST choose exactly one configured project and exact native-project path.
|
|
105
119
|
3. It MUST build the instruction with the user's outcome beginning on line 1
|
|
@@ -144,6 +158,43 @@ path. Success returns both one text content item and the stated structured
|
|
|
144
158
|
object. Validation, marker, identity, uniqueness, freshness, or filesystem
|
|
145
159
|
failures are surfaced as tool errors and MUST NOT partially mutate the log.
|
|
146
160
|
|
|
161
|
+
### `ensure_dashboard`
|
|
162
|
+
|
|
163
|
+
**Caller:** dispatcher. **Mutation:** starts at most one in-process loopback
|
|
164
|
+
HTTP server; it does not mutate dispatcher workspace files.
|
|
165
|
+
|
|
166
|
+
**Input:** empty object.
|
|
167
|
+
|
|
168
|
+
**Structured output:**
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
{ dashboard: {
|
|
172
|
+
action: "started" | "reused",
|
|
173
|
+
url: "http://127.0.0.1:3210/",
|
|
174
|
+
workspace: string,
|
|
175
|
+
taskchefVersion: string,
|
|
176
|
+
serverVersion: string
|
|
177
|
+
} }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Calls MUST serialize within one MCP process. The first call starts an owned
|
|
181
|
+
dashboard or reuses an exact compatible listener; later and concurrent calls
|
|
182
|
+
are idempotent and report reuse after the single start. The stable default MUST
|
|
183
|
+
bind only to `127.0.0.1:3210` and MUST NOT accept a model-supplied workspace,
|
|
184
|
+
host, or port.
|
|
185
|
+
|
|
186
|
+
Before reuse, TaskChef MUST query a bounded loopback identity endpoint and
|
|
187
|
+
require the exact fixed service/schema, TaskChef version, dashboard-server
|
|
188
|
+
version, and canonical workspace. An unknown, malformed, different-workspace,
|
|
189
|
+
or stale-version listener MUST produce a concise actionable conflict. TaskChef
|
|
190
|
+
MUST NOT kill, replace, signal, or otherwise control that listener. A startup
|
|
191
|
+
failure MUST leave no owned listener. The MCP server MUST close its owned
|
|
192
|
+
dashboard when its transport or process shuts down; it MUST NOT close a reused
|
|
193
|
+
external foreground server.
|
|
194
|
+
|
|
195
|
+
**Annotations:** `readOnlyHint: false`, `destructiveHint: false`,
|
|
196
|
+
`openWorldHint: false`.
|
|
197
|
+
|
|
147
198
|
### `prepare_dispatch`
|
|
148
199
|
|
|
149
200
|
**Caller:** dispatcher. **Mutation:** none.
|
|
@@ -187,7 +238,8 @@ new preparation values, though it writes no state.
|
|
|
187
238
|
|
|
188
239
|
**Structured output:** `{ task: Task }`.
|
|
189
240
|
|
|
190
|
-
The returned task has schema
|
|
241
|
+
The returned task has schema 6, `working`, null summary/turn/thread/lastResult,
|
|
242
|
+
an empty `results` array,
|
|
191
243
|
`updatedBy: dispatcher`, and equal creation/update timestamps. Duplicate IDs,
|
|
192
244
|
unknown projects, malformed markers, and invalid input fail. Repeating a
|
|
193
245
|
successful call is not idempotent; it fails as a duplicate.
|
|
@@ -216,7 +268,7 @@ marker, or ineligible state fails.
|
|
|
216
268
|
### `report_state`
|
|
217
269
|
|
|
218
270
|
**Caller:** executor, or dispatcher only for native creation failure.
|
|
219
|
-
**Mutation:** replaces the current state atomically and preserves `
|
|
271
|
+
**Mutation:** replaces the current state atomically and preserves `results`.
|
|
220
272
|
|
|
221
273
|
**Input:**
|
|
222
274
|
|
|
@@ -235,8 +287,10 @@ the current turn and last semantic result. A semantic state MUST match the
|
|
|
235
287
|
current working turn. Repeating an identical state is idempotent; conflicting
|
|
236
288
|
or older state fails. A null-identity record accepts only a fresh executor
|
|
237
289
|
creation `failed` state with both IDs null. Success sets the current state and
|
|
238
|
-
|
|
239
|
-
|
|
290
|
+
appends a semantic result to `results`; starting newer work preserves the entire
|
|
291
|
+
collection. An identical retry for any settled turn returns success without an
|
|
292
|
+
append. A different result for a settled turn, a stale turn, or a semantic
|
|
293
|
+
result that does not match the active working turn MUST fail.
|
|
240
294
|
|
|
241
295
|
**Annotations:** `readOnlyHint: false`, `destructiveHint: true`,
|
|
242
296
|
`openWorldHint: false`.
|
|
@@ -245,10 +299,10 @@ that result.
|
|
|
245
299
|
|
|
246
300
|
`report_result` retains the prior semantic-only input shape and statuses as a
|
|
247
301
|
temporary compatibility alias. It implicitly accepts a fresh supplied turn and
|
|
248
|
-
stores its semantic result, including for supported schema-4 records and
|
|
302
|
+
stores its semantic result, including for supported schema-4/5 records and
|
|
249
303
|
low-level opaque direct records. It does not accept `working`. New executor
|
|
250
|
-
instructions MUST use `report_state`. Successful mutation upgrades schema 4
|
|
251
|
-
schema
|
|
304
|
+
instructions MUST use `report_state`. Successful mutation upgrades schema 4/5
|
|
305
|
+
to schema 6; unsupported schemas remain rejected.
|
|
252
306
|
|
|
253
307
|
## Reporting and dashboard
|
|
254
308
|
|
|
@@ -258,11 +312,33 @@ state overrides cache. An inactive task does not prove completion. Focused
|
|
|
258
312
|
reports MAY read a selected task once when metadata is newer or evidence is
|
|
259
313
|
uncertain. Reports MUST NOT poll or classify assistant prose.
|
|
260
314
|
|
|
315
|
+
Task lists, summaries, and broad reports MUST use the final result by default.
|
|
261
316
|
The dashboard MUST bind only to loopback, validate the current workspace
|
|
262
|
-
snapshot, and avoid sessions or shared client state.
|
|
317
|
+
snapshot, and avoid sessions or shared client state. `GET /api/health` MUST
|
|
318
|
+
return only the bounded service identity, health schema, exact TaskChef and
|
|
319
|
+
dashboard-server versions, and canonical workspace. It MUST NOT return task
|
|
320
|
+
records, secrets, credentials, environment values, or process-control data.
|
|
321
|
+
Identity remains available while an already-started monitor retains its last
|
|
322
|
+
valid snapshot after a later invalid task log; an invalid initial log MAY fail
|
|
323
|
+
startup safely. Direct thread navigation
|
|
263
324
|
MUST require a canonical Codex UUIDv7. Otherwise it MAY open the revalidated
|
|
264
325
|
configured project. Project paths from task history MUST be matched against
|
|
265
326
|
current configuration before use.
|
|
327
|
+
Snapshot and SSE list payloads MUST omit full `results` history and include the
|
|
328
|
+
derived latest-result projection. The bounded per-task detail endpoint MAY
|
|
329
|
+
return the full validated task so the dialog can render history newest first.
|
|
330
|
+
|
|
331
|
+
## Task-log migration
|
|
332
|
+
|
|
333
|
+
`workspace migrate` MUST explicitly convert every supported schema-4/5 record
|
|
334
|
+
under the shared lock. A legacy `lastResult`, or a schema-4 current semantic
|
|
335
|
+
state, becomes zero or one initial `results` entry. Migration MUST validate the
|
|
336
|
+
complete source and complete schema-6 candidate before changing the task log,
|
|
337
|
+
create and read back an exclusive recovery backup, atomically replace the log,
|
|
338
|
+
and validate the installed result. A fully schema-6 log MUST be an idempotent
|
|
339
|
+
no-op without another backup. Invalid/unsupported input MUST remain untouched;
|
|
340
|
+
failures after backup creation MUST report the backup path and MUST never
|
|
341
|
+
partially rewrite individual lines.
|
|
266
342
|
|
|
267
343
|
## Concurrency and trust
|
|
268
344
|
|
|
@@ -279,3 +355,9 @@ loopback origin, and current configuration before acting.
|
|
|
279
355
|
TaskChef MUST NOT use lifecycle hooks, schedules, polling, recent-thread search,
|
|
280
356
|
transcript search, title matching, hidden reasoning, or token usage to discover
|
|
281
357
|
identity or infer semantic results.
|
|
358
|
+
|
|
359
|
+
TaskChef MUST NOT install or require daemons, launchd agents, login items,
|
|
360
|
+
system services, cron jobs, hooks, privileged components, or elevated/system
|
|
361
|
+
permissions for dashboard availability. Availability is best-effort while the
|
|
362
|
+
owning Codex/plugin MCP process is alive and is not guaranteed while Codex is
|
|
363
|
+
closed.
|
package/docs/workflows.md
CHANGED
|
@@ -14,16 +14,55 @@ research.
|
|
|
14
14
|
| `skills/taskchef-executor/SKILL.md` | Own, self-link, execute, and report every executor turn. |
|
|
15
15
|
| `skills/taskchef-bootstrap/SKILL.md` | Initialize current workspace and configure projects. |
|
|
16
16
|
| `skills/taskchef-report/SKILL.md` | Select cached tasks and perform bounded live checks. |
|
|
17
|
-
| `src/mcp.js` |
|
|
17
|
+
| `src/mcp.js` | Dashboard ensure, four primary lifecycle tools, one deprecated alias, shutdown ownership, and MCP annotations. |
|
|
18
18
|
| `src/delegation.js` | UUID marker, concise executor-skill invocation shape, and creation-failure handling. |
|
|
19
19
|
| `src/workspace.js` | Current schemas, validation, locking, atomic JSONL writes, linking, and result freshness. |
|
|
20
20
|
| `src/cli.js` | Administration, inspection, diagnostics, and dashboard startup. |
|
|
21
|
-
| `src/dashboard.js` |
|
|
21
|
+
| `src/dashboard.js` | Versioned health identity, validated compact snapshots, SSE fan-out, on-demand details, and bounded open actions. |
|
|
22
|
+
| `src/dashboard-manager.js` | Concurrent singleton ensure, exact listener reuse, conflicts, and owned shutdown. |
|
|
22
23
|
|
|
23
24
|
The MCP process resolves `TASKCHEF_WORKSPACE` once and never accepts a model
|
|
24
25
|
supplied path. The CLI resolves `--workspace`, then the environment, then the
|
|
25
26
|
per-user default.
|
|
26
27
|
|
|
28
|
+
## Dispatcher dashboard lifecycle
|
|
29
|
+
|
|
30
|
+
The generated managed `AGENTS.md` block makes dashboard maintenance a
|
|
31
|
+
best-effort prelude to every dispatcher turn and keeps response ordering
|
|
32
|
+
centralized instead of duplicating it across delegate/report skills.
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
sequenceDiagram
|
|
36
|
+
autonumber
|
|
37
|
+
participant D as Dispatcher
|
|
38
|
+
participant M as TaskChef MCP
|
|
39
|
+
participant H as Loopback health
|
|
40
|
+
participant S as Dashboard server
|
|
41
|
+
D->>M: ensure_dashboard()
|
|
42
|
+
M->>M: Serialize concurrent ensure calls
|
|
43
|
+
M->>H: GET 127.0.0.1:3210/api/health
|
|
44
|
+
alt Exact service, versions, and canonical workspace
|
|
45
|
+
H-->>M: Bounded compatible identity
|
|
46
|
+
M-->>D: reused, URL, workspace, versions
|
|
47
|
+
else No listener
|
|
48
|
+
H--xM: Connection refused
|
|
49
|
+
M->>S: Start in this MCP process on 127.0.0.1:3210
|
|
50
|
+
S-->>M: Owned server
|
|
51
|
+
M-->>D: started, URL, workspace, versions
|
|
52
|
+
else Unknown, stale, or different workspace
|
|
53
|
+
H-->>M: Missing or incompatible identity
|
|
54
|
+
M-->>D: Actionable conflict, listener untouched
|
|
55
|
+
end
|
|
56
|
+
Note over D: Continue even when ensure failed
|
|
57
|
+
D-->>D: Answer, report, or dispatch
|
|
58
|
+
Note over D: Created-thread directive, when any, precedes final dashboard link
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When the MCP transport or plugin process closes, it closes only the server it
|
|
62
|
+
started. A compatible foreground `taskchef dashboard` listener may be reused
|
|
63
|
+
but remains owned by that CLI process. No TaskChef path terminates an unknown
|
|
64
|
+
listener or installs OS persistence.
|
|
65
|
+
|
|
27
66
|
## Normal delegation and self-linking
|
|
28
67
|
|
|
29
68
|
The dispatcher uses native Codex project discovery for routing and MCP for
|
|
@@ -50,7 +89,7 @@ sequenceDiagram
|
|
|
50
89
|
D->>D: Choose one configured and native project
|
|
51
90
|
D->>M: record_task(id, project, title, instruction, null)
|
|
52
91
|
M->>W: recordTask()
|
|
53
|
-
W->>W: Lock, validate, append schema-
|
|
92
|
+
W->>W: Lock, validate, append schema-6 snapshot
|
|
54
93
|
W-->>M: working link-pending task
|
|
55
94
|
M-->>D: task
|
|
56
95
|
D->>C: Create executor with marked instruction
|
|
@@ -77,8 +116,8 @@ semantic callbacks.
|
|
|
77
116
|
## State reporting
|
|
78
117
|
|
|
79
118
|
The executor obtains the turn identity from an exact native read of its own
|
|
80
|
-
linked task. `report_state` records live turn state while preserving the
|
|
81
|
-
semantic result
|
|
119
|
+
linked task. `report_state` records live turn state while preserving the ordered
|
|
120
|
+
semantic result history.
|
|
82
121
|
|
|
83
122
|
```mermaid
|
|
84
123
|
sequenceDiagram
|
|
@@ -91,13 +130,13 @@ sequenceDiagram
|
|
|
91
130
|
C-->>E: Current turn ID
|
|
92
131
|
E->>M: report_state(..., working, null)
|
|
93
132
|
M->>W: reportTaskState()
|
|
94
|
-
W->>W: Store current turn and preserve
|
|
133
|
+
W->>W: Store current turn and preserve results
|
|
95
134
|
E->>E: Work, finish, or reach semantic decision
|
|
96
135
|
E->>M: report_state(..., semantic status, summary)
|
|
97
136
|
M->>W: reportTaskState()
|
|
98
137
|
W->>W: Lock and validate identity and freshness
|
|
99
138
|
alt Same current working turn
|
|
100
|
-
W->>W:
|
|
139
|
+
W->>W: Append semantic result and derive lastResult
|
|
101
140
|
W-->>M: Updated task
|
|
102
141
|
M-->>E: Recorded result
|
|
103
142
|
else Same turn and same result
|
|
@@ -134,9 +173,9 @@ sequenceDiagram
|
|
|
134
173
|
C-->>E: turnB
|
|
135
174
|
E->>M: report_state(..., turnB, working, null)
|
|
136
175
|
M->>W: reportTaskState()
|
|
137
|
-
W->>W: Require turnB greater and preserve
|
|
138
|
-
W-->>M: working snapshot plus
|
|
139
|
-
M-->>E: working snapshot plus
|
|
176
|
+
W->>W: Require turnB greater and preserve results
|
|
177
|
+
W-->>M: working snapshot plus history A
|
|
178
|
+
M-->>E: working snapshot plus history A
|
|
140
179
|
E->>M: report_state(..., turnB, completed, summaryB)
|
|
141
180
|
M->>W: reportTaskState()
|
|
142
181
|
W-->>M: completed snapshot plus result B
|
|
@@ -224,7 +263,9 @@ sequenceDiagram
|
|
|
224
263
|
F-->>D: Filesystem change
|
|
225
264
|
D->>F: Bounded read from one descriptor
|
|
226
265
|
D->>D: Validate current schema and sort
|
|
227
|
-
D-->>B: SSE snapshot
|
|
266
|
+
D-->>B: Compact SSE snapshot without results
|
|
267
|
+
B->>D: GET task detail on demand
|
|
268
|
+
D-->>B: Full validated history
|
|
228
269
|
B->>D: Open task action
|
|
229
270
|
alt Canonical Codex UUIDv7
|
|
230
271
|
D->>C: Direct thread navigation
|
|
@@ -234,9 +275,25 @@ sequenceDiagram
|
|
|
234
275
|
end
|
|
235
276
|
```
|
|
236
277
|
|
|
237
|
-
The dashboard binds to `127.0.0.1`, has no shared session state, limits
|
|
238
|
-
|
|
239
|
-
|
|
278
|
+
The dashboard binds to `127.0.0.1`, has no shared session state, limits task
|
|
279
|
+
count, file size, result count, and display fields, and checks origin/authority
|
|
280
|
+
for stateful local actions. Its bounded identity endpoint contains no task data
|
|
281
|
+
or secrets. The monitor already validates the complete log, but
|
|
282
|
+
snapshot/SSE list projections omit `results` so repeated updates do not resend
|
|
283
|
+
unnecessary history. A read-only per-task endpoint returns full history only
|
|
284
|
+
when the dialog opens. Historical project paths are untrusted until matched
|
|
285
|
+
against current configuration.
|
|
286
|
+
|
|
287
|
+
## Schema 4/5 migration
|
|
288
|
+
|
|
289
|
+
`taskchef workspace migrate` acquires the same workspace lock as lifecycle
|
|
290
|
+
writers, validates the complete legacy log, converts each schema-4/5 latest
|
|
291
|
+
result into zero or one initial schema-6 `results` entry, then validates the
|
|
292
|
+
complete candidate. Before replacement it writes and reads back an exclusive
|
|
293
|
+
`tasks.jsonl.pre-v6-*.bak` file. The task log is replaced atomically and
|
|
294
|
+
validated again. A second run sees only schema 6 and returns unchanged without
|
|
295
|
+
another backup. Unsupported or malformed input fails before backup/rewrite;
|
|
296
|
+
after a later filesystem failure, the reported backup is the recovery source.
|
|
240
297
|
|
|
241
298
|
## Concurrency and trust boundaries
|
|
242
299
|
|
|
@@ -251,6 +308,7 @@ summary is cryptographically authenticated; this is a local single-user trust
|
|
|
251
308
|
model. Managed files, instructions, project snapshots, MCP inputs, and dashboard
|
|
252
309
|
requests are validated at every action boundary.
|
|
253
310
|
|
|
254
|
-
Configuration schema 2 and task schemas 4 and
|
|
255
|
-
read
|
|
256
|
-
schema
|
|
311
|
+
Configuration schema 2 and task schemas 4, 5, and 6 are accepted. Schemas 4/5
|
|
312
|
+
are read/migration compatibility until an explicit migration or lifecycle
|
|
313
|
+
mutation upgrades each record to schema 6. Schema 6 persists `results` only and
|
|
314
|
+
derives `lastResult` for compatibility. Other schemas are rejected without rewrite.
|
package/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export {
|
|
|
10
10
|
initializeWorkspace,
|
|
11
11
|
linkTask,
|
|
12
12
|
listProjects,
|
|
13
|
+
migrateTaskLog,
|
|
13
14
|
prepareDispatch,
|
|
14
15
|
readConfig,
|
|
15
16
|
listTasks,
|
|
@@ -57,10 +58,19 @@ export {
|
|
|
57
58
|
} from "./src/codex-app.js";
|
|
58
59
|
|
|
59
60
|
export {
|
|
61
|
+
DASHBOARD_HEALTH_MAX_BYTES,
|
|
62
|
+
DASHBOARD_HEALTH_PATH,
|
|
60
63
|
DashboardMonitor,
|
|
61
64
|
createDashboardServer,
|
|
62
65
|
dashboardAuthority,
|
|
63
66
|
sortTasksByMeaningfulUpdate,
|
|
64
67
|
} from "./src/dashboard.js";
|
|
65
68
|
|
|
69
|
+
export {
|
|
70
|
+
createDashboardManager,
|
|
71
|
+
readDashboardIdentity,
|
|
72
|
+
} from "./src/dashboard-manager.js";
|
|
73
|
+
|
|
74
|
+
export { DASHBOARD_SERVER_VERSION, TASKCHEF_VERSION } from "./src/version.js";
|
|
75
|
+
|
|
66
76
|
export { createTaskChefMcpServer } from "./src/mcp.js";
|
package/mcp/server.js
CHANGED
|
@@ -5,3 +5,15 @@ import { createTaskChefMcpServer } from "../src/mcp.js";
|
|
|
5
5
|
|
|
6
6
|
const server = createTaskChefMcpServer();
|
|
7
7
|
await server.connect(new StdioServerTransport());
|
|
8
|
+
|
|
9
|
+
let shutdownPromise = null;
|
|
10
|
+
const shutdown = () => {
|
|
11
|
+
shutdownPromise ??= server.close().catch((error) => {
|
|
12
|
+
process.stderr.write(`TaskChef MCP shutdown failed: ${error.message}\n`);
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
});
|
|
15
|
+
return shutdownPromise;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
process.once("SIGINT", shutdown);
|
|
19
|
+
process.once("SIGTERM", shutdown);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taskchef",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.5.0",
|
|
4
4
|
"description": "A non-blocking interactive dispatcher for visible Codex tasks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Favo Yang",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"docs/spec.md",
|
|
27
27
|
"docs/workflows.md",
|
|
28
28
|
"docs/firstmate-taskchef-comparison.md",
|
|
29
|
+
"docs/images/result-history-dashboard.jpg",
|
|
29
30
|
"index.js",
|
|
30
31
|
"mcp",
|
|
31
32
|
"scripts/benchmark-dispatch-prepare.js",
|
|
@@ -19,8 +19,10 @@ all deterministic workspace operations.
|
|
|
19
19
|
dispatcher workspace. Preserve unrelated user-owned paths.
|
|
20
20
|
- Do not dispatch tasks or report on executor threads during bootstrap unless
|
|
21
21
|
the user separately requests those actions.
|
|
22
|
-
- Never create hooks, schedules, polling,
|
|
23
|
-
|
|
22
|
+
- Never create hooks, schedules, polling, daemons, login items, or system
|
|
23
|
+
services. The managed dispatcher instructions own best-effort dashboard
|
|
24
|
+
startup and final-link guidance; bootstrap only refreshes that managed block.
|
|
25
|
+
TaskChef executors self-link through the installed MCP server.
|
|
24
26
|
|
|
25
27
|
## Initialize and repair
|
|
26
28
|
|
|
@@ -44,14 +44,16 @@ all deterministic task-log operations.
|
|
|
44
44
|
detailed read. Native approval is live Codex state, not a `needs_input`
|
|
45
45
|
callback. An inactive status never proves semantic completion; it only
|
|
46
46
|
permits a trustworthy cached MCP result to stand.
|
|
47
|
-
4. In schema
|
|
48
|
-
execution state and treat `
|
|
49
|
-
|
|
47
|
+
4. In schema 6, treat `status`, `turnId`, and `updatedAt` as the latest reported
|
|
48
|
+
execution state and treat `results` as the ordered semantic history.
|
|
49
|
+
`lastResult` is the derived compatibility alias for `results.at(-1)`; prefer
|
|
50
|
+
the collection when full history matters and the alias for compact latest-state
|
|
51
|
+
reporting. A `working` state with a non-null `lastResult` means a newer executor
|
|
50
52
|
turn started after that result; show the prior result as history, not as the
|
|
51
53
|
current outcome. Treat a failed `lastResult` with null thread and turn IDs as
|
|
52
|
-
a fresh executor-creation failure.
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
a fresh executor-creation failure. Schema 4/5 snapshots normalize zero or one
|
|
55
|
+
semantic result into `results` and `lastResult` without rewriting their log line.
|
|
56
|
+
No live read is possible or needed for that creation failure. When identity is certain and
|
|
55
57
|
metadata says the thread is inactive, trust the latest semantic result by
|
|
56
58
|
default in a broad overview unless a newer working state makes it historical.
|
|
57
59
|
Do not read every idle terminal task in an overview merely because native
|