@0xgeorgemathew/zcode 0.4.4 → 0.5.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/lib/workspace.js CHANGED
@@ -42,16 +42,16 @@ function workspaceRoot(cwd) {
42
42
 
43
43
  // Ownership patterns arrive relative to --cwd; store them relative to the
44
44
  // workspace root, posix-style, so every session compares like with like.
45
- function normalizeOwns(patterns, cwd, root) {
45
+ function normalizeOwns(patterns, cwd, root, flag = '--owns') {
46
46
  const realCwd = fs.realpathSync(cwd);
47
47
  return patterns.map((raw) => {
48
48
  const pattern = String(raw).trim();
49
- if (!pattern) throw new OwnershipError('--owns pattern must not be empty');
49
+ if (!pattern) throw new OwnershipError(`${flag} pattern must not be empty`);
50
50
  const abs = path.isAbsolute(pattern) ? pattern : path.join(realCwd, pattern);
51
51
  const rel = toPosix(path.relative(root, abs));
52
52
  if (rel === '' || rel === '.') return '**';
53
53
  if (rel.startsWith('../') || rel === '..' || path.isAbsolute(rel)) {
54
- throw new OwnershipError(`--owns "${pattern}" is outside the workspace ${root}`);
54
+ throw new OwnershipError(`${flag} "${pattern}" is outside the workspace ${root}`);
55
55
  }
56
56
  return /[/\\]$/.test(pattern) && !hasWildcard(rel) ? `${rel}/**` : rel;
57
57
  });
@@ -150,10 +150,10 @@ function readLeases(dir) {
150
150
  // lease. Writing first and reading second means two sessions starting at
151
151
  // the same instant both see each other; the later (startedAt, id) backs
152
152
  // off, so exactly one proceeds.
153
- function acquireLease({ id, root, owns, allowOverlap = false, env = process.env }) {
153
+ function acquireLease({ id, root, owns, touch = [], allowOverlap = false, env = process.env }) {
154
154
  const dir = leaseDir(root, env);
155
155
  fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
156
- const mine = { id, pid: process.pid, root, owns, startedAt: Date.now() };
156
+ const mine = { id, pid: process.pid, root, owns, touch, startedAt: Date.now() };
157
157
  const file = path.join(dir, `${id}.json`);
158
158
  fs.writeFileSync(file, JSON.stringify(mine) + '\n', { mode: 0o600 });
159
159
 
@@ -166,6 +166,14 @@ function acquireLease({ id, root, owns, allowOverlap = false, env = process.env
166
166
  }
167
167
  others.push(lease);
168
168
  }
169
+ // --touch never reserves anything, but it may not edit what a live
170
+ // session owns (an empty ownership is the whole workspace). Not ordered by
171
+ // start time: the toucher is the one that has to step aside.
172
+ const touchConflicts = touch.length && !allowOverlap ? others.filter((o) => ownsOverlap(touch, o.owns)) : [];
173
+ if (touchConflicts.length) {
174
+ fs.rmSync(file, { force: true });
175
+ return { ok: false, conflicts: touchConflicts, others, touch: true };
176
+ }
169
177
  const conflicts = others.filter((o) => ownsOverlap(owns, o.owns));
170
178
  const blocking = conflicts.filter(
171
179
  (o) => o.startedAt < mine.startedAt || (o.startedAt === mine.startedAt && o.id < id)
@@ -183,7 +191,14 @@ function liveLeases(root, env = process.env) {
183
191
 
184
192
  // --- change tracking ----------------------------------------------------------
185
193
 
186
- const WALK_SKIP = new Set(['.git', 'node_modules', '.zcode', '.DS_Store']);
194
+ // zcode's own per-session directories (<cwd>/.zcode/out/<id>, project skills)
195
+ // are never changes of the task, at any depth. The Playwright MCP's scratch
196
+ // dir (.playwright-mcp: console logs, page snapshots) written by --visual
197
+ // verification is tooling output, not task output.
198
+ const TOOL_DIRS = new Set(['.zcode', '.playwright-mcp']);
199
+ const isZcodePath = (rel) => rel.split('/').some((seg) => TOOL_DIRS.has(seg));
200
+
201
+ const WALK_SKIP = new Set(['.git', 'node_modules', '.zcode', '.playwright-mcp', '.DS_Store']);
187
202
  const WALK_LIMIT = 20000;
188
203
  const HASH_LIMIT = 8 * 1024 * 1024;
189
204
 
@@ -253,6 +268,7 @@ function snapshot(root) {
253
268
  try {
254
269
  const entries = new Map();
255
270
  for (const [rel, code] of gitStatus(root)) {
271
+ if (isZcodePath(rel)) continue;
256
272
  entries.set(rel, { code, sig: fileSignature(path.join(root, rel)) });
257
273
  }
258
274
  return { kind: 'git', root, head: gitHead(root), entries };
@@ -314,7 +330,7 @@ function diffSnapshots(before, after) {
314
330
  if (after.kind === 'git' && before.head && after.head && before.head !== after.head) {
315
331
  const seen = new Set(out.map((f) => f.path));
316
332
  for (const f of committedChanges(after.root, before.head, after.head)) {
317
- if (!seen.has(f.path)) out.push({ ...f, committed: true });
333
+ if (!seen.has(f.path) && !isZcodePath(f.path)) out.push({ ...f, committed: true });
318
334
  }
319
335
  out.sort((a, b) => a.path.localeCompare(b.path));
320
336
  }
@@ -327,6 +343,7 @@ module.exports = {
327
343
  normalizeOwns,
328
344
  globToRegExp,
329
345
  isOwned,
346
+ isZcodePath,
330
347
  ownsOverlap,
331
348
  acquireLease,
332
349
  liveLeases,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xgeorgemathew/zcode",
3
- "version": "0.4.4",
3
+ "version": "0.5.1",
4
4
  "description": "Lean GLM-5.3 execution engine for orchestrator agents: task contracts, independent sessions, zcode-run verification, structured handbacks, subagents, MCP, skills. Wraps the ZCode engine. Zero dependencies.",
5
5
  "license": "MIT",
6
6
  "private": false,
package/skills/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Orchestrator skills
2
2
 
3
- These skills teach an orchestrating agent how to delegate work to zcode, run sessions in parallel, and read the handbacks. Both describe the same CLI; they differ only in runtime notes (tool timeouts for Claude Code, sandbox and network escalation for Codex).
3
+ These skills teach an orchestrating agent to make the design and logic decisions once, delegate the implementation to zcode (one session with units, parallel sessions, or a plan), and read the compact handbacks, spending its own tokens only on decisions and exceptions. Both describe the same CLI; they differ only in runtime notes (tool timeouts for Claude Code, sandbox and network escalation for Codex).
4
4
 
5
5
  | platform | skill in this repo | format |
6
6
  |---|---|---|
@@ -1,112 +1,142 @@
1
1
  ---
2
2
  name: zcode
3
- description: Delegate scoped implementation work to the zcode CLI (GLM-5.3 executor) and consume its verified handback. Use when you are orchestrating and want a page, component, fix or other bounded unit implemented and checked by an independent executor session — alone or several in parallel — while you keep product, design and planning decisions.
3
+ description: Delegate scoped implementation work to the zcode CLI (GLM-5.3 executor, vision-capable, has Playwright) and consume its compact verified handback. Use when you are orchestrating: you make the product, design and logic decisions once, then zcode implements, tests, visually verifies and repairs — in one session with subagent units, several parallel sessions, or a dependency plan — while you spend tokens only on decisions and exceptions.
4
4
  ---
5
5
 
6
6
  # Operating zcode as an executor
7
7
 
8
- zcode is a CLI execution engine. You hand it a scoped task; it implements the task in its own session, runs your acceptance checks itself, repairs failures within a budget, and returns a structured handback. You stay the orchestrator. You decide what to build and how it should look, how to split the work, when to run sessions in parallel, and when to review. zcode decides routine implementation details within the scope you give it.
8
+ zcode is a CLI execution engine. You decide; it builds. It implements a scoped task in its own session, runs your checks itself, screenshots and judges UI with its own vision when you ask, repairs failures within a budget, and returns a small structured handback.
9
9
 
10
- Check it is ready once per machine: `zcode doctor` (exit 3 means no key, so run `zcode login`; exit 4 means the engine is missing).
10
+ **The point is token economy.** Your tokens go to decisions and exceptions. Everything mechanical — writing code, running builds and tests, reading diffs, looking at screenshots, fixing small failures — is zcode's. If you are doing any of that after dispatch, you are paying twice.
11
11
 
12
- ## When to use it
12
+ Check readiness once per machine: `zcode doctor` (exit 3 → `zcode login`; exit 4 → engine missing). Don't run `--help`: everything you need is here.
13
13
 
14
- - Use it for bounded implementation work with a clear outcome: one page, a few components, a bug fix, a refactor of a known area, a test suite for a module.
15
- - Don't use it for product or design decisions, open-ended exploration, or work you can't describe a finished state for. Decide those yourself first, then delegate the implementation.
16
- - Size each session so you could review its result in one sitting. Several small sessions beat one huge one, because each returns its own evidence.
14
+ ## The workflow
17
15
 
18
- ## Writing the handoff
16
+ 1. **Read** the codebase as much as you need to plan. This is the one phase where reading files is expected.
17
+ 2. **Decide** everything a user could see or a system depends on (checklists below). Write the decisions down once, as decisions — a file such as `docs/decisions.md` that sessions receive with `--decisions @file`.
18
+ 3. **Shape** the work: one session with units, several sessions, or a plan (next section).
19
+ 4. **Preflight** (optional, recommended for anything large or ambiguous): `--preflight` makes zcode list every question it would otherwise guess. Answer them all in one edit to the decisions file.
20
+ 5. **Dispatch and wait** with `--detach` + `zcode wait`, or `zcode plan run` + `zcode plan wait`.
21
+ 6. **Handle exceptions only.** `completed` → move on. Anything else → read only what the brief shows, answer or adjust in one line with `zcode resume`.
19
22
 
20
- Only the objective is required. Add what the executor cannot infer:
23
+ ## Deciding: leave nothing open-ended
21
24
 
22
- | field | flag | give it when |
23
- |---|---|---|
24
- | objective | positional text | always: the outcome, not the steps |
25
- | acceptance | `--accept "…"` | you have criteria beyond "it works" |
26
- | checks | `--check "cmd"` | always if possible: shell commands zcode runs itself (build, tests, lint, a grep) |
27
- | owns | `--owns path/or/glob` | other sessions may touch the same repo |
28
- | files | `--file path` | specific files to read first |
29
- | context / design | `--context "…"` or `--context @notes.md` | design decisions, copy, references, constraints |
30
- | everything | `--task contract.json` | larger handoffs (keys: objective, scope, constraints, design, acceptance, checks, files, references, context, owns, limits, model, effort) |
25
+ The executor implements binding decisions exactly and is told not to invent anything user-visible or behavioural. Gaps either block it (a round trip for you) or get the most conservative default. Close them up front.
31
26
 
32
- Rules that keep you in charge:
27
+ **Front end:** palette (exact values), type families and scale, spacing scale, radii, iconography/illustration style; every section's layout and hierarchy at each breakpoint you care about; exact copy; component states (hover, focus, active, disabled, loading, empty, error); motion (what moves, property, distance, duration, easing, stagger, trigger, reduced-motion behaviour); accessibility (focus order, traps, labels, contrast floor); stack and libraries; performance budget.
33
28
 
34
- - Put design decisions in `design` (JSON) or `--context`, written as decisions ("Hero uses the dark palette; CTA right-aligned"). The executor is told to implement them exactly and to report `blocked` rather than invent product or design choices.
35
- - Make checks mechanical and fast. A task with no `--check` can only come back `unverified`.
36
- - Don't ask zcode to commit, push, or deploy unless you mean it. It won't by default.
29
+ **Back end / logic:** data shapes and storage keys; API routes, payloads, status codes and errors; validation rules (exact regexes, ranges); state machines (steps, transitions, what persists, what resets); auth and permissions; idempotency and retries; what is mocked vs real; side effects that are forbidden.
37
30
 
38
- ## Running sessions
31
+ **Boundaries:** what the executor may choose freely (internal names, file structure, helpers) and what it must ask about.
39
32
 
40
- Your Bash tool times out (2 minutes by default, 10 at most), and real tasks usually take longer. Start them detached and wait in bounded slices:
33
+ Write decisions as statements, not wishes: "Reveal: opacity 0→1 and translateY 16px→0, 400 ms, cubic-bezier(.2,.7,.2,1), 60 ms stagger, at 20% visibility; reduced motion: opacity only."
41
34
 
42
- ```sh
43
- zcode task --detach --id <id> --cwd <repo> [flags] "<objective>" # prints the id, returns at once
44
- zcode wait <id> --timeout-ms 540000 --json --quiet # exit 124 = still running: wait again
45
- ```
35
+ ## Shaping the work
46
36
 
47
- You can also run a foreground `zcode task … --json --quiet` with `run_in_background: true` and read its single result line when you're notified. Quick tasks (well under 2 minutes) can run in the foreground directly.
37
+ Pick the cheapest shape that keeps each session finishable without you.
48
38
 
49
- - `zcode status` lists sessions. `zcode status <id> --json` shows the state (`queued|running|finished|interrupted`), phase (`starting|executing|checking|repairing|reporting`), activity, recent events, and the result once finished. Use it only when you need it. You don't have to watch progress, and nothing waits for your approval.
50
- - `zcode cancel <id>` stops the turn and any running check; the session is recorded as `cancelled`.
51
- - `zcode resume <id> "<message>"` continues the same session with its context intact. Use it to answer questions, request follow-up changes, or continue after `interrupted`, `failed`, or `partial`. It accepts `--detach`, `--model`, `--effort`, `--timeout-ms`, and `--max-repairs`. The scope (`--cwd`, `--owns`, checks) stays as it was.
52
- - Pick your own `--id` values (`page-1`, `fix-auth`) so you can retry safely. A start with an existing id is refused (exit 2) instead of running the work twice.
39
+ - **One session with units** when the pieces share context (one page's sections, one module's functions). `--unit "hero: …"` per piece; zcode gives each unit its own subagent and integrates.
40
+ - **Several sessions** when pieces are independent and own disjoint paths. Launch them `--detach` in parallel; each may have its own units.
41
+ - **A plan** when there are dependencies (scaffold → parallel features → integration). `zcode plan run plan.json` sequences and parallelises for you; you wait once.
53
42
 
54
- ## Parallel sessions
43
+ Parallel safety is automatic: each session gets `ZCODE_PORT`, `ZCODE_OUT`, `ZCODE_TMP` and `ZCODE_SESSION_ID`. Tell the first (scaffold) session to make dev-server ports, build output dirs and test artifacts honour them. Target repos should ignore `.zcode/`.
55
44
 
56
- - Each session has its own engine context, so nothing leaks between them.
57
- - Sessions in the same repo must declare disjoint `--owns`. An overlapping start is refused with exit 7, and the error names the conflicting session. Fix the split, wait, or give the session its own `git worktree` and point `--cwd` at it.
58
- - After the work, each handback lists changed files. Anything outside the session's ownership appears in `scopeViolations` and makes the result `partial`.
59
- - You integrate the results. zcode doesn't coordinate sessions with each other.
45
+ ## The handoff
60
46
 
61
- ## Reading the handback
47
+ | field | flag | give it when |
48
+ |---|---|---|
49
+ | objective | positional text | always: the outcome, not the steps |
50
+ | decisions | `--decision "…"`, `--decisions @file` | always for anything user-visible or behavioural |
51
+ | checks | `--check "cmd"` | always: build, typecheck, tests, lint, greps — zcode runs them itself |
52
+ | visual | `--visual "criterion"`, `--viewport WxH`, `--serve "cmd"` | any UI work: zcode serves on $ZCODE_PORT, screenshots, judges and repairs |
53
+ | units | `--unit "name: objective [owns a,b]"` | one session should fan out to subagents |
54
+ | owns | `--owns path/glob` | always when other sessions may run in the same repo |
55
+ | touch | `--touch path` | a small edit to a shared file no running session owns |
56
+ | files | `--file path` | files to read first (don't also pass them as `--context @`) |
57
+ | context | `--context "…"` / `--context @file` | background that isn't a decision |
58
+ | acceptance | `--accept "…"` | criteria beyond checks and visuals |
59
+ | everything | `--task contract.json` | keys: objective, scope, constraints, decisions, design, acceptance, checks, visual, viewports, units, files, references, context, owns, touch, limits, model, effort |
62
60
 
63
- The result (`--json`: one `{"type":"result"}` line) has `status`, `summary`, `changes.files`, `checks` (zcode's own runs, with output tails), `issues`, `questions`, `unresolved`, `notVerified`, `scopeViolations`, `subagents`, and `handback` (the executor's own claims).
61
+ Model and effort: `--model glm-5.3` for real work (`flash` for trivial edits); `--effort low|high|max` (default `max`). Other values are refused before anything starts.
64
62
 
65
- | status | exit | what it means | what you do |
66
- |---|---|---|---|
67
- | `completed` | 0 | zcode's checks passed, executor reports done, scope respected | review on your own schedule; integrate |
68
- | `unverified` | 9 | executor says done, but there were no checks (or no usable handback) | verify yourself, or resume with a check added to the message |
69
- | `partial` | 8 | work remains, a criterion is unmet, or files changed outside scope | read `issues`/`unresolved`/`scopeViolations`; resume or re-scope |
70
- | `blocked` | 10 | needs you: see `questions` | decide, then `zcode resume <id> "<answer>"` |
71
- | `failed` | 8 / 5 / 124 | `error.kind`: `checks_failed` (still failing after repairs), turn/engine error, or `timeout` | read `checks[].output` / `error`; resume with guidance or re-scope |
72
- | `cancelled` | 130 | stopped | resume if wanted |
63
+ ## Running
73
64
 
74
- Trust `status`, `checks`, and `changes`. They come from what zcode observed. Treat `handback` and `summary` as the executor's report. A subagent's `success` only means it returned. zcode already verified the integrated result through your checks, so you don't need to review per subagent or per step.
65
+ ```sh
66
+ zcode task --detach --id <id> --cwd <repo> [flags] "<objective>" # prints the id, returns at once
67
+ zcode wait <id…> --timeout-ms 540000 --json --quiet # 124 = still running (one line each): wait again
68
+ zcode wait <id…> --any --timeout-ms 540000 --json --quiet # return on the first that finishes
69
+ zcode resume <id> "<answer or follow-up>" --detach # same session, context intact
70
+ zcode result <id> [--full] # brief again, or the full record
71
+ zcode cancel <id>
72
+ ```
75
73
 
76
- ## Example: small task
74
+ Plans:
77
75
 
78
76
  ```sh
79
- zcode task --id fix-typo --cwd ~/site --owns README.md \
80
- --check "grep -q '^# Acme Docs' README.md" \
81
- "Fix the misspelled top-level heading in README.md (should read 'Acme Docs')" --json --quiet
77
+ zcode plan check plan.json
78
+ zcode plan run plan.json --detach [--preflight]
79
+ zcode plan wait <name> --timeout-ms 540000 --json # one summary line per session; details only for non-completed
80
+ zcode plan resume <name> ["<message>"] # resume failed/partial, relaunch skipped
81
+ zcode plan resume <name> --session <id> "<answer>" # answer one blocked session
82
82
  ```
83
83
 
84
- Exit 0 means it's done. The result line shows the single changed file and the passing check.
84
+ `plan.json`: `{"cwd"?, "decisions"?, "context"?, "files"?, "model"?, "effort"?, "sessions": [{"id", "after"?: [ids], ...contract keys}]}`. Top-level decisions/context/files go to every session; `@` entries are files relative to the plan. The plan name is the file basename (or `--id`). Sessions that can run at the same time must own disjoint paths; `plan check` enforces it. When an upstream session ends non-completed, its dependants are `skipped` until you `plan resume`.
85
85
 
86
- ## Example: Page 1 and Page 2 in parallel
86
+ Your Bash tool times out at 10 minutes; always wait in bounded slices. Run the wait with `run_in_background` if you have other planning to do.
87
87
 
88
- You've already decided the design. Each page gets its own session, its own scope, and its own checks:
88
+ ## Reading the brief
89
89
 
90
- ```sh
91
- zcode task --detach --id page-1 --cwd ~/site --label "Home page" \
92
- --owns src/pages/home/ --file src/theme.ts \
93
- --context @specs/home.md \
94
- --accept "Hero, three feature cards, footer CTA as specified" \
95
- --check "npm run build" --check "npm test -- home" \
96
- "Implement the Home page exactly as specified in the context"
97
-
98
- zcode task --detach --id page-2 --cwd ~/site --label "Pricing page" \
99
- --owns src/pages/pricing/ --file src/theme.ts \
100
- --context @specs/pricing.md \
101
- --accept "Three plan cards, middle one highlighted; monthly/yearly toggle" \
102
- --check "npm run build" --check "npm test -- pricing" \
103
- "Implement the Pricing page exactly as specified in the context"
104
-
105
- zcode wait page-1 page-2 --timeout-ms 540000 --json --quiet # repeat while exit is 124
90
+ `--json` prints one compact line: `status`, `summary`, `files`, failing check tails, `questions`, `issues`, `unresolved`, `scopeViolations`, `touched`, `decisions`, `visual`, `units`, and `result` (path to the full record).
91
+
92
+ | status | exit | do |
93
+ |---|---|---|
94
+ | `completed` | 0 | nothing. Skim `decisions` (the executor's own in-scope choices); veto with `resume` only if one is wrong |
95
+ | `blocked` | 10 | answer `questions` (they come with options and a recommendation) via `zcode resume <id> "<answer>"`, and add the answer to your decisions file |
96
+ | `partial` | 8 | read `issues` / `unresolved` / unmet `visual` / `scopeViolations`; resume with one-line guidance or re-scope |
97
+ | `failed` | 8/5/124 | read the failing check `tail` or `error`; resume with guidance |
98
+ | `unverified` | 9 | you forgot checks: resume with a check added |
99
+ | `cancelled` | 130 | resume if wanted |
100
+
101
+ ## Hard rules after dispatch
102
+
103
+ - Don't open files a `completed` session changed. Don't re-run checks it ran. Don't look at its screenshots.
104
+ - Don't poll `status`; use `wait`.
105
+ - Don't fix code yourself; `resume` the session with one line.
106
+ - Need to know something about the result? `zcode result <id> --full` first; read code only as a last resort.
107
+ - Don't ask zcode to commit, push, publish or deploy unless the user asked; when they did, make it its own final session gated on everything else being `completed`.
108
+
109
+ ## Example: a marketing one-pager with an application form
110
+
111
+ You read the empty repo, decide the design system, copy, motion, form logic and demo constraints, and write `docs/decisions.md`. Then `plan.json`:
112
+
113
+ ```json
114
+ {
115
+ "decisions": ["@docs/decisions.md"],
116
+ "model": "glm-5.3", "effort": "high",
117
+ "sessions": [
118
+ {"id": "scaffold", "owns": ["package.json", "package-lock.json", "index.html", "*.config.*", "tsconfig*.json", "src/app/**", "src/styles/**", "src/components/**", "e2e/smoke.spec.ts", ".gitignore"],
119
+ "objective": "Vite + React + TS scaffold, tokens, shared shell, stubs for src/landing and src/apply; dev/preview/e2e honour ZCODE_PORT and ZCODE_OUT",
120
+ "checks": ["npm run build", "npm test", "npm run e2e"]},
121
+ {"id": "landing", "after": ["scaffold"], "owns": ["src/landing/**", "e2e/landing.spec.ts"],
122
+ "objective": "All landing sections per the decisions",
123
+ "units": ["hero: …", "highlights: …", "products: …", "how: …", "charges: …", "faqs: …", "about-cta: …"],
124
+ "checks": ["npm run build", "npx playwright test e2e/landing.spec.ts"],
125
+ "visual": ["hero headline fits on two lines at 390px", "product cards align on one row at 1440px", "no text overlaps any circle motif"]},
126
+ {"id": "apply", "after": ["scaffold"], "owns": ["src/apply/**", "e2e/apply.spec.ts"],
127
+ "objective": "Application dialog: demo OTP, four steps, local draft, thank-you",
128
+ "checks": ["npm run build", "npm test -- apply", "npx playwright test e2e/apply.spec.ts"],
129
+ "visual": ["OTP code is visible on screen after entering a number", "step indicator shows the current step at 390px"]},
130
+ {"id": "integration", "after": ["landing", "apply"], "owns": ["src/App.tsx", "e2e/**"],
131
+ "objective": "Wire everything, full-page pass, fix integration issues",
132
+ "checks": ["npm run build", "npm test", "npm run e2e"],
133
+ "visual": ["full page at 390 and 1440 matches the decisions; motion respects reduced motion"]}
134
+ ]
135
+ }
106
136
  ```
107
137
 
108
- If `page-2` comes back `blocked` with "Should yearly prices show the discount badge?", decide and run `zcode resume page-2 "Yes, show the 'Save 20%' badge on yearly." --detach`, then wait again. To run the pages one after another instead, start `page-2` after `page-1`'s handback. The shared `src/theme.ts` is passed with `--file` (read), not owned, so a change to it by either session would come back as a scope violation. If a page truly needs a shared change, make it yourself or give that file to exactly one session's `--owns`.
138
+ `zcode plan check plan.json` → `zcode plan run plan.json --preflight` (read-only `<id>.pre` sessions; prints only the questions) → answer them once in the decisions file → `zcode plan run plan.json --detach` → `zcode plan wait plan --timeout-ms 540000 --json`. Your total involvement: the decisions, one answer pass, one summary.
109
139
 
110
140
  ## Exit codes
111
141
 
112
- 0 completed · 2 usage (bad flag, contract, or duplicate id) · 3 no key · 4 no engine · 5 failed · 6 `agent` had no subagent · 7 workspace conflict / session busy · 8 partial or checks failing · 9 unverified · 10 blocked · 124 timeout (for `wait`: still running) · 130 cancelled.
142
+ 0 completed · 2 usage (bad flag, contract, plan, effort, or duplicate id) · 3 no key · 4 no engine · 5 failed · 6 `agent` had no subagent · 7 workspace conflict / session busy · 8 partial or checks failing · 9 unverified · 10 blocked · 124 timeout (for `wait`: still running) · 130 cancelled.
@@ -1,114 +1,142 @@
1
1
  ---
2
2
  name: zcode
3
- description: Delegate scoped implementation work to the zcode CLI (GLM-5.3 executor) and consume its verified handback. Use when you are orchestrating and want a page, component, fix or other bounded unit implemented and checked by an independent executor session — alone or several in parallel — while you keep product, design and planning decisions.
3
+ description: Delegate scoped implementation work to the zcode CLI (GLM-5.3 executor, vision-capable, has Playwright) and consume its compact verified handback. Use when you are orchestrating: you make the product, design and logic decisions once, then zcode implements, tests, visually verifies and repairs — in one session with subagent units, several parallel sessions, or a dependency plan — while you spend tokens only on decisions and exceptions.
4
4
  ---
5
5
 
6
6
  # Operating zcode as an executor
7
7
 
8
- zcode is a CLI execution engine. You hand it a scoped task; it implements the task in its own session, runs your acceptance checks itself, repairs failures within a budget, and returns a structured handback. You stay the orchestrator. You decide what to build and how it should look, how to split the work, when to run sessions in parallel, and when to review. zcode decides routine implementation details within the scope you give it.
8
+ zcode is a CLI execution engine. You decide; it builds. It implements a scoped task in its own session, runs your checks itself, screenshots and judges UI with its own vision when you ask, repairs failures within a budget, and returns a small structured handback.
9
9
 
10
- Check it is ready once per machine: `zcode doctor` (exit 3 means no key, so run `zcode login`; exit 4 means the engine is missing).
10
+ **The point is token economy.** Your tokens go to decisions and exceptions. Everything mechanical — writing code, running builds and tests, reading diffs, looking at screenshots, fixing small failures — is zcode's. If you are doing any of that after dispatch, you are paying twice.
11
11
 
12
- ## When to use it
12
+ Check readiness once per machine: `zcode doctor` (exit 3 → `zcode login`; exit 4 → engine missing). Don't run `--help`: everything you need is here.
13
13
 
14
- - Use it for bounded implementation work with a clear outcome: one page, a few components, a bug fix, a refactor of a known area, a test suite for a module.
15
- - Don't use it for product or design decisions, open-ended exploration, or work you can't describe a finished state for. Decide those yourself first, then delegate the implementation.
16
- - Size each session so you could review its result in one sitting. Several small sessions beat one huge one, because each returns its own evidence.
14
+ ## The workflow
17
15
 
18
- ## Writing the handoff
16
+ 1. **Read** the codebase as much as you need to plan. This is the one phase where reading files is expected.
17
+ 2. **Decide** everything a user could see or a system depends on (checklists below). Write the decisions down once, as decisions — a file such as `docs/decisions.md` that sessions receive with `--decisions @file`.
18
+ 3. **Shape** the work: one session with units, several sessions, or a plan (next section).
19
+ 4. **Preflight** (optional, recommended for anything large or ambiguous): `--preflight` makes zcode list every question it would otherwise guess. Answer them all in one edit to the decisions file.
20
+ 5. **Dispatch and wait** with `--detach` + `zcode wait`, or `zcode plan run` + `zcode plan wait`.
21
+ 6. **Handle exceptions only.** `completed` → move on. Anything else → read only what the brief shows, answer or adjust in one line with `zcode resume`.
19
22
 
20
- Only the objective is required. Add what the executor cannot infer:
23
+ ## Deciding: leave nothing open-ended
21
24
 
22
- | field | flag | give it when |
23
- |---|---|---|
24
- | objective | positional text | always: the outcome, not the steps |
25
- | acceptance | `--accept "…"` | you have criteria beyond "it works" |
26
- | checks | `--check "cmd"` | always if possible: shell commands zcode runs itself (build, tests, lint, a grep) |
27
- | owns | `--owns path/or/glob` | other sessions may touch the same repo |
28
- | files | `--file path` | specific files to read first |
29
- | context / design | `--context "…"` or `--context @notes.md` | design decisions, copy, references, constraints |
30
- | everything | `--task contract.json` | larger handoffs (keys: objective, scope, constraints, design, acceptance, checks, files, references, context, owns, limits, model, effort) |
31
-
32
- Rules that keep you in charge:
25
+ The executor implements binding decisions exactly and is told not to invent anything user-visible or behavioural. Gaps either block it (a round trip for you) or get the most conservative default. Close them up front.
33
26
 
34
- - Put design decisions in `design` (JSON) or `--context`, written as decisions ("Hero uses the dark palette; CTA right-aligned"). The executor is told to implement them exactly and to report `blocked` rather than invent product or design choices.
35
- - Make checks mechanical and fast. A task with no `--check` can only come back `unverified`.
36
- - Don't ask zcode to commit, push, or deploy unless you mean it. It won't by default.
27
+ **Front end:** palette (exact values), type families and scale, spacing scale, radii, iconography/illustration style; every section's layout and hierarchy at each breakpoint you care about; exact copy; component states (hover, focus, active, disabled, loading, empty, error); motion (what moves, property, distance, duration, easing, stagger, trigger, reduced-motion behaviour); accessibility (focus order, traps, labels, contrast floor); stack and libraries; performance budget.
37
28
 
38
- ## Running sessions
29
+ **Back end / logic:** data shapes and storage keys; API routes, payloads, status codes and errors; validation rules (exact regexes, ranges); state machines (steps, transitions, what persists, what resets); auth and permissions; idempotency and retries; what is mocked vs real; side effects that are forbidden.
39
30
 
40
- zcode needs network access (the GLM API) and write access to `~/.zcode-cli` and the target repo. In a sandboxed Codex session, those commands may fail with sandbox or network errors. If they do, re-run the same command with escalated permissions instead of changing the command.
31
+ **Boundaries:** what the executor may choose freely (internal names, file structure, helpers) and what it must ask about.
41
32
 
42
- Real tasks usually outlast a single shell call's timeout. Start them detached and wait in bounded slices:
33
+ Write decisions as statements, not wishes: "Reveal: opacity 0→1 and translateY 16px→0, 400 ms, cubic-bezier(.2,.7,.2,1), 60 ms stagger, at 20% visibility; reduced motion: opacity only."
43
34
 
44
- ```sh
45
- zcode task --detach --id <id> --cwd <repo> [flags] "<objective>" # prints the id, returns at once
46
- zcode wait <id> --timeout-ms 540000 --json --quiet # exit 124 = still running: wait again
47
- ```
35
+ ## Shaping the work
48
36
 
49
- Quick tasks can run in the foreground: `zcode task … --json --quiet` prints exactly one result line.
37
+ Pick the cheapest shape that keeps each session finishable without you.
50
38
 
51
- - `zcode status` lists sessions. `zcode status <id> --json` shows the state (`queued|running|finished|interrupted`), phase (`starting|executing|checking|repairing|reporting`), activity, recent events, and the result once finished. Use it only when you need it. You don't have to watch progress, and nothing waits for your approval.
52
- - `zcode cancel <id>` stops the turn and any running check; the session is recorded as `cancelled`.
53
- - `zcode resume <id> "<message>"` continues the same session with its context intact. Use it to answer questions, request follow-up changes, or continue after `interrupted`, `failed`, or `partial`. It accepts `--detach`, `--model`, `--effort`, `--timeout-ms`, and `--max-repairs`. The scope (`--cwd`, `--owns`, checks) stays as it was.
54
- - Pick your own `--id` values (`page-1`, `fix-auth`) so you can retry safely. A start with an existing id is refused (exit 2) instead of running the work twice.
39
+ - **One session with units** when the pieces share context (one page's sections, one module's functions). `--unit "hero: …"` per piece; zcode gives each unit its own subagent and integrates.
40
+ - **Several sessions** when pieces are independent and own disjoint paths. Launch them `--detach` in parallel; each may have its own units.
41
+ - **A plan** when there are dependencies (scaffold → parallel features → integration). `zcode plan run plan.json` sequences and parallelises for you; you wait once.
55
42
 
56
- ## Parallel sessions
43
+ Parallel safety is automatic: each session gets `ZCODE_PORT`, `ZCODE_OUT`, `ZCODE_TMP` and `ZCODE_SESSION_ID`. Tell the first (scaffold) session to make dev-server ports, build output dirs and test artifacts honour them. Target repos should ignore `.zcode/`.
57
44
 
58
- - Each session has its own engine context, so nothing leaks between them.
59
- - Sessions in the same repo must declare disjoint `--owns`. An overlapping start is refused with exit 7, and the error names the conflicting session. Fix the split, wait, or give the session its own `git worktree` and point `--cwd` at it.
60
- - After the work, each handback lists changed files. Anything outside the session's ownership appears in `scopeViolations` and makes the result `partial`.
61
- - You integrate the results. zcode doesn't coordinate sessions with each other.
45
+ ## The handoff
62
46
 
63
- ## Reading the handback
47
+ | field | flag | give it when |
48
+ |---|---|---|
49
+ | objective | positional text | always: the outcome, not the steps |
50
+ | decisions | `--decision "…"`, `--decisions @file` | always for anything user-visible or behavioural |
51
+ | checks | `--check "cmd"` | always: build, typecheck, tests, lint, greps — zcode runs them itself |
52
+ | visual | `--visual "criterion"`, `--viewport WxH`, `--serve "cmd"` | any UI work: zcode serves on $ZCODE_PORT, screenshots, judges and repairs |
53
+ | units | `--unit "name: objective [owns a,b]"` | one session should fan out to subagents |
54
+ | owns | `--owns path/glob` | always when other sessions may run in the same repo |
55
+ | touch | `--touch path` | a small edit to a shared file no running session owns |
56
+ | files | `--file path` | files to read first (don't also pass them as `--context @`) |
57
+ | context | `--context "…"` / `--context @file` | background that isn't a decision |
58
+ | acceptance | `--accept "…"` | criteria beyond checks and visuals |
59
+ | everything | `--task contract.json` | keys: objective, scope, constraints, decisions, design, acceptance, checks, visual, viewports, units, files, references, context, owns, touch, limits, model, effort |
64
60
 
65
- The result (`--json`: one `{"type":"result"}` line) has `status`, `summary`, `changes.files`, `checks` (zcode's own runs, with output tails), `issues`, `questions`, `unresolved`, `notVerified`, `scopeViolations`, `subagents`, and `handback` (the executor's own claims).
61
+ Model and effort: `--model glm-5.3` for real work (`flash` for trivial edits); `--effort low|high|max` (default `max`). Other values are refused before anything starts.
66
62
 
67
- | status | exit | what it means | what you do |
68
- |---|---|---|---|
69
- | `completed` | 0 | zcode's checks passed, executor reports done, scope respected | review on your own schedule; integrate |
70
- | `unverified` | 9 | executor says done, but there were no checks (or no usable handback) | verify yourself, or resume with a check added to the message |
71
- | `partial` | 8 | work remains, a criterion is unmet, or files changed outside scope | read `issues`/`unresolved`/`scopeViolations`; resume or re-scope |
72
- | `blocked` | 10 | needs you: see `questions` | decide, then `zcode resume <id> "<answer>"` |
73
- | `failed` | 8 / 5 / 124 | `error.kind`: `checks_failed` (still failing after repairs), turn/engine error, or `timeout` | read `checks[].output` / `error`; resume with guidance or re-scope |
74
- | `cancelled` | 130 | stopped | resume if wanted |
63
+ ## Running
75
64
 
76
- Trust `status`, `checks`, and `changes`. They come from what zcode observed. Treat `handback` and `summary` as the executor's report. A subagent's `success` only means it returned. zcode already verified the integrated result through your checks, so you don't need to review per subagent or per step.
65
+ ```sh
66
+ zcode task --detach --id <id> --cwd <repo> [flags] "<objective>" # prints the id, returns at once
67
+ zcode wait <id…> --timeout-ms 540000 --json --quiet # 124 = still running (one line each): wait again
68
+ zcode wait <id…> --any --timeout-ms 540000 --json --quiet # return on the first that finishes
69
+ zcode resume <id> "<answer or follow-up>" --detach # same session, context intact
70
+ zcode result <id> [--full] # brief again, or the full record
71
+ zcode cancel <id>
72
+ ```
77
73
 
78
- ## Example: small task
74
+ Plans:
79
75
 
80
76
  ```sh
81
- zcode task --id fix-typo --cwd ~/site --owns README.md \
82
- --check "grep -q '^# Acme Docs' README.md" \
83
- "Fix the misspelled top-level heading in README.md (should read 'Acme Docs')" --json --quiet
77
+ zcode plan check plan.json
78
+ zcode plan run plan.json --detach [--preflight]
79
+ zcode plan wait <name> --timeout-ms 540000 --json # one summary line per session; details only for non-completed
80
+ zcode plan resume <name> ["<message>"] # resume failed/partial, relaunch skipped
81
+ zcode plan resume <name> --session <id> "<answer>" # answer one blocked session
84
82
  ```
85
83
 
86
- Exit 0 means it's done. The result line shows the single changed file and the passing check.
84
+ `plan.json`: `{"cwd"?, "decisions"?, "context"?, "files"?, "model"?, "effort"?, "sessions": [{"id", "after"?: [ids], ...contract keys}]}`. Top-level decisions/context/files go to every session; `@` entries are files relative to the plan. The plan name is the file basename (or `--id`). Sessions that can run at the same time must own disjoint paths; `plan check` enforces it. When an upstream session ends non-completed, its dependants are `skipped` until you `plan resume`.
87
85
 
88
- ## Example: Page 1 and Page 2 in parallel
86
+ Real tasks outlast a single shell call; always wait in bounded slices. zcode needs network access (the GLM API) and write access to `~/.zcode-cli` and the target repo: in a sandboxed Codex session, if a command fails with a sandbox or network error, re-run the same command with escalated permissions instead of changing it.
89
87
 
90
- You've already decided the design. Each page gets its own session, its own scope, and its own checks:
88
+ ## Reading the brief
91
89
 
92
- ```sh
93
- zcode task --detach --id page-1 --cwd ~/site --label "Home page" \
94
- --owns src/pages/home/ --file src/theme.ts \
95
- --context @specs/home.md \
96
- --accept "Hero, three feature cards, footer CTA as specified" \
97
- --check "npm run build" --check "npm test -- home" \
98
- "Implement the Home page exactly as specified in the context"
99
-
100
- zcode task --detach --id page-2 --cwd ~/site --label "Pricing page" \
101
- --owns src/pages/pricing/ --file src/theme.ts \
102
- --context @specs/pricing.md \
103
- --accept "Three plan cards, middle one highlighted; monthly/yearly toggle" \
104
- --check "npm run build" --check "npm test -- pricing" \
105
- "Implement the Pricing page exactly as specified in the context"
106
-
107
- zcode wait page-1 page-2 --timeout-ms 540000 --json --quiet # repeat while exit is 124
90
+ `--json` prints one compact line: `status`, `summary`, `files`, failing check tails, `questions`, `issues`, `unresolved`, `scopeViolations`, `touched`, `decisions`, `visual`, `units`, and `result` (path to the full record).
91
+
92
+ | status | exit | do |
93
+ |---|---|---|
94
+ | `completed` | 0 | nothing. Skim `decisions` (the executor's own in-scope choices); veto with `resume` only if one is wrong |
95
+ | `blocked` | 10 | answer `questions` (they come with options and a recommendation) via `zcode resume <id> "<answer>"`, and add the answer to your decisions file |
96
+ | `partial` | 8 | read `issues` / `unresolved` / unmet `visual` / `scopeViolations`; resume with one-line guidance or re-scope |
97
+ | `failed` | 8/5/124 | read the failing check `tail` or `error`; resume with guidance |
98
+ | `unverified` | 9 | you forgot checks: resume with a check added |
99
+ | `cancelled` | 130 | resume if wanted |
100
+
101
+ ## Hard rules after dispatch
102
+
103
+ - Don't open files a `completed` session changed. Don't re-run checks it ran. Don't look at its screenshots.
104
+ - Don't poll `status`; use `wait`.
105
+ - Don't fix code yourself; `resume` the session with one line.
106
+ - Need to know something about the result? `zcode result <id> --full` first; read code only as a last resort.
107
+ - Don't ask zcode to commit, push, publish or deploy unless the user asked; when they did, make it its own final session gated on everything else being `completed`.
108
+
109
+ ## Example: a marketing one-pager with an application form
110
+
111
+ You read the empty repo, decide the design system, copy, motion, form logic and demo constraints, and write `docs/decisions.md`. Then `plan.json`:
112
+
113
+ ```json
114
+ {
115
+ "decisions": ["@docs/decisions.md"],
116
+ "model": "glm-5.3", "effort": "high",
117
+ "sessions": [
118
+ {"id": "scaffold", "owns": ["package.json", "package-lock.json", "index.html", "*.config.*", "tsconfig*.json", "src/app/**", "src/styles/**", "src/components/**", "e2e/smoke.spec.ts", ".gitignore"],
119
+ "objective": "Vite + React + TS scaffold, tokens, shared shell, stubs for src/landing and src/apply; dev/preview/e2e honour ZCODE_PORT and ZCODE_OUT",
120
+ "checks": ["npm run build", "npm test", "npm run e2e"]},
121
+ {"id": "landing", "after": ["scaffold"], "owns": ["src/landing/**", "e2e/landing.spec.ts"],
122
+ "objective": "All landing sections per the decisions",
123
+ "units": ["hero: …", "highlights: …", "products: …", "how: …", "charges: …", "faqs: …", "about-cta: …"],
124
+ "checks": ["npm run build", "npx playwright test e2e/landing.spec.ts"],
125
+ "visual": ["hero headline fits on two lines at 390px", "product cards align on one row at 1440px", "no text overlaps any circle motif"]},
126
+ {"id": "apply", "after": ["scaffold"], "owns": ["src/apply/**", "e2e/apply.spec.ts"],
127
+ "objective": "Application dialog: demo OTP, four steps, local draft, thank-you",
128
+ "checks": ["npm run build", "npm test -- apply", "npx playwright test e2e/apply.spec.ts"],
129
+ "visual": ["OTP code is visible on screen after entering a number", "step indicator shows the current step at 390px"]},
130
+ {"id": "integration", "after": ["landing", "apply"], "owns": ["src/App.tsx", "e2e/**"],
131
+ "objective": "Wire everything, full-page pass, fix integration issues",
132
+ "checks": ["npm run build", "npm test", "npm run e2e"],
133
+ "visual": ["full page at 390 and 1440 matches the decisions; motion respects reduced motion"]}
134
+ ]
135
+ }
108
136
  ```
109
137
 
110
- If `page-2` comes back `blocked` with "Should yearly prices show the discount badge?", decide and run `zcode resume page-2 "Yes, show the 'Save 20%' badge on yearly." --detach`, then wait again. To run the pages one after another instead, start `page-2` after `page-1`'s handback. The shared `src/theme.ts` is passed with `--file` (read), not owned, so a change to it by either session would come back as a scope violation. If a page truly needs a shared change, make it yourself or give that file to exactly one session's `--owns`.
138
+ `zcode plan check plan.json` → `zcode plan run plan.json --preflight` (read-only `<id>.pre` sessions; prints only the questions) → answer them once in the decisions file → `zcode plan run plan.json --detach` → `zcode plan wait plan --timeout-ms 540000 --json`. Your total involvement: the decisions, one answer pass, one summary.
111
139
 
112
140
  ## Exit codes
113
141
 
114
- 0 completed · 2 usage (bad flag, contract, or duplicate id) · 3 no key · 4 no engine · 5 failed · 6 `agent` had no subagent · 7 workspace conflict / session busy · 8 partial or checks failing · 9 unverified · 10 blocked · 124 timeout (for `wait`: still running) · 130 cancelled.
142
+ 0 completed · 2 usage (bad flag, contract, plan, effort, or duplicate id) · 3 no key · 4 no engine · 5 failed · 6 `agent` had no subagent · 7 workspace conflict / session busy · 8 partial or checks failing · 9 unverified · 10 blocked · 124 timeout (for `wait`: still running) · 130 cancelled.