opencode-gbuild 0.5.0 → 0.6.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.
@@ -1,8 +1,8 @@
1
1
  # Graph shapes
2
2
 
3
3
  `plan` classifies each cluster of nodes it creates into one of these. `run` uses the classification to
4
- decide how to schedule it. This is a lens for judgement, not a field stored on the node — the shape
5
- falls out of `dependencies`.
4
+ decide how to schedule it. This is a lens for judgement, not a property stored on the node — the shape
5
+ falls out of the `DEPENDS_ON` edges.
6
6
 
7
7
  ## Chain
8
8
 
@@ -24,10 +24,11 @@ though nothing requires it; the whole point of a real dependency graph is that `
24
24
  ## Router
25
25
 
26
26
  One node whose output selects which of several downstream nodes actually runs — not all of them, not
27
- none, exactly the branch the output implies. Model this as a `decision`-type node whose `contract.output`
28
- names the chosen branch, with the downstream nodes each depending on it; `run`'s job is to only dispatch
29
- the node(s) the router's output actually selected, and mark the un-selected siblings `cancelled` (which,
30
- per the derived-queries rule, still satisfies anything waiting on "the router resolved").
27
+ none, exactly the branch the output implies. Model this as a `decision`-type node with an `OUTPUT`
28
+ field naming the chosen branch, and each downstream node depending on it with an `INPUT` field `FROM`
29
+ that output; `run`'s job is to only dispatch the node(s) the router's output actually selected, and mark
30
+ the un-selected siblings `cancelled` (which, per the status lifecycle, still satisfies anything waiting
31
+ on "the router resolved").
31
32
 
32
33
  ## Controlled cycle
33
34
 
@@ -40,9 +41,9 @@ in a graph must have, at plan time:
40
41
  - an explicit **exit node** reached either by the verify passing or by hitting the cap and escalating
41
42
 
42
43
  `run` implements this as a bounded loop (see `skills/run/SKILL.md`), never as extra graph edges that
43
- loop back on themselves — `scripts/graph.py` rejects literal cycles in `dependencies` (that's how it
44
- catches a malformed graph). A controlled cycle is a *behavior* `run` executes around a small
45
- sub-cluster, not a topology `graph.py` has to tolerate.
44
+ loop back on themselves — `validate.cypher` rejects literal `DEPENDS_ON` cycles (that's how it catches a
45
+ malformed graph). A controlled cycle is a *behavior* `run` executes around a small sub-cluster, not a
46
+ topology the graph has to tolerate.
46
47
 
47
48
  ## Choosing a shape
48
49
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Decomposes a feature into a real dependency graph in .gbuild/<feature>/db/graph.json — nodes with typed contracts, mandatory concrete acceptance criteria, and edges that pass the cut test. Use when starting new gbuild work, before /gbuild:run.
2
+ description: Decomposes a feature into a real dependency graph in the gbuild CypherLite store (.gbuild/<feature>/db) — nodes with typed field contracts, mandatory concrete acceptance criteria, and edges that pass the cut test. Use when starting new gbuild work, before /gbuild:run.
3
3
  ---
4
4
 
5
5
  Plan the work described in `$ARGUMENTS` as a graph.
@@ -11,9 +11,11 @@ skill: `/gbuild:run <slug>` once — it iterates waves until the graph completes
11
11
  `/gbuild:review <slug>`; if it finds issues, reopen with `/gbuild:plan <slug> --add "<fix>"` and
12
12
  `/gbuild:run` again; if clean, `/gbuild:pr <slug>`.
13
13
 
14
- Read `${CLAUDE_PLUGIN_ROOT}/reference/graph-format.md` before doing anything — it's the normative schema. `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md`,
15
- `${CLAUDE_PLUGIN_ROOT}/reference/failure-policies.md`, and `${CLAUDE_PLUGIN_ROOT}/reference/cost-model.md` inform the choices below.
16
- `${CLAUDE_PLUGIN_ROOT}/reference/checklist.md` is the self-check at the end.
14
+ Read `${CLAUDE_PLUGIN_ROOT}/reference/graph-format.md` (the normative graph model) and
15
+ `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md` (how to talk to the store) before doing anything, and run
16
+ its version check. `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md`,
17
+ `${CLAUDE_PLUGIN_ROOT}/reference/failure-policies.md`, and `${CLAUDE_PLUGIN_ROOT}/reference/cost-model.md`
18
+ inform the choices below. `${CLAUDE_PLUGIN_ROOT}/reference/checklist.md` is the self-check at the end.
17
19
 
18
20
  ## Mode
19
21
 
@@ -22,7 +24,7 @@ Read `${CLAUDE_PLUGIN_ROOT}/reference/graph-format.md` before doing anything —
22
24
  | a description, link, or file path | **Chart** — new feature |
23
25
  | an existing feature slug with `--add "<req>"` | **Reopen** |
24
26
 
25
- A bare slug with no `.gbuild/<slug>/` is a description, not a slug — chart it.
27
+ A bare slug with no `.gbuild/<slug>/db/` is a description, not a slug — chart it.
26
28
 
27
29
  ## Chart
28
30
 
@@ -30,7 +32,7 @@ A bare slug with no `.gbuild/<slug>/` is a description, not a slug — chart it.
30
32
 
31
33
  Derive the feature slug from `$ARGUMENTS`: kebab-case, ≤4 words, names the outcome not the mechanism
32
34
  (`oauth-device-flow`, not `add-some-auth-stuff`). It's the `.gbuild/<slug>/` directory name and the
33
- `feature` field in `graph.json` — immutable once charted.
35
+ `Feature` node's `feature` property — immutable once charted.
34
36
 
35
37
  Then get onto a branch for it, so `run`'s commits land somewhere isolated:
36
38
 
@@ -44,9 +46,9 @@ Report the branch. Everything below happens on it.
44
46
 
45
47
  ### 2. Analyse the codebase
46
48
 
47
- Read the project manifest(s), directory structure, `README.md`, and any existing `.gbuild/*/db/graph.json`
48
- for related in-flight work. Resolve file paths or URLs in `$ARGUMENTS`; if a reference fails to load,
49
- say so and ask.
49
+ Read the project manifest(s), directory structure, `README.md`, and — for related in-flight work — the
50
+ `Feature` of every existing store (`feature.cypher` against each `.gbuild/*/db`, one at a time). Resolve
51
+ file paths or URLs in `$ARGUMENTS`; if a reference fails to load, say so and ask.
50
52
 
51
53
  ### 3. Validate and explore
52
54
 
@@ -77,8 +79,8 @@ the survey when there's only one real way — don't perform thoroughness for its
77
79
  a `research`-typed GbuildNode in the first wave — `plan` charts it, `run` executes it. `plan` does
78
80
  not run prototypes inline (the "Plan, don't do" rule below). The one exception: a check so cheap it
79
81
  finishes in a single tool call (grep, read a file, check an installed version) — do that inline and
80
- note the result. A prototype worth charting names the specific question it answers in its
81
- `contract.output`, and its `acceptance` is the answer to that question.
82
+ note the result. A prototype worth charting names the specific question it answers in its `OUTPUT`
83
+ field, and its `acceptance` is the answer to that question.
82
84
 
83
85
  ### 4. Name the destination
84
86
 
@@ -87,111 +89,103 @@ done. Do not proceed until it's that sharp; everything past it goes in `out_of_s
87
89
 
88
90
  ### 5. Decompose into nodes, not steps
89
91
 
90
- List the real pieces of work. For each pair, apply the **cut test** (`${CLAUDE_PLUGIN_ROOT}/reference/graph-format.md`):
91
- does one actually read the other's output? If no, they're independent — same wave, not a chain. This is
92
- the step hone-ai v1 skipped, and the whole reason gbuild exists: state the true dependency structure,
93
- don't default to the order you thought of things in.
94
-
95
- Classify each cluster's shape per `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md` (chain / diamond / router / controlled cycle).
96
- A controlled cycle needs its round cap and dedup rule decided now, not left to `run` to invent.
97
-
98
- The graph is a **CypherLite GraphData file** (see `${CLAUDE_PLUGIN_ROOT}/reference/graph-format.md` — normative). You
99
- write three kinds of nodes and three kinds of relationships:
100
-
101
- - **`Feature` node** (id 1) — one per graph, properties `feature` (the slug), `destination`, `context`,
102
- `out_of_scope` (array). No `acceptance` property here.
103
- - **`Acceptance` nodes** — one per feature-level bullet, properties `id` (`a-1`, `a-2`, …) and `text`.
104
- Each linked `Feature -[:HAS_ACCEPTANCE]-> Acceptance`.
105
- - **`GbuildNode`s** — one per unit of work. Integer `id` (sequential after the Feature and Acceptance
106
- nodes), `labels` `["GbuildNode", <PascalCase type>]`, properties `slug` / `title` / `type` (lowercase
107
- enum) / `contract` (`{input,output}`) / `acceptance` (node-level local criteria) / `verify` / `failure_policy`
108
- / `model_tier`. No `satisfies` property — use a `SATISFIES` edge instead.
109
- - **`DEPENDS_ON` relationships** — one per dependency that passed the cut test. Direction
110
- dependent→dependency (`start_node` depends on `end_node`). Both endpoints are GbuildNodes.
111
- - **`SATISFIES` relationships** — `GbuildNode -[:SATISFIES]-> Acceptance` for each global criterion a
112
- node covers.
113
- - **`HAS_ACCEPTANCE` relationships** — `Feature -[:HAS_ACCEPTANCE]-> Acceptance`, one per bullet.
114
-
115
- For each GbuildNode, write:
116
-
117
- - `id` — integer, sequential, unique, never reused. Authoring convenience; `slug` is the stable identity.
118
- - `slug` — filename-safe, kebab-case, immutable once created. This is what skills and checkpoint files
119
- key on; it's how nodes are referred to in anything the user reads.
120
- - `type` — `research | decision | code | test | verify | chore`. Set both the lowercase `type` property
121
- and the matching PascalCase label (`Code`, `Research`, …).
122
- - `contract.input` / `contract.output` — structured shapes, not prose. A downstream node's `input`
123
- should be able to reference an upstream node's `output` field directly.
124
- - `acceptance` — **mandatory, non-empty, concrete.** No vague adjectives ("looks correct", "works
125
- well"). A criterion a fresh context with no other information couldn't check is not concrete enough.
126
- Rewrite it until it names a file, a shape, a value, or a command's result.
127
- - `verify` — only set when this node needs something *beyond* the standard `gbuild-reviewer` pass
128
- (adversarial check, fact-check, human approval). Usually `null`.
129
- - `failure_policy` — pick per `${CLAUDE_PLUGIN_ROOT}/reference/failure-policies.md`, don't default everything to `retry`.
130
- - `model_tier` — `strong` only where judgement, not throughput, is the bottleneck
131
- (`${CLAUDE_PLUGIN_ROOT}/reference/cost-model.md`).
132
-
133
- Wire each dependency as a `DEPENDS_ON` relationship (not a `dependencies` array on the node), and each
134
- criterion a node covers as a `SATISFIES` relationship (not a `satisfies` array). Set `next_node_id` and
135
- `next_rel_id` to `max(id)+1` for each kind. `${CLAUDE_PLUGIN_ROOT}/templates/graph.json` is a complete worked example.
92
+ List the real pieces of work. For each pair, apply the **cut test** (`graph-format.md`): does one
93
+ actually read the other's output? If no, they're independent — same wave, not a chain. This is the step
94
+ hone-ai v1 skipped, and the whole reason gbuild exists: state the true dependency structure, don't
95
+ default to the order you thought of things in.
96
+
97
+ Classify each cluster's shape per `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md` (chain / diamond / router /
98
+ controlled cycle). A controlled cycle needs its round cap and dedup rule decided now, not left to `run`
99
+ to invent.
100
+
101
+ For each GbuildNode decide (full model in `graph-format.md`):
102
+
103
+ - `slug` — kebab-case, immutable; what skills and the store key on. `title` — what the user reads.
104
+ - `type` — `research | decision | code | test | verify | chore`, plus the matching PascalCase label.
105
+ - **`OUTPUT` fields** — every node declares at least one, each with a precise `shape`
106
+ (`<integer>`, `<list of changed file paths>`, `<commit sha>`). Values will be scalars or lists of
107
+ scalars; for anything nested, the shape says it is a JSON-encoded string.
108
+ - **`INPUT` fields** — one per value the node reads. If it comes from another node, wire it
109
+ `FROM` that node's `OUTPUT` field and add the `DEPENDS_ON`. If it comes from the codebase or the
110
+ environment, leave it without `FROM` and say where in its `shape`. The cut test is now concrete:
111
+ a `DEPENDS_ON` exists exactly when the node reads one of the other's outputs.
112
+ - `acceptance` — **mandatory, non-empty, concrete.** No vague adjectives. A criterion a fresh context
113
+ with no other information couldn't check is not concrete enough — rewrite it until it names a file, a
114
+ shape, a value, or a command's result.
115
+ - `verify` — only when the node needs something *beyond* the standard `gbuild-reviewer` pass. Usually
116
+ omitted.
117
+ - `failure_policy` — per `${CLAUDE_PLUGIN_ROOT}/reference/failure-policies.md`, don't default everything
118
+ to `retry`. `model_tier` — `strong` only where judgement, not throughput, is the bottleneck.
119
+ - `status: 'pending'` — every new node starts pending.
136
120
 
137
121
  ### 6. Write the global acceptance bar
138
122
 
139
- The feature-level bar is one `Acceptance` node per bullet, each linked `Feature -[:HAS_ACCEPTANCE]-> Acceptance`,
140
- with ids `a-1`, `a-2`, …. Every bullet must end up covered by at least one node's `SATISFIES` edge —
141
- that's checked in step 7 and enforced by the validator.
123
+ The feature-level bar is one `Acceptance` node per bullet (`id` `a-1`, `a-2`, …), each linked
124
+ `(:Feature)-[:HAS_ACCEPTANCE]->(:Acceptance)`. Every bullet must end up covered by at least one node's
125
+ `SATISFIES` edge — the validator enforces it.
142
126
 
143
127
  ### 7. Self-check against the checklist
144
128
 
145
- Walk every item in `${CLAUDE_PLUGIN_ROOT}/reference/checklist.md` against the graph you just wrote. Fix the graph, don't
146
- annotate around a failing item.
129
+ Walk every item in `${CLAUDE_PLUGIN_ROOT}/reference/checklist.md` against the graph you designed. Fix the
130
+ design, don't annotate around a failing item.
147
131
 
148
- ### 8. Write and validate
132
+ ### 8. Create the store and write the graph
149
133
 
150
- Write `.gbuild/<slug>/db/graph.json` (a CypherLite GraphData file). It lives alone in the `db/` folder so
151
- CypherLite can open that folder as a JSON-store database; checkpoints stay in the sibling
152
- `.gbuild/<slug>/nodes/` directory. **Run the format validator first:**
134
+ Create the store exactly as `reference/cypher.md` § Creating a store shows (`mkdir`, `schema.cypher` with
135
+ `--snapshot-format json`, the `db/.gitignore`).
136
+
137
+ Then write the whole graph as **one** Cypher script, piped through a quoted heredoc.
138
+ `${CLAUDE_PLUGIN_ROOT}/templates/example.cypher` is a complete worked example — follow its structure:
139
+ `.begin`, a single statement of `CREATE` clauses (so variables like `a1` or `a_value` stay in scope for
140
+ the edges), `.commit`, `.checkpoint`.
153
141
 
154
142
  ```
155
- python3 ${CLAUDE_PLUGIN_ROOT}/scripts/validate_format.py .gbuild/<slug>/db/graph.json
143
+ cypherlite .gbuild/<slug>/db <<'CYPHER'
144
+ .begin
145
+ CREATE (f:Feature {feature: '<slug>', destination: '...', context: '...', out_of_scope: ['...']})
146
+ CREATE (a1:Acceptance {id: 'a-1', text: '...'})
147
+ CREATE (f)-[:HAS_ACCEPTANCE]->(a1)
148
+ CREATE (n:GbuildNode:Code {slug: '...', title: '...', type: 'code', acceptance: ['...'],
149
+ failure_policy: 'repair', model_tier: 'cheap', status: 'pending'})
150
+ CREATE (n)-[:OUTPUT]->(n_out:Field {name: '...', shape: '<...>'})
151
+ ...
152
+ CREATE (m)-[:DEPENDS_ON]->(n)
153
+ CREATE (m)-[:INPUT]->(:Field {name: '...', shape: '<...>'})-[:FROM]->(n_out)
154
+ CREATE (m)-[:SATISFIES]->(a1);
155
+ .commit
156
+ .checkpoint
157
+ CYPHER
156
158
  ```
157
159
 
158
- If it prints `invalid: ...`, fix the file and re-run — never hand off or commit a file that fails
159
- validation. The validator is the format gate; it checks the GraphData envelope, node shapes, the three
160
- relationship types, id/counter invariants, acyclicity, and coverage. **Run it after every change** —
161
- initial write, reopen, any hand-edit, any fix-up — before doing anything else with the file.
160
+ A constraint violation (`ConstraintValidationFailed`: a missing property, a wrong type, a duplicate
161
+ slug) fails the transaction and writes nothing — fix the script and run it again.
162
162
 
163
- Then confirm run-readiness:
163
+ ### 9. Validate
164
164
 
165
165
  ```
166
- python3 ${CLAUDE_PLUGIN_ROOT}/scripts/graph.py .gbuild/<slug>/db/graph.json --status
166
+ cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
167
167
  ```
168
168
 
169
- The graph is now queryable with Cypher **if the `cypherlite` binary is on PATH** (`command -v
170
- cypherlite`) — in that case you can mention it to the user. Point CypherLite at the `db/` folder
171
- (not the `.json` file), and keep it read-only:
169
+ No output means valid. Every row is a violation (`check`, `detail`): fix it with Cypher — a `.begin` …
170
+ `.commit` … `.checkpoint` script of `MATCH … SET/CREATE/DELETE` — and re-run until it prints nothing. Never
171
+ hand off or commit a graph that fails validation, and never edit `graph.json` directly.
172
+
173
+ Then confirm run-readiness:
172
174
 
173
175
  ```
174
- cypherlite .gbuild/<slug>/db "MATCH (n:GbuildNode) RETURN n.slug, n.type"
176
+ cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
175
177
  ```
176
178
 
177
- If the binary is absent, skip this without comment. CypherLite is an optional consumer, never a
178
- requirement — `validate_format.py` already cross-checks with it when present and passes without it,
179
- and the user should never be asked to install it.
180
-
181
- ### 9. Fire research nodes
182
-
183
- For each `research`-typed node in the initial wave, dispatch a subagent **in parallel** (one message,
184
- multiple `Agent` calls). Give each the node's `contract.input`, `acceptance`, and enough context to
185
- work independently. Each writes its `output` to `.gbuild/<slug>/nodes/<id>.json` directly (`status:
186
- completed`) — these still get a `gbuild-reviewer` pass before `run` will treat them as satisfying
187
- anyone's dependency, same as every other node type.
179
+ One row per wave: each row's `open` slugs are the decomposition, and the `frontier` counts are what
180
+ `run` claims first. Nodes you expected to run together should share a wave.
188
181
 
189
182
  ### 10. Commit and stop
190
183
 
191
- Commit `.gbuild/<slug>/` unless the repo ignores it (`git check-ignore -q .gbuild/`; if true, don't
192
- stage anything under it). Message: `<slug>: chart graph`.
184
+ Commit `.gbuild/<slug>/` unless the repo ignores it (`git check-ignore -q .gbuild/`; if true, don't stage
185
+ anything under it). The store's own `.gitignore` limits that to `db/graph.json` and `db/.gitignore`.
186
+ Message: `<slug>: chart graph`.
193
187
 
194
- Report the branch, the wave decomposition, and the frontier. Close with `next: /gbuild:run <slug>`.
188
+ Report the branch, the waves, and the frontier. Close with `next: /gbuild:run <slug>`.
195
189
 
196
190
  ## Reopen
197
191
 
@@ -199,22 +193,41 @@ Report the branch, the wave decomposition, and the frontier. Close with `next: /
199
193
 
200
194
  0. Check out the feature's existing branch if you're not on it. Never chart a reopen onto a different
201
195
  branch than the one the graph was charted on.
202
- 1. Add a new `Acceptance` node (next `a-` id) + a `Feature -[:HAS_ACCEPTANCE]-> Acceptance` edge for the
203
- requirement.
204
- 2. Decompose whatever new GbuildNodes it needs, wire `DEPENDS_ON` edges against the *existing* graph (a
205
- new node may depend on an already-completed one — that's fine, its dependency is satisfied) and
206
- `SATISFIES` edges to the new (or existing) `Acceptance` nodes it covers. Assign the next available
207
- integer ids, bump `next_node_id`/`next_rel_id`. Re-run the checklist against the delta.
208
- 3. **Re-run `validate_format.py`** (counters, coverage, acyclicity all re-checked on the mutated graph),
209
- then `graph.py --status`. Commit (`<slug>: reopen graph — <what was added>`), report the new frontier.
196
+ 1. Read the current graph narrowly: `progress.cypher` for its shape and what's done, and `node.cypher`
197
+ only for the nodes the requirement touches.
198
+ 2. Design the delta: a new `Acceptance` node (next `a-` id) linked from the `Feature`, and whatever new
199
+ GbuildNodes it needs, with their `Field`s. A new node may depend on an already-completed one — wire
200
+ its `INPUT` `FROM` that node's `OUTPUT` like any other; its value is already recorded. Re-run the
201
+ checklist against the delta.
202
+ 3. Write it as one script that `MATCH`es what it connects to and `CREATE`s the rest:
203
+
204
+ ```
205
+ cypherlite .gbuild/<slug>/db <<'CYPHER'
206
+ .begin
207
+ MATCH (f:Feature), (up:GbuildNode {slug: '<existing-slug>'})-[:OUTPUT]->(up_out:Field {name: '<field>'})
208
+ CREATE (f)-[:HAS_ACCEPTANCE]->(a:Acceptance {id: 'a-3', text: '...'})
209
+ CREATE (n:GbuildNode:Code {slug: '...', ..., status: 'pending'})
210
+ CREATE (n)-[:DEPENDS_ON]->(up)
211
+ CREATE (n)-[:INPUT]->(:Field {name: '...', shape: '<...>'})-[:FROM]->(up_out)
212
+ CREATE (n)-[:OUTPUT]->(:Field {name: '...', shape: '<...>'})
213
+ CREATE (n)-[:SATISFIES]->(a);
214
+ .commit
215
+ .checkpoint
216
+ CYPHER
217
+ ```
218
+
219
+ 4. **Re-run `validate.cypher`** until it prints nothing, then `progress.cypher`. Commit
220
+ (`<slug>: reopen graph — <what was added>`), report the new frontier.
210
221
 
211
222
  If the requirement needs no new nodes (an existing node's contract already covers it), say so and stop
212
223
  — don't manufacture graph churn.
213
224
 
214
225
  ## Rules
215
226
 
216
- - **Plan, don't do.** Nodes here get *defined*, not executed — even `research` nodes just write
217
- findings to their own checkpoint, they don't touch anything `run` is responsible for.
227
+ - **Plan, don't do.** Nodes here get *defined*, not executed — even `research` nodes. They land in the
228
+ first wave and `run` dispatches them.
229
+ - **The store is only touched through `cypherlite`**, from this skill, one command at a time
230
+ (`reference/cypher.md`).
218
231
  - **Acceptance criteria are the bar, not a formality.** A node with vague acceptance is a node
219
232
  `gbuild-reviewer` can't actually check — that's a planning failure, not something to fix later.
220
- - **Refer to nodes by title in anything the user reads.** IDs are for the graph, not the conversation.
233
+ - **Refer to nodes by title in anything the user reads.** Slugs are for the graph, not the conversation.
@@ -12,7 +12,9 @@ This skill MUST run in the **main conversation context**. It MUST NOT be invoked
12
12
 
13
13
  `$ARGUMENTS` is free-form text: an optional feature slug and an optional `--max-rounds N` flag.
14
14
 
15
- - **slug**: the first token that isn't a flag. If absent, infer it — the current branch commonly ends in the slug (`plan` checks out `<prefix>/<slug>`), otherwise fall back to the most recently modified `.gbuild/*/db/graph.json`. If neither resolves, leave `<slug>` unresolved (the auto-fix step degrades gracefully — see Step 4).
15
+ - **slug**: the first token that isn't a flag. If absent, infer it — the current branch commonly ends in the slug (`plan` checks out `<prefix>/<slug>`), otherwise fall back to the store whose `.gbuild/*/db/graph.json` was most recently modified. If neither resolves, leave `<slug>` unresolved (the auto-fix step degrades gracefully — see Step 4).
16
+
17
+ When `<slug>` resolved, every graph read below goes through `cypherlite`: run `cypherlite --version` first (missing → stop; gbuild needs it), one command at a time, always `--mode jsonl` (no output = no rows), and on `storage locked` wait and retry up to 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
16
18
  - **max_rounds**: the value of `--max-rounds N` (also accept `--max-rounds=N`). Default `3` when absent.
17
19
 
18
20
  ## Step 1: Preconditions
@@ -25,7 +27,7 @@ Verify the environment before touching the remote. Stop with a clear, actionable
25
27
  4. **Not on base.** Get the current branch (`git branch --show-current`). If it equals `<base>`, stop — there is nothing to open a PR for.
26
28
  5. **Clean tree.** Check for uncommitted changes (`git status --porcelain`). `/gbuild:run` commits each node's work as it goes, so the tree should be clean. If there are uncommitted changes, warn the user and ask whether to proceed (they may want to commit first).
27
29
  6. **Commits ahead of base.** Confirm the branch has commits the base lacks (`git log <base>..HEAD --oneline`). If empty, stop — nothing to push.
28
- 7. **Graph finished.** When `<slug>` resolved, run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/graph.py .gbuild/<slug>/db/graph.json --status`. If the frontier is non-empty or nodes are still `in_progress`, warn that the graph isn't finished and ask whether to open the PR anyway. If any node is `failed`, name it — a PR built on an escalated node is usually premature.
30
+ 7. **Graph finished.** When `<slug>` resolved, run `cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher`. If any row's `open` is non-empty, warn that the graph isn't finished (name the open nodes) and ask whether to open the PR anyway. If any row has `failed` > 0, get their names from `attention.cypher` and name them — a PR built on an escalated node is usually premature.
29
31
 
30
32
  ## Step 2: Determine the remote & push
31
33
 
@@ -45,7 +47,7 @@ Gather context from:
45
47
 
46
48
  - Commit subjects: `git log <base>..HEAD --oneline`.
47
49
  - File overview: `git diff <base>...HEAD --stat`.
48
- - When present: the `Feature` node's `destination` property and the `Acceptance` nodes (linked `Feature -[:HAS_ACCEPTANCE]-> Acceptance`) from `.gbuild/<slug>/db/graph.json` (a CypherLite GraphData file), and the per-node `output` values in `.gbuild/<slug>/nodes/*.json` (keyed by GbuildNode `slug`).
50
+ - When `<slug>` resolved: `cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher` — the `destination` and the acceptance bar (with the nodes covering each criterion).
49
51
 
50
52
  Derive a concise, conventional-commit-style title from the feature/branch and the changes (e.g. `feat(auth): add OAuth login`).
51
53
 
@@ -11,20 +11,38 @@ missed abstractions that only exist *between* nodes, which no per-node review ca
11
11
  ## Arguments
12
12
 
13
13
  `$ARGUMENTS` is optional. If present, treat it as the feature slug. If absent, infer it — the current
14
- branch commonly ends in the slug (`plan` checks out `<prefix>/<slug>`), otherwise fall back to the most
15
- recently modified `.gbuild/*/db/graph.json`. Do NOT write any file — this skill outputs to chat exclusively.
14
+ branch commonly ends in the slug (`plan` checks out `<prefix>/<slug>`), otherwise fall back to the store
15
+ whose `.gbuild/*/db/graph.json` was most recently modified. Do NOT write any file — this skill outputs to
16
+ chat exclusively.
16
17
 
17
- Run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/validate_format.py .gbuild/<slug>/db/graph.json` then
18
- `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/graph.py .gbuild/<slug>/db/graph.json --status` first. If the frontier is
19
- non-empty or nodes are still `in_progress`, say the graph isn't finished and ask whether to audit anyway
20
- — auditing a half-built branch produces findings that the remaining nodes were going to address.
18
+ Store rules: run `cypherlite --version` first (missing → stop; gbuild needs it). One `cypherlite`
19
+ command at a time, always `--mode jsonl` (no output = no rows); on `storage locked` wait and retry up to
20
+ 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
21
+
22
+ Check the graph is finished — one row per wave, cheap:
23
+
24
+ ```
25
+ cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
26
+ ```
27
+
28
+ If any row's `open` is non-empty, say the graph isn't finished (name the open nodes) and ask whether to
29
+ audit anyway — auditing a half-built branch produces findings that the remaining nodes were going to
30
+ address.
21
31
 
22
32
  ## Run the audit
23
33
 
34
+ Fetch the feature context:
35
+
36
+ ```
37
+ cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher
38
+ ```
39
+
24
40
  Launch the `gbuild-auditor` subagent (agents/gbuild-auditor.md — this plugin's own copy, gbuild does not
25
41
  depend on hone-ai being installed). Pass it:
26
42
 
27
- - The resolved slug and its `.gbuild/<slug>/db/graph.json` path.
43
+ - The resolved slug and the `feature.cypher` result verbatim (destination and the acceptance bar with
44
+ the nodes covering each criterion) — the auditor never opens the store itself, and reads the code from
45
+ the branch diff.
28
46
  - Tell it to audit the current branch.
29
47
 
30
48
  The sub-agent runs the full audit in its own fresh context and returns the audit as its final message.