taskchef 3.0.1 → 3.0.3
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/BACKLOG.md +15 -0
- package/README.md +28 -7
- package/SPEC.md +79 -33
- package/index.js +18 -0
- package/node_modules/graceful-fs/LICENSE +15 -0
- package/node_modules/graceful-fs/README.md +143 -0
- package/node_modules/graceful-fs/clone.js +23 -0
- package/node_modules/graceful-fs/graceful-fs.js +448 -0
- package/node_modules/graceful-fs/legacy-streams.js +118 -0
- package/node_modules/graceful-fs/package.json +53 -0
- package/node_modules/graceful-fs/polyfills.js +355 -0
- package/node_modules/proper-lockfile/CHANGELOG.md +108 -0
- package/node_modules/proper-lockfile/LICENSE +21 -0
- package/node_modules/proper-lockfile/README.md +183 -0
- package/node_modules/proper-lockfile/index.js +40 -0
- package/node_modules/proper-lockfile/lib/adapter.js +85 -0
- package/node_modules/proper-lockfile/lib/lockfile.js +342 -0
- package/node_modules/proper-lockfile/lib/mtime-precision.js +55 -0
- package/node_modules/proper-lockfile/package.json +71 -0
- package/node_modules/retry/.npmignore +3 -0
- package/node_modules/retry/.travis.yml +15 -0
- package/node_modules/retry/License +21 -0
- package/node_modules/retry/Makefile +18 -0
- package/node_modules/retry/README.md +227 -0
- package/node_modules/retry/equation.gif +0 -0
- package/node_modules/retry/example/dns.js +31 -0
- package/node_modules/retry/example/stop.js +40 -0
- package/node_modules/retry/index.js +1 -0
- package/node_modules/retry/lib/retry.js +100 -0
- package/node_modules/retry/lib/retry_operation.js +158 -0
- package/node_modules/retry/package.json +32 -0
- package/node_modules/retry/test/common.js +10 -0
- package/node_modules/retry/test/integration/test-forever.js +24 -0
- package/node_modules/retry/test/integration/test-retry-operation.js +258 -0
- package/node_modules/retry/test/integration/test-retry-wrap.js +101 -0
- package/node_modules/retry/test/integration/test-timeouts.js +69 -0
- package/node_modules/signal-exit/LICENSE.txt +16 -0
- package/node_modules/signal-exit/README.md +39 -0
- package/node_modules/signal-exit/index.js +202 -0
- package/node_modules/signal-exit/package.json +38 -0
- package/node_modules/signal-exit/signals.js +53 -0
- package/package.json +5 -2
- package/skills/taskchef-bootstrap/SKILL.md +2 -3
- package/skills/taskchef-delegate/SKILL.md +75 -11
- package/skills/taskchef-report/SKILL.md +20 -10
- package/src/cli.js +19 -1
- package/src/delegation.js +555 -0
- package/src/workspace.js +53 -172
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "signal-exit",
|
|
3
|
+
"version": "3.0.7",
|
|
4
|
+
"description": "when you want to fire an event no matter how a process exits.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "tap",
|
|
8
|
+
"snap": "tap",
|
|
9
|
+
"preversion": "npm test",
|
|
10
|
+
"postversion": "npm publish",
|
|
11
|
+
"prepublishOnly": "git push origin --follow-tags"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"index.js",
|
|
15
|
+
"signals.js"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/tapjs/signal-exit.git"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"signal",
|
|
23
|
+
"exit"
|
|
24
|
+
],
|
|
25
|
+
"author": "Ben Coe <ben@npmjs.com>",
|
|
26
|
+
"license": "ISC",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/tapjs/signal-exit/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/tapjs/signal-exit",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"chai": "^3.5.0",
|
|
33
|
+
"coveralls": "^3.1.1",
|
|
34
|
+
"nyc": "^15.1.0",
|
|
35
|
+
"standard-version": "^9.3.1",
|
|
36
|
+
"tap": "^15.1.1"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// This is not the set of all possible signals.
|
|
2
|
+
//
|
|
3
|
+
// It IS, however, the set of all signals that trigger
|
|
4
|
+
// an exit on either Linux or BSD systems. Linux is a
|
|
5
|
+
// superset of the signal names supported on BSD, and
|
|
6
|
+
// the unknown signals just fail to register, so we can
|
|
7
|
+
// catch that easily enough.
|
|
8
|
+
//
|
|
9
|
+
// Don't bother with SIGKILL. It's uncatchable, which
|
|
10
|
+
// means that we can't fire any callbacks anyway.
|
|
11
|
+
//
|
|
12
|
+
// If a user does happen to register a handler on a non-
|
|
13
|
+
// fatal signal like SIGWINCH or something, and then
|
|
14
|
+
// exit, it'll end up firing `process.emit('exit')`, so
|
|
15
|
+
// the handler will be fired anyway.
|
|
16
|
+
//
|
|
17
|
+
// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
|
|
18
|
+
// artificially, inherently leave the process in a
|
|
19
|
+
// state from which it is not safe to try and enter JS
|
|
20
|
+
// listeners.
|
|
21
|
+
module.exports = [
|
|
22
|
+
'SIGABRT',
|
|
23
|
+
'SIGALRM',
|
|
24
|
+
'SIGHUP',
|
|
25
|
+
'SIGINT',
|
|
26
|
+
'SIGTERM'
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
if (process.platform !== 'win32') {
|
|
30
|
+
module.exports.push(
|
|
31
|
+
'SIGVTALRM',
|
|
32
|
+
'SIGXCPU',
|
|
33
|
+
'SIGXFSZ',
|
|
34
|
+
'SIGUSR2',
|
|
35
|
+
'SIGTRAP',
|
|
36
|
+
'SIGSYS',
|
|
37
|
+
'SIGQUIT',
|
|
38
|
+
'SIGIOT'
|
|
39
|
+
// should detect profiler and enable/disable accordingly.
|
|
40
|
+
// see #21
|
|
41
|
+
// 'SIGPROF'
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (process.platform === 'linux') {
|
|
46
|
+
module.exports.push(
|
|
47
|
+
'SIGIO',
|
|
48
|
+
'SIGPOLL',
|
|
49
|
+
'SIGPWR',
|
|
50
|
+
'SIGSTKFLT',
|
|
51
|
+
'SIGUNUSED'
|
|
52
|
+
)
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taskchef",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "A non-blocking interactive dispatcher for visible Codex tasks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Favo Yang",
|
|
@@ -41,5 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"proper-lockfile": "^4.1.2"
|
|
44
|
-
}
|
|
44
|
+
},
|
|
45
|
+
"bundleDependencies": [
|
|
46
|
+
"proper-lockfile"
|
|
47
|
+
]
|
|
45
48
|
}
|
|
@@ -24,9 +24,8 @@ all deterministic workspace operations.
|
|
|
24
24
|
|
|
25
25
|
1. Run `workspace init --json`. It takes no stdin, creates an empty
|
|
26
26
|
configuration when missing, creates the append-only task log, refreshes
|
|
27
|
-
managed instructions, and
|
|
28
|
-
|
|
29
|
-
the dispatcher workspace.
|
|
27
|
+
managed instructions, and removes legacy TaskChef skill links. The installed
|
|
28
|
+
plugin provides all three TaskChef skills outside the dispatcher workspace.
|
|
30
29
|
2. Run `doctor --json` after setup or when the user asks to diagnose the
|
|
31
30
|
workspace. Doctor is read-only. Rerun `workspace init --json` to repair the
|
|
32
31
|
managed scaffold.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: taskchef-delegate
|
|
3
|
-
description: "Dispatch actionable requests from an initialized TaskChef workspace into independently openable Codex project tasks. Use for ordinary work requests in a TaskChef workspace, explicit delegation, or splitting independent work across projects.
|
|
3
|
+
description: "Dispatch actionable requests from an initialized TaskChef workspace into independently openable Codex project tasks. Use for ordinary work requests in a TaskChef workspace, explicit delegation, or splitting independent work across projects. Preserve unresolved delegations for later marker-based recovery, and never use subagents, hooks, schedules, daemons, or executor-completion waiting."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TaskChef Delegate
|
|
@@ -17,7 +17,10 @@ for all deterministic workspace and task-record operations.
|
|
|
17
17
|
- Keep only `AGENTS.md`, `taskchef.json`, and `tasks.jsonl` in a dispatcher
|
|
18
18
|
workspace.
|
|
19
19
|
- Use real Codex tasks, never collaboration or subagent tools.
|
|
20
|
-
- Never use hooks, callbacks, schedules, polling, or
|
|
20
|
+
- Never use hooks, callbacks, schedules, daemons, indefinite polling, or
|
|
21
|
+
background monitors.
|
|
22
|
+
- Use only bounded provisional-ID resolution after `create_thread` returns a
|
|
23
|
+
provisional client ID. Prefer a native Codex wait or resolver when available.
|
|
21
24
|
- Never wait for delegated work after executor creation.
|
|
22
25
|
- Never collect transcripts or hidden reasoning.
|
|
23
26
|
|
|
@@ -33,16 +36,77 @@ for all deterministic workspace and task-record operations.
|
|
|
33
36
|
`path` only as checkout identity. Ask when metadata does not produce one
|
|
34
37
|
clear project match.
|
|
35
38
|
4. Resolve native projects once and require the exact configured path.
|
|
36
|
-
5.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
5. Generate a lowercase full UUID task ID before creation. Prefix the complete
|
|
40
|
+
executor instruction with exactly `# taskchef_id=<full UUID>`, followed by a
|
|
41
|
+
blank line and the instruction body. Preserve this marked instruction for
|
|
42
|
+
recording, and note the creation time. Do not take a pre-creation thread
|
|
43
|
+
snapshot; the exact random marker is the correlation key.
|
|
44
|
+
6. Create one real Codex task using the exact configured project, a local
|
|
45
|
+
environment on its executor host, the marked instruction, and a short title.
|
|
46
|
+
7. When `create_thread` returns a durable `threadId`, immediately run
|
|
40
47
|
`<plugin-root>/bin/taskchef.js task record --json --workspace <workspace>`.
|
|
41
48
|
Send exactly `id`, `project`, `title`, `instruction`, and `threadId` as JSON
|
|
42
|
-
on stdin. Use the configured project path for `project
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
on stdin. Use the configured project path for `project`, and send the marked
|
|
50
|
+
instruction unchanged. Never persist a provisional `clientThreadId` or
|
|
51
|
+
`pendingWorktreeId` as `threadId`. Never persist `hostId`, status, results,
|
|
52
|
+
transcripts, or hidden reasoning.
|
|
53
|
+
8. When creation returns only `clientThreadId` or `pendingWorktreeId`, keep it
|
|
54
|
+
only for the created-thread directive and diagnostic reporting. It is not a
|
|
55
|
+
durable ID and cannot be passed to thread tools or converted directly.
|
|
56
|
+
Immediately record the marked instruction with `threadId: null` using the
|
|
57
|
+
command from step 7, then resolve the durable ID with this bounded workflow:
|
|
58
|
+
|
|
59
|
+
- If the current Codex tool surface provides a dedicated operation that
|
|
60
|
+
accepts the provisional ID and waits for or resolves its durable thread
|
|
61
|
+
ID, call it exactly once with a timeout of at most 30 seconds. Do not invent
|
|
62
|
+
an operation or pass the provisional ID to tools that require `threadId`.
|
|
63
|
+
- When no native operation is available, take at most two `list_threads`
|
|
64
|
+
snapshots with limit 50, near 10 and 30 seconds after the provisional
|
|
65
|
+
result. Count tool latency against the 30-second deadline. Do not start a
|
|
66
|
+
snapshot, candidate read, marker verification, or task-resolution write
|
|
67
|
+
after it.
|
|
68
|
+
- Filter Codex candidates by the expected host, project, creation time
|
|
69
|
+
(allow five seconds of clock skew), and worktree environment whenever
|
|
70
|
+
those fields are present. Use the title only to prioritize reads; Codex
|
|
71
|
+
may normalize it, so never exclude a candidate because its title differs.
|
|
72
|
+
- Read every remaining candidate with `read_thread`, requesting one turn and
|
|
73
|
+
no command output. Read candidates concurrently when the tool surface
|
|
74
|
+
permits. Inspect only the structured
|
|
75
|
+
`userMessage.content[].codexDelegation.input`; do not trust titles,
|
|
76
|
+
summaries, previews, plain-text echoes, or assistant output as proof.
|
|
77
|
+
- Accept a candidate only when the structured input's first line is exactly
|
|
78
|
+
the task's `# taskchef_id=<full UUID>` marker and exactly one candidate
|
|
79
|
+
matches. Apply the same marker verification to a thread ID returned by a
|
|
80
|
+
native resolver. Reject any returned or discovered thread ID equal to the
|
|
81
|
+
provisional identifier or in its `local:` namespace. Then use
|
|
82
|
+
the task-resolution command under **Later resolution** to atomically fill
|
|
83
|
+
the nullable field.
|
|
84
|
+
- Treat native-resolution, snapshot, candidate-read, wait, and task-resolution
|
|
85
|
+
failures as indeterminate. If the workflow ends with zero exact matches,
|
|
86
|
+
multiple matches, or errors, leave the already-recorded `threadId: null`,
|
|
87
|
+
clearly report the unresolved reason and provisional diagnostic ID, and
|
|
88
|
+
never guess.
|
|
89
|
+
|
|
90
|
+
9. If executor creation fails, do not record a task. If recording fails
|
|
45
91
|
after creation, still return the created task and clearly say that it is not
|
|
46
92
|
in the task log. Do not delete the executor.
|
|
47
|
-
|
|
48
|
-
|
|
93
|
+
10. Return immediately after immediate recording or the bounded ID-resolution
|
|
94
|
+
workflow. Emit the appropriate created-thread directive, but label a
|
|
95
|
+
client-thread directive as provisional when resolution failed. Treat a
|
|
96
|
+
nullable record as preserved but unresolved, not as a durable task link. Do
|
|
97
|
+
not read an executor for progress and never wait for executor work
|
|
98
|
+
completion.
|
|
99
|
+
|
|
100
|
+
The package exports pure marker, candidate-filtering, and injected-adapter
|
|
101
|
+
orchestration helpers from `src/delegation.js` for deterministic tests and
|
|
102
|
+
hosts that can supply thread-tool callbacks. The standalone Node CLI cannot
|
|
103
|
+
call desktop thread tools; perform the tool calls in Codex and use the CLI only
|
|
104
|
+
for validated workspace data operations.
|
|
105
|
+
|
|
106
|
+
## Later resolution
|
|
107
|
+
|
|
108
|
+
When a later Codex workflow finds exactly one durable thread whose structured
|
|
109
|
+
delegated input contains an unresolved task's exact marker, run
|
|
110
|
+
`<plugin-root>/bin/taskchef.js task resolve <task-id> --thread-id <thread-id> --json --workspace <workspace>`.
|
|
111
|
+
Never edit `tasks.jsonl` directly. The CLI permits only an idempotent one-way
|
|
112
|
+
transition from `threadId: null` to one unique durable thread ID.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
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."
|
|
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, may resolve a nullable thread ID from one exact marker match, never polls or waits, and never persists status or results."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TaskChef Report
|
|
@@ -23,16 +23,26 @@ all deterministic task-log operations.
|
|
|
23
23
|
`<plugin-root>/bin/taskchef.js task list --json --workspace <workspace>`
|
|
24
24
|
once, then select matching entries. Ask the user if the match is ambiguous.
|
|
25
25
|
- Use the full list only when the user asks for an overview of the task history.
|
|
26
|
-
2.
|
|
27
|
-
with
|
|
28
|
-
|
|
26
|
+
2. Separate entries whose `threadId` is `null`. For those entries, take one
|
|
27
|
+
`list_threads` snapshot with limit 50, filter by available project metadata,
|
|
28
|
+
and inspect candidate structured delegated inputs. Use title only to
|
|
29
|
+
prioritize candidates, never to exclude them. When exactly one candidate
|
|
30
|
+
starts with the task's exact marker, run
|
|
31
|
+
`<plugin-root>/bin/taskchef.js task resolve <task-id> --thread-id <thread-id> --json --workspace <workspace>`.
|
|
32
|
+
Do not resolve zero or multiple matches. Report unmatched entries as
|
|
33
|
+
recorded but unresolved and do not pass them to native thread tools.
|
|
34
|
+
3. Query every resolved or previously durable thread exactly once using
|
|
35
|
+
immediate native snapshots, with no more than eight targets per call.
|
|
36
|
+
4. Summarize the live state and any reported outcome for each requested task.
|
|
29
37
|
Distinguish active work, requests for user input, completed work, and failed
|
|
30
38
|
or partial attempts.
|
|
31
|
-
|
|
32
|
-
TaskChef
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
5. Treat each Codex task as the source of truth. The task log records what
|
|
40
|
+
TaskChef submitted, but it does not contain the task's current state.
|
|
41
|
+
6. Never edit `tasks.jsonl` directly. Use `task resolve` only for one exact
|
|
42
|
+
marker match. Never persist status, results, transcripts, or hidden
|
|
43
|
+
reasoning. Do not poll or wait for future activity.
|
|
35
44
|
|
|
36
45
|
If the task history is empty, say that TaskChef has not recorded any tasks. If
|
|
37
|
-
a
|
|
38
|
-
|
|
46
|
+
a task has no durable thread ID, identify it by task ID and say that its marker
|
|
47
|
+
remains available for later recovery. If a recorded thread cannot be read,
|
|
48
|
+
identify it by task ID and thread ID, then continue with the remaining entries.
|
package/src/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
readTask,
|
|
13
13
|
recordTask,
|
|
14
14
|
removeProject,
|
|
15
|
+
resolveTask,
|
|
15
16
|
} from "./workspace.js";
|
|
16
17
|
|
|
17
18
|
async function readStdin() {
|
|
@@ -92,7 +93,6 @@ async function initialize(args) {
|
|
|
92
93
|
`Workspace: ${value.workspace}`,
|
|
93
94
|
`Configuration: ${value.config.action}`,
|
|
94
95
|
`Task log: ${value.tasks.action}`,
|
|
95
|
-
`Legacy tasks: ${value.legacyTasks.action}`,
|
|
96
96
|
`Instructions: ${value.instructions.action}`,
|
|
97
97
|
`Legacy skill links removed: ${value.legacySkills.removed.length}`,
|
|
98
98
|
].join("\n"));
|
|
@@ -180,6 +180,22 @@ async function taskRecord(args) {
|
|
|
180
180
|
return 0;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
async function taskResolve(args) {
|
|
184
|
+
if (!args[2] || args[2].startsWith("--")) throw new Error("task resolve requires a task ID");
|
|
185
|
+
validateCommandArgs(args, 3, {
|
|
186
|
+
values: ["--thread-id", "--workspace"],
|
|
187
|
+
switches: ["--json"],
|
|
188
|
+
});
|
|
189
|
+
if (!args.includes("--thread-id")) throw new Error("task resolve requires --thread-id");
|
|
190
|
+
const task = await resolveTask(
|
|
191
|
+
workspaceRoot(args),
|
|
192
|
+
args[2],
|
|
193
|
+
option(args, "--thread-id"),
|
|
194
|
+
);
|
|
195
|
+
print(task, args, (value) => `Resolved ${value.id}: ${value.threadId}`);
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
183
199
|
async function taskShow(args) {
|
|
184
200
|
validateCommandArgs(args, 3, { values: ["--workspace"], switches: ["--json"] });
|
|
185
201
|
print(await readTask(workspaceRoot(args), args[2]), args);
|
|
@@ -229,6 +245,7 @@ Usage:
|
|
|
229
245
|
taskchef project list [--json] [--workspace <path>]
|
|
230
246
|
taskchef project remove <name> [--json] [--workspace <path>]
|
|
231
247
|
taskchef task record [--json] [--workspace <path>]
|
|
248
|
+
taskchef task resolve <task-id> --thread-id <thread-id> [--json] [--workspace <path>]
|
|
232
249
|
taskchef task show <task-id> [--json] [--workspace <path>]
|
|
233
250
|
taskchef task list [--project <name-or-path>] [--json] [--workspace <path>]
|
|
234
251
|
taskchef task summary [--json] [--workspace <path>]
|
|
@@ -250,6 +267,7 @@ export async function runCli(args) {
|
|
|
250
267
|
if (args[0] === "project" && args[1] === "list") return projectList(args);
|
|
251
268
|
if (args[0] === "project" && args[1] === "remove") return projectRemove(args);
|
|
252
269
|
if (args[0] === "task" && args[1] === "record") return taskRecord(args);
|
|
270
|
+
if (args[0] === "task" && args[1] === "resolve") return taskResolve(args);
|
|
253
271
|
if (args[0] === "task" && args[1] === "show" && args[2]) return taskShow(args);
|
|
254
272
|
if (args[0] === "task" && args[1] === "list") return taskList(args);
|
|
255
273
|
if (args[0] === "task" && args[1] === "summary") return taskSummary(args);
|