taskchef 8.2.2 → 8.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "8.2.2",
3
+ "version": "8.3.1",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
package/README.md CHANGED
@@ -62,8 +62,6 @@ AGENTS.md managed dispatcher instructions plus user additions
62
62
  taskchef.json schema-2 Codex project index, dashboard preference, and delegation metadata
63
63
  tasks.jsonl one task snapshot per line (schema 10; schema 4-9 migration supported)
64
64
  .taskchef-usage.json optional mode-0600 ccusage snapshot and turn-boundary cache
65
- .taskchef-dashboard-owner.json optional mode-0600 current dashboard identity and control credential; retained and atomically replaced
66
- .taskchef-dashboard-handoff.json optional mode-0600 secret-free signed final lease snapshot; retained and atomically overwritten
67
65
  ```
68
66
 
69
67
  Index or inspect Codex projects conversationally:
@@ -179,13 +177,14 @@ Use $taskchef-executor to execute and report this delegated TaskChef assignment.
179
177
 
180
178
  ### Model roles
181
179
 
182
- TaskChef can apply personal Planner, Implementer, and Reviewer model preferences
183
- from `~/.codex/agents/`. Planning-only tasks use Planner, while coding tasks and
184
- single tasks that plan and then execute use Implementer throughout. To apply
185
- both models, finish a Planner task that saves its plan, then create a separate
186
- Implementer task using that plan. Reviewer preferences apply when a workflow
187
- explicitly starts a review subagent. Explicit per-task model choices take
188
- precedence, and changes affect only tasks created afterward.
180
+ TaskChef can apply personal Orchestrator, Planner, Implementer, and Reviewer
181
+ model preferences from `~/.codex/agents/`. Every delegated task uses the
182
+ Orchestrator preference for its visible parent. For repository work, a combined
183
+ investigate-or-plan-and-implement request runs fresh Planner, Implementer, and
184
+ Reviewer subagents in that order. A direct implementation, or a later request
185
+ to implement prior investigation, skips the Planner and runs a fresh Implementer
186
+ and Reviewer in the same visible task. Explicit model choices take precedence
187
+ for the role they target.
189
188
 
190
189
  ## Work with and report executors
191
190
 
@@ -271,40 +270,36 @@ $taskchef-dashboard Ensure and open the TaskChef dashboard.
271
270
  MCP activation and `$taskchef-dashboard` call the input-free `ensure_dashboard`
272
271
  MCP tool. It starts at most one loopback dashboard scoped to the running Codex
273
272
  session on `127.0.0.1:3210`, or reuses a listener only when its bounded
274
- `/api/health` identity proves the exact TaskChef/dashboard-server version,
275
- canonical workspace, and `session` launcher. The response says `started` or
276
- `reused` and includes the stable URL, canonical workspace, and versions.
273
+ `/api/health` identity reports the exact TaskChef/dashboard-server version,
274
+ canonical workspace, and recognized launcher. The response says `started` or
275
+ `reused` and includes the stable URL, canonical workspace, versions, and actual
276
+ launcher.
277
277
 
278
278
  The dashboard is launched by MCP but is not hosted by one MCP transport. It
279
279
  therefore survives an individual MCP close, stdin EOF, signal, or plugin reload.
280
- Each MCP securely registers its original Codex parent PID; after every
281
- registered Codex session PID disappears for a grace period, the dashboard
282
- closes and exits. Activating an installed newer TaskChef MCP authenticates and
283
- retires a compatible older `mcp`- or `session`-owned dashboard for the same
284
- canonical workspace, then starts the installed version. These are best-effort
280
+ Only a listener launched as `session` registers each same-version MCP's original
281
+ Codex parent PID in its in-memory lease. After every registered Codex session
282
+ PID disappears for a grace period, the dashboard closes and exits. Activating
283
+ an installed newer TaskChef MCP recognizes and
284
+ gracefully stops an older TaskChef dashboard for the same canonical workspace,
285
+ waits boundedly for the port, then starts the installed version in that ensure.
286
+ Lease state is not transferred across versions; the replacement initially knows
287
+ only the activating session. These are best-effort
285
288
  local guards, not a claim that Codex supplies a restart guarantee. TaskChef adds
286
289
  no daemon or OS-persistent component. See the complete
287
290
  [dashboard lifecycle](docs/dashboard-lifecycle.md).
288
291
 
289
- Authenticated handoff requires the older listener to have written TaskChef's
290
- private mode-0600 ownership record in that canonical workspace. A nonce-bound
291
- HMAC challenge proves the listener has the matching secret before TaskChef
292
- sends an authenticated two-phase handoff. A session listener prepares by
293
- fencing ordinary joins, adding the activating Codex PID, and returning a signed
294
- bounded lease snapshot while remaining live. A separate authenticated commit
295
- allows a short concurrent-activator grace, returns the signed final immutable
296
- lease set, and then schedules graceful shutdown after a bounded response-retry
297
- window. A mode-`0600`, secret-free, signed final-snapshot record permits exact
298
- lease recovery if every commit response is lost; a prior MCP-owned listener
299
- receives a separately authenticated graceful shutdown request. The secret is never
300
- returned by `/api/health`, sent in a request, or logged. Standalone,
301
- different-workspace, newer, malformed,
302
- unverified, and spoofed listeners are left untouched. Versions predating this
303
- protocol cannot be taken over safely and may require one final manual cleanup.
304
- The ownership record is durable metadata: shutdown retains it, and the next
305
- MCP owner atomically replaces it after binding. This avoids both a live
306
- credentialless retirement window and an old process deleting its replacement's
307
- proof.
292
+ TaskChef uses a trusted, single-user localhost model. Exact structured health is
293
+ sufficient service recognition; it is not cryptographic authentication. Simple
294
+ session and shutdown controls require exact Host and Origin, JSON content, a
295
+ non-simple request header, and an exact bounded body to block ordinary
296
+ cross-site browser requests. Each control names the exact health identity the
297
+ caller observed; the listener refuses a stale identity and the caller probes the
298
+ port again before deciding what to do. Unknown, malformed, different-workspace,
299
+ unrelated, and newer listeners remain untouched. A release using the former HMAC control
300
+ protocol refuses the new simple shutdown request, so the first upgrade across
301
+ that boundary may require stopping that verified legacy TaskChef listener once
302
+ before ensuring again.
308
303
 
309
304
  Autostart is enabled when `dashboard` is absent and in new workspaces. To opt
310
305
  out, add this optional exact object to `taskchef.json` while retaining its other
@@ -381,10 +376,9 @@ The header shows the running TaskChef package version reported by the same
381
376
  bounded health identity used for compatible-listener checks.
382
377
  The Settings page shows the ccusage version reported by the executable that
383
378
  TaskChef resolves at runtime.
384
- The canonical port is owned by a dashboard session process initialized by the
385
- TaskChef MCP before its tool transport connects. Health identity records a
386
- `session` launcher, and MCP recovery reuses only another exact-compatible,
387
- authenticated session dashboard;
379
+ The canonical port is normally owned by a dashboard session process initialized
380
+ by the TaskChef MCP before its tool transport connects. MCP recovery reuses an
381
+ exact-compatible same-workspace dashboard and reports its actual launcher;
388
382
  a foreground `taskchef dashboard` process is intentionally standalone so its
389
383
  child commands cannot silently inherit an agent-shell sandbox.
390
384
  Task and result times are relative through 29 days (with minute detail for the
@@ -399,11 +393,16 @@ its task disappears; selecting it then explains that current details are no
399
393
  longer available.
400
394
  Apart from an explicit manual state selection from the task-detail menu, it does not mutate
401
395
  TaskChef data and prints its local URL. A foreground dashboard identifies
402
- itself as standalone and is never reused on the canonical MCP port. If a
403
- standalone, unknown, different-workspace, or stale-version process owns port
404
- 3210, TaskChef reports a concise conflict and never kills or replaces that
405
- process. The foreground CLI similarly asks you to stop the listener or choose
406
- another `--port`.
396
+ itself as `standalone`. An exact-current, healthy same-workspace listener with a
397
+ recognized `standalone`, `mcp`, or `session` launcher may be reused on the
398
+ canonical MCP port; ensure reports its actual launcher, and only `session`
399
+ listeners register Codex PID leases. If an unknown, malformed, or
400
+ different-workspace process owns port 3210, TaskChef reports a concise conflict
401
+ and never kills that process. A recognized older same-workspace TaskChef
402
+ listener receives a simple guarded graceful shutdown request. If it lacks the
403
+ compatible callback or refuses the request, it remains running and ensure
404
+ reports a conflict. The foreground CLI similarly asks you to stop a conflicting
405
+ listener or choose another `--port`.
407
406
 
408
407
  The health endpoint contains only a fixed service marker, health schema,
409
408
  TaskChef version, dashboard-server version, canonical workspace, and launcher.
@@ -471,24 +470,22 @@ does not necessarily reload Codex. Then run `$taskchef-dashboard` (or call
471
470
 
472
471
  - the expected released TaskChef version;
473
472
  - the expected dashboard protocol `serverVersion`;
474
- - the `session` dashboard launcher;
473
+ - the reported dashboard launcher (`session` for a newly started canonical dashboard);
475
474
  - the canonical TaskChef workspace path;
476
475
  - the canonical `http://127.0.0.1:3210/` URL.
477
476
 
478
477
  The release-install sequence is therefore: install plugin, activate or reload
479
478
  the new MCP process, ensure the dashboard, then verify TaskChef version,
480
- protocol `serverVersion`, `session` launcher, canonical workspace, and URL.
481
- Exact-compatible session servers may be reused; standalone and unknown listeners
482
- remain untouched.
479
+ protocol `serverVersion`, reported launcher, canonical workspace, and URL.
480
+ Exact-compatible same-workspace servers with a recognized launcher may be
481
+ reused; unknown listeners remain untouched.
483
482
 
484
483
  If autostart reports a **verified older TaskChef** listener, the port occupant
485
- passed the bounded TaskChef identity check but could not complete authenticated
486
- handoff. For a release older than the ownership protocol, stop that one known
487
- legacy MCP process once through the application/session that launched it, then
488
- activate the installed plugin again. Do not kill an arbitrary port owner. A
489
- listener from a handoff-capable prior release should retire automatically; if
490
- it does not, retain it for diagnosis because TaskChef deliberately refuses to
491
- weaken the ownership proof.
484
+ passed the bounded TaskChef identity check but refused the simple graceful
485
+ shutdown request. Releases using the former HMAC control protocol form a
486
+ one-time compatibility boundary: stop that verified legacy TaskChef listener
487
+ through the application/session that launched it, then activate the installed
488
+ plugin and ensure again. Do not kill an arbitrary port owner.
492
489
 
493
490
  ## Development
494
491
 
@@ -5,214 +5,128 @@ reloads, changes version, and stops. The [specification](spec.md) is normative;
5
5
  the [README](../README.md) covers user operation, and
6
6
  [workflows](workflows.md) maps these guarantees to implementation.
7
7
 
8
- ## Ownership model
8
+ ## Process model
9
9
 
10
10
  The canonical dashboard is a loopback-only process scoped to a running Codex
11
- application session. It is launched and maintained by TaskChef MCP activation,
12
- but it is not hosted by one MCP transport. This distinction lets the dashboard
13
- survive an individual MCP EOF, signal, transport close, or plugin reload while
14
- other TaskChef MCP transports in the same Codex session continue using it.
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
15
 
16
16
  TaskChef does not install a daemon, login item, lifecycle hook, or privileged
17
- service. A foreground `taskchef dashboard` process remains a separate
18
- `standalone` launcher and is never adopted as the canonical session dashboard.
17
+ service. A foreground `taskchef dashboard` remains a separate `standalone`
18
+ launcher.
19
19
 
20
- The dashboard was originally moved into the MCP runtime so the experimental
21
- chat-archive action could inherit the MCP host environment. That action is now
22
- disabled because Codex does not expose a reliable supported app-callable
23
- archive interface. The dashboard still benefits from MCP activation,
24
- workspace resolution, and startup isolation, but none of those requires the
25
- HTTP listener to share one MCP transport's lifetime. The session process keeps
26
- those benefits without retaining the obsolete per-transport ownership.
27
-
28
- ## Token usage presentation
29
-
30
- The detail view distinguishes an active turn whose final usage is pending from
31
- a terminal turn whose usage is being calculated. Available usage keeps both
32
- the token total and API-equivalent USD estimate. Task cards keep the latest
33
- cumulative value visible during a newer active turn and label it as updating;
34
- pending is reserved for tasks that do not have a usage snapshot yet.
35
-
36
- The dashboard owns a small background recovery queue for derived usage. It
37
- deduplicates tasks, limits concurrent ccusage reads, preserves successful cache
38
- records, and revisits missing, interrupted, or cooldown-expired records without
39
- requiring a detail request. The queue starts with the dashboard, reacts to task
40
- log revisions, performs periodic recovery passes, and stops with the dashboard.
41
- Settings reports the version returned by the resolved ccusage executable.
42
-
43
- ![Pending token usage in the task detail view](images/dashboard-token-pending.jpg)
44
-
45
- ## Reported work presentation
46
-
47
- The task detail view reports wall-clock elapsed time from TaskChef lifecycle
48
- timestamps. Each terminal turn's **Elapsed** value is `result.updatedAt` minus
49
- `startedAt`. **Total reported work** is the sum of valid terminal-turn elapsed
50
- times, so idle gaps between follow-up turns and the unfinished portion of an
51
- active turn are excluded. A working turn shows a live **Elapsed so far** value
52
- from `startedAt` to the current time without adding it to the task total.
53
-
54
- Durations below one minute use whole seconds; durations below one hour use
55
- minutes and seconds; durations below one day use hours and minutes; longer
56
- durations use days and hours. Each displayed unit is floored, and positive
57
- sub-second durations display as `<1s`. Missing, malformed, reversed, or
58
- unsupported timestamp ranges display an explicit unavailable state. Zero-width
59
- terminal ranges are also unavailable because existing records cannot reliably
60
- distinguish synthesized boundaries from same-millisecond measured work. Timing
61
- is derived independently of `.taskchef-usage.json` and is reported wall-clock
62
- elapsed time, not model compute time.
63
-
64
- ![Reported work across a multi-turn task](images/reported-work-duration-desktop.jpg)
20
+ ## Start and reuse
65
21
 
66
- ![Unavailable reported work on a narrow layout](images/reported-work-duration-mobile.jpg)
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.
67
25
 
68
- ## Start and reuse
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.
69
51
 
70
- An actual new dashboard server creates or deduplicates a verified private state
71
- snapshot before monitors or derived-state writers start. Reusing an existing
72
- listener does not create another startup snapshot. Snapshot failure aborts the
73
- new server start and does not weaken MCP reporting isolation.
52
+ ## MCP reload and plugin upgrade
74
53
 
75
- The dashboard watches both task history and the project index. It warns when
76
- historical task snapshots reference paths absent from the current index, and
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
77
105
  offers recovery-oriented read-only commands. It never mutates or restores
78
106
  configuration.
79
107
 
80
- Unless `dashboard.autostart` is explicitly `false`, MCP activation runs the
81
- same serialized ensure operation exposed by `ensure_dashboard` before the MCP
82
- transport connects. An explicit ensure remains available when autostart is
83
- disabled. Failure is isolated from MCP tool startup and emits only a bounded,
84
- non-sensitive diagnostic.
85
-
86
- The canonical session manager requires an explicit nonzero port and normally
87
- binds `127.0.0.1:3210`; ephemeral port zero remains available only to direct
88
- foreground/server callers that own the returned listener. Reuse requires an
89
- exact bounded health identity:
90
-
91
- - TaskChef dashboard service and health schema;
92
- - installed TaskChef version;
93
- - dashboard protocol version;
94
- - canonical workspace;
95
- - `session` launcher.
96
-
97
- The MCP then authenticates the listener with the private ownership credential
98
- and registers its original Codex parent PID as a session lease. Registration
99
- success and transferred lease sets carry response HMACs bound to their fresh
100
- request nonce and complete result, so a different process appearing between
101
- the challenge and control request cannot be adopted. Concurrent starts
102
- serialize locally and converge across processes by authenticating the single
103
- listener that wins the port race.
104
-
105
- A detached child reports readiness over a private inherited IPC channel only
106
- after the listener is bound and the new owner record is durably published.
107
- Startup errors use the same channel. A bounded timeout sends a cooperative
108
- cancellation message, so slow or failed initialization cannot be mistaken for
109
- success or silently strand a late or partially constructed listener. Owner
110
- publication checks cancellation before atomic replacement; while publication
111
- is in flight, every close path retains the port until publication settles, so
112
- an older credential writer cannot race and overwrite a succeeding session's
113
- owner record.
108
+ The detail view distinguishes an active turn whose final usage is pending from
109
+ a terminal turn whose usage is being calculated. Available usage keeps both the
110
+ token total and API-equivalent USD estimate. The dashboard owns a bounded
111
+ background queue for derived usage and stops that queue with the server.
114
112
 
115
- ## MCP reload and plugin upgrade
113
+ ![Pending token usage in the task detail view](images/dashboard-token-pending.jpg)
116
114
 
117
- Closing one MCP transport does not close the session dashboard. EOF, SIGINT,
118
- SIGTERM, protocol close, failed transport startup, and detected MCP-parent loss
119
- still close that MCP process promptly, but the independently hosted dashboard
120
- remains while a registered Codex session PID is alive.
121
-
122
- After a plugin upgrade, installing files alone cannot execute new code. When
123
- the newly installed MCP activates, it compares the live identity with its own
124
- version. An exact current listener is reused. A verified older TaskChef
125
- `mcp`- or `session`-launched listener for the same canonical workspace receives
126
- an authenticated graceful handoff request. A session listener prepares an
127
- idempotent handoff by fencing new registrations, adding the activating Codex
128
- PID, and snapshotting its bounded live leases while it remains running. Only
129
- after the MCP receives and verifies that signed result does it send a separate
130
- authenticated commit that schedules graceful shutdown. A lost prepare response
131
- is safely retried; an abandoned preparation expires and reopens registration.
132
- A commit begins a short bounded finalization grace during which concurrent
133
- authenticated activators can join. The commit response then returns the final
134
- immutable lease snapshot with a credential-bound proof. The listener remains
135
- available for a bounded commit-response retry window before graceful shutdown,
136
- so a surviving activator can replace an elected peer that exits before launch
137
- without discarding the older live sessions. The replacement starts with the
138
- verified final leases. A full lease set refuses a distinct activating PID
139
- without stopping the old listener. Finalization also reserves one of the 64
140
- bounded lease slots for a distinct recovery activator; a 64-lease snapshot
141
- cannot commit retirement and leaves the old listener running. The new MCP then
142
- starts the current `session` version. A newer listener is never downgraded,
143
- including during the brief old-to-new listener gap. If different newer versions
144
- race, a higher contender authenticates and replaces a lower winner until the
145
- highest active version remains.
146
-
147
- Before acknowledging commit, the retiring session atomically records that
148
- signed final snapshot in the mode-`0600` workspace file
149
- `.taskchef-dashboard-handoff.json`. The record
150
- contains no control secret. It exists only so an activator that loses every
151
- commit response can authenticate and recover the exact finalized leases after
152
- the old listener closes. The single record is retained and atomically
153
- overwritten by the next finalized handoff; it cannot authenticate against a
154
- new owner identity and secret. Avoiding post-publication deletion prevents one
155
- replacement from removing a newer handoff generation. Invalid, permissively
156
- readable, foreign-workspace, or incorrectly signed records are ignored and
157
- never authorize takeover.
158
-
159
- Both private metadata writers sync the completed file, atomically rename it,
160
- and sync the canonical workspace directory before reporting publication. Final
161
- lease joins are fenced before the immutable snapshot and durable write begin.
162
-
163
- Versions predating authenticated ownership cannot be retired safely. Such a
164
- legacy listener may require one final manual cleanup. This limitation is
165
- intentional; TaskChef does not weaken listener safety to automate migration.
166
-
167
- ## Codex session end
168
-
169
- Each MCP registers the exact PID of the Codex process that launched it. The
170
- dashboard checks only those registered PIDs with a non-signalling existence
171
- probe. When none remains alive for the configured grace period, the dashboard
172
- gracefully closes its HTTP listener and exits. Registering another live Codex
173
- session during the grace period cancels expiry.
174
-
175
- This is a best-effort local lifecycle guard, not a claim that Codex documents
176
- or guarantees restart cleanup. PID existence cannot prove application identity
177
- after an unlikely PID reuse, and abrupt operating-system termination can always
178
- interrupt graceful cleanup. A later MCP activation still performs authenticated
179
- version handoff, which is the recovery boundary for a recognized stale
180
- TaskChef listener.
181
-
182
- ## Security boundary
183
-
184
- TaskChef writes ownership to `.taskchef-dashboard-owner.json` and finalized
185
- handoff metadata to `.taskchef-dashboard-handoff.json` as private regular
186
- mode-0600 files in the canonical workspace. The credential never appears in health responses,
187
- diagnostics, URLs, or logs. A fresh nonce-bound HMAC challenge proves that the
188
- listener and owner record share the credential. Shutdown and session
189
- registration use separate action-bound proofs; successful registration and
190
- handoff responses are also nonce- and result-bound. Nonces are single-use within
191
- a bounded five-minute replay window. The replay cache has a fixed capacity and
192
- refuses overflow while entries remain valid.
193
-
194
- TaskChef sends control requests only after all public identity and private
195
- ownership fields match. It never discovers or kills a port owner, sends OS
196
- signals to a listener, uses `kill -9`, searches broadly for processes, or
197
- requires elevated permission. These listeners remain untouched:
198
-
199
- - standalone dashboards;
200
- - unknown or spoofed services;
201
- - different canonical workspaces;
202
- - newer TaskChef versions;
203
- - malformed or mismatched ownership records;
204
- - listeners that fail the authenticated challenge;
205
- - uncooperative legacy listeners without the handoff protocol.
115
+ Reported work is wall-clock elapsed time derived from TaskChef lifecycle
116
+ timestamps. It excludes idle gaps and unfinished portions of active turns from
117
+ the terminal total. Missing, malformed, reversed, zero-width, or unsupported
118
+ timestamp ranges display an unavailable state.
206
119
 
207
120
  ## Lifecycle matrix
208
121
 
209
- | Event | MCP transport | Canonical dashboard |
210
- | --- | --- | --- |
211
- | MCP activation, no listener | Starts | Starts current session version |
212
- | MCP activation, exact listener | Starts | Authenticated reuse and lease registration |
213
- | One MCP EOF, signal, or reload | Closes | Remains while a Codex session PID is alive |
214
- | Plugin upgrade activates newer MCP | Starts current version | Verified older version retires; current version starts |
215
- | All registered Codex session PIDs disappear | May already be closed | Graceful close after the grace period |
216
- | `dashboard.autostart: false` | Starts normally | No activation-time ensure; explicit ensure still works |
217
- | Foreground `taskchef dashboard` | Unrelated | Standalone process follows its foreground CLI lifetime |
218
- | Unknown or unverified port occupant | Starts normally | Occupant is untouched; ensure reports a bounded conflict |
122
+ | Event | Result |
123
+ | --- | --- |
124
+ | Activation with no listener | Start installed session dashboard |
125
+ | Activation with exact current listener | Register a session lease when supported, verify health again, reuse |
126
+ | Activation with recognized older listener | Request graceful shutdown, wait boundedly, start installed version |
127
+ | Activation with recognized newer listener | Refuse downgrade and leave it running |
128
+ | Activation with unknown or different-workspace listener | Report conflict and leave it untouched |
129
+ | One MCP EOF, signal, or reload | Dashboard remains while a registered Codex PID is alive |
130
+ | All registered Codex PIDs disappear | Dashboard closes after the grace period |
131
+ | `dashboard.autostart: false` | Explicit ensure remains available |
132
+ | Foreground `taskchef dashboard` | Standalone process follows foreground CLI lifetime |