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.
@@ -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.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "TaskChef Report"
3
+ short_description: "Report on dispatched Codex tasks"
4
+ default_prompt: "Use $taskchef-report to query the live state of work in the TaskChef task history once."
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
- `Skills: ${value.skills.skills.map((skill) => `${skill.name}=${skill.action}`).join(", ")}`,
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", "--force"],
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 create(args) {
176
+ async function taskRecord(args) {
192
177
  validateCommandArgs(args, 2, { values: ["--workspace"], switches: ["--json"] });
193
- const task = await createTask(workspaceRoot(args), await readJsonStdin());
194
- print(task, args, (value) => `Created ${value.id}: ${value.title} (${value.status})`);
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 show(args) {
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", "--status", "--project"],
191
+ values: ["--workspace", "--project"],
214
192
  switches: ["--json"],
215
- repeatable: ["--status"],
216
193
  });
217
- const tasks = await filterTasks(workspaceRoot(args), {
218
- statuses: options(args, "--status"),
194
+ const dispatches = await filterTasks(workspaceRoot(args), {
219
195
  project: option(args, "--project", null),
220
196
  });
221
- const projects = await listProjects(workspaceRoot(args));
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", "STATUS", "PROJECT", "TITLE"],
226
- value.tasks.map((task) => [
227
- task.id,
228
- task.status,
229
- projectNames.get(task.project) ?? path.basename(task.project),
230
- task.title,
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.statusCounts).map(([status, count]) => `${status}: ${count}`),
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> [--force] [--json] [--workspace <path>]
269
- taskchef task create [--json] [--workspace <path>]
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 [--status <status>]... [--project <name-or-path>] [--json] [--workspace <path>]
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 create and update read JSON from standard input. Project import reads a
277
- JSON array from a file, or from standard input when the source is '-' or omitted.
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] === "create") return create(args);
293
- if (args[0] === "task" && args[1] === "update" && args[2]) return update(args);
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;