input-kanban 0.0.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/ENVIRONMENT.md +39 -0
- package/PROJECT_GUIDE.md +331 -0
- package/README.md +157 -0
- package/bin/input-kanban.js +71 -0
- package/package.json +40 -0
- package/public/index.html +492 -0
- package/src/appServerClient.js +90 -0
- package/src/orchestrator.js +734 -0
- package/src/server.js +111 -0
- package/src/utils.js +78 -0
package/ENVIRONMENT.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Environment Variables
|
|
2
|
+
|
|
3
|
+
This file documents the runtime environment variables supported by Input Kanban. It is intended for local deployment and runtime configuration, not as the main implementation guide for agents.
|
|
4
|
+
|
|
5
|
+
CLI options take precedence over environment variables. Environment variables take precedence over defaults.
|
|
6
|
+
|
|
7
|
+
## Variables
|
|
8
|
+
|
|
9
|
+
- `PORT`: HTTP server port. Default: `8787`. CLI option: `--port`.
|
|
10
|
+
- `HOST`: HTTP bind host. Default: `127.0.0.1`. CLI option: `--host`.
|
|
11
|
+
- `KANBAN_DEFAULT_REPO`: Default target repository path for new runs. Default: the current working directory when `input-kanban` is launched. CLI option: `--repo`.
|
|
12
|
+
- `KANBAN_RUNS_DIR`: Directory for run state, logs, and artifacts. Default: `.input-kanban/runs` under the user's home directory. CLI option: `--runs-dir`.
|
|
13
|
+
- `KANBAN_CODEX_BIN`: Codex CLI executable name or path. Default: `codex`. CLI option: `--codex-bin`.
|
|
14
|
+
|
|
15
|
+
## Environment Example
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
PORT=8787 \
|
|
19
|
+
KANBAN_DEFAULT_REPO=/path/to/child-repo \
|
|
20
|
+
KANBAN_RUNS_DIR=/path/to/kanban-runs \
|
|
21
|
+
KANBAN_CODEX_BIN=codex \
|
|
22
|
+
input-kanban
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Equivalent CLI Example
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
input-kanban \
|
|
29
|
+
--port 8787 \
|
|
30
|
+
--repo /path/to/child-repo \
|
|
31
|
+
--runs-dir /path/to/kanban-runs \
|
|
32
|
+
--codex-bin codex
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
|
|
37
|
+
- `KANBAN_DEFAULT_REPO` / `--repo` should point to the actual git repository where work should run.
|
|
38
|
+
- The runtime runs directory contains task text, logs, model output, artifacts, and possible audit information. It should not be committed to git.
|
|
39
|
+
- Avoid writing machine-specific absolute paths into public or shared documentation.
|
package/PROJECT_GUIDE.md
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# Input Kanban Project Guide
|
|
2
|
+
|
|
3
|
+
This document explains how Input Kanban is implemented so that humans and coding agents can quickly understand the project before making changes.
|
|
4
|
+
|
|
5
|
+
## Current Status
|
|
6
|
+
|
|
7
|
+
Implementation status:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
mvp / batch-scheduler / codex-exec-primary / buildkite-style-ui / manual-recovery / stop-archive / cli-bootstrap
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Recent validation:
|
|
14
|
+
|
|
15
|
+
- `npm run check` passes for the CLI entry and backend modules.
|
|
16
|
+
- A smoke test can start `input-kanban` on a temporary port and read `GET /api/health`.
|
|
17
|
+
- The frontend is a single HTML file; its inline script can be extracted and checked with `node --check` when edited.
|
|
18
|
+
|
|
19
|
+
## Project Purpose
|
|
20
|
+
|
|
21
|
+
Input Kanban is a local Codex orchestration dashboard. It is not a business service and not a CI system.
|
|
22
|
+
|
|
23
|
+
It runs local `codex exec --json` processes, stores run state and logs on the filesystem, and serves a static HTML dashboard that polls the backend.
|
|
24
|
+
|
|
25
|
+
The intended use case is:
|
|
26
|
+
|
|
27
|
+
1. Create a run from a user task.
|
|
28
|
+
2. Ask a planner to split the task into batches and workers.
|
|
29
|
+
3. Dispatch workers by strict batch barriers.
|
|
30
|
+
4. Observe logs, status, artifacts, and Codex session IDs.
|
|
31
|
+
5. Stop or archive runs when needed.
|
|
32
|
+
6. Run one final judge pass after all batches complete.
|
|
33
|
+
|
|
34
|
+
## Important Boundaries
|
|
35
|
+
|
|
36
|
+
- If the current workspace is a multi-repo umbrella, the target repo must be a concrete child repository, not the umbrella root.
|
|
37
|
+
- Workers can modify the target repository. Failed workers are not automatically retried because a partial modification may already exist.
|
|
38
|
+
- The planner only creates a plan and does not modify the target repo. Planner failures, invalid output, and empty plans can be safely retried before any worker or judge starts.
|
|
39
|
+
- Local process state, `exit_code`, logs, and artifacts are the source of truth. Codex App Server session lookup is auxiliary.
|
|
40
|
+
- There is no batch-level judge. Only one final judge pass runs after all batches complete.
|
|
41
|
+
|
|
42
|
+
## CLI Entry
|
|
43
|
+
|
|
44
|
+
The npm CLI entry is:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
bin/input-kanban.js
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
It parses CLI options, sets environment variables before importing backend modules, and starts the HTTP server.
|
|
51
|
+
|
|
52
|
+
Supported options:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
--host <host>
|
|
56
|
+
--port <port>
|
|
57
|
+
--repo <path>
|
|
58
|
+
--runs-dir <path>
|
|
59
|
+
--codex-bin <path>
|
|
60
|
+
--open
|
|
61
|
+
--no-open
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Default behavior:
|
|
65
|
+
|
|
66
|
+
- default repo: current working directory when `input-kanban` is launched;
|
|
67
|
+
- default host: `127.0.0.1`;
|
|
68
|
+
- default port: `8787`;
|
|
69
|
+
- default runs directory: `~/.input-kanban/runs`;
|
|
70
|
+
- default Codex binary: `codex`.
|
|
71
|
+
|
|
72
|
+
## Data Model
|
|
73
|
+
|
|
74
|
+
### Run
|
|
75
|
+
|
|
76
|
+
A run is one user-submitted task batch. It appears as one card in the left sidebar and maps to one runtime directory:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
runs/<runId>/
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Main files:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
task.md
|
|
86
|
+
plan.json
|
|
87
|
+
run_state.json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Batch
|
|
91
|
+
|
|
92
|
+
A batch is a strict scheduling barrier produced by the planner. Only the first incomplete batch is eligible for scheduling. Later batches must wait until all earlier batches complete.
|
|
93
|
+
|
|
94
|
+
### Task
|
|
95
|
+
|
|
96
|
+
A task is one worker inside a batch. Batch-level parallelism is controlled by `batch.maxParallel`.
|
|
97
|
+
|
|
98
|
+
### Roles
|
|
99
|
+
|
|
100
|
+
- `planner`: read-only `codex exec` that returns a plan.
|
|
101
|
+
- `worker`: normally `workspace-write` `codex exec` that performs work.
|
|
102
|
+
- `judge`: read-only `codex exec` that performs final evaluation.
|
|
103
|
+
|
|
104
|
+
## Run State Machine
|
|
105
|
+
|
|
106
|
+
Common run states:
|
|
107
|
+
|
|
108
|
+
- `created`: run exists, planner has not started.
|
|
109
|
+
- `planning`: planner is running.
|
|
110
|
+
- `plan_failed`: planner failed or returned output that could not be parsed.
|
|
111
|
+
- `plan_empty`: planner returned valid JSON but zero tasks.
|
|
112
|
+
- `planned`: planner produced executable tasks.
|
|
113
|
+
- `running`: at least one worker in the current batch is running.
|
|
114
|
+
- `batch_blocked`: the current batch has a `failed` or `unknown` worker; later batches will not start.
|
|
115
|
+
- `batches_completed`: all batches completed; final judge can run.
|
|
116
|
+
- `judging`: final judge is running.
|
|
117
|
+
- `judged`: final judge process completed.
|
|
118
|
+
- `judge_failed`: final judge process failed.
|
|
119
|
+
- `stopped`: user stopped the run; no further scheduling occurs.
|
|
120
|
+
|
|
121
|
+
## Planner Retry Policy
|
|
122
|
+
|
|
123
|
+
Planner retry is allowed only before any worker or judge has started.
|
|
124
|
+
|
|
125
|
+
Before retrying, the backend:
|
|
126
|
+
|
|
127
|
+
1. Moves the current `planner/` directory to `planner_attempts/attempt-XX/`.
|
|
128
|
+
2. Clears current `tasks` and `batches`.
|
|
129
|
+
3. Resets `judge` state.
|
|
130
|
+
4. Deletes old `plan.json`.
|
|
131
|
+
5. Starts a new planner in a clean `planner/` directory.
|
|
132
|
+
|
|
133
|
+
If the planner returns valid JSON with zero tasks, the run is marked `plan_empty`. The UI shows a warning and allows planning again.
|
|
134
|
+
|
|
135
|
+
## Worker Failure Policy
|
|
136
|
+
|
|
137
|
+
Workers are not automatically retried.
|
|
138
|
+
|
|
139
|
+
Reason: a worker may have already changed files in the target repository. Retrying could duplicate edits, overwrite partial work, or create conflicts.
|
|
140
|
+
|
|
141
|
+
Recovery options:
|
|
142
|
+
|
|
143
|
+
- Inspect `events.pretty`, `stderr.log`, `last_message.md`, and artifacts.
|
|
144
|
+
- Manually mark `failed` or `unknown` workers as completed if the user confirms the work is actually done.
|
|
145
|
+
- Manual completion writes `workers/<taskId>/manual_completion.json`.
|
|
146
|
+
- The UI preserves the original failed or unknown status while also showing the manual completion marker.
|
|
147
|
+
|
|
148
|
+
## Stop and Archive
|
|
149
|
+
|
|
150
|
+
### Stop
|
|
151
|
+
|
|
152
|
+
`POST /api/runs/:runId/stop` terminates still-running local `codex exec` child processes for that run and freezes the run as `stopped`.
|
|
153
|
+
|
|
154
|
+
### Archive
|
|
155
|
+
|
|
156
|
+
`POST /api/runs/:runId/archive` performs a soft archive:
|
|
157
|
+
|
|
158
|
+
- writes `archived: true` to `run_state.json`;
|
|
159
|
+
- does not move the run directory;
|
|
160
|
+
- hides the run from default `GET /api/runs` and the left sidebar.
|
|
161
|
+
|
|
162
|
+
Archived runs can be queried with:
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
GET /api/runs?includeArchived=1
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Left Sidebar Behavior
|
|
169
|
+
|
|
170
|
+
The left sidebar is rendered from API summaries, not direct file reads.
|
|
171
|
+
|
|
172
|
+
Flow:
|
|
173
|
+
|
|
174
|
+
1. Backend scans `runs/<runId>/run_state.json`.
|
|
175
|
+
2. `summaryOfRun()` creates summaries.
|
|
176
|
+
3. `GET /api/runs` returns those summaries.
|
|
177
|
+
4. Frontend renders run cards.
|
|
178
|
+
|
|
179
|
+
Current behavior:
|
|
180
|
+
|
|
181
|
+
- Shows the newest 10 runs by default.
|
|
182
|
+
- `Show more` appends 10 more runs.
|
|
183
|
+
- Sidebar height is fixed to the viewport; the run list has its own vertical scroll.
|
|
184
|
+
- Each card shows label, status, run ID, creation time, progress, running count, and failed count.
|
|
185
|
+
- Long labels are clamped to two lines with a browser tooltip for the full value.
|
|
186
|
+
|
|
187
|
+
## Final Judge
|
|
188
|
+
|
|
189
|
+
Final Judge runs once after all batches complete.
|
|
190
|
+
|
|
191
|
+
Before starting the judge, the backend generates:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
runs/<runId>/judge/judge_input.json
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
This manifest is the judge's primary source of truth. It contains:
|
|
198
|
+
|
|
199
|
+
- run metadata;
|
|
200
|
+
- original task text;
|
|
201
|
+
- `plan.json`;
|
|
202
|
+
- batch summaries and task order;
|
|
203
|
+
- planner status, output, and parse errors;
|
|
204
|
+
- worker status, exit code, start/end timestamps, expected artifacts;
|
|
205
|
+
- each worker's `last_message.md`, `result.json`, `evidence.json`, `manual_completion.json`, and stderr tail.
|
|
206
|
+
|
|
207
|
+
The judge prompt instructs the model to use `judge_input.json` first and inspect other run artifacts only if needed. This makes final evaluation more deterministic than asking the judge to discover files on its own.
|
|
208
|
+
|
|
209
|
+
## File Viewer
|
|
210
|
+
|
|
211
|
+
The file viewer calls:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
GET /api/runs/:runId/tasks/:taskId/file?name=...
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
It can read planner, worker, and judge files.
|
|
218
|
+
|
|
219
|
+
Current behavior:
|
|
220
|
+
|
|
221
|
+
- Selecting a task updates the file viewer title to `runId / taskId`.
|
|
222
|
+
- If a file tab is already open, switching tasks reloads the same file for the newly selected task.
|
|
223
|
+
- Auto refresh also reloads the selected task's selected file and attempts to preserve scroll position.
|
|
224
|
+
- `events.pretty` is a virtual file generated by formatting `events.jsonl` into a readable Chinese execution log.
|
|
225
|
+
- The execution view shows event counts and a jump-to-bottom button.
|
|
226
|
+
- `last_message.md` has a hover copy button in the top-left of the text area.
|
|
227
|
+
- `judge_input.json` can be viewed through the `Judge Input` tab.
|
|
228
|
+
|
|
229
|
+
## Files and Responsibilities
|
|
230
|
+
|
|
231
|
+
```text
|
|
232
|
+
bin/input-kanban.js CLI entry; parses args and starts server
|
|
233
|
+
src/server.js HTTP server, static files, API routes
|
|
234
|
+
src/orchestrator.js run state machine, scheduling, codex exec, stop/archive, file formatting
|
|
235
|
+
src/appServerClient.js Codex App Server stdio client and session lookup
|
|
236
|
+
src/utils.js paths, IDs, atomic JSON writes, file info, JSON extraction
|
|
237
|
+
public/index.html single-file frontend, no build step
|
|
238
|
+
README.md user-facing overview
|
|
239
|
+
PROJECT_GUIDE.md implementation guide for humans and agents
|
|
240
|
+
ENVIRONMENT.md runtime environment variable reference
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Runtime files:
|
|
244
|
+
|
|
245
|
+
```text
|
|
246
|
+
runs/<runId>/run_state.json
|
|
247
|
+
runs/<runId>/task.md
|
|
248
|
+
runs/<runId>/plan.json
|
|
249
|
+
runs/<runId>/planner/
|
|
250
|
+
runs/<runId>/planner_attempts/attempt-XX/
|
|
251
|
+
runs/<runId>/workers/<taskId>/
|
|
252
|
+
runs/<runId>/judge/judge_input.json
|
|
253
|
+
runs/<runId>/judge/verdict.json
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## API
|
|
257
|
+
|
|
258
|
+
- `GET /`
|
|
259
|
+
- `GET /api/health`
|
|
260
|
+
- `GET /api/runs`
|
|
261
|
+
- `GET /api/runs?includeArchived=1`
|
|
262
|
+
- `POST /api/runs`
|
|
263
|
+
- `GET /api/runs/:runId/status`
|
|
264
|
+
- `POST /api/runs/:runId/plan`
|
|
265
|
+
- `POST /api/runs/:runId/dispatch`
|
|
266
|
+
- `POST /api/runs/:runId/judge`
|
|
267
|
+
- `POST /api/runs/:runId/stop`
|
|
268
|
+
- `POST /api/runs/:runId/archive`
|
|
269
|
+
- `GET /api/runs/:runId/task-text`
|
|
270
|
+
- `GET /api/runs/:runId/tasks/:taskId/file?name=...`
|
|
271
|
+
- `POST /api/runs/:runId/tasks/:taskId/mark-completed`
|
|
272
|
+
|
|
273
|
+
## Planner Output
|
|
274
|
+
|
|
275
|
+
Preferred shape:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"batches": [
|
|
280
|
+
{
|
|
281
|
+
"id": "batch-1",
|
|
282
|
+
"name": "first batch",
|
|
283
|
+
"maxParallel": 3,
|
|
284
|
+
"tasks": [
|
|
285
|
+
{
|
|
286
|
+
"id": "T-01",
|
|
287
|
+
"name": "short name",
|
|
288
|
+
"prompt": "worker prompt",
|
|
289
|
+
"sandbox": "workspace-write",
|
|
290
|
+
"expectedArtifacts": []
|
|
291
|
+
}
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
"finalJudgeRequired": true
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Backward-compatible shape:
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"tasks": [
|
|
304
|
+
{
|
|
305
|
+
"id": "T-01",
|
|
306
|
+
"name": "short name",
|
|
307
|
+
"prompt": "worker prompt",
|
|
308
|
+
"sandbox": "workspace-write",
|
|
309
|
+
"expectedArtifacts": []
|
|
310
|
+
}
|
|
311
|
+
]
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
The old `tasks` format is wrapped into `batch-1` automatically.
|
|
316
|
+
|
|
317
|
+
## Development Checks
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
npm run check
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
When editing `public/index.html`, also consider extracting the inline script and checking it with `node --check`.
|
|
324
|
+
|
|
325
|
+
## Change Guidelines
|
|
326
|
+
|
|
327
|
+
- Do not add automatic worker retry unless there is a verified rollback or idempotency mechanism.
|
|
328
|
+
- Do not default to `--skip-git-repo-check`; prefer a concrete target child repository.
|
|
329
|
+
- Preserve batch barriers when modifying scheduling logic.
|
|
330
|
+
- Decide clearly between soft archive and physical directory archive before changing archive semantics.
|
|
331
|
+
- Keep the frontend buildless unless there is a strong reason to introduce a build pipeline.
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Input Kanban
|
|
2
|
+
|
|
3
|
+
Input Kanban is a lightweight local dashboard for splitting a Codex task into batches and workers, running them with `codex exec`, observing status, stopping or archiving runs, and performing a final judge pass.
|
|
4
|
+
|
|
5
|
+
For implementation details and agent-facing project context, see:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
PROJECT_GUIDE.md
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For runtime environment variables, see:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
ENVIRONMENT.md
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- Static HTML dashboard with no frontend build step.
|
|
20
|
+
- Node.js backend that can:
|
|
21
|
+
- create multiple runs;
|
|
22
|
+
- start a `codex exec` planner and materialize `plan.json`;
|
|
23
|
+
- safely retry planner runs before any worker or judge starts;
|
|
24
|
+
- detect `plan_empty` when the planner returns zero tasks;
|
|
25
|
+
- schedule workers by strict batch barriers and `batch.maxParallel`;
|
|
26
|
+
- generate `judge_input.json` before the final judge pass;
|
|
27
|
+
- start an independent `codex exec` final judge;
|
|
28
|
+
- aggregate PID, exit code, events, stderr, last message, artifacts, and Codex session IDs;
|
|
29
|
+
- stop runs, soft-archive runs, and manually mark failed or unknown workers as completed.
|
|
30
|
+
|
|
31
|
+
## CLI Usage
|
|
32
|
+
|
|
33
|
+
Run from the target repository directory:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
input-kanban
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or provide the target repository explicitly:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
input-kanban --repo /path/to/repo
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then open:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
http://127.0.0.1:8787
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Common options:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
input-kanban --port 8787
|
|
55
|
+
input-kanban --host 127.0.0.1
|
|
56
|
+
input-kanban --runs-dir ~/.input-kanban/runs
|
|
57
|
+
input-kanban --codex-bin codex
|
|
58
|
+
input-kanban --open
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm start
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For local CLI development:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm link
|
|
71
|
+
input-kanban
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Workflow
|
|
75
|
+
|
|
76
|
+
1. Click `New Run`, then enter a label, target repo, max parallel value, and task text.
|
|
77
|
+
2. Click `Create Run`.
|
|
78
|
+
3. Click `Plan` to start the planner:
|
|
79
|
+
- planner uses `codex exec --json --sandbox read-only`;
|
|
80
|
+
- output is stored under `runs/<runId>/planner/`.
|
|
81
|
+
4. When planning succeeds, `plan.json` is created and the worker list is shown.
|
|
82
|
+
5. Click `Dispatch` to start workers according to batch barriers and `batch.maxParallel`.
|
|
83
|
+
6. The page polls status every 3 seconds.
|
|
84
|
+
7. After all batches complete, click `Final Judge` to run the final judge pass.
|
|
85
|
+
|
|
86
|
+
The current UI labels are localized, but the project documentation is written in English for easier agent consumption.
|
|
87
|
+
|
|
88
|
+
## Planner Output Format
|
|
89
|
+
|
|
90
|
+
The preferred planner response is a JSON object with `batches`. The older `tasks` shape is also supported.
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"batches": [
|
|
95
|
+
{
|
|
96
|
+
"id": "batch-1",
|
|
97
|
+
"name": "first batch name",
|
|
98
|
+
"maxParallel": 3,
|
|
99
|
+
"tasks": [
|
|
100
|
+
{
|
|
101
|
+
"id": "T-01",
|
|
102
|
+
"name": "short name",
|
|
103
|
+
"prompt": "complete worker prompt",
|
|
104
|
+
"sandbox": "workspace-write",
|
|
105
|
+
"expectedArtifacts": ["tmp/example-result.json"]
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"finalJudgeRequired": true
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The backend extracts the first JSON object from `last_message.md`. If the planner succeeds but returns zero tasks, the run is marked `plan_empty` and can be planned again before any worker or judge starts.
|
|
115
|
+
|
|
116
|
+
## Status Sources
|
|
117
|
+
|
|
118
|
+
Worker status is primarily determined from local state:
|
|
119
|
+
|
|
120
|
+
- Node child process tracking
|
|
121
|
+
- `exit_code`
|
|
122
|
+
- `events.jsonl`
|
|
123
|
+
- `stderr.log`
|
|
124
|
+
- `last_message.md`
|
|
125
|
+
- expected artifacts
|
|
126
|
+
|
|
127
|
+
Codex App Server is an auxiliary source only:
|
|
128
|
+
|
|
129
|
+
- the backend starts `codex app-server --stdio`;
|
|
130
|
+
- it calls `thread/list`;
|
|
131
|
+
- it matches sessions using prompt markers:
|
|
132
|
+
- `ORCHESTRATOR_RUN_ID`
|
|
133
|
+
- `ORCHESTRATOR_TASK_ID`
|
|
134
|
+
|
|
135
|
+
A Codex App Server `notLoaded` state does not mean a worker failed. The local process, exit code, logs, and artifacts remain the source of truth.
|
|
136
|
+
|
|
137
|
+
## Runtime Directory
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
runs/<runId>/
|
|
141
|
+
├── task.md
|
|
142
|
+
├── plan.json
|
|
143
|
+
├── run_state.json
|
|
144
|
+
├── planner/
|
|
145
|
+
├── workers/<taskId>/
|
|
146
|
+
└── judge/
|
|
147
|
+
├── judge_input.json
|
|
148
|
+
└── verdict.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The development `runs/` directory is gitignored. For CLI usage, the default runtime directory is `~/.input-kanban/runs`.
|
|
152
|
+
|
|
153
|
+
## Checks
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npm run check
|
|
157
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
function parseArgs(argv) {
|
|
6
|
+
const args = { host: '127.0.0.1', port: undefined, repo: undefined, runsDir: undefined, codexBin: undefined, open: false, help: false };
|
|
7
|
+
for (let i = 0; i < argv.length; i++) {
|
|
8
|
+
const arg = argv[i];
|
|
9
|
+
const next = () => argv[++i];
|
|
10
|
+
if (arg === '--help' || arg === '-h') args.help = true;
|
|
11
|
+
else if (arg === '--open') args.open = true;
|
|
12
|
+
else if (arg === '--no-open') args.open = false;
|
|
13
|
+
else if (arg === '--host') args.host = next();
|
|
14
|
+
else if (arg === '--port' || arg === '-p') args.port = Number(next());
|
|
15
|
+
else if (arg === '--repo' || arg === '-r') args.repo = next();
|
|
16
|
+
else if (arg === '--runs-dir') args.runsDir = next();
|
|
17
|
+
else if (arg === '--codex-bin') args.codexBin = next();
|
|
18
|
+
else throw new Error(`unknown argument: ${arg}`);
|
|
19
|
+
}
|
|
20
|
+
return args;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function printHelp() {
|
|
24
|
+
console.log(`input-kanban
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
input-kanban [options]
|
|
28
|
+
|
|
29
|
+
Options:
|
|
30
|
+
--host <host> Host to bind, default 127.0.0.1
|
|
31
|
+
-p, --port <port> Port to bind, default 8787
|
|
32
|
+
-r, --repo <path> Default target repository, default current directory
|
|
33
|
+
--runs-dir <path> Runtime runs directory, default ~/.input-kanban/runs
|
|
34
|
+
--codex-bin <path> Codex CLI executable, default codex
|
|
35
|
+
--open Open browser after starting
|
|
36
|
+
--no-open Do not open browser, default
|
|
37
|
+
-h, --help Show help
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function openBrowser(url) {
|
|
42
|
+
const command = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';
|
|
43
|
+
const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
|
|
44
|
+
const child = spawn(command, args, { stdio: 'ignore', detached: true });
|
|
45
|
+
child.unref();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const args = parseArgs(process.argv.slice(2));
|
|
50
|
+
if (args.help) { printHelp(); process.exit(0); }
|
|
51
|
+
if (args.port) process.env.PORT = String(args.port);
|
|
52
|
+
if (args.host) process.env.HOST = args.host;
|
|
53
|
+
if (args.repo) process.env.KANBAN_DEFAULT_REPO = path.resolve(args.repo);
|
|
54
|
+
else if (!process.env.KANBAN_DEFAULT_REPO) process.env.KANBAN_DEFAULT_REPO = process.cwd();
|
|
55
|
+
if (args.runsDir) process.env.KANBAN_RUNS_DIR = path.resolve(args.runsDir);
|
|
56
|
+
if (args.codexBin) process.env.KANBAN_CODEX_BIN = args.codexBin;
|
|
57
|
+
|
|
58
|
+
const { startServer } = await import('../src/server.js');
|
|
59
|
+
const instance = await startServer({ host: process.env.HOST, port: Number(process.env.PORT || 8787), log: false });
|
|
60
|
+
console.log('Input Kanban started');
|
|
61
|
+
console.log(`URL: ${instance.url}`);
|
|
62
|
+
console.log(`Repo: ${instance.defaultRepo}`);
|
|
63
|
+
console.log(`Runs: ${instance.runsDir}`);
|
|
64
|
+
if (args.open) openBrowser(instance.url);
|
|
65
|
+
const shutdown = () => { instance.stop().finally(() => process.exit(0)); };
|
|
66
|
+
process.on('SIGINT', shutdown);
|
|
67
|
+
process.on('SIGTERM', shutdown);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error(error.message || String(error));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "input-kanban",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"input-kanban": "bin/input-kanban.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start": "node bin/input-kanban.js",
|
|
10
|
+
"check": "node --check bin/input-kanban.js && node --check src/server.js && node --check src/orchestrator.js && node --check src/appServerClient.js && node --check src/utils.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {},
|
|
13
|
+
"description": "A local Codex orchestration kanban dashboard",
|
|
14
|
+
"files": [
|
|
15
|
+
"bin",
|
|
16
|
+
"src",
|
|
17
|
+
"public",
|
|
18
|
+
"README.md",
|
|
19
|
+
"PROJECT_GUIDE.md",
|
|
20
|
+
"ENVIRONMENT.md"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"codex",
|
|
24
|
+
"kanban",
|
|
25
|
+
"orchestration",
|
|
26
|
+
"cli",
|
|
27
|
+
"agent"
|
|
28
|
+
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/zhang3xing1/Input-Kanban.git"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/zhang3xing1/Input-Kanban/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/zhang3xing1/Input-Kanban#readme",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20"
|
|
39
|
+
}
|
|
40
|
+
}
|