taskchef 8.7.0 → 9.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.
Files changed (149) hide show
  1. package/.codex-plugin/plugin.json +7 -10
  2. package/.mcp.json +3 -2
  3. package/README.md +31 -158
  4. package/docs/mcp-app.md +21 -4
  5. package/docs/spec.md +38 -746
  6. package/docs/taskchef-next-storage.md +2 -2
  7. package/index.js +2 -99
  8. package/package.json +12 -49
  9. package/skills/delegate/SKILL.md +44 -0
  10. package/skills/delegate/agents/openai.yaml +4 -0
  11. package/src/codex-app.js +3 -152
  12. package/src/codex-session-scanner.js +2 -2
  13. package/src/file-lock.js +25 -0
  14. package/src/mcp-app/react/NextTaskDetail.test.tsx +1 -1
  15. package/src/mcp-app/react/NextTaskDetail.tsx +8 -8
  16. package/src/mcp-app/react/main.test.tsx +3 -3
  17. package/src/mcp-app/react/main.tsx +7 -7
  18. package/src/mcp-app.js +4 -4
  19. package/src/mcp.js +4 -542
  20. package/src/next-cache.js +2 -2
  21. package/src/next-github.js +3 -3
  22. package/src/next-notifications.js +2 -2
  23. package/src/{dashboard/react → ui}/components/CardStatusIcons.tsx +1 -1
  24. package/src/{dashboard/react → ui}/components/GitHubLinks.tsx +1 -1
  25. package/src/{dashboard/react → ui}/components/LinkedText.tsx +1 -1
  26. package/src/{dashboard/react → ui}/components/RelativeTime.test.tsx +1 -1
  27. package/src/{dashboard/react → ui}/components/RelativeTime.tsx +1 -1
  28. package/src/{dashboard/react → ui}/components/ReplyImagePreview.test.tsx +1 -1
  29. package/src/{dashboard/react → ui}/components/TaskBoard.tsx +1 -1
  30. package/src/{dashboard/react → ui}/components/TaskCard.tsx +1 -1
  31. package/src/{dashboard/react → ui}/components/TurnContent.tsx +1 -1
  32. package/src/{dashboard/react → ui}/presentation.ts +1 -1
  33. package/src/version.js +2 -1
  34. package/BACKLOG.md +0 -48
  35. package/assets/e2e-benchmark-example.json +0 -50
  36. package/assets/taskchef-dispatcher-instructions.md +0 -44
  37. package/bin/taskchef.js +0 -20
  38. package/docs/advanced-guide.md +0 -497
  39. package/docs/dashboard-lifecycle.md +0 -149
  40. package/docs/dashboard-ui.md +0 -40
  41. package/docs/firstmate-taskchef-comparison.md +0 -283
  42. package/docs/images/ccusage-token-consumption.png +0 -0
  43. package/docs/images/dashboard-identity.jpg +0 -0
  44. package/docs/images/dashboard-token-pending.jpg +0 -0
  45. package/docs/images/interrupted-turn-recovery.jpg +0 -0
  46. package/docs/images/notification-event-snapshots.jpg +0 -0
  47. package/docs/images/readme-board.png +0 -0
  48. package/docs/images/readme-completed.png +0 -0
  49. package/docs/images/readme-list.png +0 -0
  50. package/docs/images/readme-needs-input.png +0 -0
  51. package/docs/images/readme-roles.png +0 -0
  52. package/docs/images/reported-work-duration-desktop.jpg +0 -0
  53. package/docs/images/reported-work-duration-mobile.jpg +0 -0
  54. package/docs/images/result-history-dashboard.jpg +0 -0
  55. package/docs/images/taskchef-pr-icon-comparison.jpg +0 -0
  56. package/docs/images/taskchef-unified-status-popup.jpg +0 -0
  57. package/docs/workflows.md +0 -476
  58. package/mcp/dashboard-session.js +0 -51
  59. package/scripts/benchmark-dispatch-prepare.js +0 -90
  60. package/scripts/e2e-benchmark.js +0 -206
  61. package/scripts/roles/resolve_roles.py +0 -293
  62. package/skills/taskchef-bootstrap/SKILL.md +0 -96
  63. package/skills/taskchef-bootstrap/agents/openai.yaml +0 -4
  64. package/skills/taskchef-bootstrap/references/project-index.md +0 -154
  65. package/skills/taskchef-copilot/SKILL.md +0 -75
  66. package/skills/taskchef-copilot/agents/openai.yaml +0 -4
  67. package/skills/taskchef-dashboard/SKILL.md +0 -24
  68. package/skills/taskchef-dashboard/agents/openai.yaml +0 -4
  69. package/skills/taskchef-delegate/SKILL.md +0 -102
  70. package/skills/taskchef-delegate/agents/openai.yaml +0 -4
  71. package/skills/taskchef-delegate/references/model-roles.md +0 -29
  72. package/skills/taskchef-executor/SKILL.md +0 -154
  73. package/skills/taskchef-executor/agents/openai.yaml +0 -4
  74. package/skills/taskchef-executor/references/compatibility.md +0 -22
  75. package/skills/taskchef-executor/references/ending-actions.md +0 -26
  76. package/src/backups.js +0 -359
  77. package/src/cli.js +0 -733
  78. package/src/config-audit.js +0 -99
  79. package/src/config-mutations.js +0 -106
  80. package/src/dashboard/actions.js +0 -136
  81. package/src/dashboard/app.js +0 -1172
  82. package/src/dashboard/dist/app.js +0 -269
  83. package/src/dashboard/dist/app.js.map +0 -1
  84. package/src/dashboard/dist/index.html +0 -16
  85. package/src/dashboard/dist/styles.css +0 -1
  86. package/src/dashboard/index.html +0 -148
  87. package/src/dashboard/react/App.test.tsx +0 -346
  88. package/src/dashboard/react/App.tsx +0 -515
  89. package/src/dashboard/react/api.test.ts +0 -40
  90. package/src/dashboard/react/api.ts +0 -103
  91. package/src/dashboard/react/components/ActivityTimeline.tsx +0 -118
  92. package/src/dashboard/react/components/ModelSettings.test.tsx +0 -180
  93. package/src/dashboard/react/components/ModelSettings.tsx +0 -106
  94. package/src/dashboard/react/components/NotificationCenter.test.tsx +0 -76
  95. package/src/dashboard/react/components/NotificationCenter.tsx +0 -111
  96. package/src/dashboard/react/components/PullRequestBadges.tsx +0 -18
  97. package/src/dashboard/react/components/TaskDetail.test.tsx +0 -255
  98. package/src/dashboard/react/components/TaskDetail.tsx +0 -271
  99. package/src/dashboard/react/components/UsagePanel.tsx +0 -96
  100. package/src/dashboard/react/index.html +0 -15
  101. package/src/dashboard/react/main.tsx +0 -12
  102. package/src/dashboard/react/overlay-state.test.ts +0 -110
  103. package/src/dashboard/react/overlay-state.ts +0 -60
  104. package/src/dashboard/react/presentation.test.tsx +0 -571
  105. package/src/dashboard/styles.css +0 -261
  106. package/src/dashboard-control.js +0 -34
  107. package/src/dashboard-manager.js +0 -339
  108. package/src/dashboard-session-process.js +0 -88
  109. package/src/dashboard-session.js +0 -86
  110. package/src/dashboard.js +0 -1303
  111. package/src/delegation.js +0 -277
  112. package/src/github.js +0 -107
  113. package/src/model-roles.js +0 -70
  114. package/src/recorded-usage-tracker.js +0 -92
  115. package/src/usage-tracker.js +0 -650
  116. package/src/usage.js +0 -367
  117. package/src/workspace-path.js +0 -48
  118. package/src/workspace.js +0 -3629
  119. /package/src/{dashboard/react → ui}/components/AnimatedUsage.test.tsx +0 -0
  120. /package/src/{dashboard/react → ui}/components/CardStatusIcons.test.tsx +0 -0
  121. /package/src/{dashboard/react → ui}/components/ImageGallery.tsx +0 -0
  122. /package/src/{dashboard/react → ui}/components/OpenChatButton.test.tsx +0 -0
  123. /package/src/{dashboard/react → ui}/components/OpenChatButton.tsx +0 -0
  124. /package/src/{dashboard/react → ui}/components/PrGlyph.tsx +0 -0
  125. /package/src/{dashboard/react → ui}/components/QueuedPrompts.test.tsx +0 -0
  126. /package/src/{dashboard/react → ui}/components/QueuedPrompts.tsx +0 -0
  127. /package/src/{dashboard/react → ui}/components/ReplyCover.test.tsx +0 -0
  128. /package/src/{dashboard/react → ui}/components/ReplyCover.tsx +0 -0
  129. /package/src/{dashboard/react → ui}/components/ReplyImagePreview.tsx +0 -0
  130. /package/src/{dashboard/react → ui}/components/ReplyMarkdown.test.tsx +0 -0
  131. /package/src/{dashboard/react → ui}/components/ReplyMarkdown.tsx +0 -0
  132. /package/src/{dashboard/react → ui}/components/SavedUsageFormat.test.tsx +0 -0
  133. /package/src/{dashboard/react → ui}/components/SavedUsageFormat.tsx +0 -0
  134. /package/src/{dashboard/react → ui}/components/ShimmerText.tsx +0 -0
  135. /package/src/{dashboard/react → ui}/components/StatsGrid.tsx +0 -0
  136. /package/src/{dashboard/react → ui}/components/StatusBadge.tsx +0 -0
  137. /package/src/{dashboard/react → ui}/components/TaskBoard.test.tsx +0 -0
  138. /package/src/{dashboard/react → ui}/components/TaskCardStats.test.tsx +0 -0
  139. /package/src/{dashboard/react → ui}/components/TaskCardStats.tsx +0 -0
  140. /package/src/{dashboard/react → ui}/components/TurnContent.test.tsx +0 -0
  141. /package/src/{dashboard/react → ui}/fixtures.ts +0 -0
  142. /package/src/{dashboard → ui}/github-links.js +0 -0
  143. /package/src/{dashboard/react → ui}/image-cache.test.ts +0 -0
  144. /package/src/{dashboard/react → ui}/image-cache.ts +0 -0
  145. /package/src/{dashboard → ui}/state.js +0 -0
  146. /package/src/{dashboard/react → ui}/styles.css +0 -0
  147. /package/src/{dashboard/react → ui}/test-setup.ts +0 -0
  148. /package/src/{dashboard → ui}/time.js +0 -0
  149. /package/src/{dashboard/react → ui}/types.ts +0 -0
@@ -1,497 +0,0 @@
1
- # TaskChef advanced guide
2
-
3
- Detailed setup, operation, recovery, and development reference for TaskChef.
4
-
5
- ## Install
6
-
7
- TaskChef requires Node.js 18 or newer, Git, Codex desktop, and local access to
8
- the projects that will receive work.
9
-
10
- TaskChef uses its own accounting engine for token usage and API-equivalent cost
11
- estimates. Usage requires Node.js 22.18+ and readable local Codex records.
12
- It includes linked subagents and uses the same pricing data as the board.
13
- Lifecycle reporting and the dashboard continue to work when usage is unavailable.
14
-
15
- ```sh
16
- codex plugin marketplace add favoyang/codex-plugins
17
- codex plugin add taskchef@favoyang-plugins
18
- ```
19
-
20
- The plugin provides five skills and a local MCP server. Its skills use the CLI
21
- bundled with the plugin, so a global npm installation is not needed for the
22
- dispatcher workflow. To run `taskchef` directly from a terminal, install the
23
- CLI separately:
24
-
25
- ```sh
26
- npm install --global taskchef
27
- ```
28
-
29
- TaskChef installs no hooks, schedules, daemons, login items, system services,
30
- or background identity search and needs no elevated permissions.
31
-
32
- ## Bootstrap and index projects
33
-
34
- For the first run, ask the bootstrap skill to create and verify the per-user
35
- dispatcher and import saved local Codex projects:
36
-
37
- ```text
38
- $taskchef-bootstrap Set up TaskChef and index my local Codex projects.
39
- ```
40
-
41
- The canonical workspace is `~/.agents/taskchef`. TaskChef owns only:
42
-
43
- ```text
44
- AGENTS.md managed dispatcher instructions plus user additions
45
- taskchef.json schema-2 Codex project index, dashboard preference, and delegation metadata
46
- tasks.jsonl one task snapshot per line (schema 10; schema 4-9 migration supported)
47
- .taskchef-usage.json optional mode-0600 normalized usage cache
48
- ```
49
-
50
- To inspect or manually adjust the project index later, use the bootstrap skill:
51
-
52
- ```text
53
- $taskchef-bootstrap List my indexed Codex projects.
54
- $taskchef-bootstrap Index /workspace/payments as payments. It owns authorization, capture, refunds, and retries.
55
- $taskchef-bootstrap Reindex after the Codex projects I added today.
56
- ```
57
-
58
- TaskChef indexes existing Codex projects for delegation. The index stores
59
- canonical paths and routing metadata; it never indexes repository contents or
60
- creates another kind of project. For a folder already saved as a local Codex
61
- project, the bootstrap skill requires an exact canonical-path match before
62
- writing and verifying its TaskChef index entry. For a new folder, or an existing
63
- folder not yet saved by Codex, it creates the directory only when explicitly
64
- requested, opens the canonical path with the validated Codex Desktop CLI's
65
- `codex app <path>` mechanism, re-lists native projects, and requires the same
66
- exact match before indexing it. An open request without a verified native
67
- project is reported as partial setup, not delegation-ready.
68
-
69
- Update one indexed project with taskchef project update; repeated
70
- --github-repo values replace that entry's complete repository list while
71
- leaving every other project untouched. project list --json returns stable
72
- configuration and project-set hashes for postcondition checks.
73
-
74
- Whole-index replacement, project removal, and restore are preview-bound. Run
75
- them with --dry-run, inspect the exact diff, then apply with the returned
76
- hashes, counts, plan hash, and exact removed-name confirmation after the user
77
- approves every removed project. TaskChef creates private snapshots under
78
- backups/ before mutations and actual dashboard startup. Use taskchef backup
79
- list, create, verify, restore, and prune; restore never runs automatically and
80
- creates a pre-restore safety snapshot. If the live configuration is missing or
81
- malformed, preview an explicit config or state restore, then bind the apply to
82
- the preview's raw-state hash and plan with --confirm-unreadable-current.
83
-
84
- The dispatcher also reconciles saved Codex projects automatically before each
85
- delegation batch. You do not need a separate reindex step when adding a native
86
- Codex project. Manual reindexing compares exact same-host canonical paths from
87
- one native schema-2 project snapshot.
88
- Reconciliation adds eligible paths and identity bindings atomically, isolates
89
- per-project failures, and preserves existing curated names, descriptions, and
90
- complete repository lists. It does not delete missing projects. Duplicate
91
- native IDs, duplicate canonical targets, and identity/path moves remain
92
- diagnostics rather than guesses.
93
-
94
- Configuration schema 2 accepts an optional strict `projectIndex` containing
95
- local native identity bindings, explicit exclusions, and bounded routing hints.
96
- Removing a project records an exclusion so reconciliation cannot silently
97
- re-add it; `include_project` clears an exact exclusion before a later reconcile.
98
- Aliases come only from explicit selection or correction. Repository ownership
99
- requires an inspected exact origin, and report-derived responsibilities retain
100
- their accepted task/thread/turn provenance. Forgetting keeps bounded suppression
101
- so an old report retry cannot recreate a removed hint. Older TaskChef releases
102
- reject this optional field; use a compatible backup before downgrading.
103
-
104
- Codex CLI resolution follows the same contract as
105
- `workspace init --register-codex`: an explicit `--codex-cli` path wins, then
106
- `TASKCHEF_CODEX_CLI`; either must be executable and support `app --help`.
107
- Without an override, TaskChef prefers a validated `codex` PATH candidate under
108
- `Contents/Resources`; otherwise it validates only the first executable `codex`
109
- in PATH order. It does not assume an arbitrary shell command or hard-code an
110
- application bundle location.
111
-
112
- Or use the CLI:
113
-
114
- ```sh
115
- taskchef project add /workspace/payments --name payments \
116
- --description "Authorization, capture, refunds, and retries."
117
- taskchef project list
118
- ```
119
-
120
- The CLI command writes TaskChef metadata only; it does not query Codex. Before
121
- using it directly, verify that `/workspace/payments` exactly matches the
122
- canonical path of an existing local Codex project. The bootstrap skill performs
123
- that native-project check for you.
124
-
125
- A project may advertise several GitHub repositories with repeated
126
- `--github-repo`. Explicit values replace automatic origin detection and form
127
- the complete advertised list, so include the origin when it should remain
128
- routable. A managed `*-workspace` should advertise every relevant child or
129
- subrepository canonical GitHub URL, plus the workspace repository itself when
130
- applicable, so issue and pull-request links select the correct Codex project.
131
- TaskChef accepts Git roots and ordinary local folders on the same execution
132
- host. Unsupported configuration schemas are rejected and are never rewritten
133
- automatically.
134
-
135
- ## Dispatch
136
-
137
- Open the TaskChef dispatcher project and ask for an outcome:
138
-
139
- ```text
140
- In payments, fix duplicate charges after a retry, add a regression test, and report what changed.
141
- ```
142
-
143
- From another project, invoke the delegation skill explicitly:
144
-
145
- ```text
146
- $taskchef-delegate In payments, add structured logs for failed retries and test them.
147
- ```
148
-
149
- The dispatcher lists native projects once per batch, reconciles that snapshot,
150
- then prepares a UUID and marker for each outcome, persists the task before native creation,
151
- creates the executor, and returns its task link. New executor instructions keep
152
- the assignment visible from the first line, add a concise local reporting
153
- authorization paragraph, leave one blank line, then place
154
- an explicit `$taskchef-executor` invocation immediately before the final
155
- correlation marker. That skill reads the executor's own `CODEX_THREAD_ID`, self-links, and
156
- reports lifecycle state. Independent outcomes may become separate executors;
157
- dependent work should stay together.
158
-
159
- Activating the TaskChef MCP process best-effort ensures the dashboard by
160
- default. The managed workspace instructions also retry it at the start of each
161
- dispatcher turn. A startup failure never blocks MCP tools, an answer, report,
162
- or delegation. Every dispatcher response ends with
163
- the stable [TaskChef Dashboard](http://127.0.0.1:3210/) link; a created-task
164
- directive remains on the preceding line so dispatch still returns immediately.
165
-
166
- For example, TaskChef generates this shape:
167
-
168
- ```text
169
- Fix duplicate charges after a retry and add a regression test.
170
-
171
- Report this task and its follow-ups to my local TaskChef dashboard. Relevant private-repository links and concise work, test, and deployment results are authorized; exclude secrets.
172
-
173
- Use $taskchef-executor to execute and report this delegated TaskChef assignment.
174
- <!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->
175
- ```
176
-
177
- ### Model roles
178
-
179
- TaskChef can apply personal Orchestrator, Planner, Implementer, and Reviewer
180
- model preferences from `~/.codex/agents/`. Every delegated task uses the
181
- Orchestrator preference for its visible parent. For repository work, a combined
182
- investigate-or-plan-and-implement request runs fresh Planner, Implementer, and
183
- Reviewer subagents in that order. A direct implementation, or a later request
184
- to implement prior investigation, skips the Planner and runs a fresh Implementer
185
- and Reviewer in the same visible task. Explicit model choices take precedence
186
- for the role they target.
187
-
188
- ## Work with and report executors
189
-
190
- Open an executor as an ordinary Codex task. Each executor reports `working`
191
- when a turn starts and one semantic outcome before that same turn ends:
192
-
193
- - `completed`: the requested outcome is complete;
194
- - `needs_input`: a real user decision or missing fact blocks progress;
195
- - `failed`: the executor or creation attempt ended unsuccessfully.
196
-
197
- A native approval prompt is live Codex state, not `needs_input`.
198
- When work starts, the executor reports a concise request summary. TaskChef
199
- appends a `turns` entry that pairs that request with a null result while working,
200
- then fills the same entry with the semantic outcome. A follow-up therefore shows
201
- its own request with “In progress,” never the preceding turn's result. Returned
202
- tasks still derive `results` and `lastResult` as compatibility projections.
203
- Every entry has a required `turnRef`, which is the lifecycle identity. When
204
- Codex exposes a native turn ID, both `turnRef` and `turnId` contain that value.
205
- Otherwise the executor retains a fresh UUID in `turnRef` and stores
206
- `turnId: null`; native turn lookup is never a prerequisite for work or reporting.
207
- If Codex crashes, an MCP call is lost, or the app restarts before that terminal
208
- report, the next newer `working` report atomically marks the unfinished turn
209
- `interrupted` and appends the new active turn. `interrupted` is TaskChef-authored
210
- timeline evidence, not semantic `failed`, and it never enters `results` or
211
- `lastResult`. TaskChef stores only a fixed interruption summary; it does not
212
- store transcripts, hidden reasoning, crash output, or other non-semantic events.
213
-
214
- Delegated tasks created by earlier TaskChef versions remain compatible: their
215
- inline executor protocol still parses, self-links, and may use the deprecated
216
- `report_result` alias. The v7 inline-paragraph named exports remain as deprecated
217
- historical snapshots, but new delegations use the executor skill and `report_state`.
218
-
219
- ## View tasks and ask copilot
220
-
221
- The dashboard is the primary monitoring and browsing UI. Ask copilot when you
222
- want a concise explanation or recommendation:
223
-
224
- ```text
225
- $taskchef-copilot Summarize recent delegated work and tell me what needs attention.
226
- ```
227
-
228
- Copilot starts from TaskChef's normalized cached brief. It uses live Codex
229
- metadata only when you explicitly request fresh/live verification or a focused
230
- task presents a meaningful contradiction, and it never polls. It can identify
231
- the exact executor, explain or draft a same-assignment follow-up, and—with your
232
- explicit authorization—continue that existing task. It never automatically
233
- retries failures, interrupts working tasks, or redelegates an executor. New
234
- independent work still belongs to `$taskchef-delegate`. In the dispatcher, an
235
- explicit instruction to answer, resume, or continue a named existing task
236
- routes to copilot; it re-reads that exact task before sending.
237
-
238
- The former `$taskchef-report` skill is not packaged as an alias because a
239
- second discoverable skill would preserve ambiguous behavior. Explicit
240
- historical invocations are understood as requests for `$taskchef-copilot` and
241
- receive a brief rename notice.
242
-
243
- File-backed inspection is also available:
244
-
245
- ```sh
246
- taskchef task brief
247
- taskchef task brief c0f010ff
248
- taskchef task brief --project payments
249
- taskchef task list
250
- taskchef task list --project payments
251
- taskchef task show c0f010ff
252
- taskchef task summary
253
- ```
254
-
255
- Add `--json` for structured output. `task brief` returns the stable schema-1
256
- cached coordination model and omits terminal tasks older than seven days from
257
- overviews unless `--all` is supplied. Focused task and project briefs retain
258
- their full selected scope. Task IDs accept a full UUID or an unambiguous
259
- eight-character prefix.
260
-
261
- ## Dashboard
262
-
263
- The dashboard normally starts when the TaskChef MCP activates, and the
264
- dispatcher retries startup at the beginning of each turn. Its final response
265
- includes the dashboard link even if startup fails. If the dashboard is
266
- unavailable, use the packaged recovery skill to start or open it:
267
-
268
- ```text
269
- $taskchef-dashboard Ensure and open the TaskChef dashboard.
270
- ```
271
-
272
- MCP activation and `$taskchef-dashboard` call the input-free `ensure_dashboard`
273
- MCP tool. It starts at most one loopback dashboard scoped to the running Codex
274
- session on `127.0.0.1:3210`, or reuses a listener only when its bounded
275
- `/api/health` identity reports the exact TaskChef/dashboard-server version,
276
- canonical workspace, and recognized launcher. The response says `started` or
277
- `reused` and includes the stable URL, canonical workspace, versions, and actual
278
- launcher.
279
-
280
- The dashboard is launched by MCP but is not hosted by one MCP transport. It
281
- therefore survives an individual MCP close, stdin EOF, signal, or plugin reload.
282
- Only a listener launched as `session` registers each same-version MCP's original
283
- Codex parent PID in its in-memory lease. After every registered Codex session
284
- PID disappears for a grace period, the dashboard closes and exits. Activating
285
- an installed newer TaskChef MCP recognizes and
286
- gracefully stops an older TaskChef dashboard for the same canonical workspace,
287
- waits boundedly for the port, then starts the installed version in that ensure.
288
- Lease state is not transferred across versions; the replacement initially knows
289
- only the activating session. These are best-effort
290
- local guards, not a claim that Codex supplies a restart guarantee. TaskChef adds
291
- no daemon or OS-persistent component. See the complete
292
- [dashboard lifecycle](dashboard-lifecycle.md).
293
-
294
- TaskChef uses a trusted, single-user localhost model. Exact structured health is
295
- sufficient service recognition; it is not cryptographic authentication. Simple
296
- session and shutdown controls require exact Host and Origin, JSON content, a
297
- non-simple request header, and an exact bounded body to block ordinary
298
- cross-site browser requests. Each control names the exact health identity the
299
- caller observed; the listener refuses a stale identity and the caller probes the
300
- port again before deciding what to do. Unknown, malformed, different-workspace,
301
- unrelated, and newer listeners remain untouched. A release using the former HMAC control
302
- protocol refuses the new simple shutdown request, so the first upgrade across
303
- that boundary may require stopping that verified legacy TaskChef listener once
304
- before ensuring again.
305
-
306
- Autostart is enabled when `dashboard` is absent and in new workspaces. To opt
307
- out, add this optional exact object to `taskchef.json` while retaining its other
308
- fields:
309
-
310
- ```json
311
- "dashboard": { "autostart": false }
312
- ```
313
-
314
- The manual `$taskchef-dashboard` recovery skill remains available when
315
- autostart is disabled or fails. It reports whether the compatible dashboard was
316
- started or reused and always returns its canonical clickable URL. It may open
317
- the returned localhost URL in an available in-app browser, but browser failure
318
- does not make dashboard recovery fail.
319
-
320
- For manual development, run the foreground CLI:
321
-
322
- ```sh
323
- taskchef dashboard
324
- taskchef dashboard --port 3211
325
- ```
326
-
327
- The loopback dashboard watches `tasks.jsonl`, groups current states, and opens
328
- linked Codex tasks. List snapshots and SSE events carry only the latest
329
- request/result pair; opening task details fetches the full newest-first activity
330
- timeline, including clearly labeled interrupted turns.
331
- Task details offer infrequent administrative actions without cluttering task
332
- cards. Selecting **More task actions** (`…`) reveals the action list immediately
333
- beside the disclosure and changes it to a back/hide control. The list contains
334
- **Copy Task ID** and direct **Mark completed** and **Mark failed** actions.
335
- Working and needs-input tasks offer either terminal outcome; completed tasks
336
- offer **Mark failed**, and failed tasks offer **Mark completed**. The menu
337
- disclosure is the deliberate first step; choosing an outcome submits it
338
- immediately without a second confirmation. There is no
339
- free-form reason: the audit turn records a fixed summary, timestamp, dashboard
340
- provenance, optimistic preconditions, and a unique action ID while preserving
341
- every executor turn. Same-state terminal rewrites remain invalid. Stale or
342
- concurrent changes are rejected and the dialog refreshes to the current task. A stalled
343
- local request is aborted after a bounded wait so the dialog cannot remain
344
- permanently locked; retry keeps the same idempotency identity.
345
-
346
- The archive implementation is retained behind a disabled capability gate, and
347
- the **Archive chat** control is hidden. The bundled `codex archive` command can
348
- reject a valid idle desktop-app thread even when the dashboard runs in the MCP
349
- host environment, while Codex's native app archive operation succeeds. TaskChef
350
- will keep the feature disabled until Codex exposes a reliable supported
351
- app-callable archive interface or guarantees CLI compatibility. The dormant
352
- server path also rejects requests before discovering or invoking the CLI.
353
-
354
- Task details show chat totals and native per-turn usage from saved Codex records.
355
- Historical tasks are read when needed, rather than scanned at startup. A turn
356
- without a matching native Codex turn ID shows usage unavailable; its chat total
357
- can still be shown. Missing logs and parent links make the known subtotal
358
- incomplete. Input, cached input, output, reasoning, and total counts use Codex's
359
- categories. Cached input and reasoning are subsets, not additional tokens.
360
- Dollar figures are API-equivalent estimates, using the board's pricing table.
361
- Unknown prices show cost unavailable or a known priced subtotal. Existing saved
362
- usage projections remain readable. A partial scan cannot replace a larger known
363
- historical subtotal; missing model prices cannot erase a saved priced subtotal.
364
- `.taskchef-usage.json` holds the web view's
365
- normalized projections; the underlying engine reuses the board disk caches.
366
-
367
- The same detail view reports lifecycle wall-clock elapsed time independently of
368
- token accounting. Each terminal turn shows **Elapsed** from `startedAt` to
369
- `result.updatedAt`; **Total reported work** sums only valid terminal-turn
370
- durations, excluding idle gaps and unfinished work. A working turn shows live
371
- **Elapsed so far** without contributing to the total. This is reported
372
- wall-clock elapsed time, not model compute time, and malformed or reversed
373
- timestamp ranges are shown as unavailable.
374
- The header shows the running TaskChef package version reported by the same
375
- bounded health identity used for compatible-listener checks.
376
- The Settings page identifies TaskChef as the usage provider.
377
- The canonical port is normally owned by a dashboard session process initialized
378
- by the TaskChef MCP before its tool transport connects. MCP recovery reuses an
379
- exact-compatible same-workspace dashboard and reports its actual launcher;
380
- a foreground `taskchef dashboard` process is intentionally standalone so its
381
- child commands cannot silently inherit an agent-shell sandbox.
382
- Task and result times are relative through 29 days (with minute detail for the
383
- first six hours), then use a locale-aware calendar date. Each time is a keyboard-
384
- accessible toggle for its full locale-aware date and time, and one shared
385
- 30-second timer keeps relative labels current without reloading the page.
386
- The Updates panel captures immutable event-time lifecycle notices. It identifies
387
- them by task, turn when available, and lifecycle event rather than dashboard
388
- revision, so reconnects and non-semantic rewrites do not replay a notice and a
389
- later task state cannot rewrite an older notice. A notice remains readable if
390
- its task disappears; selecting it then explains that current details are no
391
- longer available.
392
- Apart from an explicit manual state selection from the task-detail menu, it does not mutate
393
- TaskChef data and prints its local URL. A foreground dashboard identifies
394
- itself as `standalone`. An exact-current, healthy same-workspace listener with a
395
- recognized `standalone`, `mcp`, or `session` launcher may be reused on the
396
- canonical MCP port; ensure reports its actual launcher, and only `session`
397
- listeners register Codex PID leases. If an unknown, malformed, or
398
- different-workspace process owns port 3210, TaskChef reports a concise conflict
399
- and never kills that process. A recognized older same-workspace TaskChef
400
- listener receives a simple guarded graceful shutdown request. If it lacks the
401
- compatible callback or refuses the request, it remains running and ensure
402
- reports a conflict. The foreground CLI similarly asks you to stop a conflicting
403
- listener or choose another `--port`.
404
-
405
- The health endpoint contains only a fixed service marker, health schema,
406
- TaskChef version, dashboard-server version, canonical workspace, and launcher.
407
- It exposes no task data, credentials, environment variables, process control,
408
- or secrets.
409
-
410
- ![TaskChef dashboard identity and version](images/dashboard-identity.jpg)
411
-
412
- ![Immutable event-time dashboard notifications](images/notification-event-snapshots.jpg)
413
-
414
- ![Task detail activity timeline](images/result-history-dashboard.jpg)
415
-
416
- ![Deferred ccusage token consumption in task details](images/ccusage-token-consumption.png)
417
-
418
- ![Interrupted turn followed by active recovery](images/interrupted-turn-recovery.jpg)
419
-
420
- ## Common recovery
421
-
422
- Check the managed workspace:
423
-
424
- ```sh
425
- taskchef doctor
426
- taskchef workspace init
427
- taskchef workspace migrate
428
- taskchef doctor
429
- ```
430
-
431
- `doctor` is read-only. `workspace init` creates missing files and refreshes
432
- managed instructions. `workspace migrate` explicitly upgrades supported schema
433
- 4-9 task lines to schema 10 under the workspace lock. It validates task and turn
434
- counts plus the complete source and converted log before writing, creates an
435
- exclusive `tasks.jsonl.pre-v10-*.bak`
436
- backup, atomically replaces the log, validates the result, and becomes an
437
- idempotent no-op after migration. If replacement fails, the original remains
438
- or the reported backup can be restored; unsupported or invalid input is rejected
439
- before a backup or rewrite.
440
-
441
- If a new record has no thread ID, the executor is link-pending. Reopen that
442
- executor so its first action can retry `link_task`. Do not guess an identity
443
- or edit `tasks.jsonl`. If native task creation failed, the record is retained
444
- as `failed` with a retained fallback `turnRef` and null thread and Codex turn IDs.
445
-
446
- Schemas other than 4, 5, 6, 7, 8, 9, and 10 remain unsupported. Retain such a workspace
447
- unchanged and create a current workspace; the migration command deliberately
448
- does not guess how to convert unknown formats.
449
-
450
- ## Boundaries
451
-
452
- TaskChef dispatches; it is not a scheduler, supervisor, worker runtime, or
453
- merge coordinator. Executor identity is a cooperative assertion inside a local
454
- single-user trust boundary. The [specification](spec.md) defines the
455
- required contract; [workflows](workflows.md) ties it to current code.
456
-
457
- ## Update
458
-
459
- ```sh
460
- codex plugin marketplace upgrade favoyang-plugins
461
- codex plugin add taskchef@favoyang-plugins
462
- ```
463
-
464
- Replacing or installing plugin files cannot execute autostart by itself. After
465
- installation, activate or reload the new TaskChef MCP process; installation
466
- does not necessarily reload Codex. Then run `$taskchef-dashboard` (or call
467
- `ensure_dashboard`) and verify the returned dashboard identity has all of:
468
-
469
- - the expected released TaskChef version;
470
- - the expected dashboard protocol `serverVersion`;
471
- - the reported dashboard launcher (`session` for a newly started canonical dashboard);
472
- - the canonical TaskChef workspace path;
473
- - the canonical `http://127.0.0.1:3210/` URL.
474
-
475
- The release-install sequence is therefore: install plugin, activate or reload
476
- the new MCP process, ensure the dashboard, then verify TaskChef version,
477
- protocol `serverVersion`, reported launcher, canonical workspace, and URL.
478
- Exact-compatible same-workspace servers with a recognized launcher may be
479
- reused; unknown listeners remain untouched.
480
-
481
- If autostart reports a **verified older TaskChef** listener, the port occupant
482
- passed the bounded TaskChef identity check but refused the simple graceful
483
- shutdown request. Releases using the former HMAC control protocol form a
484
- one-time compatibility boundary: stop that verified legacy TaskChef listener
485
- through the application/session that launched it, then activate the installed
486
- plugin and ensure again. Do not kill an arbitrary port owner.
487
-
488
- ## Development
489
-
490
- ```sh
491
- npm ci
492
- npm test
493
- npm pack --dry-run
494
- ```
495
-
496
- Merges to `main` run semantic-release and update the shared plugin
497
- marketplace. Removing unsupported schemas is a major-version change.
@@ -1,149 +0,0 @@
1
- # Dashboard lifecycle
2
-
3
- This document defines how the canonical TaskChef dashboard starts, survives MCP
4
- reloads, changes version, and stops. The [specification](spec.md) is normative;
5
- the [README](../README.md) covers user operation, and
6
- [workflows](workflows.md) maps these guarantees to implementation.
7
-
8
- ## Process model
9
-
10
- The canonical dashboard is a loopback-only process scoped to a running Codex
11
- application session. TaskChef MCP activation launches it, but one MCP transport
12
- does not own it. It can therefore survive an individual MCP EOF, signal,
13
- transport close, or plugin reload while another TaskChef MCP transport in the
14
- same Codex session remains active.
15
-
16
- TaskChef does not install a daemon, login item, lifecycle hook, or privileged
17
- service. A foreground `taskchef dashboard` remains a separate `standalone`
18
- launcher.
19
-
20
- ## Start and reuse
21
-
22
- Unless `dashboard.autostart` is explicitly `false`, MCP activation runs the same
23
- serialized ensure operation exposed by `ensure_dashboard`. Failure is isolated
24
- from MCP startup and emits a bounded diagnostic.
25
-
26
- The canonical session manager requires an explicit nonzero port and normally
27
- binds `127.0.0.1:3210`. Its deterministic lifecycle is:
28
-
29
- 1. No listener: start the installed dashboard and wait until its health endpoint
30
- is reachable.
31
- 2. Exact current identity for the canonical workspace: reuse it after another
32
- health probe. A `session` listener first registers the activating Codex PID
33
- in its in-memory lease.
34
- 3. Exact older TaskChef identity for the canonical workspace: request graceful
35
- shutdown, wait a bounded time for port release, then start the installed
36
- version within the same ensure operation.
37
- 4. Recognized newer TaskChef identity: refuse to downgrade it.
38
- 5. Unknown, malformed, different-workspace, or unrelated listener: report a
39
- clear conflict without sending a control request or process signal.
40
-
41
- Health is an exact bounded structured identity containing the service marker,
42
- schema, TaskChef version, dashboard server version, canonical workspace, and
43
- launcher. It is sufficient service recognition in TaskChef's trusted,
44
- single-user localhost model. It is not cryptographic authentication.
45
-
46
- Concurrent activations can all observe a free port. Only one detached process
47
- can bind it; other activators inspect and reuse or replace the winner according
48
- to the same rules. A detached child reports readiness over inherited IPC after
49
- the server has bound, completed initialization, and created its first in-memory
50
- lease. A bounded timeout cancels failed or slow startup.
51
-
52
- ## MCP reload and plugin upgrade
53
-
54
- Closing an MCP transport does not close the dashboard. Each exact same-version
55
- reuse registers the activating Codex PID. The dashboard checks these in-memory
56
- leases with non-signalling existence probes and closes after all registered PIDs
57
- are gone for the configured grace period.
58
-
59
- Lease state is deliberately not transferred across versions. A replacement
60
- dashboard initially knows only the activating session. A later ensure from
61
- another session registers that session, and can restart the dashboard if the
62
- first lease has already expired. This accepted consequence keeps upgrade
63
- behavior deterministic and avoids durable or cross-version ownership state.
64
-
65
- Releases using the former HMAC control protocol do not understand the simple
66
- shutdown request. The first upgrade from such a release reports that the
67
- recognized older listener refused graceful shutdown and leaves it running. Stop
68
- that verified TaskChef listener through its existing lifecycle, then activate
69
- or ensure the newly installed plugin again. TaskChef never adds a generic
70
- process-kill fallback to cross this one-time compatibility boundary.
71
-
72
- ## Local control boundary
73
-
74
- The dashboard listens only on `127.0.0.1` or `::1` and has no browser login.
75
- Its health identity contains no task data, credentials, environment variables,
76
- or process-control details.
77
-
78
- The session-registration and graceful-shutdown endpoints are intentionally
79
- small localhost controls. They require the exact listener Host and Origin,
80
- JSON content type, a non-simple `X-TaskChef-Control` header, and an exact bounded
81
- body. Each body includes the exact structured health identity observed by the
82
- caller. The receiver compares it with its own identity before registering a
83
- session or accepting shutdown. On a mismatch the caller probes the listener
84
- again and applies the normal lifecycle rules to the current occupant. These
85
- checks block ordinary cross-site browser requests and DNS rebinding to a
86
- different Host. They are request-shape checks, not authentication or an
87
- ownership protocol.
88
-
89
- Future LAN access is outside this model. It must be a separate opt-in feature
90
- with password-backed user authentication and suitable transport protection.
91
-
92
- TaskChef sends graceful shutdown only after exact recognized TaskChef health for
93
- the same canonical workspace. It never discovers or kills a port owner, sends
94
- OS signals to an unknown process, uses forceful termination, searches broadly
95
- for processes, or requires elevated permission.
96
-
97
- ## Dashboard state and presentation
98
-
99
- A newly started server creates or deduplicates a verified private workspace
100
- snapshot before monitors or derived-state writers start. Reuse does not create
101
- another startup snapshot. Snapshot failure aborts the new server.
102
-
103
- The dashboard watches task history and the project index. It warns when
104
- historical task snapshots reference paths absent from the current index and
105
- offers recovery-oriented read-only commands. It never mutates or restores
106
- configuration.
107
-
108
- The task dashboard offers List and Board views at every screen width. List
109
- remains the default and keeps its status filter, task metrics, and
110
- actions. Board groups tasks by recorded status, with an Unresolved column only
111
- when needed. The view switch precedes the project and Updated filters in both
112
- views. Both filters apply to Board and List; Updated offers the latest 24 hours,
113
- latest 7 days, and all time. Board ignores
114
- the remembered List status filter. Completed initially shows five cards, with
115
- five more available per click. Each Board card shows its project's name, title,
116
- current request or latest reported result, relative update time, and a chat
117
- shortcut when the task has a linked chat. Opening the title uses the full task
118
- detail view. Board columns are 340 px wide where space permits and scroll
119
- horizontally when needed. On phones, a column fits the viewport with a peek of
120
- the next. Swipe or scroll horizontally to reach every column, or focus the
121
- board to scroll it with a keyboard; the page still scrolls vertically through
122
- tasks.
123
- The view preference is stored locally when browser storage is available.
124
-
125
- The detail view distinguishes an active turn whose final usage is pending from
126
- a terminal turn whose usage is being calculated. Available usage keeps both the
127
- token total and API-equivalent USD estimate. The dashboard owns a bounded
128
- background queue for derived usage and stops that queue with the server.
129
-
130
- ![Pending token usage in the task detail view](images/dashboard-token-pending.jpg)
131
-
132
- Reported work is wall-clock elapsed time derived from TaskChef lifecycle
133
- timestamps. It excludes idle gaps and unfinished portions of active turns from
134
- the terminal total. Missing, malformed, reversed, zero-width, or unsupported
135
- timestamp ranges display an unavailable state.
136
-
137
- ## Lifecycle matrix
138
-
139
- | Event | Result |
140
- | --- | --- |
141
- | Activation with no listener | Start installed session dashboard |
142
- | Activation with exact current listener | Register a session lease when supported, verify health again, reuse |
143
- | Activation with recognized older listener | Request graceful shutdown, wait boundedly, start installed version |
144
- | Activation with recognized newer listener | Refuse downgrade and leave it running |
145
- | Activation with unknown or different-workspace listener | Report conflict and leave it untouched |
146
- | One MCP EOF, signal, or reload | Dashboard remains while a registered Codex PID is alive |
147
- | All registered Codex PIDs disappear | Dashboard closes after the grace period |
148
- | `dashboard.autostart: false` | Explicit ensure remains available |
149
- | Foreground `taskchef dashboard` | Standalone process follows foreground CLI lifetime |