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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.3.0",
3
+ "version": "7.5.0",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
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 the latest compact
7
- snapshot for navigation and reporting.
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 + last result
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 schema-4/5 snapshot per task (new writes use schema 5)
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 separately preserves
116
- the last concise semantic result. A follow-up therefore appears as `working`
117
- immediately without erasing the previous outcome. TaskChef does not store the
118
- transcript or a lifecycle event log.
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. It does not mutate TaskChef data and prints its local URL.
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
+ ![Task detail result history](docs/images/result-history-dashboard.jpg)
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 current-schema files
167
- and refreshes managed instructions; it does not migrate unsupported
168
- configuration or task records.
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
- If an unsupported workspace must be retained, keep it as a backup and create a
176
- new current workspace. TaskChef provides no conversion or merge command.
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 -->
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
- | **Last semantic result** | The most recent `completed`, `needs_input`, or `failed` outcome, preserved separately while a newer turn is working. |
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 plus the deprecated
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 or schema-5
71
- records, one per line. Schema 4 is read compatibility for the previously
72
- released format; every new record and state mutation MUST write schema 5.
73
- Other schemas or unsupported fields MUST be rejected without conversion.
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 `5`; schema-4 records remain readable until their next mutation. |
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
- | `lastResult` | Null before a semantic result; otherwise `{status, summary, turnId, updatedAt}` preserving the latest semantic result. |
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 5, `working`, null summary/turn/thread/lastResult,
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 `lastResult`.
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
- preserves the semantic state in `lastResult`; starting newer work does not erase
239
- that result.
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 to
251
- schema 5; unsupported schemas remain rejected.
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. Direct thread navigation
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` | Four primary lifecycle tools, one deprecated alias, and MCP annotations. |
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` | Validated snapshots, SSE fan-out, and bounded open actions. |
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-5 snapshot
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 last
81
- semantic result separately.
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 lastResult
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: Store semantic state and lastResult
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 result A
138
- W-->>M: working snapshot plus lastResult A
139
- M-->>E: working snapshot plus lastResult A
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
- request bodies, and checks origin/authority for stateful local actions. Historical
239
- project paths are untrusted until matched against current configuration.
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 5 are accepted. Schema 4 is
255
- read-only compatibility until a lifecycle mutation upgrades that record to
256
- schema 5. Other schemas are rejected without rewrite.
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.0",
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, or daemons. TaskChef executors
23
- self-link through the installed MCP server.
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 5, treat `status`, `turnId`, and `updatedAt` as the latest reported
48
- execution state and treat `lastResult` as the separately preserved semantic
49
- result. A `working` state with a non-null `lastResult` means a newer executor
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. No live read is possible or needed.
53
- Schema 4 snapshots normalize a structurally complete result into
54
- `lastResult` without rewriting their log line. When identity is certain and
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