taskchef 5.7.2 → 5.8.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.
- package/.codex-plugin/plugin.json +2 -2
- package/BACKLOG.md +4 -4
- package/README.md +78 -45
- package/SPEC.md +106 -89
- package/docs/delegation-design.md +158 -254
- package/hooks/hooks.json +18 -0
- package/hooks/taskchef-initial-prompt.js +17 -0
- package/index.js +6 -1
- package/package.json +2 -1
- package/skills/taskchef-bootstrap/SKILL.md +6 -3
- package/skills/taskchef-delegate/SKILL.md +49 -91
- package/skills/taskchef-report/SKILL.md +60 -27
- package/src/cli.js +8 -2
- package/src/delegation.js +109 -359
- package/src/hook.js +60 -0
- package/src/mcp.js +35 -2
- package/src/workspace-path.js +5 -1
- package/src/workspace.js +211 -14
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: taskchef-delegate
|
|
3
|
-
description: "Dispatch actionable requests through the per-user TaskChef workspace into independently openable Codex project tasks. Use automatically for actionable work received in the canonical TaskChef dispatcher workspace. From any other project, use only when the user explicitly asks to delegate or split separate work into Codex tasks; TaskChef-related subject matter alone is not delegation intent.
|
|
3
|
+
description: "Dispatch actionable requests through the per-user TaskChef workspace into independently openable Codex project tasks. Use automatically for actionable work received in the canonical TaskChef dispatcher workspace. From any other project, use only when the user explicitly asks to delegate or split separate work into Codex tasks; TaskChef-related subject matter alone is not delegation intent. Record before creation, rely on the initial TaskChef hook for provisional identity, and never wait for executor completion."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TaskChef Delegate
|
|
@@ -19,7 +19,7 @@ This does not prevent the task from using TaskChef later. Use this skill
|
|
|
19
19
|
normally when the initial assignment explicitly asks to delegate separate
|
|
20
20
|
work, or when the user later explicitly requests a new delegation.
|
|
21
21
|
|
|
22
|
-
Use the bundled TaskChef `prepare_dispatch`, `record_task`, and `
|
|
22
|
+
Use the bundled TaskChef `prepare_dispatch`, `record_task`, `resolve_task`, and `report_result`
|
|
23
23
|
tools for deterministic workspace and task-record operations. Call them
|
|
24
24
|
directly; never probe for them or fall back to shell CLI writes. If a required
|
|
25
25
|
tool is unavailable, stop and report that the TaskChef plugin must be reloaded
|
|
@@ -32,27 +32,29 @@ explicitly requested benchmark artifact.
|
|
|
32
32
|
- Keep only `AGENTS.md`, `taskchef.json`, and `tasks.jsonl` in a dispatcher
|
|
33
33
|
workspace.
|
|
34
34
|
- Use real Codex tasks, never collaboration or subagent tools.
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
- Use only TaskChef's `UserPromptSubmit` hook: it resolves initial identity and
|
|
36
|
+
provides read-only current-turn context on follow-up prompts. Never infer
|
|
37
|
+
lifecycle state from hooks.
|
|
38
|
+
- Never use schedules, daemons, polling, thread-discovery retries, or background
|
|
39
|
+
monitors.
|
|
39
40
|
- Never wait for delegated work after executor creation.
|
|
40
41
|
- Never collect transcripts or hidden reasoning.
|
|
41
42
|
|
|
42
43
|
## Dispatch
|
|
43
44
|
|
|
44
|
-
1.
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
1. Split the request into the smallest independently useful outcomes. Include
|
|
46
|
+
constraints, expected testing, and reporting in every instruction.
|
|
47
|
+
2. In parallel, list the native Codex projects once and call `prepare_dispatch`
|
|
48
|
+
exactly once for each outcome. Every preparation produces a distinct task
|
|
49
|
+
UUID and marker; never reuse either across executors. The preparation tool
|
|
50
|
+
resolves the canonical workspace, loads and validates the configured routing targets,
|
|
47
51
|
generates the lowercase full UUID task ID, and returns `preparedAt` plus the
|
|
48
52
|
exact first-line marker. Use
|
|
49
53
|
`$taskchef-bootstrap` if the workspace is missing or unhealthy.
|
|
50
|
-
The tool resolves `TASKCHEF_WORKSPACE`, then
|
|
54
|
+
The tool resolves an absolute (or `~/`-prefixed) `TASKCHEF_WORKSPACE`, then
|
|
51
55
|
`~/.agents/taskchef`; do not substitute the current project. Reject the
|
|
52
56
|
dispatcher workspace itself as a target. Never take a pre-creation thread
|
|
53
57
|
snapshot.
|
|
54
|
-
2. Split the request into the smallest independently useful outcomes. Include
|
|
55
|
-
constraints, expected testing, and reporting in every instruction.
|
|
56
58
|
3. Classify against configured `name`, every URL in the `githubRepos` list, and
|
|
57
59
|
`description`. Use `path` only as checkout identity. Managed `*-workspace`
|
|
58
60
|
projects advertise their child or sub-repositories in this list.
|
|
@@ -64,103 +66,59 @@ explicitly requested benchmark artifact.
|
|
|
64
66
|
matches. Ask instead of guessing when no project or several projects match.
|
|
65
67
|
4. Resolve the selected configured path against the already-loaded native
|
|
66
68
|
projects and require an exact match. Do not list native projects again.
|
|
67
|
-
5.
|
|
68
|
-
|
|
69
|
+
5. For each outcome, use only its corresponding task ID, preparation time, and
|
|
70
|
+
marker returned by its own preparation call.
|
|
69
71
|
Prefix the complete executor instruction with
|
|
70
72
|
exactly `<!-- taskchef_id=<full UUID> -->` as the first line, followed by a
|
|
71
|
-
blank line, this executor-role paragraph, another blank line,
|
|
72
|
-
|
|
73
|
+
blank line, this executor-role paragraph, another blank line, the result
|
|
74
|
+
paragraph below, another blank line, and the instruction body:
|
|
73
75
|
|
|
74
76
|
> This task owns the delegated assignment. Execute it in this task; do not re-dispatch it merely because it concerns TaskChef or a configured project. Explicit requests to delegate separate work remain valid.
|
|
75
77
|
|
|
78
|
+
> Before ending, call the TaskChef report_result MCP tool with completed, needs_input, or failed and a concise summary. Use needs_input only for a semantic decision or information the user must provide; a native approval prompt is live Codex state, not a TaskChef result. Do not include secrets, transcripts, or raw command output.
|
|
79
|
+
|
|
76
80
|
Preserve this
|
|
77
81
|
marked instruction for recording, and note the creation time. The exact
|
|
78
82
|
random marker is the sole correlation proof.
|
|
79
|
-
6.
|
|
83
|
+
6. Before creating each executor, call `record_task` exactly once with `id`,
|
|
84
|
+
`project`, `title`, the marked `instruction`, and `threadId: null`. This
|
|
85
|
+
closes the hook race: the entry exists before the executor can submit its
|
|
86
|
+
initial prompt.
|
|
87
|
+
7. Create one real Codex task using the exact configured project, a local
|
|
80
88
|
environment on its executor host, the marked instruction, and a short title.
|
|
81
|
-
|
|
82
|
-
`
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
tool from step 7, then resolve the durable ID with this bounded workflow:
|
|
93
|
-
|
|
94
|
-
- The supported Codex surface has no provisional-ID resolver. Do not inspect
|
|
95
|
-
the tool surface for one after creation and do not pass the provisional ID
|
|
96
|
-
to tools that require `threadId`.
|
|
97
|
-
- Take at most two post-creation `list_threads` snapshots with limit 50. The
|
|
98
|
-
nominal schedule is 10 and 30 seconds after
|
|
99
|
-
the provisional result. Treat the first checkpoint as due, not expired: if
|
|
100
|
-
nullable recording or other required work finishes after 10 seconds, take
|
|
101
|
-
the first snapshot immediately. Start the second snapshot no sooner than
|
|
102
|
-
20 seconds after the first snapshot actually started. Useful candidate
|
|
103
|
-
work counts toward that interval; when it finishes sooner, wait only the
|
|
104
|
-
remainder. Never suppress either snapshot merely because an earlier step
|
|
105
|
-
ran late, and never take a third snapshot.
|
|
106
|
-
- Filter Codex candidates by the expected host, project, creation time
|
|
107
|
-
(allow five seconds of clock skew), and worktree environment whenever
|
|
108
|
-
those fields are present. Use the title only to prioritize reads; Codex
|
|
109
|
-
may normalize it, so never exclude a candidate because its title differs.
|
|
110
|
-
- Read every remaining candidate with `read_thread`, requesting one turn and
|
|
111
|
-
no command output. Issue all independent reads together in exactly one
|
|
112
|
-
programmatic batch per snapshot. Do not probe for batching support and do
|
|
113
|
-
not fall back to serial tool-call round trips. When the required batch
|
|
114
|
-
cannot be executed, preserve the nullable record as unresolved. Inspect
|
|
115
|
-
only the
|
|
116
|
-
structured
|
|
117
|
-
`userMessage.content[].codexDelegation.input`; do not trust titles,
|
|
118
|
-
summaries, previews, plain-text echoes, or assistant output as proof.
|
|
119
|
-
- Accept a candidate only when the structured input's first line is exactly
|
|
120
|
-
the task's `<!-- taskchef_id=<full UUID> -->` marker and exactly one
|
|
121
|
-
candidate matches. Require an immediately following blank line. Reject old
|
|
122
|
-
heading-style markers, malformed comments, missing blank separators, and
|
|
123
|
-
marker-like text anywhere else. Reject any discovered thread ID equal to
|
|
124
|
-
the provisional identifier or in its `local:` namespace. Then call
|
|
125
|
-
`resolve_task` once to atomically fill the nullable field.
|
|
126
|
-
- Treat snapshot, candidate-read, wait, and task-resolution
|
|
127
|
-
failures as indeterminate. If the workflow ends with zero exact matches,
|
|
128
|
-
multiple matches, or errors, leave the already-recorded `threadId: null`,
|
|
129
|
-
clearly report the unresolved reason and provisional diagnostic ID, and
|
|
130
|
-
never guess.
|
|
131
|
-
|
|
132
|
-
9. If executor creation fails, do not record a task. If recording fails
|
|
133
|
-
after creation, still return the created task and clearly say that it is not
|
|
134
|
-
in the task log. Do not delete the executor.
|
|
135
|
-
10. Return immediately after immediate recording or the bounded ID-resolution
|
|
136
|
-
workflow. Emit the appropriate created-thread directive, but label a
|
|
137
|
-
client-thread directive as provisional when resolution failed. Treat a
|
|
138
|
-
nullable record as preserved but unresolved, not as a durable task link. Do
|
|
139
|
-
not read an executor for progress and never wait for executor work
|
|
140
|
-
completion.
|
|
89
|
+
8. If creation returns a durable `threadId`, call `resolve_task` immediately.
|
|
90
|
+
If creation returns only `clientThreadId`, `pendingWorktreeId`, or a `local:`
|
|
91
|
+
ID, retain it only for the created-thread directive. Return immediately; the
|
|
92
|
+
initial TaskChef hook will atomically fill the durable root thread ID. Never
|
|
93
|
+
list, read, wait for, or poll threads to resolve it.
|
|
94
|
+
|
|
95
|
+
9. If executor creation fails, call `report_result` for the already-recorded
|
|
96
|
+
task with `failed`, null thread/turn IDs, and a concise creation error.
|
|
97
|
+
10. Emit the appropriate created-thread directive and return immediately.
|
|
98
|
+
Treat a nullable record as preserved but not yet linked. Do not read an
|
|
99
|
+
executor for progress and never wait for executor work completion.
|
|
141
100
|
|
|
142
101
|
The bundled structured tools are the only dispatch-time path to the canonical
|
|
143
102
|
workspace. They reuse the same exact-field validation, locking, atomic writes,
|
|
144
103
|
and one-way nullable resolution as the CLI without shell parsing, stdin, or
|
|
145
|
-
per-command filesystem escalation. The package exports
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
`src/delegation.js`, for deterministic tests and hosts that can supply
|
|
149
|
-
thread-tool callbacks. The standalone Node CLI cannot call desktop thread
|
|
150
|
-
tools; perform thread discovery in Codex. Keep the CLI for bootstrap, manual
|
|
151
|
-
inspection, and recovery outside delegation.
|
|
104
|
+
per-command filesystem escalation. The package exports repository routing,
|
|
105
|
+
marker, and record-before-create orchestration helpers for deterministic tests.
|
|
106
|
+
Keep the CLI for bootstrap, manual inspection, and recovery outside delegation.
|
|
152
107
|
|
|
153
108
|
## Later resolution
|
|
154
109
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
once. Never edit `tasks.jsonl` directly.
|
|
158
|
-
|
|
110
|
+
The trusted initial hook normally resolves an unresolved task. For manual
|
|
111
|
+
recovery, require one exact structured marker match, then call `resolve_task`
|
|
112
|
+
once. Never edit `tasks.jsonl` directly. Resolution is an idempotent one-way
|
|
113
|
+
transition from `threadId: null` to one unique durable root thread ID.
|
|
159
114
|
|
|
160
|
-
##
|
|
115
|
+
## Legacy benchmark compatibility
|
|
161
116
|
|
|
162
|
-
|
|
163
|
-
|
|
117
|
+
The schema-v1 benchmark fixtures below describe the removed snapshot resolver
|
|
118
|
+
and remain only for historical-result validation. Do not use that resolver for
|
|
119
|
+
new delegation benchmarks. A future benchmark schema should measure record,
|
|
120
|
+
creation, initial-hook resolution, and result callback without polling. The
|
|
121
|
+
legacy fixture starts from
|
|
164
122
|
`<plugin-root>/assets/e2e-benchmark-example.json`. Capture one ISO start/end
|
|
165
123
|
interval for the parallel preparation/project-list operation, followed by
|
|
166
124
|
sequential non-overlapping creation, recording, and optional provisional
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: taskchef-report
|
|
3
|
-
description: "Report
|
|
3
|
+
description: "Report useful current state for Codex tasks recorded by TaskChef. Use only when the user asks for delegated-task status, outcomes, or a report. Prefer cached semantic results, filter old terminal tasks from overviews, use one cheap live metadata snapshot to override active or approval-waiting tasks, and reserve detailed reads for anomalies. Never poll or wait."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TaskChef Report
|
|
7
7
|
|
|
8
|
-
Read the canonical per-user TaskChef task
|
|
9
|
-
|
|
8
|
+
Read the canonical per-user TaskChef task snapshots and report useful current
|
|
9
|
+
state once. A stored result is cached semantic evidence, not permanent truth.
|
|
10
10
|
|
|
11
11
|
Resolve this skill directory with `realpath`. The TaskChef plugin root is two
|
|
12
12
|
parents above the skill directory. Invoke `<plugin-root>/bin/taskchef.js` for
|
|
@@ -15,7 +15,8 @@ all deterministic task-log operations.
|
|
|
15
15
|
## Report
|
|
16
16
|
|
|
17
17
|
1. Run `<plugin-root>/bin/taskchef.js workspace path --json`. The CLI resolves
|
|
18
|
-
`--workspace`, then `TASKCHEF_WORKSPACE`, then
|
|
18
|
+
`--workspace`, then an absolute (or `~/`-prefixed) `TASKCHEF_WORKSPACE`, then
|
|
19
|
+
`~/.agents/taskchef`; never
|
|
19
20
|
infer the history from the current project. Select only the tasks the user
|
|
20
21
|
asked about:
|
|
21
22
|
- For an exact task ID, run
|
|
@@ -26,28 +27,60 @@ all deterministic task-log operations.
|
|
|
26
27
|
`<plugin-root>/bin/taskchef.js task list --json`
|
|
27
28
|
once, then select matching entries. Ask the user if the match is ambiguous.
|
|
28
29
|
- Use the full list only when the user asks for an overview of the task history.
|
|
29
|
-
2.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
3.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
2. For an overview, select only attention-worthy candidates before detailed
|
|
31
|
+
reads:
|
|
32
|
+
- always include `working`, `needs_input`, null-status legacy entries, and
|
|
33
|
+
entries with a null `threadId`;
|
|
34
|
+
- include `completed` and `failed` entries updated during the last seven
|
|
35
|
+
days;
|
|
36
|
+
- omit older terminal entries by default and report the omitted count;
|
|
37
|
+
- include any omitted task whose Codex metadata appears as active or awaiting
|
|
38
|
+
native approval in the recent-thread snapshot.
|
|
39
|
+
Explicit task, title, or project requests override this age filter.
|
|
40
|
+
3. Take one recent `list_threads` metadata snapshot for the whole report. This
|
|
41
|
+
is a cheap contradiction check across many tasks, not one call per task.
|
|
42
|
+
Match only exact durable `threadId` values. A metadata status that is active
|
|
43
|
+
or awaiting native approval immediately overrides a cached result without a
|
|
44
|
+
detailed read. Native approval is live Codex state, not a `needs_input`
|
|
45
|
+
callback. An inactive status never proves semantic completion; it only
|
|
46
|
+
permits a trustworthy cached MCP result to stand.
|
|
47
|
+
4. Treat `updatedBy: mcp`, `status: failed`, and null thread/turn IDs as a fresh
|
|
48
|
+
executor-creation failure. No live read is possible or needed; report the
|
|
49
|
+
stored failure summary, not unresolved. Otherwise, only a snapshot with
|
|
50
|
+
`updatedBy: mcp` is a cached semantic result. A
|
|
51
|
+
dispatcher- or hook-written `working` snapshot has no semantic callback and
|
|
52
|
+
requires one live task query when selected; if the task is inactive and no
|
|
53
|
+
callback exists, report the outcome as unknown rather than treating
|
|
54
|
+
`working` as fresh. When identity is certain and metadata says the thread is
|
|
55
|
+
inactive, trust the latest MCP result by default in a broad overview. Do not
|
|
56
|
+
read every idle terminal task in an overview merely because native
|
|
57
|
+
`updatedAt` is later: callbacks normally run before Codex finalizes the same
|
|
58
|
+
turn, and overview performance matters more than investigating every rare
|
|
59
|
+
missed callback.
|
|
60
|
+
|
|
61
|
+
For a focused task, title, or project report, perform at most one detailed
|
|
62
|
+
read for each selected inactive task when matched metadata `updatedAt` is
|
|
63
|
+
later than the cached result `updatedAt`, by any amount. Read once as well
|
|
64
|
+
when there is no semantic callback, identity or metadata is uncertain or
|
|
65
|
+
contradictory, or the user explicitly requests a fully live result. If
|
|
66
|
+
focused metadata is not newer, trust the cache. Absence from the bounded
|
|
67
|
+
recent snapshot is not by itself a reason to read every cached terminal
|
|
68
|
+
overview entry. Batch immediate native reads with no more than eight targets
|
|
69
|
+
per call. When a detailed read occurs, compare the latest structured turn ID
|
|
70
|
+
and native turn state with stored `turnId`: a newer turn without a callback
|
|
71
|
+
makes the cache stale, while an interrupted or cancelled callback turn
|
|
72
|
+
cannot prove completion. Never classify assistant prose.
|
|
73
|
+
5. Report each task as one of: working, needs input, awaiting native approval,
|
|
74
|
+
completed, failed, unresolved, or unknown. Show the cached summary when it
|
|
75
|
+
remains fresh. If a newer turn exists without a callback, describe the live
|
|
76
|
+
state and label the cached result stale rather than overwriting it.
|
|
77
|
+
6. Never edit `tasks.jsonl` directly during reporting. The initial hook normally
|
|
78
|
+
resolves null identity; manual recovery may call `task resolve` only after
|
|
79
|
+
one exact structured marker match. Never persist inferred status,
|
|
80
|
+
transcripts, prose classifications, or hidden reasoning. Do not poll or wait.
|
|
49
81
|
|
|
50
82
|
If the task history is empty, say that TaskChef has not recorded any tasks. If
|
|
51
|
-
a task has no durable thread ID
|
|
52
|
-
remains available for
|
|
53
|
-
|
|
83
|
+
a task has no durable thread ID and is not a stored creation failure, identify
|
|
84
|
+
it by task ID and say that its marker remains available for recovery. If live
|
|
85
|
+
metadata or a targeted read fails, use the cached result with an explicit
|
|
86
|
+
freshness warning and continue.
|
package/src/cli.js
CHANGED
|
@@ -169,10 +169,15 @@ function taskDetails(task) {
|
|
|
169
169
|
return [
|
|
170
170
|
`Title: ${singleLineDetail(task.title)}`,
|
|
171
171
|
`Project: ${singleLineDetail(task.project.name)}`,
|
|
172
|
+
`Status: ${singleLineDetail(task.status ?? "unknown")}`,
|
|
173
|
+
`Summary: ${singleLineDetail(task.summary ?? "-")}`,
|
|
172
174
|
`Project path: ${singleLineDetail(task.project.path)}`,
|
|
173
175
|
`Created: ${singleLineDetail(task.createdAt)}`,
|
|
176
|
+
`Updated: ${singleLineDetail(task.updatedAt ?? "-")}`,
|
|
177
|
+
`Updated by: ${singleLineDetail(task.updatedBy ?? "-")}`,
|
|
174
178
|
`Task ID: ${singleLineDetail(task.id)}`,
|
|
175
179
|
`Thread ID: ${singleLineDetail(task.threadId ?? "-")}`,
|
|
180
|
+
`Turn ID: ${singleLineDetail(task.turnId ?? "-")}`,
|
|
176
181
|
"Instruction:",
|
|
177
182
|
task.instruction,
|
|
178
183
|
].join("\n");
|
|
@@ -381,11 +386,12 @@ async function taskList(args) {
|
|
|
381
386
|
const result = { taskCount: dispatches.length, tasks: dispatches };
|
|
382
387
|
const fullId = args.includes("--full-id");
|
|
383
388
|
print(result, args, (value) => table(
|
|
384
|
-
["TITLE", "PROJECT", "
|
|
389
|
+
["TITLE", "PROJECT", "STATUS", "UPDATED", "ID", "THREAD ID"],
|
|
385
390
|
value.tasks.map((dispatch) => [
|
|
386
391
|
dispatch.title,
|
|
387
392
|
dispatch.project?.name,
|
|
388
|
-
dispatch.
|
|
393
|
+
dispatch.status ?? "unknown",
|
|
394
|
+
dispatch.updatedAt ?? dispatch.createdAt,
|
|
389
395
|
displayId(dispatch.id, fullId),
|
|
390
396
|
displayId(dispatch.threadId, fullId),
|
|
391
397
|
]),
|