taskchef 4.0.0 → 4.1.1
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 +24 -0
- package/SPEC.md +3 -2
- package/package.json +1 -1
- package/src/cli.js +53 -16
package/README.md
CHANGED
|
@@ -253,6 +253,19 @@ taskchef project list --workspace <workspace>
|
|
|
253
253
|
taskchef project remove payments --workspace <workspace>
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
Human-readable project listings show one parent row per project. Configured
|
|
257
|
+
GitHub repositories appear beneath it as indented tree rows, with repeated kind
|
|
258
|
+
and path cells left blank. A project without a configured repository has only
|
|
259
|
+
its parent row, containing `-` in the repository column:
|
|
260
|
+
|
|
261
|
+
```text
|
|
262
|
+
NAME KIND GITHUB REPOSITORY PATH
|
|
263
|
+
notes folder - /workspace/notes
|
|
264
|
+
payments git - /workspace/payments
|
|
265
|
+
├─ repository https://github.com/example/payments-api
|
|
266
|
+
└─ repository https://github.com/example/payments-sdk
|
|
267
|
+
```
|
|
268
|
+
|
|
256
269
|
Import projects as a JSON array from a file or standard input:
|
|
257
270
|
|
|
258
271
|
```sh
|
|
@@ -296,9 +309,20 @@ Inspect the task history without querying Codex tasks:
|
|
|
296
309
|
taskchef task show t1 --workspace <workspace>
|
|
297
310
|
taskchef task list --workspace <workspace>
|
|
298
311
|
taskchef task list --project payments --workspace <workspace>
|
|
312
|
+
taskchef task list --ascending --workspace <workspace>
|
|
299
313
|
taskchef task summary --workspace <workspace>
|
|
300
314
|
```
|
|
301
315
|
|
|
316
|
+
Human-readable task listings put the scannable fields first and the durable ID
|
|
317
|
+
last. Values are kept in full and aligned in columns. Tasks are newest-first by
|
|
318
|
+
default; pass `--ascending` to list them from oldest to newest. The same order
|
|
319
|
+
applies to the `tasks` array in `--json` output.
|
|
320
|
+
|
|
321
|
+
```text
|
|
322
|
+
TITLE PROJECT CREATED ID
|
|
323
|
+
Add retry logs payments 2026-08-12T10:00:00.000Z c0f010ff-84f2-4838-a69d-0ff1f5d721d7
|
|
324
|
+
```
|
|
325
|
+
|
|
302
326
|
The complete data contract is in [SPEC.md](SPEC.md). Deferred ideas are in
|
|
303
327
|
[BACKLOG.md](BACKLOG.md).
|
|
304
328
|
|
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
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
resolveTask,
|
|
16
16
|
} from "./workspace.js";
|
|
17
17
|
|
|
18
|
+
const BLANK_TABLE_CELL = Symbol("blank table cell");
|
|
19
|
+
|
|
18
20
|
async function readStdin() {
|
|
19
21
|
let input = "";
|
|
20
22
|
process.stdin.setEncoding("utf8");
|
|
@@ -88,12 +90,51 @@ function print(value, args, human) {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
function table(headers, rows) {
|
|
93
|
+
const display = (value) => {
|
|
94
|
+
if (value === BLANK_TABLE_CELL) return "";
|
|
95
|
+
if (value === null || value === undefined || value === "") return "-";
|
|
96
|
+
return String(value);
|
|
97
|
+
};
|
|
91
98
|
const widths = headers.map((header, index) =>
|
|
92
|
-
Math.max(header.length, ...rows.map((row) =>
|
|
93
|
-
const format = (row) => row.map((value, index) =>
|
|
99
|
+
Math.max(header.length, ...rows.map((row) => display(row[index]).length)));
|
|
100
|
+
const format = (row) => row.map((value, index) => index === row.length - 1
|
|
101
|
+
? display(value)
|
|
102
|
+
: display(value).padEnd(widths[index])).join(" ").trimEnd();
|
|
94
103
|
return [format(headers), ...rows.map(format)].join("\n");
|
|
95
104
|
}
|
|
96
105
|
|
|
106
|
+
function projectRows(projects) {
|
|
107
|
+
return projects.flatMap((project) => [
|
|
108
|
+
[
|
|
109
|
+
project.name,
|
|
110
|
+
project.isGitRepository ? "git" : "folder",
|
|
111
|
+
null,
|
|
112
|
+
project.path,
|
|
113
|
+
],
|
|
114
|
+
...project.githubRepos.map((repository, index) => [
|
|
115
|
+
` ${index === project.githubRepos.length - 1 ? "└─" : "├─"} repository`,
|
|
116
|
+
BLANK_TABLE_CELL,
|
|
117
|
+
repository,
|
|
118
|
+
BLANK_TABLE_CELL,
|
|
119
|
+
]),
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function sortTasksByCreatedAt(tasks, ascending) {
|
|
124
|
+
return tasks
|
|
125
|
+
.map((task, index) => ({ task, index }))
|
|
126
|
+
.sort((left, right) => {
|
|
127
|
+
const leftCreatedAt = left.task.createdAt;
|
|
128
|
+
const rightCreatedAt = right.task.createdAt;
|
|
129
|
+
if (!leftCreatedAt && !rightCreatedAt) return left.index - right.index;
|
|
130
|
+
if (!leftCreatedAt) return 1;
|
|
131
|
+
if (!rightCreatedAt) return -1;
|
|
132
|
+
const chronological = Date.parse(leftCreatedAt) - Date.parse(rightCreatedAt);
|
|
133
|
+
return (ascending ? chronological : -chronological) || left.index - right.index;
|
|
134
|
+
})
|
|
135
|
+
.map(({ task }) => task);
|
|
136
|
+
}
|
|
137
|
+
|
|
97
138
|
async function initialize(args) {
|
|
98
139
|
validateCommandArgs(args, 2, { values: ["--workspace"], switches: ["--json"] });
|
|
99
140
|
const result = await initializeWorkspace(workspaceRoot(args));
|
|
@@ -161,13 +202,8 @@ async function projectList(args) {
|
|
|
161
202
|
validateCommandArgs(args, 2, { values: ["--workspace"], switches: ["--json"] });
|
|
162
203
|
const projects = await listProjects(workspaceRoot(args));
|
|
163
204
|
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
|
-
]),
|
|
205
|
+
["NAME", "KIND", "GITHUB REPOSITORY", "PATH"],
|
|
206
|
+
projectRows(value.projects),
|
|
171
207
|
));
|
|
172
208
|
return 0;
|
|
173
209
|
}
|
|
@@ -215,19 +251,20 @@ async function taskShow(args) {
|
|
|
215
251
|
async function taskList(args) {
|
|
216
252
|
validateCommandArgs(args, 2, {
|
|
217
253
|
values: ["--workspace", "--project"],
|
|
218
|
-
switches: ["--json"],
|
|
254
|
+
switches: ["--ascending", "--json"],
|
|
219
255
|
});
|
|
220
|
-
const
|
|
256
|
+
const filtered = await filterTasks(workspaceRoot(args), {
|
|
221
257
|
project: option(args, "--project", null),
|
|
222
258
|
});
|
|
259
|
+
const dispatches = sortTasksByCreatedAt(filtered, args.includes("--ascending"));
|
|
223
260
|
const result = { taskCount: dispatches.length, tasks: dispatches };
|
|
224
261
|
print(result, args, (value) => table(
|
|
225
|
-
["
|
|
262
|
+
["TITLE", "PROJECT", "CREATED", "ID"],
|
|
226
263
|
value.tasks.map((dispatch) => [
|
|
227
|
-
dispatch.id,
|
|
228
|
-
dispatch.createdAt,
|
|
229
|
-
dispatch.project.name,
|
|
230
264
|
dispatch.title,
|
|
265
|
+
dispatch.project?.name,
|
|
266
|
+
dispatch.createdAt,
|
|
267
|
+
dispatch.id,
|
|
231
268
|
]),
|
|
232
269
|
));
|
|
233
270
|
return 0;
|
|
@@ -257,7 +294,7 @@ Usage:
|
|
|
257
294
|
taskchef task record [--json] [--workspace <path>]
|
|
258
295
|
taskchef task resolve <task-id> --thread-id <thread-id> [--json] [--workspace <path>]
|
|
259
296
|
taskchef task show <task-id> [--json] [--workspace <path>]
|
|
260
|
-
taskchef task list [--project <name-or-path>] [--json] [--workspace <path>]
|
|
297
|
+
taskchef task list [--project <name-or-path>] [--ascending] [--json] [--workspace <path>]
|
|
261
298
|
taskchef task summary [--json] [--workspace <path>]
|
|
262
299
|
|
|
263
300
|
Task record reads JSON from standard input. Project import reads a JSON
|