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
package/docs/spec.md CHANGED
@@ -1,758 +1,50 @@
1
- # TaskChef specification
1
+ # TaskChef native product contract
2
2
 
3
- This is TaskChef's normative agent-facing contract. **MUST**, **MUST NOT**,
4
- **SHOULD**, and **MAY** are requirements in the RFC 2119 sense. The
5
- [advanced guide](advanced-guide.md) owns detailed user setup and operation;
6
- [workflows](workflows.md) owns implementation walkthroughs; the
7
- [FirstMate comparison](firstmate-taskchef-comparison.md) is dated research,
8
- not contract.
3
+ TaskChef is a local Codex dashboard. Codex databases and rollout logs own chat
4
+ identity, recorded prompts and replies, turn state, schedules, queue contents,
5
+ and token usage. TaskChef reads them without rewriting Codex data.
9
6
 
10
- ## Terminology
7
+ ## Runtime
11
8
 
12
- | Term | Definition |
13
- | --- | --- |
14
- | **TaskChef** | The plugin, skills, MCP server, CLI, dashboard, and current workspace formats defined here. |
15
- | **Dispatcher workspace** | The per-user local data project selected by `--workspace`, then `TASKCHEF_WORKSPACE`, then `~/.agents/taskchef`. |
16
- | **Dispatcher** | The Codex task that accepts a request, routes it, records it, creates executors, and returns without supervising them. |
17
- | **Configured project** | One routing target in `taskchef.json`, identified by canonical local path and described by `name`, optional `description`, `isGitRepository`, and `githubRepos`. |
18
- | **Mutation preview** | A read-only, hash-bound exact before/after project-index diff required before destructive replacement, removal, or restore. |
19
- | **State backup** | A private, verified snapshot under the dispatcher workspace's `backups/` directory. It never restores automatically. |
20
- | **Routing** | Selecting exactly one configured project and exactly one matching native Codex project for an outcome. |
21
- | **Delegated task** | One independently useful outcome represented by one TaskChef task UUID and snapshot. |
22
- | **Executor** | The native Codex task created to own and perform one delegated task. |
23
- | **Task record** | One complete JSON object in `tasks.jsonl`; it contains immutable intent/project fields and mutable identity/result fields. |
24
- | **Marker** | The exact correlation line `<!-- taskchef_id=<lowercase full UUID> -->`; new instructions place it on the final line, immediately after the executor-skill invocation. |
25
- | **Record-before-create** | Persisting a link-pending task before asking Codex to create its executor. |
26
- | **Self-linking** | The executor's one-way registration of its own canonical Codex UUIDv7 from `CODEX_THREAD_ID`. |
27
- | **Link-pending** | A working task whose `threadId` is null and `updatedBy` is `dispatcher`. |
28
- | **Current execution state** | The latest reported executor turn and its `working`, `needs_input`, `completed`, or `failed` status. |
29
- | **Turn timeline** | The ordered collection pairing each turn's concise request summary with its semantic result, TaskChef-generated interruption outcome, or current in-progress state. |
30
- | **Interrupted turn** | A formerly active turn that lacked a terminal report when a newer valid turn started; TaskChef closes it with the fixed timeline-only `interrupted` outcome. |
31
- | **Last semantic result** | The final result-history entry, exposed through the derived `lastResult` compatibility alias. |
32
- | **Turn reference** | Required lifecycle identity for one executor prompt. It is the native Codex turn ID when available, otherwise a retained client-generated UUID. |
33
- | **Current turn ID** | Optional Codex metadata for the reported prompt; null when native turn reading is unavailable. |
34
- | **Dashboard** | The loopback UI derived from validated workspace snapshots, with optional local usage projections, bounded native actions, and an explicit audited manual-outcome mutation. |
35
- | **Skill** | One packaged agent procedure: `taskchef-bootstrap`, `taskchef-dashboard`, `taskchef-delegate`, `taskchef-executor`, or `taskchef-copilot`. |
9
+ The plugin launches one stdio MCP server and advertises the native sidebar app.
10
+ It does not start an HTTP server, create a dispatcher workspace, index a second
11
+ project registry, or maintain tasks.jsonl. Only native dashboard tools are
12
+ registered. No task markers, self-linking, executor reports, or lifecycle
13
+ callbacks are needed for a chat to appear.
36
14
 
37
- ## Components and ownership
15
+ The MCP process closes its transport and resources on EOF, signals, protocol
16
+ close, or parent loss. Settings and caches use atomic writes. Shared state
17
+ writes also use the existing file lock, with its filename and timing preserved.
18
+ Open-chat callers must provide a UUID; the boundary check does not insist on
19
+ UUIDv7 or generate IDs.
38
20
 
39
- - `taskchef-bootstrap` MUST own initialization, project configuration, and
40
- diagnostics. It MUST NOT dispatch or report unless separately requested.
41
- - `taskchef-delegate` MUST own routing and record-before-create delegation.
42
- It MUST return after creation and MUST NOT poll, supervise, or infer identity.
43
- - `taskchef-executor` MUST own executor assignment ownership, self-linking,
44
- exact thread/turn identity, per-turn state reporting, failure behavior,
45
- privacy, and idempotency. It MUST NOT dispatch the owned assignment again.
46
- - `taskchef-copilot` MUST own conversational outcome explanation, attention,
47
- and next-action recommendations. It MUST use cached normalized briefs by
48
- default and MUST NOT poll or persist inferred state.
49
- - `taskchef-dashboard` MUST own manual dashboard ensure and recovery. It MUST
50
- NOT dispatch work or inspect task outcomes, and browser navigation failure
51
- MUST NOT suppress the returned dashboard URL.
52
- - The MCP server MUST expose `ensure_dashboard`, four primary lifecycle tools,
53
- and the deprecated `report_result` compatibility alias specified below.
54
- - The CLI MAY administer and inspect the workspace, but MUST NOT provide a
55
- second agent lifecycle protocol.
56
- - The dashboard MUST be read-only with respect to dispatcher files except for
57
- the explicit audited manual-transition operation defined below.
58
- - `docs/spec.md` is the single normative behavior source. Other documents
59
- MUST link here rather than redefine the contract.
21
+ ## Feature state
60
22
 
61
- ## Workspace contract
23
+ TaskChef retains its current native settings, GitHub credentials, Done marks,
24
+ notification state, and scan/PR/usage/pricing caches. Credentials remain in the
25
+ system credential store. A Done mark is bound to the current turn. A new turn
26
+ invalidates stale derived data. Damaged state is preserved and reported rather
27
+ than silently reset. See [storage](taskchef-next-storage.md).
62
28
 
63
- TaskChef MUST manage only `AGENTS.md`, `taskchef.json`, `tasks.jsonl`, and the
64
- optional `.taskchef-usage.json` cache inside the dispatcher workspace. It MUST
65
- preserve unrelated paths. Dashboard process identity and Codex-session leases
66
- MUST remain in memory and MUST NOT create owner, secret, or handoff files.
29
+ ## Delegation
67
30
 
68
- `taskchef.json` MUST have schema version 2, the following required fields, and
69
- optional exact `dashboard` and `projectIndex` objects:
31
+ The packaged `$taskchef:delegate` skill uses native Codex project discovery and chat
32
+ creation. It passes an ordinary assignment, resolves ambiguity with the user,
33
+ and returns the native link. Explicit follow-ups use the selected existing
34
+ chat. Codex owns execution and outcomes; TaskChef does not mirror task records.
70
35
 
71
- ```json
72
- {
73
- "schemaVersion": 2,
74
- "projects": []
75
- }
76
- ```
36
+ Optional routing memory contains only confirmed project aliases and explicit
37
+ preferences. Revalidate it against current native projects. It is not a task
38
+ log, a source of authority, or a store for prompts, results, or credentials.
77
39
 
78
- Each project MUST contain `name`, normalized absolute `path`, boolean
79
- `isGitRepository`, and array `githubRepos`; `description` is optional.
80
- Names and paths MUST be unique. Git projects MUST be exact Git roots.
81
- Repository URLs MUST canonicalize to `https://github.com/<owner>/<repository>`
82
- and be case-insensitively deduplicated.
40
+ ## Transition and delivery
83
41
 
84
- When present, `dashboard` MUST contain exactly boolean `autostart`. Its absence
85
- is backward-compatible and means `true`; new workspaces SHOULD write
86
- `{"autostart": true}`. `false` disables MCP-lifecycle autostart but MUST NOT
87
- disable the explicit `ensure_dashboard` tool.
42
+ Retiring the dispatcher CLI, skills, tools and exported API is a breaking
43
+ change delivered in a major release. Existing legacy workspaces, task logs and
44
+ Codex data remain untouched. There is no automatic data deletion or archive
45
+ export feature. The release remains TaskChef; a development copy uses the
46
+ separate taskchef-next identity and TaskChef Dev name.
88
47
 
89
- When present, `projectIndex` MUST contain exactly `bindings`, `exclusions`, and
90
- `routingHints` arrays. Bindings map one `(hostId: local, projectId)` to one
91
- configured canonical path. Exclusions retain exact removed native identities
92
- or paths. Routing hints are bounded per canonical configured path and retain
93
- aliases, canonical repositories, concise responsibilities, and forgotten-value
94
- suppression. Every fact has one compact provenance record; accepted-report
95
- facts include the exact task, thread, and current terminal turn. Absence means
96
- empty state. Older releases reject the optional field rather than rewriting it.
97
-
98
- `tasks.jsonl` MUST contain zero or more newline-terminated schema-4 through
99
- schema-10 records, one per line. Schemas 4 through 9 are supported
100
- migration/read formats; every new record and state mutation MUST write schema 10. Other schemas
101
- or unsupported fields MUST be rejected without conversion.
102
- Reads and writes MUST reject symlinked managed files. Mutations
103
- MUST hold the shared workspace lock and replace state atomically; read-only
104
- operations MUST NOT require write permission.
105
-
106
- ## Task schema
107
-
108
- Every record MUST contain exactly these fields:
109
-
110
- | Field | Contract |
111
- | --- | --- |
112
- | `schemaVersion` | Integer `10`; schema-4/5/6/7/8/9 records remain readable until explicit migration or their next mutation. |
113
- | `id` | Unique safe TaskChef ID; delegation uses a lowercase full UUID. |
114
- | `project` | Immutable configured-project snapshot. |
115
- | `title` | Non-empty display title. |
116
- | `instruction` | Non-empty executor instruction; link-pending records MUST contain the exact marker for `id`. |
117
- | `threadId` | Null while link-pending; after self-link, canonical Codex UUIDv7. Low-level current-schema direct records may hold another durable non-provisional ID but are outside the MCP delegation journey. |
118
- | `createdAt` | ISO 8601 creation timestamp. |
119
- | `status` | `working`, `needs_input`, `completed`, or `failed`. |
120
- | `summary` | Null while working; otherwise the current semantic state's non-empty summary of at most 2,000 characters. |
121
- | `turnRef` | Null before reporting begins; otherwise the required lifecycle identity of the current turn. Self-linking journeys use a native or fallback UUID. Migrated low-level `report_result` compatibility records may retain an opaque ref equal to their opaque `turnId`. |
122
- | `turnId` | Optional Codex metadata. When non-null it equals `turnRef`; null indicates fallback identity. |
123
- | `updatedAt` | ISO 8601 timestamp not earlier than `createdAt` or the prior `updatedAt`; clock rollback cannot backdate a transition. |
124
- | `updatedBy` | `dispatcher`, `mcp`, or `dashboard`. `dashboard` is valid only when the latest turn is a manual dashboard transition. |
125
- | `turns` | Ordered oldest-first array of `{turnRef, turnId, requestSummary, startedAt, result, provenance}`. Every `turnRef` is required. `requestSummary` is null only for migrated/compatibility turns. `result` is null only for the latest working turn, a semantic `{status, summary, updatedAt}` result, or the fixed TaskChef `interrupted` outcome. `provenance` is `{kind: legacy}` or `{kind: mcp}` for ordinary turns, or the audited manual-transition record defined below. New self-linking and manual turn refs are unique. A migrated low-level opaque record may retain one final reused native-derived ref for its legacy ambiguity. |
126
-
127
- Returned Task objects MUST additionally expose `latestTurn` as null for an empty
128
- timeline or the final `turns` entry. They MUST derive `results` only from
129
- semantic `needs_input`, `completed`, and `failed` turn results and `lastResult`
130
- from the final derived semantic result. Interrupted outcomes MUST be excluded.
131
- These projections MUST NOT be persisted in schema 10 and remain compatibility
132
- aliases for existing callers.
133
-
134
- ## Project-index mutation and recovery
135
-
136
- TaskChef MUST provide a targeted update that preserves every unrelated project
137
- and replaces an explicitly supplied repository list in full. Project list JSON
138
- MUST expose stable semantic hashes. Whole-index replacement, project removal,
139
- and restore MUST first return an exact diff and MUST reject stale hashes,
140
- incomplete removed-name confirmation, mismatched counts, and unconfirmed large
141
- count collapse. Agents MUST obtain explicit user permission for every removed
142
- project entry and verify the complete post-state.
143
-
144
- Every actual configuration mutation and actual dashboard-server start MUST
145
- create or deduplicate a mode-private, manifest-and-hash-verified state snapshot
146
- before writing. Mutations MUST append bounded attribution-free prepared and
147
- terminal audit records. Backup list, create, and verify are read-only except for
148
- explicit creation. Restore MUST default to projects only, show a diff, require
149
- explicit approval, and create a pre-restore safety snapshot. TaskChef MUST NOT
150
- restore automatically. State restore authorization MUST bind the selected
151
- backup and every selected live/source payload hash. Missing or malformed live
152
- configuration requires config or state scope plus exact raw-state and explicit
153
- unreadable-current confirmation; a forensic safety snapshot remains eligible
154
- for rollback when its own integrity verifies.
155
-
156
- The dashboard MUST distinguish an unreadable index from missing historical
157
- project paths, warn without rewriting state, and expose recovery guidance
158
- without backup payload contents.
159
-
160
- ## Optional usage projection
161
-
162
- TaskChef MUST use its own saved-record accounting engine for the board and web
163
- dashboard. Usage requires Node.js 22.18+ and readable local Codex records.
164
- Unavailable usage MUST NOT block lifecycle tools or dashboard loading.
165
-
166
- Per-turn usage MUST match the native Codex turn ID. A dispatcher turn without
167
- that match MUST show unavailable turn usage, while its chat total MAY remain
168
- available. Administrative dashboard turns MUST NOT receive execution usage.
169
- Historical tasks MUST remain lazy; opening Details reads their usage. Requests
170
- MUST be deduplicated and bounded, and queued work MUST stop on dashboard close.
171
-
172
- The engine MUST include descendant usage once, preserve input, cached input,
173
- output, reasoning, and total categories, and avoid counting cached input or
174
- reasoning subsets twice. Missing logs or parent-turn links MUST mark known
175
- subtotals incomplete. Dollar values MUST be API-equivalent estimates using
176
- known model prices. Unknown model prices MUST NOT imply a zero-dollar cost.
177
-
178
- Board accounting caches MUST live under the TaskChef state directory's `cache/`
179
- folder. The web dashboard MUST retain normalized usage in the mode-0600
180
- `.taskchef-usage.json` cache. Writes MUST use the workspace lock and atomic
181
- replacement. Existing schema-2 projections from the previous provider MUST
182
- remain readable. Cache files MUST contain accounting data and source metadata,
183
- not prompts, replies, or reasoning text. Source changes MUST invalidate derived
184
- accounting results. Cache errors MUST allow source accounting to continue.
185
- The dashboard Settings response MUST identify TaskChef and its package version.
186
-
187
- Task IDs and non-null thread identities MUST be unique. The immutable intent
188
- fields MUST NOT change after recording.
189
-
190
- ## Required lifecycle
191
-
192
- Before the canonical TaskChef MCP server connects and exposes its transport, it
193
- MUST invoke the same serialized dashboard ensure path once by default. It MUST read the
194
- canonical configuration and skip this only for explicit
195
- `dashboard.autostart: false`. Initialization failures, invalid workspace state,
196
- port conflicts, and dashboard errors MUST NOT prevent tool registration or MCP
197
- availability. They MUST emit only a bounded non-sensitive diagnostic through
198
- the MCP process logging channel. MCP initialization MUST NOT open a browser.
199
- If transport connection fails after dashboard startup, the MCP server MUST
200
- best-effort close its manager and partially attached transport, then propagate
201
- the original connection failure even when cleanup also fails. Closing that
202
- individual MCP MUST NOT directly close a valid Codex-session dashboard.
203
-
204
- At the start of every dispatcher turn, the dispatcher SHOULD call
205
- `ensure_dashboard` best-effort. Failure MUST NOT block direct TaskChef answers,
206
- reporting, or delegation. Every dispatcher final response MUST end with the
207
- exact clickable `[TaskChef Dashboard](http://127.0.0.1:3210/)` link even when
208
- ensure failed. A created-thread directive MUST remain on its own line before
209
- the final link, preserving the delegate skill's immediate-return contract.
210
-
211
- 1. The dispatcher MUST list native projects once per batch and call
212
- `reconcile_projects` once with that exact schema-2 snapshot.
213
- 2. It MUST call `prepare_dispatch` once per outcome and choose exactly one
214
- configured project. Before `record_task` or native creation, the selected
215
- native project's exact `(hostId, projectId, canonical path)` MUST occur in
216
- the reconciliation response's `available` array. Presence in the native
217
- snapshot or configured preparation is insufficient. Curated and learned
218
- routing matches are both ambiguous when more than one project matches.
219
- 3. It MUST build the instruction with the user's outcome beginning on line 1
220
- and remaining uninterrupted, followed by one blank line and the authorization
221
- `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.`
222
- followed by exactly two newline characters
223
- (one blank line), exactly one concise explicit `$taskchef-executor`
224
- invocation, one newline, and the returned marker on the final line. It MUST
225
- NOT place a blank line between the invocation and marker or inline the
226
- executor protocol into a new instruction.
227
- 4. It MUST call `record_task` with `threadId: null` before native creation.
228
- 5. It MUST create exactly one native Codex executor using the resolved
229
- Orchestrator preference when configured, then return immediately.
230
- 6. The executor MUST read its own `CODEX_THREAD_ID` and call `link_task`
231
- before substantive work. It MUST NOT use parent/session identity or guess.
232
- 7. After initial linking, the executor MUST establish a `turnRef`. It MUST use
233
- the native Codex turn ID for both `turnRef` and `turnId` when available;
234
- otherwise it MUST retain a fresh UUID `turnRef` and use `turnId: null`.
235
- It MUST call `report_state` with that identity, `working`, and no summary before work.
236
- 8. Before ending, it MUST call `report_state` with the same `turnRef` and
237
- `turnId` metadata as the working report and a
238
- semantic status and concise summary.
239
- 9. A follow-up MUST report `working` with a new `turnRef` before work.
240
- It MUST NOT reuse a prior prompt's ref. If the preceding turn is still unfinished,
241
- TaskChef MUST atomically close it as `interrupted` before appending the new
242
- working turn; the executor MUST NOT report semantic `failed` for recovery.
243
-
244
- For repository work, the visible executor MUST route an explicit combined
245
- investigate-or-plan-and-implement request through a fresh Planner, then a fresh
246
- Implementer, then a fresh Reviewer. A direct implementation request, or a later
247
- request to implement prior investigation or planning, MUST skip the Planner and
248
- use a fresh Implementer followed by a fresh Reviewer in the same visible task.
249
- It MUST resolve the applicable role preference immediately before creating a
250
- child when agent TOML exists; absent agent configuration inherits the parent's
251
- model settings without requiring Python. It MUST keep at most one writing agent
252
- active and verify child results. TaskChef persists only the visible executor's
253
- lifecycle and MUST NOT store or infer child phases, identities, or usage.
254
-
255
- Normal executor completion MUST stop after the terminal callback and return
256
- normally. It MUST NOT archive, hand off, close, navigate away from, or otherwise
257
- terminate the Codex task merely because work completed. Archive is authorized
258
- only by an explicit request in the current assignment or follow-up for that
259
- exact Codex task; `finish`, `complete`, `done`, `ship`, and ordinary cleanup do
260
- not imply authorization.
261
-
262
- For an explicitly authorized archive, the executor MUST finish and verify the
263
- work, read its exact task identity, submit the current turn's terminal
264
- `report_state`, verify TaskChef accepted that state, and only then invoke the
265
- native archive operation as the final state-changing action. It MUST require
266
- native confirmation before claiming archive succeeded. The same callback-first
267
- ordering applies to any separately authorized action that can make the executor
268
- unavailable before reporting, including handoff or terminating or restarting
269
- the process that owns the TaskChef MCP transport; this rule does not itself
270
- authorize those actions. A terminal reporting failure MUST prevent the later
271
- action and leave the executor accessible. Failure of a later action MUST NOT
272
- change or reopen the already accepted semantic terminal state.
273
-
274
- Request and result summaries are the durable source for dashboard related-link
275
- projection; TaskChef does not scan full Codex transcripts. When known, an
276
- executor MUST preserve the selected repository as a canonical GitHub repository
277
- URL and issues or pull requests as canonical URLs. A result spanning both a
278
- managed child repository and its workspace/root repository MUST include both
279
- pull-request URLs. Executors MUST NOT guess unresolved repository identity.
280
-
281
- If native creation fails after recording, the dispatcher MUST call
282
- `report_state` with `failed`, a retained fallback UUID `turnRef`, null thread
283
- and Codex turn IDs, and a bounded summary.
284
- A link failure MUST remain visible and retryable; the executor MUST report it
285
- visibly and MUST NOT continue substantive work.
286
-
287
- Previously recorded instructions with the trailing marker before the
288
- invocation, with or without the former blank line before that marker; a
289
- former compact assignment-to-invocation boundary with the marker last; a
290
- first-line HTML marker; the older first-line
291
- `# taskchef_id=<full UUID>` heading, or the former blank line and inline
292
- executor protocol MUST remain marker-readable and executable. Their
293
- `report_result` calls MUST remain supported by the deprecated alias. New
294
- instructions MUST use the explicit executor invocation followed by the final
295
- trailing marker contract above. A historical first-line instruction with an
296
- executor-skill invocation MUST contain exactly one invocation as its final
297
- line. A former inline-protocol instruction MUST retain non-whitespace
298
- task-specific content beyond its known lifecycle paragraphs.
299
-
300
- `needs_input` MUST mean a semantic user decision or missing fact. A native
301
- approval prompt MUST remain live Codex state and MUST NOT be stored as
302
- `needs_input`.
303
-
304
- ## MCP interface
305
-
306
- All tools resolve the workspace internally. Callers MUST NOT supply a workspace
307
- path. Success returns both one text content item and the stated structured
308
- object. Validation, marker, identity, uniqueness, freshness, or filesystem
309
- failures are surfaced as tool errors and MUST NOT partially mutate the log.
310
-
311
- ### `ensure_dashboard`
312
- **Caller:** dispatcher. **Mutation:** starts or reuses the
313
- Codex-session-scoped loopback dashboard.
314
-
315
- **Input:** empty object.
316
-
317
- **Structured output:**
318
-
319
- ```text
320
- { dashboard: {
321
- action: "started" | "reused",
322
- launcher: "session" | "standalone" | "mcp",
323
- url: "http://127.0.0.1:3210/",
324
- workspace: string,
325
- taskchefVersion: string,
326
- serverVersion: string
327
- } }
328
- ```
329
-
330
- MCP initialization MUST complete its best-effort ensure before exposing the
331
- MCP transport. Calls MUST serialize within one MCP process. The first call
332
- starts a dashboard session process or reuses the exact current listener; later
333
- and concurrent calls are idempotent. The stable default MUST bind only to
334
- `127.0.0.1:3210` and MUST NOT accept a model-supplied workspace, host, port,
335
- session PID, or credential.
336
-
337
- Exact reuse MUST require the fixed service/schema, TaskChef version,
338
- dashboard-server version, canonical workspace, and recognized launcher identity.
339
- A `session` listener MUST register the MCP's original Codex parent PID in its
340
- in-memory lease. Every launcher MUST complete another exact health probe before
341
- ensure reports `reused`, and the response MUST report the observed launcher.
342
- The independent dashboard MUST survive closure of an individual MCP transport.
343
- The session manager MUST require an explicit nonzero port because a detached
344
- child cannot safely return an ephemeral bound port without an additional IPC
345
- readiness channel. Direct foreground server callers MAY continue to bind port
346
- zero when they retain the returned listener.
347
-
348
- The dashboard MUST track only same-version explicitly registered PIDs using non-signalling
349
- existence probes. Once every registered PID is absent for the grace period, it
350
- MUST gracefully close its HTTP listener and exit. A new live
351
- registration during the grace period MUST cancel expiry. This is a local
352
- best-effort session guard, not a Codex restart guarantee.
353
-
354
- When exact structured health identifies an older TaskChef dashboard for the
355
- same canonical workspace, the new MCP MUST request simple graceful shutdown,
356
- wait a bounded time for port release, and start its installed `session` version
357
- within the same ensure operation. It MUST NOT transfer in-memory PID leases
358
- across versions. The replacement initially knows only the activating session;
359
- a later ensure MAY register another live session or restart the dashboard after
360
- the activating lease expires.
361
-
362
- A recognized newer TaskChef listener MUST NOT be downgraded. Concurrent
363
- activation and replacement MUST converge through health probing and exclusive
364
- port binding. Unknown, malformed, different-workspace, or unrelated occupants
365
- MUST receive no control request or process signal and MUST remain untouched.
366
- TaskChef MUST NOT discover or kill port owners.
367
-
368
- TaskChef's dashboard uses a trusted, single-user localhost threat model. Exact
369
- bounded health identity is sufficient service recognition and MUST NOT be
370
- described as cryptographic authentication. The dashboard MUST NOT create or use
371
- an owner secret, HMAC challenge, durable ownership record, handoff record,
372
- prepare/commit protocol, recovery lease, or cross-version lease transfer.
373
-
374
- The session-registration and shutdown controls MUST remain loopback-only and
375
- MUST require the exact listener Host and Origin, JSON content type, a non-simple
376
- TaskChef control header, and an exact bounded request body containing the exact
377
- structured health identity observed by the caller. The receiver MUST compare
378
- that expected identity with its own identity before registering a session or
379
- accepting shutdown. It MUST refuse a mismatch, and the manager MUST probe again
380
- before applying lifecycle rules to the current occupant. These request-shape
381
- checks protect against ordinary cross-site browser requests; they MUST NOT be
382
- described as authentication. Future LAN access is outside this contract and
383
- requires a separate opt-in design with password-backed user authentication and
384
- suitable transport protection.
385
-
386
- A listener using the former HMAC control protocol will refuse the new simple
387
- shutdown request. It MUST be reported as a recognized older TaskChef conflict
388
- and left running. Crossing that one-time compatibility boundary requires the
389
- verified legacy listener to stop through its existing lifecycle before ensure
390
- is retried; TaskChef MUST NOT add a process-kill fallback.
391
-
392
- Detached session startup MUST use a private child readiness acknowledgement
393
- sent only after listener bind, initialization, and initial in-memory lease
394
- creation. Startup errors MUST propagate through that channel. A bounded
395
- readiness timeout MUST cooperatively cancel the exact child so late
396
- initialization cannot strand an unreported listener.
397
-
398
- MCP EOF, explicit close, protocol close, SIGINT, SIGTERM, transport-start
399
- failure, and MCP-parent loss MUST still bound MCP shutdown. They MUST close the
400
- MCP manager and transport without directly closing the independently hosted
401
- session dashboard. Foreground `taskchef dashboard` remains `standalone`, is
402
- never adopted by MCP, and follows its foreground process lifetime.
403
-
404
- The packaged `$taskchef-dashboard` skill MUST call this tool, report `started`
405
- or `reused`, and return the canonical clickable URL. It MAY use an available
406
- in-app browser when permitted; absent or blocked browser navigation MUST fall
407
- back to the link without failing. It MUST NOT inspect task outcomes or dispatch.
408
-
409
- **Annotations:** `readOnlyHint: false`, `destructiveHint: false`,
410
- `openWorldHint: false`.
411
-
412
- The complete operational rationale and limits are documented in
413
- [Dashboard lifecycle](dashboard-lifecycle.md).
414
-
415
- ### `prepare_dispatch`
416
-
417
- **Caller:** dispatcher. **Mutation:** none.
418
-
419
- **Input:** empty object.
420
-
421
- **Structured output:**
422
-
423
- ```text
424
- { preparation: {
425
- schemaVersion: 1,
426
- workspace: string,
427
- taskId: string,
428
- preparedAt: string,
429
- marker: string,
430
- projectCount: number,
431
- projects: Project[],
432
- routingHints: {path, aliases[], githubRepos[], responsibilities[]}[]
433
- } }
434
- ```
435
-
436
- The tool generates a fresh task UUID and exact marker and returns current
437
- routing targets. An invocation is not idempotent: each successful call creates
438
- new preparation values, though it writes no state.
439
-
440
- **Annotations:** `readOnlyHint: true`, `destructiveHint: false`,
441
- `openWorldHint: false`.
442
-
443
- ### `record_task`
444
-
445
- **Caller:** dispatcher. **Mutation:** atomically appends one task.
446
-
447
- **Input:**
448
-
449
- | Field | Type and rule |
450
- | --- | --- |
451
- | `id` | Non-empty string; MUST equal the instruction marker. |
452
- | `project` | Non-empty configured project path. |
453
- | `title` | Non-empty string. |
454
- | `instruction` | Non-empty string containing exactly one accepted marker and a non-empty assignment. New instructions use the required trailing marker and executor-invocation scaffold; historical first-line forms remain accepted. |
455
- | `threadId` | Literal null. |
456
-
457
- **Structured output:** `{ task: Task }`.
458
-
459
- The returned task has schema 10, `working`, null summary/turn/thread/latestTurn/lastResult,
460
- empty `turns` and derived `results` arrays,
461
- `updatedBy: dispatcher`, and equal creation/update timestamps. Duplicate IDs,
462
- unknown projects, malformed markers, and invalid input fail. Repeating a
463
- successful call is not idempotent; it fails as a duplicate.
464
-
465
- Configuration is read structurally so unavailable unrelated entries do not
466
- block preparation or recording. `record_task` validates the selected actual
467
- directory or Git root before snapshotting it.
468
-
469
- **Annotations:** `readOnlyHint: false`, `destructiveHint: false`,
470
- `openWorldHint: false`.
471
-
472
- ### `reconcile_projects`, `include_project`, and `update_project_hint`
473
-
474
- `reconcile_projects` accepts one agent-supplied native Codex schema-2 project
475
- snapshot. Node does not call native tools or inspect private Codex state. It
476
- considers only local projects with `hostId: local`, canonicalizes each eligible
477
- path, excludes the dispatcher and its ancestors, isolates per-project failures,
478
- and commits additions and exact identity bindings under the configuration lock.
479
- It preserves curated metadata and absent projects. Repeated identical or empty
480
- snapshots do not write. Duplicate IDs, canonical targets, or identity/path moves
481
- produce bounded diagnostics. Its MCP response contains counts, current eligible
482
- targets, diagnostics, and changed state rather than full configuration copies.
483
-
484
- Removing a configured project records an exclusion. `include_project` removes
485
- one exact exclusion by native project ID or canonical path; a later reconcile
486
- must validate and add the target. A move is handled through exact preview-bound
487
- removal, explicit inclusion, and reconciliation of the new path.
488
-
489
- `update_project_hint` remembers, corrects, or forgets one bounded fact. Aliases
490
- require explicit user evidence; correction is the only operation that removes
491
- the same alias from another project. Repository ownership requires an inspected
492
- exact origin from the selected project or a contained Git root. Responsibilities
493
- require an accepted current terminal task/thread/turn. Forgetting requires
494
- explicit user evidence and leaves bounded suppression against stale report
495
- replay. Learning remains separate from terminal reporting and a learning error
496
- cannot undo an accepted result.
497
-
498
- ### `link_task`
499
-
500
- **Caller:** executor. **Mutation:** one atomic identity transition.
501
-
502
- **Input:** `{ taskId: non-empty string, threadId: non-empty string }`.
503
- The workspace layer requires `threadId` to be a canonical Codex UUIDv7.
504
-
505
- **Structured output:** `{ task: Task }`.
506
-
507
- The eligible record MUST be link-pending, working, dispatcher-written, and have
508
- the exact marker. The thread ID MUST be unused. Success sets `threadId`,
509
- refreshes `updatedAt`, and sets `updatedBy: mcp`. An exact successful retry
510
- is idempotent. A different identity, terminal record, reused identity, missing
511
- marker, or ineligible state fails.
512
-
513
- **Annotations:** `readOnlyHint: false`, `destructiveHint: false`,
514
- `openWorldHint: false`.
515
-
516
- ### `report_state`
517
-
518
- **Caller:** executor, or dispatcher only for native creation failure.
519
- **Mutation:** replaces the current state atomically and preserves `turns`.
520
-
521
- **Input:**
522
-
523
- | Field | Type and rule |
524
- | --- | --- |
525
- | `taskId` | Non-empty string. |
526
- | `threadId` | Matching non-empty ID for a linked task; null only for creation failure. |
527
- | `turnRef` | Stable UUID for this prompt. It may be omitted only by legacy callers that supply a non-null `turnId`, in which case TaskChef derives the same value. |
528
- | `turnId` | Optional Codex metadata. When present it MUST equal `turnRef`; null is valid for fallback UUID refs. Maximum 256 characters. |
529
- | `status` | `working`, `needs_input`, `completed`, or `failed`. |
530
- | `summary` | Omitted or null for `working`; required non-empty string of at most 2,000 characters otherwise. Known GitHub issues and pull requests use canonical URLs. |
531
- | `requestSummary` | Concise current request of at most 1,000 characters for `working`; optional for backward compatibility and omitted for semantic states. A known selected GitHub repository uses its canonical URL. |
532
-
533
- **Structured output:** `{ task: Task }`.
534
-
535
- For a linked self-linking journey, a new `working` state MUST use a `turnRef`
536
- not already assigned to a different turn. An exact retry of the current
537
- working start MUST return the current task without mutation.
538
- When `turnId` is present, its native-backed `turnRef` MUST also be newer than
539
- every previously stored native-backed ref. Fallback UUID refs are opaque and
540
- MUST NOT be lexically ordered.
541
- A semantic state MUST match the current working turn. Conflicting or stale
542
- state fails. A null-thread record accepts only a fresh executor creation
543
- `failed` state with a retained `turnRef` and null thread/turn IDs. Starting work appends one turn with
544
- its request and a null result. When the previous latest turn is unfinished, the
545
- same locked atomic rewrite MUST first fill it with the fixed TaskChef-generated
546
- `interrupted` outcome. The semantic report fills the active turn's result.
547
- An identical retry for the current settled turn returns success without an
548
- append. Once a newer turn starts, every callback for a historical ref is stale
549
- and fails, even when its content exactly matches the stored callback. A
550
- different request or result for the same turn, a stale turn, or a semantic
551
- result that does not match the active working turn MUST fail.
552
-
553
- `interrupted` MUST NOT be accepted as MCP input or projected as task `status`.
554
- It MUST NOT alter `summary`, `results`, or `lastResult`, and its fixed summary
555
- MUST contain no crash output, transcript, user text, or inferred failure cause.
556
-
557
- **Annotations:** `readOnlyHint: false`, `destructiveHint: true`,
558
- `openWorldHint: false`.
559
-
560
- Reporting tool descriptions MUST identify the configured local `tasks.jsonl`
561
- path and local `.taskchef-usage.json` tracking side effect. GitHub URLs remain
562
- references in that log; reporting does not publish them to GitHub. The
563
- `destructiveHint: true` annotation is retained because reports update existing
564
- state and can recover an unfinished predecessor as interrupted; these tools
565
- are not purely additive. The compatibility alias also changes existing state.
566
- Executors MUST verify accepted terminal reporting before claiming TaskChef was
567
- updated. A platform rejection of an authorized report MUST be described using
568
- only the returned rationale, without inferring causes or retrying around an
569
- explicit denial. Authorization and unit tests do not guarantee platform approval.
570
-
571
- ### `report_result` (deprecated)
572
-
573
- `report_result` retains the prior semantic-only input shape and statuses as a
574
- temporary compatibility alias. It implicitly accepts a fresh supplied turn and
575
- stores its semantic result in a request-unknown turn, including for supported schema-4/5/6 records and
576
- low-level opaque direct records. It does not accept `working`. New executor
577
- instructions MUST use `report_state`. Successful mutation upgrades schema 4-9
578
- to schema 10; unsupported schemas remain rejected. Legacy callers that omit
579
- `turnRef` remain compatible when `turnId` is non-null.
580
-
581
- ## Copilot and dashboard
582
-
583
- A semantic result is cached evidence, not permanent live truth. The dashboard
584
- MUST remain the primary monitoring and browsing UI. Copilot MUST start from the
585
- schema-1 normalized cached brief and explain what finished, what needs
586
- attention, why, and the recommended next action. It MUST NOT need to interpret
587
- historical task schema versions. A working task's current summary MUST remain
588
- null; any prior semantic result MUST be exposed separately as a clearly
589
- historical `lastOutcome`. A link-pending task with no exact thread identity MUST
590
- recommend passive waiting or inspection, never retry or continuation.
591
-
592
- Copilot MAY take one bounded native metadata snapshot only when the user
593
- explicitly requests fresh/live verification or a focused task presents a
594
- meaningful contradiction. Active or approval-waiting native state overrides
595
- cache. An inactive task does not prove completion. Copilot MAY read the exact
596
- selected task once for an explicit focused live-verification request or to
597
- resolve a focused contradiction. It MUST NOT poll, wait, perform exhaustive
598
- live audits, or classify assistant prose.
599
-
600
- Copilot MAY identify the exact existing executor, explain or draft a
601
- same-assignment follow-up, and continue that executor only with explicit user
602
- authorization. It MUST NOT automatically retry failures, interrupt working
603
- tasks, or redelegate an existing executor. Independent new work MUST route
604
- through delegation. Managed dispatcher routing MUST give same-assignment
605
- answer, follow-up, resume, and continue requests precedence over the blanket
606
- new-work delegation rule. A direct imperative naming the exact existing task
607
- MAY constitute send authorization, but copilot MUST re-read that exact task
608
- immediately before sending.
609
-
610
- The published plugin MUST NOT package `taskchef-report` as a discoverable alias.
611
- Its historical explicit name is a documented rename hint handled by copilot,
612
- not a second workflow.
613
-
614
- Task lists, summaries, and broad briefs MUST use the final result by default.
615
- The dashboard MUST bind only to loopback, validate the current workspace
616
- snapshot, and avoid sessions or shared client state. `GET /api/health` MUST
617
- return only the bounded service identity, health schema, exact TaskChef and
618
- dashboard-server versions, and canonical workspace. It MUST NOT return task
619
- records, secrets, credentials, environment values, or process-control data.
620
- Identity remains available while an already-started monitor retains its last
621
- valid snapshot after a later invalid task log; an invalid initial log MAY fail
622
- startup safely. Direct thread navigation
623
- MUST require a canonical Codex UUIDv7. Otherwise it MAY open the revalidated
624
- configured project. Project paths from task history MUST be matched against
625
- current configuration before use.
626
- The task-detail dashboard MAY offer manual outcomes from `working` or
627
- `needs_input` to either `completed` or `failed`, from `completed` to `failed`,
628
- and from `failed` to `completed`. It MUST reject same-state terminal
629
- transitions and MUST keep this infrequent administrative action out of list
630
- cards. A keyboard-accessible **More task
631
- actions** disclosure MUST reveal its action list immediately beside it and
632
- change from an ellipsis to an accessible back/hide control while expanded. The
633
- list MUST group **Copy Task ID** and each currently valid **Mark completed** or
634
- **Mark failed** action. **Archive chat** MUST remain hidden while the archive capability
635
- gate is disabled because the bundled CLI does not reliably archive desktop-app
636
- threads. The dormant server endpoint MUST reject requests before discovering or
637
- invoking the CLI. Re-enabling requires a reliable supported app-callable archive
638
- interface or guaranteed CLI compatibility. Opening the
639
- list is the deliberate disclosure step; choosing a terminal outcome submits it
640
- immediately without a second confirmation. Escape MUST close the idle list,
641
- pending controls MUST be
642
- disabled, and failure feedback MUST remain in the dialog. Pending state MUST
643
- focus and announce a stable status inside the dialog. Failed MUST have
644
- destructive styling. The client MUST bound and abort a stalled manual-transition
645
- request, restore the dialog controls, and preserve the action ID so a retry can
646
- resolve idempotently if the server committed before the timeout.
647
-
648
- `POST /api/tasks/:id/manual-transition` MUST require the exact loopback origin,
649
- `application/json`, a bounded body, and exactly this versioned shape:
650
- `{schemaVersion: 1, actionId, expected: {status, turnRef, threadId, updatedAt},
651
- targetStatus}`. The server MUST compare every expected field while holding the
652
- workspace lock. A stale request, invalid transition, or reused action ID with a
653
- different operation MUST return a conflict without mutation. Replaying the
654
- same committed action ID and operation MUST return the current task as an
655
- idempotent success. The operation MUST atomically append one new manual turn;
656
- it MUST NOT overwrite executor history. An active unfinished turn MUST first
657
- receive the standard interrupted timeline outcome. The manual turn MUST have a
658
- new server-generated `turnRef`, null `turnId`, one monotonic timestamp for its
659
- start, result, and task update, `updatedBy: dashboard`, and deterministic
660
- request/result summaries. It MUST record provenance
661
- `{kind: dashboard_manual, actionId, fromStatus, toStatus, expectedTurnRef,
662
- expectedThreadId, expectedUpdatedAt}`. No free-form reason is collected or
663
- persisted. A committed write remains successful if the subsequent best-effort
664
- monitor refresh or notification delivery fails.
665
-
666
- The task-detail dashboard MAY offer Codex chat archival only when the stored
667
- thread ID is a canonical Codex UUID and the current TaskChef state is not
668
- `working`. It MUST revalidate both conditions for the POST request, require the
669
- exact loopback origin, and obtain explicit user confirmation in the browser.
670
- It MUST invoke the `archive` subcommand by directly executing only a Codex CLI
671
- inside the canonical ChatGPT or Codex desktop application bundle under macOS
672
- `/Applications`, with the thread UUID as a separate argument. It MUST NOT use a shell, a generic `PATH` fallback, a
673
- private desktop endpoint, or direct session-file manipulation. Successful
674
- archival MUST NOT modify dispatcher files or remove the TaskChef task record.
675
- The UI MUST disclose that spawned descendant chats may also be archived and
676
- that TaskChef history remains available.
677
- Snapshot and SSE list payloads MUST omit full `turns` and derived `results`
678
- history and include `latestTurn`. The bounded per-task detail endpoint MAY
679
- return the full validated task so the dialog can render the paired timeline newest first.
680
- Dashboard notifications MUST capture an immutable event-time projection of the
681
- task title, lifecycle state and event, turn ref and optional Codex turn ID, event timestamp,
682
- and relevant concise summary. Rendering MUST NOT resolve historical notice text
683
- from the task's later current state. Notice identity and deduplication MUST use
684
- task ID, turn ref, and lifecycle event; a creation notice without a turn ref MUST
685
- fall back to task ID plus the immutable creation timestamp. Dashboard revision
686
- MUST NOT be the sole identity. Identical snapshots, SSE reconnects, idempotent
687
- reports, schema normalization, and non-semantic rewrites MUST NOT add notices.
688
- Distinct working and semantic-result events for one turn MAY each be retained.
689
- When one compact snapshot first exposes both a latest semantic result and a
690
- newer working turn, the browser MUST reconcile both events. Temporary task
691
- absence MUST NOT discard the prior semantic signature or turn a later
692
- reappearance into another creation event. The first page snapshot MUST establish
693
- a quiet baseline rather than replay existing history. After that baseline, a
694
- new task first observed with a turn or semantic result MUST retain its creation
695
- event and each lifecycle event observable in that compact projection.
696
-
697
- Working with no prior result SHOULD be labeled as a task start. Working on a
698
- newer turn while a prior result remains projected SHOULD be labeled as a
699
- follow-up start. Creation, completion, input-needed, and failure labels MUST be
700
- distinct. The Updates panel MUST remain bounded and support individual dismiss
701
- and clear-all without resetting replay protection. A retained notice whose task
702
- is absent from the current list MUST remain readable; selecting it MUST NOT
703
- navigate or mutate data and SHOULD explain that current details are unavailable.
704
- The retained notice list MUST NOT be a live region that re-announces old notices
705
- when it rerenders. A separate polite status region MUST announce only newly
706
- reconciled events. Each notice control's accessible description MUST include
707
- its displayed summary when present, event time, and missing-task state.
708
-
709
- ## Task-log migration
710
-
711
- `workspace migrate` MUST explicitly convert every supported schema-4/5/6/7/8/9 record
712
- under the shared lock. Each legacy semantic result becomes a request-unknown
713
- completed turn; a newer working state becomes a final unfinished turn, and a
714
- schema-7/8 timeline is preserved. Each non-null legacy `turnId` becomes the
715
- same `turnRef`; each null legacy `turnId` receives one durably persisted UUID.
716
- Migration MUST validate the complete source, record/turn counts, turn-ref
717
- invariants, and complete schema-10 candidate before changing the task log,
718
- create and read back an exclusive recovery backup, atomically replace the log,
719
- and validate the installed result. A fully schema-10 log MUST be an idempotent
720
- no-op without another backup. Invalid/unsupported input MUST remain untouched;
721
- failures after backup creation MUST report the backup path and MUST never
722
- partially rewrite individual lines.
723
-
724
- ## Concurrency and trust
725
-
726
- All task and configuration writers MUST share one workspace lock. Duplicate ID,
727
- duplicate thread, link, and result freshness checks MUST occur while holding
728
- that lock. Atomic replacement MUST preserve valid unrelated records.
729
-
730
- TaskChef is designed for a local, single-user boundary. Executor self-linking is
731
- a cooperative assertion, not transport-authenticated proof. Task instructions,
732
- stored project snapshots, and dashboard requests are untrusted input.
733
- Implementations MUST validate exact shapes, canonical paths, safe IDs, markers,
734
- loopback origin, and current configuration before acting.
735
-
736
- TaskChef MUST NOT use lifecycle hooks, schedules, polling, recent-thread search,
737
- transcript search, title matching, hidden reasoning, or token usage to discover
738
- identity or infer semantic results.
739
-
740
- TaskChef MUST NOT install or require daemons, launchd agents, login items,
741
- system services, cron jobs, hooks, privileged components, or elevated/system
742
- permissions for dashboard availability. Availability is best-effort while a
743
- registered Codex session process is alive and is not guaranteed while Codex is
744
- closed.
745
-
746
- Releases using the former HMAC dashboard control protocol are legacy listeners.
747
- A verified legacy listener MUST be reported distinctly from an unknown port
748
- conflict and MUST remain running when it refuses simple graceful shutdown. One
749
- final stop through that listener's existing lifecycle is required when crossing
750
- this boundary. Releases implementing simple localhost control replace older
751
- recognized versions automatically.
752
-
753
- Installing or replacing plugin files MUST NOT be described as activating the
754
- new MCP code. Release verification MUST install the plugin, activate or reload
755
- the new MCP process, ensure the dashboard, and verify the expected TaskChef
756
- version, dashboard protocol `serverVersion`, reported launcher, canonical workspace,
757
- and canonical URL. Exact-compatible session-listener reuse remains valid; installation MUST NOT be
758
- claimed to reload Codex automatically.
48
+ Release validation must exercise the native MCP server, bundled UI, delegate
49
+ skill and required dependencies, without requiring retired dispatcher files.
50
+ A future web product does not require shipping the old HTTP runtime.