taskchef 1.0.2 → 3.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.
- package/.codex-plugin/plugin.json +37 -0
- package/BACKLOG.md +35 -82
- package/README.md +220 -89
- package/SPEC.md +114 -247
- package/assets/taskchef-dispatcher-instructions.md +4 -3
- package/index.js +2 -5
- package/package.json +10 -2
- package/skills/taskchef-bootstrap/SKILL.md +13 -12
- package/skills/taskchef-delegate/SKILL.md +18 -20
- package/skills/taskchef-report/SKILL.md +38 -0
- package/skills/taskchef-report/agents/openai.yaml +4 -0
- package/src/cli.js +27 -71
- package/src/workspace.js +380 -290
- package/skills/taskchef-reconcile/SKILL.md +0 -35
- package/skills/taskchef-reconcile/agents/openai.yaml +0 -4
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: taskchef-report
|
|
3
|
+
description: "Report the live state of Codex tasks recorded in a TaskChef task history. Use only when the user asks for status, outcomes, or a report about delegated work. Queries each relevant task once, never polls or waits, and never persists status or results."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# TaskChef Report
|
|
7
|
+
|
|
8
|
+
Read the TaskChef task history and report the current state of its Codex
|
|
9
|
+
tasks once.
|
|
10
|
+
|
|
11
|
+
Resolve this skill directory with `realpath`. The TaskChef plugin root is two
|
|
12
|
+
parents above the skill directory. Invoke `<plugin-root>/bin/taskchef.js` for
|
|
13
|
+
all deterministic task-log operations.
|
|
14
|
+
|
|
15
|
+
## Report
|
|
16
|
+
|
|
17
|
+
1. Select only the tasks the user asked about:
|
|
18
|
+
- For an exact task ID, run
|
|
19
|
+
`<plugin-root>/bin/taskchef.js task show <task-id> --json --workspace <workspace>`.
|
|
20
|
+
- For a project, run
|
|
21
|
+
`<plugin-root>/bin/taskchef.js task list --project <name-or-path> --json --workspace <workspace>`.
|
|
22
|
+
- For a title or other description, run
|
|
23
|
+
`<plugin-root>/bin/taskchef.js task list --json --workspace <workspace>`
|
|
24
|
+
once, then select matching entries. Ask the user if the match is ambiguous.
|
|
25
|
+
- Use the full list only when the user asks for an overview of the task history.
|
|
26
|
+
2. Query every selected thread exactly once using immediate native snapshots,
|
|
27
|
+
with no more than eight targets per call.
|
|
28
|
+
3. Summarize the live state and any reported outcome for each requested task.
|
|
29
|
+
Distinguish active work, requests for user input, completed work, and failed
|
|
30
|
+
or partial attempts.
|
|
31
|
+
4. Treat each Codex task as the source of truth. The task log proves that
|
|
32
|
+
TaskChef created the task, but it does not contain the task's current state.
|
|
33
|
+
5. Never update `tasks.jsonl`. Never persist status, results, transcripts,
|
|
34
|
+
or hidden reasoning. Do not poll or wait for future activity.
|
|
35
|
+
|
|
36
|
+
If the task history is empty, say that TaskChef has not recorded any tasks. If
|
|
37
|
+
a recorded task cannot be read, identify it by task ID and thread ID, then
|
|
38
|
+
continue with the remaining entries.
|
package/src/cli.js
CHANGED
|
@@ -3,17 +3,15 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
addProject,
|
|
6
|
-
buildReconciliationCandidates,
|
|
7
6
|
buildTaskSummary,
|
|
8
|
-
createTask,
|
|
9
7
|
doctorWorkspace,
|
|
10
8
|
filterTasks,
|
|
11
9
|
importProjects,
|
|
12
10
|
initializeWorkspace,
|
|
13
11
|
listProjects,
|
|
14
12
|
readTask,
|
|
13
|
+
recordTask,
|
|
15
14
|
removeProject,
|
|
16
|
-
updateTask,
|
|
17
15
|
} from "./workspace.js";
|
|
18
16
|
|
|
19
17
|
async function readStdin() {
|
|
@@ -38,19 +36,6 @@ function option(args, name, fallback) {
|
|
|
38
36
|
return args[index + 1];
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
function options(args, name) {
|
|
42
|
-
const values = [];
|
|
43
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
44
|
-
if (args[index] !== name) continue;
|
|
45
|
-
if (!args[index + 1] || args[index + 1].startsWith("--")) {
|
|
46
|
-
throw new Error(`${name} requires a value`);
|
|
47
|
-
}
|
|
48
|
-
values.push(args[index + 1]);
|
|
49
|
-
index += 1;
|
|
50
|
-
}
|
|
51
|
-
return values;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
39
|
function validateCommandArgs(
|
|
55
40
|
args,
|
|
56
41
|
startIndex,
|
|
@@ -106,8 +91,10 @@ async function initialize(args) {
|
|
|
106
91
|
print(result, args, (value) => [
|
|
107
92
|
`Workspace: ${value.workspace}`,
|
|
108
93
|
`Configuration: ${value.config.action}`,
|
|
94
|
+
`Task log: ${value.tasks.action}`,
|
|
95
|
+
`Legacy tasks: ${value.legacyTasks.action}`,
|
|
109
96
|
`Instructions: ${value.instructions.action}`,
|
|
110
|
-
`
|
|
97
|
+
`Legacy skill links removed: ${value.legacySkills.removed.length}`,
|
|
111
98
|
].join("\n"));
|
|
112
99
|
return 0;
|
|
113
100
|
}
|
|
@@ -179,30 +166,21 @@ async function projectRemove(args) {
|
|
|
179
166
|
if (!args[2] || args[2].startsWith("--")) throw new Error("project remove requires a name");
|
|
180
167
|
validateCommandArgs(args, 3, {
|
|
181
168
|
values: ["--workspace"],
|
|
182
|
-
switches: ["--json"
|
|
183
|
-
});
|
|
184
|
-
const result = await removeProject(workspaceRoot(args), args[2], {
|
|
185
|
-
force: args.includes("--force"),
|
|
169
|
+
switches: ["--json"],
|
|
186
170
|
});
|
|
171
|
+
const result = await removeProject(workspaceRoot(args), args[2]);
|
|
187
172
|
print(result, args, (value) => `Removed ${value.project.name}: ${value.project.path}`);
|
|
188
173
|
return 0;
|
|
189
174
|
}
|
|
190
175
|
|
|
191
|
-
async function
|
|
176
|
+
async function taskRecord(args) {
|
|
192
177
|
validateCommandArgs(args, 2, { values: ["--workspace"], switches: ["--json"] });
|
|
193
|
-
const
|
|
194
|
-
print(
|
|
195
|
-
return 0;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async function update(args) {
|
|
199
|
-
validateCommandArgs(args, 3, { values: ["--workspace"], switches: ["--json"] });
|
|
200
|
-
const task = await updateTask(workspaceRoot(args), args[2], await readJsonStdin());
|
|
201
|
-
print(task, args, (value) => `Updated ${value.id}: ${value.status}`);
|
|
178
|
+
const dispatch = await recordTask(workspaceRoot(args), await readJsonStdin());
|
|
179
|
+
print(dispatch, args, (value) => `Recorded ${value.id}: ${value.title}`);
|
|
202
180
|
return 0;
|
|
203
181
|
}
|
|
204
182
|
|
|
205
|
-
async function
|
|
183
|
+
async function taskShow(args) {
|
|
206
184
|
validateCommandArgs(args, 3, { values: ["--workspace"], switches: ["--json"] });
|
|
207
185
|
print(await readTask(workspaceRoot(args), args[2]), args);
|
|
208
186
|
return 0;
|
|
@@ -210,24 +188,20 @@ async function show(args) {
|
|
|
210
188
|
|
|
211
189
|
async function taskList(args) {
|
|
212
190
|
validateCommandArgs(args, 2, {
|
|
213
|
-
values: ["--workspace", "--
|
|
191
|
+
values: ["--workspace", "--project"],
|
|
214
192
|
switches: ["--json"],
|
|
215
|
-
repeatable: ["--status"],
|
|
216
193
|
});
|
|
217
|
-
const
|
|
218
|
-
statuses: options(args, "--status"),
|
|
194
|
+
const dispatches = await filterTasks(workspaceRoot(args), {
|
|
219
195
|
project: option(args, "--project", null),
|
|
220
196
|
});
|
|
221
|
-
const
|
|
222
|
-
const projectNames = new Map(projects.map((project) => [project.path, project.name]));
|
|
223
|
-
const result = { taskCount: tasks.length, tasks };
|
|
197
|
+
const result = { taskCount: dispatches.length, tasks: dispatches };
|
|
224
198
|
print(result, args, (value) => table(
|
|
225
|
-
["ID", "
|
|
226
|
-
value.tasks.map((
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
199
|
+
["ID", "CREATED", "PROJECT", "TITLE"],
|
|
200
|
+
value.tasks.map((dispatch) => [
|
|
201
|
+
dispatch.id,
|
|
202
|
+
dispatch.createdAt,
|
|
203
|
+
dispatch.project.name,
|
|
204
|
+
dispatch.title,
|
|
231
205
|
]),
|
|
232
206
|
));
|
|
233
207
|
return 0;
|
|
@@ -238,23 +212,11 @@ async function taskSummary(args) {
|
|
|
238
212
|
const summary = await buildTaskSummary(workspaceRoot(args));
|
|
239
213
|
print(summary, args, (value) => [
|
|
240
214
|
`Tasks: ${value.taskCount}`,
|
|
241
|
-
...Object.entries(value.
|
|
215
|
+
...Object.entries(value.projectCounts).map(([project, count]) => `${project}: ${count}`),
|
|
242
216
|
].join("\n"));
|
|
243
217
|
return 0;
|
|
244
218
|
}
|
|
245
219
|
|
|
246
|
-
async function reconciliationCandidates(args) {
|
|
247
|
-
validateCommandArgs(args, 2, {
|
|
248
|
-
values: ["--workspace"],
|
|
249
|
-
switches: ["--json", "--include-finished"],
|
|
250
|
-
});
|
|
251
|
-
const result = await buildReconciliationCandidates(workspaceRoot(args), {
|
|
252
|
-
includeFinished: args.includes("--include-finished"),
|
|
253
|
-
});
|
|
254
|
-
print(result, args);
|
|
255
|
-
return 0;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
220
|
function usage() {
|
|
259
221
|
process.stdout.write(`TaskChef workspace utility
|
|
260
222
|
|
|
@@ -265,16 +227,14 @@ Usage:
|
|
|
265
227
|
taskchef project add <path> [--name <name>] [--description <text>] [--github-repo <url> | --no-github] [--json] [--workspace <path>]
|
|
266
228
|
taskchef project import [<file> | -] [--replace] [--json] [--workspace <path>]
|
|
267
229
|
taskchef project list [--json] [--workspace <path>]
|
|
268
|
-
taskchef project remove <name> [--
|
|
269
|
-
taskchef task
|
|
270
|
-
taskchef task update <task-id> [--json] [--workspace <path>]
|
|
230
|
+
taskchef project remove <name> [--json] [--workspace <path>]
|
|
231
|
+
taskchef task record [--json] [--workspace <path>]
|
|
271
232
|
taskchef task show <task-id> [--json] [--workspace <path>]
|
|
272
|
-
taskchef task list [--
|
|
233
|
+
taskchef task list [--project <name-or-path>] [--json] [--workspace <path>]
|
|
273
234
|
taskchef task summary [--json] [--workspace <path>]
|
|
274
|
-
taskchef task reconcile-candidates [--include-finished] [--json] [--workspace <path>]
|
|
275
235
|
|
|
276
|
-
Task
|
|
277
|
-
|
|
236
|
+
Task record reads JSON from standard input. Project import reads a JSON
|
|
237
|
+
array from a file, or from standard input when the source is '-' or omitted.
|
|
278
238
|
`);
|
|
279
239
|
}
|
|
280
240
|
|
|
@@ -289,14 +249,10 @@ export async function runCli(args) {
|
|
|
289
249
|
if (args[0] === "project" && args[1] === "import") return projectImport(args);
|
|
290
250
|
if (args[0] === "project" && args[1] === "list") return projectList(args);
|
|
291
251
|
if (args[0] === "project" && args[1] === "remove") return projectRemove(args);
|
|
292
|
-
if (args[0] === "task" && args[1] === "
|
|
293
|
-
if (args[0] === "task" && args[1] === "
|
|
294
|
-
if (args[0] === "task" && args[1] === "show" && args[2]) return show(args);
|
|
252
|
+
if (args[0] === "task" && args[1] === "record") return taskRecord(args);
|
|
253
|
+
if (args[0] === "task" && args[1] === "show" && args[2]) return taskShow(args);
|
|
295
254
|
if (args[0] === "task" && args[1] === "list") return taskList(args);
|
|
296
255
|
if (args[0] === "task" && args[1] === "summary") return taskSummary(args);
|
|
297
|
-
if (args[0] === "task" && args[1] === "reconcile-candidates") {
|
|
298
|
-
return reconciliationCandidates(args);
|
|
299
|
-
}
|
|
300
256
|
process.stderr.write(`Unknown command: ${args.join(" ")}\n`);
|
|
301
257
|
usage();
|
|
302
258
|
return 2;
|