taskchef 7.11.0 → 7.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.11.0",
3
+ "version": "7.12.0",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
package/README.md CHANGED
@@ -88,11 +88,11 @@ $taskchef-delegate In payments, add structured logs for failed retries and test
88
88
 
89
89
  TaskChef prepares a UUID and marker, persists the task before native creation,
90
90
  creates the executor, and returns its task link. New executor instructions keep
91
- the assignment visible from the first line, then place the correlation marker
92
- immediately before an explicit `$taskchef-executor` invocation. That skill
93
- reads the executor's own `CODEX_THREAD_ID`, self-links, and reports lifecycle
94
- state. Independent outcomes may become separate executors; dependent work
95
- should stay together.
91
+ the assignment visible from the first line, then place an explicit
92
+ `$taskchef-executor` invocation immediately before the final correlation
93
+ marker. That skill reads the executor's own `CODEX_THREAD_ID`, self-links, and
94
+ reports lifecycle state. Independent outcomes may become separate executors;
95
+ dependent work should stay together.
96
96
 
97
97
  At the start of every dispatcher turn, the managed workspace instructions ask
98
98
  the MCP server to best-effort ensure the dashboard. A startup failure never
@@ -104,8 +104,8 @@ For example, TaskChef generates this shape:
104
104
 
105
105
  ```text
106
106
  Fix duplicate charges after a retry and add a regression test.
107
- <!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->
108
107
  Use $taskchef-executor to execute and report this delegated TaskChef assignment.
108
+ <!-- taskchef_id=c0f010ff-84f2-4838-a69d-0ff1f5d721d7 -->
109
109
  ```
110
110
 
111
111
  ## Work with and report executors
package/docs/spec.md CHANGED
@@ -18,7 +18,7 @@ is dated research, not contract.
18
18
  | **Delegated task** | One independently useful outcome represented by one TaskChef task UUID and snapshot. |
19
19
  | **Executor** | The native Codex task created to own and perform one delegated task. |
20
20
  | **Task record** | One complete JSON object in `tasks.jsonl`; it contains immutable intent/project fields and mutable identity/result fields. |
21
- | **Marker** | The exact correlation line `<!-- taskchef_id=<lowercase full UUID> -->`; new instructions place it after the complete assignment and immediately before the executor-skill invocation. |
21
+ | **Marker** | The exact correlation line `<!-- taskchef_id=<lowercase full UUID> -->`; new instructions place it on the final line, immediately after the executor-skill invocation. |
22
22
  | **Record-before-create** | Persisting a link-pending task before asking Codex to create its executor. |
23
23
  | **Self-linking** | The executor's one-way registration of its own canonical Codex UUIDv7 from `CODEX_THREAD_ID`. |
24
24
  | **Link-pending** | A working task whose `threadId` is null and `updatedBy` is `dispatcher`. |
@@ -119,10 +119,10 @@ the final link, preserving the delegate skill's immediate-return contract.
119
119
  1. The dispatcher MUST call `prepare_dispatch` once per outcome.
120
120
  2. It MUST choose exactly one configured project and exact native-project path.
121
121
  3. It MUST build the instruction with the user's outcome beginning on line 1
122
- and remaining uninterrupted, followed by exactly one newline, the returned
123
- marker, one newline, and exactly one concise explicit `$taskchef-executor`
124
- invocation on the final line. It MUST NOT place a blank line before or after
125
- the marker or inline the executor protocol into a new instruction.
122
+ and remaining uninterrupted, followed by exactly one newline, exactly one
123
+ concise explicit `$taskchef-executor` invocation, one newline, and the
124
+ returned marker on the final line. It MUST NOT place blank lines around the
125
+ invocation or marker or inline the executor protocol into a new instruction.
126
126
  4. It MUST call `record_task` with `threadId: null` before native creation.
127
127
  5. It MUST create exactly one native Codex executor and return immediately.
128
128
  6. The executor MUST read its own `CODEX_THREAD_ID` and call `link_task`
@@ -141,16 +141,17 @@ If native creation fails after recording, the dispatcher MUST call
141
141
  A link failure MUST remain visible and retryable; the executor MUST report it
142
142
  visibly and MUST NOT continue substantive work.
143
143
 
144
- Previously recorded instructions with the former blank line before a trailing
145
- marker, a first-line HTML marker, the older first-line
144
+ Previously recorded instructions with the trailing marker before the
145
+ invocation, with or without the former blank line before that marker; a
146
+ first-line HTML marker; the older first-line
146
147
  `# taskchef_id=<full UUID>` heading, or the former blank line and inline
147
148
  executor protocol MUST remain marker-readable and executable. Their
148
149
  `report_result` calls MUST remain supported by the deprecated alias. New
149
- instructions MUST use the trailing marker and explicit executor skill contract
150
- above. A historical first-line instruction with an executor-skill invocation
151
- MUST contain exactly one invocation as its final line. A former inline-protocol
152
- instruction MUST retain non-whitespace task-specific content beyond its known
153
- lifecycle paragraphs.
150
+ instructions MUST use the explicit executor invocation followed by the final
151
+ trailing marker contract above. A historical first-line instruction with an
152
+ executor-skill invocation MUST contain exactly one invocation as its final
153
+ line. A former inline-protocol instruction MUST retain non-whitespace
154
+ task-specific content beyond its known lifecycle paragraphs.
154
155
 
155
156
  `needs_input` MUST mean a semantic user decision or missing fact. A native
156
157
  approval prompt MUST remain live Codex state and MUST NOT be stored as
package/docs/workflows.md CHANGED
@@ -107,8 +107,8 @@ Record-before-create makes native creation failure observable. Executor
107
107
  self-linking removes dispatcher-side polling, task search, title matching, and
108
108
  parent/child identity inference.
109
109
 
110
- The generated task begins with the complete assignment, then places its marker
111
- immediately before one explicit `$taskchef-executor` invocation. Older
110
+ The generated task begins with the complete assignment, then places one explicit
111
+ `$taskchef-executor` invocation immediately before its final marker. Older
112
112
  recorded tasks with first-line HTML or heading markers and former inline
113
113
  protocol remain readable; the deprecated `report_result` alias preserves their
114
114
  semantic callbacks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.11.0",
3
+ "version": "7.12.0",
4
4
  "description": "A non-blocking interactive dispatcher for visible Codex tasks.",
5
5
  "license": "MIT",
6
6
  "author": "Favo Yang",
@@ -11,17 +11,18 @@ and return immediately.
11
11
  ## Invocation boundary
12
12
 
13
13
  A task whose initial structured `codexDelegation.input` contains either the
14
- exact new trailing TaskChef marker plus final `$taskchef-executor` invocation,
15
- an exact first-line HTML marker, or the historical first-line
14
+ exact new trailing `$taskchef-executor` invocation plus final TaskChef marker,
15
+ an accepted former trailing marker-plus-invocation scaffold, an exact
16
+ first-line HTML marker, or the historical first-line
16
17
  `# taskchef_id=<full UUID>` heading already owns that delegated assignment.
17
18
  This includes former inline-protocol tasks that lack the skill invocation.
18
19
  An owned instruction must have exactly one accepted marker and a non-whitespace
19
20
  task-specific assignment. If it contains an executor-skill invocation, require
20
- exactly one as the final line. Marker-only, duplicate-marker, scaffold-only, or
21
- misplaced-invocation inputs are not valid delegated tasks. Execute a valid one
22
- in the current task. Do not re-dispatch it merely because it concerns TaskChef
23
- or a configured project. Explicit requests to delegate separate work remain
24
- valid.
21
+ exactly one adjacent to the marker in an accepted order. Marker-only,
22
+ duplicate-marker, scaffold-only, or misplaced-invocation inputs are not valid
23
+ delegated tasks. Execute a valid one in the current task. Do not re-dispatch it
24
+ merely because it concerns TaskChef or a configured project. Explicit requests
25
+ to delegate separate work remain valid.
25
26
 
26
27
  Use the bundled `prepare_dispatch`, `record_task`, and `report_state` MCP tools
27
28
  directly. Never fall back to shell writes. If a required tool is unavailable,
@@ -52,11 +53,12 @@ stop and report that the TaskChef plugin must be reloaded or installed.
52
53
 
53
54
  - Begin with the actual assignment on the first line and keep its complete
54
55
  body uninterrupted.
55
- - After the assignment's final character, add exactly one newline and the
56
- preparation's exact marker on its own line. Do not add a blank line before
57
- or after the marker.
58
- - Immediately after the marker, end the instruction with exactly:
56
+ - After the assignment's final character, add exactly one newline and this
57
+ invocation on its own line:
59
58
  `Use $taskchef-executor to execute and report this delegated TaskChef assignment.`
59
+ - Immediately after the invocation, end the instruction with one newline
60
+ and the preparation's exact marker on its own final line. Do not add blank
61
+ lines around the invocation or marker.
60
62
  - Include exactly one marker and exactly one executor-skill invocation.
61
63
  - Do not inline executor ownership, identity, linking, or result-reporting
62
64
  protocol. The explicitly invoked executor skill owns those mechanics.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: taskchef-executor
3
- description: "Execute an assignment carrying either the new exact TaskChef marker-plus-invocation scaffold or an accepted historical first-line TaskChef marker or inline protocol. Includes executor ownership, self-linking, per-turn lifecycle reporting, identity safety, and final semantic state. Use when explicitly invoked by a new delegated instruction or when resuming the same new or historical executor task. Do not use to dispatch work or report on other TaskChef tasks."
3
+ description: "Execute an assignment carrying either the new exact TaskChef invocation-plus-final-marker scaffold or an accepted historical first-line or marker-before-invocation protocol. Includes executor ownership, self-linking, per-turn lifecycle reporting, identity safety, and final semantic state. Use when explicitly invoked by a new delegated instruction or when resuming the same new or historical executor task. Do not use to dispatch work or report on other TaskChef tasks."
4
4
  ---
5
5
 
6
6
  # TaskChef Executor
@@ -10,12 +10,12 @@ re-dispatch it merely because it concerns TaskChef or a configured project.
10
10
  Explicit requests to delegate separate work remain valid.
11
11
 
12
12
  New instructions present the complete assignment first, followed by exactly one
13
- newline, the exact `<!-- taskchef_id=<full UUID> -->` marker, one newline, and
14
- the final explicit skill invocation. There is no blank line before or after the
15
- marker. Treat that UUID as the TaskChef task ID. The assignment is everything
16
- before the marker; the marker and invocation are lifecycle scaffolding, not
17
- part of the deliverable. Require exactly one marker and do not infer an ID from
18
- similar prose.
13
+ newline, the explicit skill invocation, one newline, and the exact
14
+ `<!-- taskchef_id=<full UUID> -->` marker on the final line. There are no blank
15
+ lines around the invocation or marker. Treat that UUID as the TaskChef task ID.
16
+ The assignment is everything before the invocation; the invocation and marker
17
+ are lifecycle scaffolding, not part of the deliverable. Require exactly one
18
+ marker and do not infer an ID from similar prose.
19
19
 
20
20
  ## Start every execution turn
21
21
 
@@ -77,9 +77,10 @@ Existing delegated tasks may include the former inline ownership, linking, and
77
77
  re-dispatching. Prefer `report_state` when available. If an older installed
78
78
  TaskChef exposes only `report_result`, follow its inline protocol; after an
79
79
  upgrade, the deprecated `report_result` alias remains available for exact
80
- legacy retries. Also accept historical instructions with the former blank line
81
- before a trailing marker, an exact HTML marker on the first line with or
82
- without the former blank line, or the older exact
80
+ legacy retries. Also accept historical trailing instructions that place the
81
+ marker before the invocation, with or without the former blank line before the
82
+ marker; an exact HTML marker on the first line with or without the former blank
83
+ line; or the older exact
83
84
  first-line `# taskchef_id=<full UUID>` heading. These compatibility forms do not
84
85
  change the identity or lifecycle rules above. For either first-line form, the
85
86
  assignment follows the marker. Ignore the final executor invocation and any
@@ -29,12 +29,22 @@
29
29
 
30
30
  <main>
31
31
  <section class="toolbar" aria-label="Task filters">
32
- <label>
33
- Project
34
- <select id="project-filter">
35
- <option value="">All projects</option>
36
- </select>
37
- </label>
32
+ <div class="toolbar-primary">
33
+ <label>
34
+ Project
35
+ <select id="project-filter">
36
+ <option value="">All projects</option>
37
+ </select>
38
+ </label>
39
+ <label>
40
+ Updated
41
+ <select id="date-filter">
42
+ <option value="24h">Latest 24 hours</option>
43
+ <option value="7d">Latest 7 days</option>
44
+ <option value="all" selected>All time</option>
45
+ </select>
46
+ </label>
47
+ </div>
38
48
  <fieldset class="status-filter-fieldset">
39
49
  <legend>Status</legend>
40
50
  <div id="status-filter" class="status-filter-options">
@@ -60,14 +70,6 @@
60
70
  </label>
61
71
  </div>
62
72
  </fieldset>
63
- <label>
64
- Updated
65
- <select id="date-filter">
66
- <option value="24h">Latest 24 hours</option>
67
- <option value="7d">Latest 7 days</option>
68
- <option value="all" selected>All time</option>
69
- </select>
70
- </label>
71
73
  <p id="task-count" class="task-count" aria-live="polite"></p>
72
74
  </section>
73
75
 
@@ -62,15 +62,22 @@ h3 { margin-bottom: 8px; font-size: 0.84rem; letter-spacing: 0.08em; text-transf
62
62
  main { padding-block: 28px 80px; }
63
63
 
64
64
  .toolbar {
65
- display: flex;
66
- align-items: flex-end;
67
- gap: 16px;
65
+ display: grid;
66
+ gap: 12px;
68
67
  margin-bottom: 22px;
69
68
  }
70
69
 
70
+ .toolbar-primary {
71
+ display: grid;
72
+ grid-template-columns: repeat(2, minmax(180px, 240px));
73
+ align-items: end;
74
+ gap: 16px;
75
+ }
76
+
71
77
  label { display: grid; gap: 6px; color: var(--muted); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
72
78
  select { min-width: 180px; padding: 9px 34px 9px 11px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); }
73
- .status-filter-fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
79
+ .toolbar-primary select { width: 100%; }
80
+ .status-filter-fieldset { width: 100%; min-width: 0; margin: 0; padding: 0; border: 0; }
74
81
  .status-filter-fieldset legend { margin-bottom: 6px; padding: 0; color: var(--muted); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
75
82
  .status-filter-options { display: flex; flex-wrap: wrap; gap: 6px; }
76
83
  .status-filter-option { position: relative; display: block; color: var(--text); font-size: 0.82rem; letter-spacing: 0; text-transform: none; cursor: pointer; }
@@ -79,7 +86,7 @@ select { min-width: 180px; padding: 9px 34px 9px 11px; border: 1px solid var(--b
79
86
  .status-filter-option:hover span { border-color: var(--accent); }
80
87
  .status-filter-option:has(input:checked) span { border-color: var(--accent); background: var(--accent); color: white; box-shadow: 0 1px 2px rgb(24 33 29 / 16%); }
81
88
  .status-filter-option:has(input:focus-visible) span { outline: 3px solid var(--accent); outline-offset: 3px; }
82
- .task-count { margin: 0 0 9px auto; color: var(--muted); font-size: 0.9rem; }
89
+ .task-count { justify-self: end; margin: 0; color: var(--muted); font-size: 0.9rem; }
83
90
 
84
91
  .task-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
85
92
  .task-card { padding: 20px 22px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); box-shadow: 0 1px 0 rgb(0 0 0 / 2%); }
@@ -159,10 +166,10 @@ pre { max-height: 280px; margin: 0; padding: 14px; overflow: auto; border-radius
159
166
  @media (max-width: 650px) {
160
167
  .site-header { align-items: flex-start; padding-top: 32px; }
161
168
  .title-row { align-items: flex-start; }
162
- .toolbar { align-items: stretch; flex-direction: column; }
163
- .toolbar label, .toolbar select { width: 100%; }
169
+ .toolbar-primary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
170
+ .toolbar-primary label, .toolbar-primary select { width: 100%; min-width: 0; }
164
171
  .toolbar .status-filter-option { width: auto; }
165
- .task-count { margin: 0; }
172
+ .task-count { justify-self: start; }
166
173
  .task-heading { align-items: flex-start; }
167
174
  .task-footer { align-items: flex-start; flex-direction: column; }
168
175
  .task-open { align-self: flex-start; }
@@ -171,6 +178,10 @@ pre { max-height: 280px; margin: 0; padding: 14px; overflow: auto; border-radius
171
178
  .metadata dt { padding-bottom: 0; border-bottom: 0; }
172
179
  }
173
180
 
181
+ @media (max-width: 480px) {
182
+ .toolbar-primary { grid-template-columns: minmax(0, 1fr); }
183
+ }
184
+
174
185
  @media (prefers-color-scheme: dark) {
175
186
  :root {
176
187
  color-scheme: dark;
package/src/delegation.js CHANGED
@@ -162,6 +162,16 @@ export function parseTaskChefMarker(instruction) {
162
162
  return hasHistoricalAssignment() ? id : null;
163
163
  }
164
164
  const executorSkillReferences = instruction.match(/\$taskchef-executor\b/gi) ?? [];
165
+ const isFinalMarkerScaffold = index === lines.length - 1
166
+ && index >= 2
167
+ && lines[0].trim().length > 0
168
+ && lines.at(-2) === EXECUTOR_SKILL_INVOCATION
169
+ && lines.at(-3).trim().length > 0
170
+ && hasTaskSpecificContent(lines.slice(0, index - 1))
171
+ && !lines.slice(0, index - 1).some((line) => HISTORICAL_EXECUTOR_SCAFFOLD_LINES.has(line))
172
+ && executorSkillReferences.length === 1;
173
+ if (isFinalMarkerScaffold) return id;
174
+
165
175
  const hasCompactBoundary = index >= 1
166
176
  && lines.at(index - 1).trim().length > 0;
167
177
  const hasHistoricalBlankBoundary = index >= 2
@@ -202,7 +212,7 @@ export function prepareDelegation(instruction, { taskId = randomUUID() } = {}) {
202
212
  const id = requireUuid(taskId);
203
213
  return {
204
214
  id,
205
- instruction: `${body}\n${taskChefMarker(id)}\n${EXECUTOR_SKILL_INVOCATION}`,
215
+ instruction: `${body}\n${EXECUTOR_SKILL_INVOCATION}\n${taskChefMarker(id)}`,
206
216
  };
207
217
  }
208
218