taskchef 4.0.0 → 4.1.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 +1 -1
- package/README.md +22 -0
- package/SPEC.md +3 -2
- package/package.json +1 -1
- package/src/cli.js +44 -16
package/README.md
CHANGED
|
@@ -253,6 +253,17 @@ taskchef project list --workspace <workspace>
|
|
|
253
253
|
taskchef project remove payments --workspace <workspace>
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
Human-readable project listings use one row per GitHub repository. Project
|
|
257
|
+
details repeat on each row so multi-repository projects remain clear, while a
|
|
258
|
+
project without a configured repository has one row containing `-`:
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
NAME KIND GITHUB REPOSITORY PATH
|
|
262
|
+
payments git https://github.com/example/payments-api /workspace/payments
|
|
263
|
+
payments git https://github.com/example/payments-sdk /workspace/payments
|
|
264
|
+
notes folder - /workspace/notes
|
|
265
|
+
```
|
|
266
|
+
|
|
256
267
|
Import projects as a JSON array from a file or standard input:
|
|
257
268
|
|
|
258
269
|
```sh
|
|
@@ -296,9 +307,20 @@ Inspect the task history without querying Codex tasks:
|
|
|
296
307
|
taskchef task show t1 --workspace <workspace>
|
|
297
308
|
taskchef task list --workspace <workspace>
|
|
298
309
|
taskchef task list --project payments --workspace <workspace>
|
|
310
|
+
taskchef task list --ascending --workspace <workspace>
|
|
299
311
|
taskchef task summary --workspace <workspace>
|
|
300
312
|
```
|
|
301
313
|
|
|
314
|
+
Human-readable task listings put the scannable fields first and the durable ID
|
|
315
|
+
last. Values are kept in full and aligned in columns. Tasks are newest-first by
|
|
316
|
+
default; pass `--ascending` to list them from oldest to newest. The same order
|
|
317
|
+
applies to the `tasks` array in `--json` output.
|
|
318
|
+
|
|
319
|
+
```text
|
|
320
|
+
TITLE PROJECT CREATED ID
|
|
321
|
+
Add retry logs payments 2026-08-12T10:00:00.000Z c0f010ff-84f2-4838-a69d-0ff1f5d721d7
|
|
322
|
+
```
|
|
323
|
+
|
|
302
324
|
The complete data contract is in [SPEC.md](SPEC.md). Deferred ideas are in
|
|
303
325
|
[BACKLOG.md](BACKLOG.md).
|
|
304
326
|
|
package/SPEC.md
CHANGED
|
@@ -201,8 +201,9 @@ it was not recorded.
|
|
|
201
201
|
The CLI reads persisted history without contacting Codex:
|
|
202
202
|
|
|
203
203
|
- `task show <id>` returns one entry.
|
|
204
|
-
- `task list` returns entries
|
|
205
|
-
historical project name or exact path.
|
|
204
|
+
- `task list` returns entries newest-first by creation time, optionally filtered
|
|
205
|
+
by historical project name or exact path. `--ascending` returns oldest-first.
|
|
206
|
+
The selected order applies to both human rows and the JSON `tasks` array.
|
|
206
207
|
- `task summary` returns the total and per-project counts.
|
|
207
208
|
- `task resolve <id> --thread-id <thread-id>` atomically fills one nullable
|
|
208
209
|
thread ID after Codex verifies the exact structured marker match.
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -88,12 +88,44 @@ function print(value, args, human) {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function table(headers, rows) {
|
|
91
|
+
const display = (value) => value === null || value === undefined || value === ""
|
|
92
|
+
? "-"
|
|
93
|
+
: String(value);
|
|
91
94
|
const widths = headers.map((header, index) =>
|
|
92
|
-
Math.max(header.length, ...rows.map((row) =>
|
|
93
|
-
const format = (row) => row.map((value, index) =>
|
|
95
|
+
Math.max(header.length, ...rows.map((row) => display(row[index]).length)));
|
|
96
|
+
const format = (row) => row.map((value, index) => index === row.length - 1
|
|
97
|
+
? display(value)
|
|
98
|
+
: display(value).padEnd(widths[index])).join(" ");
|
|
94
99
|
return [format(headers), ...rows.map(format)].join("\n");
|
|
95
100
|
}
|
|
96
101
|
|
|
102
|
+
function projectRows(projects) {
|
|
103
|
+
return projects.flatMap((project) => {
|
|
104
|
+
const repositories = project.githubRepos.length > 0 ? project.githubRepos : [null];
|
|
105
|
+
return repositories.map((repository) => [
|
|
106
|
+
project.name,
|
|
107
|
+
project.isGitRepository ? "git" : "folder",
|
|
108
|
+
repository,
|
|
109
|
+
project.path,
|
|
110
|
+
]);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function sortTasksByCreatedAt(tasks, ascending) {
|
|
115
|
+
return tasks
|
|
116
|
+
.map((task, index) => ({ task, index }))
|
|
117
|
+
.sort((left, right) => {
|
|
118
|
+
const leftCreatedAt = left.task.createdAt;
|
|
119
|
+
const rightCreatedAt = right.task.createdAt;
|
|
120
|
+
if (!leftCreatedAt && !rightCreatedAt) return left.index - right.index;
|
|
121
|
+
if (!leftCreatedAt) return 1;
|
|
122
|
+
if (!rightCreatedAt) return -1;
|
|
123
|
+
const chronological = Date.parse(leftCreatedAt) - Date.parse(rightCreatedAt);
|
|
124
|
+
return (ascending ? chronological : -chronological) || left.index - right.index;
|
|
125
|
+
})
|
|
126
|
+
.map(({ task }) => task);
|
|
127
|
+
}
|
|
128
|
+
|
|
97
129
|
async function initialize(args) {
|
|
98
130
|
validateCommandArgs(args, 2, { values: ["--workspace"], switches: ["--json"] });
|
|
99
131
|
const result = await initializeWorkspace(workspaceRoot(args));
|
|
@@ -161,13 +193,8 @@ async function projectList(args) {
|
|
|
161
193
|
validateCommandArgs(args, 2, { values: ["--workspace"], switches: ["--json"] });
|
|
162
194
|
const projects = await listProjects(workspaceRoot(args));
|
|
163
195
|
print({ projectCount: projects.length, projects }, args, (value) => table(
|
|
164
|
-
["NAME", "KIND", "GITHUB
|
|
165
|
-
value.projects
|
|
166
|
-
project.name,
|
|
167
|
-
project.isGitRepository ? "git" : "folder",
|
|
168
|
-
project.githubRepos.join(", ") || "-",
|
|
169
|
-
project.path,
|
|
170
|
-
]),
|
|
196
|
+
["NAME", "KIND", "GITHUB REPOSITORY", "PATH"],
|
|
197
|
+
projectRows(value.projects),
|
|
171
198
|
));
|
|
172
199
|
return 0;
|
|
173
200
|
}
|
|
@@ -215,19 +242,20 @@ async function taskShow(args) {
|
|
|
215
242
|
async function taskList(args) {
|
|
216
243
|
validateCommandArgs(args, 2, {
|
|
217
244
|
values: ["--workspace", "--project"],
|
|
218
|
-
switches: ["--json"],
|
|
245
|
+
switches: ["--ascending", "--json"],
|
|
219
246
|
});
|
|
220
|
-
const
|
|
247
|
+
const filtered = await filterTasks(workspaceRoot(args), {
|
|
221
248
|
project: option(args, "--project", null),
|
|
222
249
|
});
|
|
250
|
+
const dispatches = sortTasksByCreatedAt(filtered, args.includes("--ascending"));
|
|
223
251
|
const result = { taskCount: dispatches.length, tasks: dispatches };
|
|
224
252
|
print(result, args, (value) => table(
|
|
225
|
-
["
|
|
253
|
+
["TITLE", "PROJECT", "CREATED", "ID"],
|
|
226
254
|
value.tasks.map((dispatch) => [
|
|
227
|
-
dispatch.id,
|
|
228
|
-
dispatch.createdAt,
|
|
229
|
-
dispatch.project.name,
|
|
230
255
|
dispatch.title,
|
|
256
|
+
dispatch.project?.name,
|
|
257
|
+
dispatch.createdAt,
|
|
258
|
+
dispatch.id,
|
|
231
259
|
]),
|
|
232
260
|
));
|
|
233
261
|
return 0;
|
|
@@ -257,7 +285,7 @@ Usage:
|
|
|
257
285
|
taskchef task record [--json] [--workspace <path>]
|
|
258
286
|
taskchef task resolve <task-id> --thread-id <thread-id> [--json] [--workspace <path>]
|
|
259
287
|
taskchef task show <task-id> [--json] [--workspace <path>]
|
|
260
|
-
taskchef task list [--project <name-or-path>] [--json] [--workspace <path>]
|
|
288
|
+
taskchef task list [--project <name-or-path>] [--ascending] [--json] [--workspace <path>]
|
|
261
289
|
taskchef task summary [--json] [--workspace <path>]
|
|
262
290
|
|
|
263
291
|
Task record reads JSON from standard input. Project import reads a JSON
|