opencode-gbuild 0.7.0 → 0.8.0

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/README.md CHANGED
@@ -98,7 +98,7 @@ OpenCode (same order, kebab-case names):
98
98
  ```
99
99
 
100
100
  - **`plan`** creates the feature branch in its own git worktree and charts the feature into a
101
- CypherLite graph store there (`.gbuild/<feature>/db/`) — `Feature`,
101
+ machine-local CypherLite graph store (`<git-common-dir>/gbuild/<feature>/db`) — `Feature`,
102
102
  `Acceptance`, and `GbuildNode` nodes, each node's contract as `INPUT`/`OUTPUT` `Field` nodes, and
103
103
  `FROM` edges carrying data from one node's output to the next node's input. Every dependency edge
104
104
  passes the cut test — and because data flow is explicit, the validator checks it; every node has
@@ -185,7 +185,7 @@ decision is wanted; neither guesses.
185
185
 
186
186
  ## Runtime
187
187
 
188
- gbuild **requires the [CypherLite](https://github.com/neo4j-labs/cypherlite) CLI**, 0.7.0 or newer:
188
+ gbuild **requires the [CypherLite](https://github.com/neo4j-labs/cypherlite) CLI**, 0.12.0 or newer:
189
189
 
190
190
  ```bash
191
191
  curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash
@@ -193,12 +193,12 @@ curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash
193
193
 
194
194
  Every skill reads and writes the graph with `cypherlite` and nothing else — there is no Python and no
195
195
  direct JSON editing. The plugin ships the queries as `.cypher` files; skills pipe them into the store
196
- (`.gbuild/<feature>/db` inside the feature's worktree — examples below run from there):
196
+ (`<git-common-dir>/gbuild/<feature>/db` — machine-local, never committed):
197
197
 
198
198
  ```bash
199
- cypherlite .gbuild/<feature>/db --mode jsonl < plugins/gbuild/cypher/validate.cypher # format gate: no output = valid
200
- cypherlite .gbuild/<feature>/db --mode jsonl < plugins/gbuild/cypher/progress.cypher # one row per wave: counts + open nodes
201
- cypherlite .gbuild/<feature>/db --mode jsonl "MATCH (n:GbuildNode {status: 'failed'}) RETURN n.slug" # anything else
199
+ cypherlite query --read-only --database <git-common-dir>/gbuild/<feature>/db --mode jsonl < plugins/gbuild/cypher/validate.cypher # format gate: no output = valid
200
+ cypherlite query --read-only --database <git-common-dir>/gbuild/<feature>/db --mode jsonl < plugins/gbuild/cypher/progress.cypher # one row per wave: counts + open nodes
201
+ cypherlite query --read-only "MATCH (n:GbuildNode {status: 'failed'}) RETURN n.slug" --database <git-common-dir>/gbuild/<feature>/db --mode jsonl # anything else
202
202
  ```
203
203
 
204
204
  Reads are deliberately narrow so a run doesn't pay for the whole graph on every step: `run` claims a
@@ -233,10 +233,10 @@ plugins/gbuild/
233
233
  ```
234
234
 
235
235
  State lives outside the plugin, in the project: one CypherLite store per feature at
236
- `.gbuild/<feature>/db/` inside the feature's own git worktree. It holds the plan, every node's status
237
- and output values, and the full review
238
- history. Only `db/graph.json` (CypherLite's JSON snapshot, kept current by every write) and the store's
239
- own `.gitignore` are committed (on the feature branch). All of a feature's worktrees live under
236
+ `<git-common-dir>/gbuild/<feature>/db` — machine-local, never committed and never carried by a clone.
237
+ It holds the plan, every node's status and output values, and the full review history; CypherLite
238
+ checkpoints the store on exit, so `db/graph.json` is just the engine's local snapshot. All of a
239
+ feature's worktrees live under
240
240
  `.git/gbuild/<feature>/` — never in `git status`: `tree/` is the feature worktree itself, created by
241
241
  `plan` and kept until the feature is done, and during a run each file-touching node gets a `<node>/`
242
242
  worktree that is removed the moment its node is accepted (merged into the feature branch, in `tree/`)
@@ -7,7 +7,7 @@ description: Strict end-of-feature maintainability auditor for a gbuild feature
7
7
 
8
8
  Unusually strict review of implementation quality, maintainability, and abstraction health. Push for **ambitious** restructurings — "code judo" moves that preserve behavior while making the code dramatically simpler, smaller, and more direct. Delete complexity; don't rearrange it.
9
9
 
10
- The caller passes you the resolved feature slug, the **feature worktree** path, and the feature context it read from the gbuild store: the `destination` and the acceptance bar (each criterion with the nodes covering it). Use the context for scoping only — you are auditing the branch's code, not re-grading individual nodes (`gbuild-reviewer` already did that per node, against each node's own contract; your job is the thing no per-node pass can see — what the accumulated diff did to the codebase as a whole). The feature branch is checked out in the feature worktree: every file read, every check, and every git command runs there (`git -C <worktree> …` or with it as your working directory), never in the main tree. Do not open `.gbuild/` or run `cypherlite` — the caller owns the store. Do NOT write any file — output your audit as your final message exclusively.
10
+ The caller passes you the resolved feature slug, the **feature worktree** path, and the feature context it read from the gbuild store: the `destination` and the acceptance bar (each criterion with the nodes covering it). Use the context for scoping only — you are auditing the branch's code, not re-grading individual nodes (`gbuild-reviewer` already did that per node, against each node's own contract; your job is the thing no per-node pass can see — what the accumulated diff did to the codebase as a whole). The feature branch is checked out in the feature worktree: every file read, every check, and every git command runs there (`git -C <worktree> …` or with it as your working directory), never in the main tree. Do not open the gbuild store or run `cypherlite` — the caller owns the store. Do NOT write any file — output your audit as your final message exclusively.
11
11
 
12
12
  ## Run the branch's checks first
13
13
 
@@ -22,7 +22,7 @@ flag them here. Three things belong to you: the contract, the acceptance criteri
22
22
  - For `code`/`test`/`chore` nodes: the git diff for this node's work (`git diff HEAD`, or
23
23
  `git diff --staged`, or `git log -1 -p` if it already committed).
24
24
 
25
- Everything you need is in your prompt — do not open `.gbuild/` or run `cypherlite`; the caller owns the
25
+ Everything you need is in your prompt — do not open the gbuild store or run `cypherlite`; the caller owns the
26
26
  store and records your verdict.
27
27
 
28
28
  ## REVIEW OBJECTIVE
@@ -3,7 +3,7 @@
3
3
  // in_progress claimed but not recorded; if no run is active, an interrupted wave left it
4
4
  // blocked-by-failed pending behind a failed node, so it can never unblock on its own;
5
5
  // `detail` = the failed nodes it waits on
6
- // cypherlite .gbuild/<slug>/db --mode jsonl < cypher/attention.cypher
6
+ // cypherlite query --read-only --database <git-common-dir>/gbuild/<slug>/db --mode jsonl < cypher/attention.cypher
7
7
  CALL {
8
8
  MATCH (n:GbuildNode {status: 'failed'})
9
9
  RETURN n.slug AS slug, 'failed' AS reason,
@@ -5,7 +5,7 @@
5
5
  // external, and its `shape` says where to find it. No rows = nothing is
6
6
  // ready (the graph is done or stuck — ask progress.cypher / attention.cypher).
7
7
  // For a router, cancel the unselected branches with set-status.cypher first.
8
- // cypherlite .gbuild/<slug>/db --mode jsonl < cypher/dispatch.cypher
8
+ // cypherlite query --database <git-common-dir>/gbuild/<slug>/db --mode jsonl < cypher/dispatch.cypher
9
9
  MATCH (n:GbuildNode {status: 'pending'})
10
10
  WHERE NOT EXISTS { MATCH (n)-[:DEPENDS_ON]->(d:GbuildNode) WHERE NOT d.status IN ['completed', 'cancelled'] }
11
11
  SET n.status = 'in_progress'
@@ -28,4 +28,3 @@ RETURN n.slug AS slug,
28
28
  RETURN {name: f.name, shape: f.shape}
29
29
  } AS outputs
30
30
  ORDER BY slug;
31
- .checkpoint
@@ -2,7 +2,7 @@
2
2
  // nodes that cover each criterion. What review hands the auditor and what pr
3
3
  // builds the description from. Per-node output values are not included — get
4
4
  // one node's with node.cypher if you actually need it.
5
- // cypherlite .gbuild/<slug>/db --mode jsonl < cypher/feature.cypher
5
+ // cypherlite query --read-only --database <git-common-dir>/gbuild/<slug>/db --mode jsonl < cypher/feature.cypher
6
6
  MATCH (f:Feature)
7
7
  RETURN f.feature AS feature,
8
8
  f.destination AS destination,
@@ -3,7 +3,7 @@
3
3
  // external (from the codebase / environment): its `from` and `value` are null.
4
4
  // Used for reopen and ad-hoc inspection; run gets its definitions from
5
5
  // dispatch.cypher instead.
6
- // cypherlite .gbuild/<slug>/db --mode jsonl --param 'slug="<node-slug>"' < cypher/node.cypher
6
+ // cypherlite query --read-only --database <git-common-dir>/gbuild/<slug>/db --mode jsonl --param 'slug="<node-slug>"' < cypher/node.cypher
7
7
  MATCH (n:GbuildNode {slug: $slug})
8
8
  RETURN n.slug AS slug,
9
9
  n.title AS title,
@@ -2,7 +2,7 @@
2
2
  // that wave not yet completed or cancelled. A wave with `open: []` is done;
3
3
  // the graph is done when every row's `open` is empty. `wave` is the longest
4
4
  // DEPENDS_ON chain below a node (0 = no dependencies).
5
- // cypherlite .gbuild/<slug>/db --mode jsonl < cypher/progress.cypher
5
+ // cypherlite query --read-only --database <git-common-dir>/gbuild/<slug>/db --mode jsonl < cypher/progress.cypher
6
6
  MATCH (n:GbuildNode)
7
7
  OPTIONAL MATCH p = (n)-[:DEPENDS_ON*]->()
8
8
  WITH n, coalesce(max(length(p)), 0) AS wave
@@ -7,7 +7,7 @@
7
7
  // you sent. Output values must be scalars or lists of scalars — one nested
8
8
  // value rejects the whole batch (InvalidPropertyType); JSON-encode it and
9
9
  // resend.
10
- // cypherlite .gbuild/<slug>/db --mode jsonl --param 'results=[
10
+ // cypherlite query --database <git-common-dir>/gbuild/<slug>/db --mode jsonl --param 'results=[
11
11
  // {"slug": "a", "verdict": "pass", "failed_criteria": [], "outputs": {"value": 7},
12
12
  // "started_at": "<iso>", "completed_at": "<iso>"},
13
13
  // {"slug": "b", "verdict": "fail", "failed_criteria": ["<criterion>"]}
@@ -35,4 +35,3 @@ FOREACH (_ IN CASE WHEN ok THEN [1] ELSE [] END |
35
35
  SET n.status = 'completed', n.started_at = r.started_at, n.completed_at = r.completed_at)
36
36
  RETURN n.slug AS slug, attempt, review.verdict AS verdict, ok AS completed, missing AS missing_outputs
37
37
  ORDER BY slug;
38
- .checkpoint
@@ -1,5 +1,5 @@
1
1
  // gbuild store schema. Run once, when plan creates the store:
2
- // cypherlite .gbuild/<slug>/db --snapshot-format json < cypher/schema.cypher
2
+ // cypherlite query --database <git-common-dir>/gbuild/<slug>/db --snapshot-format json < cypher/schema.cypher
3
3
  // Everything the engine can enforce at write time lives here; the rest of the
4
4
  // contract is checked by validate.cypher.
5
5
  CREATE CONSTRAINT feature_name FOR (n:Feature) REQUIRE n.feature IS :: STRING;
@@ -42,4 +42,3 @@ CREATE CONSTRAINT review_verdict_exists FOR (n:Review) REQUIRE n.verdict IS NOT
42
42
  CREATE CONSTRAINT review_at FOR (n:Review) REQUIRE n.at IS :: STRING;
43
43
  CREATE CONSTRAINT review_at_exists FOR (n:Review) REQUIRE n.at IS NOT NULL;
44
44
  CREATE CONSTRAINT review_failed_criteria FOR (n:Review) REQUIRE n.failed_criteria IS :: LIST<STRING NOT NULL>;
45
- .checkpoint
@@ -3,7 +3,7 @@
3
3
  // retry/repair, stop), or `pending` (reset nodes an interrupted run left
4
4
  // in_progress). `completed` is rejected — only record.cypher may set it, so it
5
5
  // can require a passing review and every output value.
6
- // cypherlite .gbuild/<slug>/db --mode jsonl --param 'slugs=["a","b"]' --param 'status="cancelled"' \
6
+ // cypherlite query --database <git-common-dir>/gbuild/<slug>/db --mode jsonl --param 'slugs=["a","b"]' --param 'status="cancelled"' \
7
7
  // < cypher/set-status.cypher
8
8
  UNWIND $slugs AS s
9
9
  MATCH (n:GbuildNode {slug: s})
@@ -11,4 +11,3 @@ WHERE $status IN ['pending', 'in_progress', 'failed', 'cancelled']
11
11
  SET n.status = $status
12
12
  RETURN n.slug AS slug, n.status AS status
13
13
  ORDER BY slug;
14
- .checkpoint
@@ -4,7 +4,7 @@
4
4
  // otherwise = the stored status (in_progress, completed, failed, cancelled)
5
5
  // `wave` is the longest DEPENDS_ON chain below the node (0 = no dependencies),
6
6
  // so nodes sharing a wave are safe to run concurrently.
7
- // cypherlite .gbuild/<slug>/db --mode jsonl < cypher/status.cypher
7
+ // cypherlite query --read-only --database <git-common-dir>/gbuild/<slug>/db --mode jsonl < cypher/status.cypher
8
8
  MATCH (n:GbuildNode)
9
9
  OPTIONAL MATCH p = (n)-[:DEPENDS_ON*]->()
10
10
  WITH n, coalesce(max(length(p)), 0) AS wave
@@ -1,5 +1,5 @@
1
1
  // gbuild format gate. Zero rows = valid; every row is one violation.
2
- // cypherlite .gbuild/<slug>/db --mode jsonl < cypher/validate.cypher
2
+ // cypherlite query --read-only --database <git-common-dir>/gbuild/<slug>/db --mode jsonl < cypher/validate.cypher
3
3
  // Required properties, their types and slug/acceptance-id uniqueness are
4
4
  // engine constraints (schema.cypher) — a write that breaks them never lands.
5
5
  // This query checks everything the engine can't: enums, label/type agreement,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "opencode-gbuild",
4
- "version": "0.7.0",
4
+ "version": "0.8.0",
5
5
  "description": "OpenCode plugin for gbuild — graph-native task planning and execution with concurrent fan-out, per-node review, and durable checkpoints.",
6
6
  "type": "module",
7
7
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  # Ship checklist
2
2
 
3
- `plan` runs this checklist against the graph it just wrote, before committing the store. Any item that
3
+ `plan` runs this checklist against the graph it just wrote, before handing off to `run`. Any item that
4
4
  fails means revise the graph (with Cypher), not add a caveat in prose.
5
5
 
6
6
  1. **Risky assumptions are resolved, not deferred.** Every assumption that would invalidate nodes or
@@ -1,13 +1,14 @@
1
1
  # Talking to the gbuild store
2
2
 
3
- Every gbuild skill reads and writes the feature store (`.gbuild/<feature>/db/` inside the feature's git
4
- worktree, modelled in
5
- `reference/graph-format.md`) with the `cypherlite` CLI and nothing else. This file is the full operating
6
- manual; the skills that only run plugin scripts carry the short version of these rules inline.
3
+ Every gbuild skill reads and writes the feature store (modelled in `reference/graph-format.md`) with the
4
+ `cypherlite` CLI and nothing else. `DB` throughout is the store path:
5
+ `<git-common-dir>/gbuild/<feature>/db` — beside the feature worktree, machine-local, never committed.
6
+ This file is the full operating manual; the skills that only run plugin scripts carry the short version
7
+ of these rules inline.
7
8
 
8
9
  ## Requirement
9
10
 
10
- `cypherlite` 0.7.0 or newer must be on PATH. Check first, in every skill:
11
+ `cypherlite` 0.12.0 or newer must be on PATH. Check first, in every skill:
11
12
 
12
13
  ```
13
14
  cypherlite --version
@@ -17,42 +18,47 @@ If the command is missing, stop and tell the user gbuild needs it:
17
18
  `curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash`. Never fall back to reading or
18
19
  editing `graph.json` by hand.
19
20
 
21
+ The floor is the ADR-0200 CLI cutover: the store path is a flag (`-d` / `--database PATH`), the first
22
+ positional is the Cypher statement (never the database), and piped scripts and the interactive shell
23
+ require the explicit `query` verb. The old path-first form — database as the first argument — hard-fails.
24
+
20
25
  ## One writer, one command at a time
21
26
 
22
27
  CypherLite takes an exclusive lock on the store while a process has it open. A second process — reader
23
- or writer — fails with `storage locked` (exit 1). So:
28
+ or writer — fails with `storage locked` (exit 5). So:
24
29
 
25
30
  - **Only the skill running in the main context runs `cypherlite` against the store.** Subagents never
26
31
  do: give them what they need in their prompt, have them report results in their final message, and
27
32
  record those results yourself.
28
33
  - **Never run two `cypherlite` commands against the same store at once** — no parallel tool calls on it.
29
34
  Fan-out is for agents, not for store access.
30
- - On `storage locked`, another process holds the store (another gbuild command, a REPL left open). Wait a
31
- few seconds and retry, up to 3 times; then stop and report. Never delete `.cypherlite.lock`.
35
+ - On `storage locked` (exit 5), another process holds the store (another gbuild command, a REPL left
36
+ open). Wait a few seconds and retry, up to 3 times; then stop and report. Never delete
37
+ `.cypherlite.lock`.
32
38
 
33
39
  ## Invocation
34
40
 
35
41
  Always pass `--mode jsonl`: one compact JSON object per row, one row per line, and no output at all when
36
- there are no rows. `DB` below is the feature store: `.gbuild/<feature>/db` inside the feature worktree
37
- (`<git-common-dir>/gbuild/<feature>/tree/`), or in the main tree for a feature charted before the
38
- worktree layout.
42
+ there are no rows. Every call is `cypherlite query [STATEMENT] --database DB …`; with no STATEMENT the
43
+ piped stdin is the script list. Pure reads add `--read-only`: no exit flush, a shared lock, and a
44
+ fail-fast on a wrong path — a read-only call never creates a missing store. Writes (schema creation,
45
+ dispatch, record, set-status, authored heredocs) go without.
39
46
 
40
47
  ```
41
- # a plugin script
42
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
48
+ # a plugin read script
49
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
43
50
 
44
- # a plugin script with parameters
45
- cypherlite DB --mode jsonl --param 'slug="b-consume-doubled"' < ${CLAUDE_PLUGIN_ROOT}/cypher/node.cypher
51
+ # a plugin read script with parameters
52
+ cypherlite query --read-only --database DB --mode jsonl --param 'slug="b-consume-doubled"' < ${CLAUDE_PLUGIN_ROOT}/cypher/node.cypher
46
53
 
47
54
  # an ad-hoc read — return only the columns you need, and keep a LIMIT on anything that can grow
48
- cypherlite DB --mode jsonl "MATCH (n:GbuildNode {status: 'failed'}) RETURN n.slug LIMIT 20"
55
+ cypherlite query "MATCH (n:GbuildNode {status: 'failed'}) RETURN n.slug LIMIT 20" --read-only --database DB --mode jsonl
49
56
 
50
57
  # a write you author (plan, reopen, fixes) — quoted heredoc delimiter, so the shell expands nothing
51
- cypherlite DB <<'CYPHER'
58
+ cypherlite query --database DB <<'CYPHER'
52
59
  .begin
53
60
  MATCH (n:GbuildNode {slug: 'b-consume-doubled'}) SET n.title = 'Consume the value, double it';
54
61
  .commit
55
- .checkpoint
56
62
  CYPHER
57
63
  ```
58
64
 
@@ -66,33 +72,46 @@ CYPHER
66
72
  Bare values that start with a digit — timestamps, `01-…` slugs — are rejected, so always quote.
67
73
  - **String literals** in Cypher you author: single quotes by default; double quotes when the text
68
74
  contains an apostrophe (`"gbuild's"`); backslash-escape (`\'`, `\"`) when it contains both.
69
- - **Authored writes are atomic and checkpointed.** Wrap them in `.begin` / `.commit` — if any statement
70
- fails, the whole transaction is discarded — and end with `.checkpoint` so `graph.json` on disk (what
71
- git commits) is always current. The plugin write scripts already do both.
75
+ - **Authored writes are atomic.** Wrap them in `.begin` / `.commit` — if any statement fails, the whole
76
+ transaction is discarded. The plugin write scripts already do. Never write `.checkpoint`: a writable
77
+ session checkpoints on exit by itself.
72
78
  - **Values are scalars or lists of scalars.** CypherLite cannot store a map as a property value;
73
79
  JSON-encode anything nested into a string.
74
80
  - **Read the result.** The plugin write scripts are guarded and return what they actually changed.
75
81
  Compare it with what you asked for; never assume a write landed.
76
- - **Exit code 1 is a failure** — lock, constraint violation (`ConstraintValidationFailed`), syntax. Read
77
- stderr, fix, retry the whole transaction.
82
+ - **Check the exit code.** `0` is success (an empty result included). `5` is `storage locked` or a
83
+ write conflict — wait and retry as above. `6` is a rejected statement — syntax, semantic, or type
84
+ error, including `ConstraintValidationFailed` and writes on a `--read-only` store — read stderr, fix,
85
+ retry the whole transaction. `2` is a usage error — fix the invocation, not the data. `1` is any other
86
+ runtime failure. With `--mode jsonl` a failure also prints one JSON error envelope on stdout, after
87
+ any rows already written: `{"error":{"code","exit_code","kind","message","retryable"}}`.
88
+ - **Agent output is capped at 100 rows.** Under a detected agent harness with non-terminal stdout —
89
+ gbuild skills always are — a statement prints at most 100 rows, warns on stderr, and still exits `0`.
90
+ Keep a `LIMIT` on anything that can grow; when you genuinely need every row, pass `--max-rows 0` (or
91
+ set `CYPHERLITE_MAX_ROWS=0`).
78
92
 
79
93
  ## Creating a store
80
94
 
81
- Only `plan` does this, once per feature, with `DB` = `.gbuild/<feature>/db` inside the feature worktree
82
- it just created:
95
+ Only `plan` does this, once per feature:
83
96
 
84
97
  ```
85
98
  mkdir -p DB
86
- cypherlite DB --snapshot-format json < ${CLAUDE_PLUGIN_ROOT}/cypher/schema.cypher
87
- printf '*\n!.gitignore\n!graph.json\n' > DB/.gitignore
99
+ cypherlite query --database DB --snapshot-format json < ${CLAUDE_PLUGIN_ROOT}/cypher/schema.cypher
88
100
  ```
89
101
 
90
102
  `--snapshot-format json` belongs on this first call only (it applies to an empty directory). It installs
91
- the schema constraints and pins the JSON codec, so `graph.json` exists from the start.
103
+ the schema constraints and pins the JSON codec for cross-build compatibility: a parquet-enabled
104
+ CypherLite build defaults a new store to Parquet, and a JSON-pinned store opens in every build.
105
+
106
+ ## Migrating an old store
107
+
108
+ Stores charted by gbuild ≤ 0.7.1 live at `<tree>/.gbuild/<slug>/db` and are git-tracked. Migrate with
109
+ `git rm -r --cached .gbuild` (commit the removal) and
110
+ `mv <tree>/.gbuild/<slug>/db <git-common-dir>/gbuild/<slug>/db`.
92
111
 
93
112
  ## Script catalog
94
113
 
95
- All in `${CLAUDE_PLUGIN_ROOT}/cypher/`. Writes end with `.checkpoint`.
114
+ All in `${CLAUDE_PLUGIN_ROOT}/cypher/`.
96
115
 
97
116
  | script | params | returns | used by |
98
117
  | -------------------- | ------------------------- | -------------------------------------------------------------- | ------- |
@@ -2,12 +2,12 @@
2
2
 
3
3
  This file is normative. Where a skill disagrees with this doc, this doc wins.
4
4
 
5
- One CypherLite store per feature: `.gbuild/<feature>/db/` inside the feature's git worktree
6
- (`<git-common-dir>/gbuild/<feature>/tree/` — `plan` creates the worktree; a feature charted before the
7
- worktree layout keeps its store in the main tree). `plan` creates and charts it, `run` records
8
- progress in it, and every skill reads it — **all through Cypher**. No skill reads or writes `graph.json`
9
- directly; it is CypherLite's snapshot of the store. How to talk to the store (the single-writer rule,
10
- invocation, quoting, the script catalog) is in `reference/cypher.md`.
5
+ One CypherLite store per feature: `<git-common-dir>/gbuild/<feature>/db/`, beside the feature worktree
6
+ (`<git-common-dir>/gbuild/<feature>/tree/`, which `plan` creates) — untracked, machine-local, never
7
+ committed. `plan` creates and charts it, `run` records progress in it, and every skill reads it — **all
8
+ through Cypher**. No skill reads or writes `graph.json` directly; it is CypherLite's local snapshot of
9
+ the store, not a gbuild artifact. How to talk to the store (the single-writer rule, invocation, quoting,
10
+ the script catalog) is in `reference/cypher.md`.
11
11
 
12
12
  `templates/example.cypher` is a complete worked example — a 4-node diamond — written exactly the way
13
13
  `plan` writes a new feature.
@@ -15,17 +15,17 @@ invocation, quoting, the script catalog) is in `reference/cypher.md`.
15
15
  ## Store layout
16
16
 
17
17
  ```
18
- .gbuild/<feature>/db/
19
- graph.json CypherLite JSON snapshot — committed; always current (every write ends with .checkpoint)
20
- .gitignore "*", "!.gitignore", "!graph.json" — committed
21
- manifest.json engine files — ignored
18
+ <git-common-dir>/gbuild/<feature>/db/
19
+ graph.json CypherLite JSON snapshot — the engine's local snapshot; gbuild never reads or writes it
20
+ manifest.json engine files
22
21
  wal/
23
22
  .cypherlite.lock
24
23
  ```
25
24
 
26
- The store is created with the JSON codec (`--snapshot-format json`, see `reference/cypher.md`) so
27
- `graph.json` diffs are reviewable in a PR, and a clone holding only `graph.json` is a complete store —
28
- data **and** constraints.
25
+ The store lives outside every checkout: untracked, machine-local, never committed. It is created with
26
+ the JSON codec (`--snapshot-format json`, see `reference/cypher.md`) for cross-build compatibility: a
27
+ parquet-enabled CypherLite build defaults a new store to Parquet, and a JSON-pinned store opens in every
28
+ build.
29
29
 
30
30
  ## Nodes
31
31
 
@@ -41,7 +41,7 @@ data **and** constraints.
41
41
 
42
42
  | property | type | meaning |
43
43
  | -------------- | -------------- | ---------------------------------------------------- |
44
- | `feature` | string | the slug — matches the `.gbuild/<feature>/` dir in the feature worktree, immutable |
44
+ | `feature` | string | the slug — matches the `<feature>` segment of the store path, immutable |
45
45
  | `destination` | string | one line: what is true once this is done |
46
46
  | `context` | string | why this exists, one or two lines |
47
47
  | `out_of_scope` | list of string | bullets, may be empty |
@@ -1,9 +1,9 @@
1
1
  # Ad-hoc queries
2
2
 
3
3
  The plugin scripts (`reference/cypher.md` § Script catalog) cover everything the skills do. These are for
4
- the questions in between. Run them with `cypherlite DB --mode jsonl "<query>"`, one at a
5
- time — `DB` is the feature store (`.gbuild/<feature>/db` inside the feature worktree);
6
- return only the columns you need and keep a `LIMIT` on anything that can grow.
4
+ the questions in between. Run them with `cypherlite query "<query>" --read-only --database DB --mode
5
+ jsonl`, one at a time — `DB` is the feature store (`reference/cypher.md`); return only the columns you
6
+ need and keep a `LIMIT` on anything that can grow.
7
7
 
8
8
  ```cypher
9
9
  -- the whole plan with progress
@@ -24,23 +24,24 @@ inform the choices below. `${CLAUDE_PLUGIN_ROOT}/reference/checklist.md` is the
24
24
  | a description, link, or file path | **Chart** — new feature |
25
25
  | an existing feature slug with `--add "<req>"` | **Reopen** |
26
26
 
27
- A bare slug with no store is a description, not a slug — chart it. A slug's store lives in its feature
28
- worktree at `<git-common-dir>/gbuild/<slug>/tree/.gbuild/<slug>/db` (a feature charted before the
29
- worktree layout keeps its store at `.gbuild/<slug>/db` in the main tree).
27
+ A bare slug with no store is a description, not a slug — chart it. A slug's store lives beside its
28
+ feature worktree at `<git-common-dir>/gbuild/<slug>/db`, machine-local and never committed (a gbuild ≤ 0.7.1
29
+ store needs the move in `reference/cypher.md`).
30
30
 
31
31
  ## Chart
32
32
 
33
33
  ### 1. Slug, branch, and feature worktree
34
34
 
35
35
  Derive the feature slug from `$ARGUMENTS`: kebab-case, ≤4 words, names the outcome not the mechanism
36
- (`oauth-device-flow`, not `add-some-auth-stuff`). It's the `.gbuild/<slug>/` directory name and the
36
+ (`oauth-device-flow`, not `add-some-auth-stuff`). It's the `gbuild/<slug>/` directory name and the
37
37
  `Feature` node's `feature` property — immutable once charted.
38
38
 
39
39
  gbuild never changes the branch of the user's checkout: the feature branch lives in its own **feature
40
40
  worktree**, so several features can be charted and run in parallel without racing each other's `HEAD`,
41
- and uncommitted work in the main tree is irrelevant — there is no dirty-tree check. Resolve two paths,
42
- both absolute: `GC` = `git rev-parse --git-common-dir` (resolve it to an absolute path), and `FT` =
43
- `GC/gbuild/<slug>/tree` — the feature worktree, the one place the feature branch is checked out. Then:
41
+ and uncommitted work in the main tree is irrelevant — there is no dirty-tree check. Resolve these paths,
42
+ all absolute: `GC` = `git rev-parse --git-common-dir` (resolve it to an absolute path), `WT` =
43
+ `GC/gbuild/<slug>` — the feature's worktree root, inside `.git/` so nothing under it is ever committed —
44
+ and `FT` = `WT/tree`, the feature worktree, the one place the feature branch is checked out. Then:
44
45
 
45
46
  - `FT` is already a registered worktree (`git worktree list --porcelain`) → reuse it, say so.
46
47
  - A branch named `<slug>` or ending `/<slug>` already exists → if it's checked out somewhere (a feature
@@ -55,14 +56,13 @@ both absolute: `GC` = `git rev-parse --git-common-dir` (resolve it to an absolut
55
56
  Take `<prefix>` from the repo's convention — project or user instructions first, else the dominant
56
57
  pattern in `git branch --list` — and fall back to `gbuild` when there is none.
57
58
 
58
- Report the branch and `FT`. Everything below happens in `FT`; `DB` below is
59
- `FT/.gbuild/<slug>/db`.
59
+ Report the branch and `FT`. Everything below happens in `FT`; `DB` below is `WT/db`.
60
60
 
61
61
  ### 2. Analyse the codebase
62
62
 
63
63
  Read the project manifest(s), directory structure, `README.md`, and — for related in-flight work — the
64
- `Feature` of every existing store (`feature.cypher` against each `GC/gbuild/*/tree/.gbuild/*/db`, plus
65
- any legacy `.gbuild/*/db` in the main tree, one at a time). Resolve
64
+ `Feature` of every existing store (`feature.cypher` with `--read-only` against each `GC/gbuild/*/db`,
65
+ one at a time). Resolve
66
66
  file paths or URLs in `$ARGUMENTS`; if a reference fails to load, say so and ask.
67
67
 
68
68
  ### 3. Validate and explore
@@ -146,16 +146,16 @@ design, don't annotate around a failing item.
146
146
 
147
147
  ### 8. Create the store and write the graph
148
148
 
149
- Create the store exactly as `reference/cypher.md` § Creating a store shows (`mkdir`, `schema.cypher` with
150
- `--snapshot-format json`, the `db/.gitignore`).
149
+ Create the store exactly as `reference/cypher.md` § Creating a store shows (`mkdir -p DB`, then
150
+ `schema.cypher` with `--snapshot-format json`).
151
151
 
152
152
  Then write the whole graph as **one** Cypher script, piped through a quoted heredoc.
153
153
  `${CLAUDE_PLUGIN_ROOT}/templates/example.cypher` is a complete worked example — follow its structure:
154
154
  `.begin`, a single statement of `CREATE` clauses (so variables like `a1` or `a_value` stay in scope for
155
- the edges), `.commit`, `.checkpoint`.
155
+ the edges), `.commit`.
156
156
 
157
157
  ```
158
- cypherlite DB <<'CYPHER'
158
+ cypherlite query --database DB <<'CYPHER'
159
159
  .begin
160
160
  CREATE (f:Feature {feature: '<slug>', destination: '...', context: '...', out_of_scope: ['...']})
161
161
  CREATE (a1:Acceptance {id: 'a-1', text: '...'})
@@ -168,7 +168,6 @@ CREATE (m)-[:DEPENDS_ON]->(n)
168
168
  CREATE (m)-[:INPUT]->(:Field {name: '...', shape: '<...>'})-[:FROM]->(n_out)
169
169
  CREATE (m)-[:SATISFIES]->(a1);
170
170
  .commit
171
- .checkpoint
172
171
  CYPHER
173
172
  ```
174
173
 
@@ -178,30 +177,26 @@ slug) fails the transaction and writes nothing — fix the script and run it aga
178
177
  ### 9. Validate
179
178
 
180
179
  ```
181
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
180
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
182
181
  ```
183
182
 
184
183
  No output means valid. Every row is a violation (`check`, `detail`): fix it with Cypher — a `.begin` …
185
- `.commit` … `.checkpoint` script of `MATCH … SET/CREATE/DELETE` — and re-run until it prints nothing. Never
186
- hand off or commit a graph that fails validation, and never edit `graph.json` directly.
184
+ `.commit` script of `MATCH … SET/CREATE/DELETE` — and re-run until it prints nothing. Never
185
+ hand off a graph that fails validation, and never edit `graph.json` directly.
187
186
 
188
187
  Then confirm run-readiness:
189
188
 
190
189
  ```
191
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
190
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
192
191
  ```
193
192
 
194
193
  One row per wave: each row's `open` slugs are the decomposition, and the `frontier` counts are what
195
194
  `run` claims first. Nodes you expected to run together should share a wave.
196
195
 
197
- ### 10. Commit and stop
196
+ ### 10. Report and stop
198
197
 
199
- Commit `.gbuild/<slug>/` on the feature branch unless the repo ignores it (`git -C FT check-ignore -q
200
- .gbuild/`; if true, don't stage anything under it). The store's own `.gitignore` limits that to
201
- `db/graph.json` and `db/.gitignore`. Stage and commit from the feature worktree:
202
- `git -C FT add .gbuild/<slug>` and `git -C FT commit -m "<slug>: chart graph"`.
203
-
204
- Report the branch, `FT`, the waves, and the frontier. Close with `next: /gbuild:run <slug>`.
198
+ There is nothing to commit — the store is machine-local, outside every checkout. Report the branch,
199
+ `FT`, the waves, and the frontier. Close with `next: /gbuild:run <slug>`.
205
200
 
206
201
  ## Reopen
207
202
 
@@ -220,7 +215,7 @@ Report the branch, `FT`, the waves, and the frontier. Close with `next: /gbuild:
220
215
  3. Write it as one script that `MATCH`es what it connects to and `CREATE`s the rest:
221
216
 
222
217
  ```
223
- cypherlite DB <<'CYPHER'
218
+ cypherlite query --database DB <<'CYPHER'
224
219
  .begin
225
220
  MATCH (f:Feature), (up:GbuildNode {slug: '<existing-slug>'})-[:OUTPUT]->(up_out:Field {name: '<field>'})
226
221
  CREATE (f)-[:HAS_ACCEPTANCE]->(a:Acceptance {id: 'a-3', text: '...'})
@@ -230,13 +225,11 @@ Report the branch, `FT`, the waves, and the frontier. Close with `next: /gbuild:
230
225
  CREATE (n)-[:OUTPUT]->(:Field {name: '...', shape: '<...>'})
231
226
  CREATE (n)-[:SATISFIES]->(a);
232
227
  .commit
233
- .checkpoint
234
228
  CYPHER
235
229
  ```
236
230
 
237
- 4. **Re-run `validate.cypher`** until it prints nothing, then `progress.cypher`. Commit in `FT`
238
- (`git -C FT commit -m "<slug>: reopen graph — <what was added>"` after staging `.gbuild/<slug>`,
239
- same ignore rule as Chart's step 10), report the new frontier.
231
+ 4. **Re-run `validate.cypher`** until it prints nothing, then `progress.cypher`, and report the new
232
+ frontier.
240
233
 
241
234
  If the requirement needs no new nodes (an existing node's contract already covers it), say so and stop
242
235
  — don't manufacture graph churn.
@@ -12,9 +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 — if exactly one feature worktree exists (`<git-common-dir>/gbuild/*/tree`), that's the slug; otherwise fall back to the most recently modified `graph.json` under `<git-common-dir>/gbuild/*/tree/.gbuild/*/db` (or, for features charted before the worktree layout, `.gbuild/*/db/graph.json` in the main tree). 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 — if exactly one feature worktree exists (`<git-common-dir>/gbuild/*/tree`), that's the slug; otherwise fall back to the most recently modified `graph.json` under `<git-common-dir>/gbuild/*/db`. If neither resolves, leave `<slug>` unresolved (the auto-fix step degrades gracefully — see Step 4).
16
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`. `DB` below is `FT/.gbuild/<slug>/db` (see Step 1 for `FT`).
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 `--read-only --mode jsonl` (no output = no rows — this skill only reads the store), and on `storage locked` wait and retry up to 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`. `DB` below is `<git-common-dir>/gbuild/<slug>/db`, beside the feature worktree (a gbuild ≤ 0.7.1 store needs the move in `reference/cypher.md`).
18
18
  - **max_rounds**: the value of `--max-rounds N` (also accept `--max-rounds=N`). Default `3` when absent.
19
19
 
20
20
  ## Step 1: Preconditions
@@ -27,7 +27,7 @@ Verify the environment before touching the remote. Stop with a clear, actionable
27
27
  4. **Feature worktree and branch.** Resolve `FT` (the feature worktree) and `<branch>` (the feature branch checked out there) exactly as `/gbuild:run`'s step 0 describes — the registered worktree at `<git-common-dir>/gbuild/<slug>/tree`, a legacy feature whose branch is in the main tree, or attach a branch that is checked out nowhere. When `<slug>` is unresolved, use the main tree's current branch as `<branch>` and its root as `FT`. If `<branch>` equals `<base>`, stop — there is nothing to open a PR for.
28
28
  5. **Clean tree.** Check for uncommitted changes in the feature worktree (`git -C FT status --porcelain`). `/gbuild:run` commits each node's work as it goes, so it should be clean. If there are uncommitted changes, warn the user and ask whether to proceed (they may want to commit first).
29
29
  6. **Commits ahead of base.** Confirm the branch has commits the base lacks (`git log <base>..<branch> --oneline`). If empty, stop — nothing to push.
30
- 7. **Graph finished.** When `<slug>` resolved, run `cypherlite 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.
30
+ 7. **Graph finished.** When `<slug>` resolved, run `cypherlite query --read-only --database 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.
31
31
 
32
32
  ## Step 2: Determine the remote & push
33
33
 
@@ -48,7 +48,7 @@ Gather context from:
48
48
 
49
49
  - Commit subjects: `git log <base>..<branch> --oneline`.
50
50
  - File overview: `git diff <base>...<branch> --stat`.
51
- - When `<slug>` resolved: `cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher` — the `destination` and the acceptance bar (with the nodes covering each criterion).
51
+ - When `<slug>` resolved: `cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher` — the `destination` and the acceptance bar (with the nodes covering each criterion).
52
52
 
53
53
  Derive a concise, conventional-commit-style title from the feature/branch and the changes (e.g. `feat(auth): add OAuth login`).
54
54
 
@@ -103,4 +103,6 @@ next: /gbuild:status <slug>
103
103
  ```
104
104
 
105
105
  The feature worktree `FT` keeps the branch checked out until removed — once the PR is merged and the
106
- graph is no longer needed, `git worktree remove FT` (and `git branch -d <branch>`) cleans up.
106
+ graph is no longer needed, `git worktree remove WT/tree && rm -rf WT && git branch -d <branch>` (with
107
+ `WT` = `<git-common-dir>/gbuild/<slug>`) cleans up: the whole `WT`, store included, dies with the
108
+ feature.
@@ -12,21 +12,22 @@ missed abstractions that only exist *between* nodes, which no per-node review ca
12
12
 
13
13
  `$ARGUMENTS` is optional. If present, treat it as the feature slug. If absent, infer it — if exactly one
14
14
  feature worktree exists (`<git-common-dir>/gbuild/*/tree`), that's the slug; otherwise fall back to the
15
- most recently modified `graph.json` under `<git-common-dir>/gbuild/*/tree/.gbuild/*/db` (or, for
16
- features charted before the worktree layout, `.gbuild/*/db/graph.json` in the main tree). Do NOT write
15
+ most recently modified `graph.json` under `<git-common-dir>/gbuild/*/db`. Do NOT write
17
16
  any file — this skill outputs to chat exclusively.
18
17
 
19
18
  Resolve `FT`, the feature worktree, exactly as `/gbuild:run`'s step 0 describes (reuse the registered
20
- worktree, attach if the feature branch is checked out nowhere). `DB` below is `FT/.gbuild/<slug>/db`.
19
+ worktree, attach if the feature branch is checked out nowhere). `DB` below is
20
+ `<git-common-dir>/gbuild/<slug>/db`, beside the worktree (a gbuild ≤ 0.7.1 store needs the move in
21
+ `reference/cypher.md`).
21
22
 
22
23
  Store rules: run `cypherlite --version` first (missing → stop; gbuild needs it). One `cypherlite`
23
- command at a time, always `--mode jsonl` (no output = no rows); on `storage locked` wait and retry up to
24
- 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
24
+ command at a time, always `--read-only --mode jsonl` (no output = no rows — this skill only reads); on
25
+ `storage locked` wait and retry up to 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
25
26
 
26
27
  Check the graph is finished — one row per wave, cheap:
27
28
 
28
29
  ```
29
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
30
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
30
31
  ```
31
32
 
32
33
  If any row's `open` is non-empty, say the graph isn't finished (name the open nodes) and ask whether to
@@ -38,7 +39,7 @@ address.
38
39
  Fetch the feature context:
39
40
 
40
41
  ```
41
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher
42
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher
42
43
  ```
43
44
 
44
45
  Launch the `gbuild-auditor` subagent (agents/gbuild-auditor.md — this plugin's own copy, gbuild does not
@@ -2,8 +2,8 @@
2
2
  description: Executes a gbuild graph — dispatches every ready-and-independent node in the current wave concurrently, each file-touching node in its own git worktree, reviews each node's output with gbuild-reviewer before merging its branch and recording it complete, and resumes only the remaining frontier on re-invocation. Use after /gbuild:plan has charted the graph.
3
3
  ---
4
4
 
5
- Run the graph for the feature `$ARGUMENTS` (the slug; step 0 resolves `DB`, the store — it lives in
6
- the feature's own worktree, so this skill never changes the branch of the user's checkout).
5
+ Run the graph for the feature `$ARGUMENTS` (the slug; step 0 resolves `DB`, the store — the feature
6
+ branch lives in its own worktree, so this skill never changes the branch of the user's checkout).
7
7
 
8
8
  **CRITICAL: this skill must run in the main context, not inside a forked agent.** It dispatches its own
9
9
  subagents per node; a subagent cannot itself fan out further subagents reliably. It is also the store's
@@ -17,6 +17,8 @@ back in their final message, and this skill records it.
17
17
  - One `cypherlite` command at a time against `DB` — never parallel tool calls on it, never from a subagent.
18
18
  - Always `--mode jsonl`: one JSON object per row, no output = no rows. Every `--param` value is JSON,
19
19
  single-quoted for the shell (`--param 'slugs=["a","b"]'`).
20
+ - Pure reads (validate, attention, progress below) open the store `--read-only`; the writes (dispatch,
21
+ set-status, record) stay writable — the CLI checkpoints a writable store on exit itself.
20
22
  - `storage locked` → another process holds the store: wait a few seconds, retry up to 3 times, then stop.
21
23
  Exit code 1 = failure; read stderr. Anything beyond the scripts below: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
22
24
  - Never re-read what you already hold. The claimed wave's definitions stay valid for its retries.
@@ -28,7 +30,7 @@ Default to `git`. Resolve these facts first, absolute paths, and reuse them thro
28
30
  - `GC` = `git rev-parse --git-common-dir`, resolved to an absolute path; `WT` = `GC/gbuild/$ARGUMENTS`
29
31
  (the worktree root — inside `.git/`, so worktrees never appear in `git status` or get committed).
30
32
  - `FT` = the feature worktree and `BRANCH` = the feature branch — the one place `BRANCH` is checked
31
- out, and where every merge and store commit below lands:
33
+ out, and where every merge below lands:
32
34
  1. `WT/tree` is a registered worktree (`git worktree list --porcelain`) → `FT` = it, `BRANCH` =
33
35
  `git -C FT branch --show-current`.
34
36
  2. Else a worktree whose branch is `$ARGUMENTS` or ends `/$ARGUMENTS` → `FT` = that worktree's path
@@ -36,14 +38,14 @@ Default to `git`. Resolve these facts first, absolute paths, and reuse them thro
36
38
  3. Else such a branch exists but is checked out nowhere → attach it: `git worktree add WT/tree
37
39
  <branch>`, `FT` = `WT/tree`.
38
40
  4. Else → stop: there is no feature branch for `$ARGUMENTS` — chart it with `/gbuild:plan` first.
39
- - `DB` = `FT/.gbuild/$ARGUMENTS/db`. `git -C FT check-ignore -q .gbuild/` tells you whether to commit
40
- the store at all.
41
+ - `DB` = `WT/db` — the feature's store, beside the worktree: machine-local, never committed (a gbuild ≤ 0.7.1
42
+ store needs the move in `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`).
41
43
 
42
44
  Then check and recover:
43
45
 
44
46
  ```
45
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
46
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
47
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
48
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
47
49
  ```
48
50
 
49
51
  - `validate` printing anything → stop and report the rows; do not run a graph `plan` didn't finish
@@ -55,7 +57,7 @@ cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
55
57
  them all in one call so they re-dispatch, and mention it in the report:
56
58
 
57
59
  ```
58
- cypherlite DB --mode jsonl --param 'slugs=["<slug>", ...]' --param 'status="pending"' \
60
+ cypherlite query --database DB --mode jsonl --param 'slugs=["<slug>", ...]' --param 'status="pending"' \
59
61
  < ${CLAUDE_PLUGIN_ROOT}/cypher/set-status.cypher
60
62
  ```
61
63
 
@@ -87,7 +89,7 @@ behavior this plugin replaces.
87
89
  1. **CLAIM.**
88
90
 
89
91
  ```
90
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/dispatch.cypher
92
+ cypherlite query --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/dispatch.cypher
91
93
  ```
92
94
 
93
95
  It moves the whole frontier to `in_progress` and prints one row per claimed node with everything its
@@ -122,7 +124,7 @@ behavior this plugin replaces.
122
124
  nested into a string;
123
125
  - record its own UTC start and finish (`date -u +%Y-%m-%dT%H:%M:%SZ`) and end its final message with
124
126
  `{"started_at": "...", "completed_at": "...", "outputs": {...}}`;
125
- - **not** run `cypherlite` or touch `.gbuild/`.
127
+ - **not** run `cypherlite` or touch the store.
126
128
 
127
129
  3. **REVIEW.** Once IMPLEMENT returns, spawn a `gbuild-reviewer` per node, again all in one message
128
130
  (`agents/gbuild-reviewer.md` — this plugin's own copy, gbuild does not depend on hone-ai being
@@ -151,7 +153,7 @@ behavior this plugin replaces.
151
153
  `VERDICT:` line, `failed_criteria` from its `[fail]` lines:
152
154
 
153
155
  ```
154
- cypherlite DB --mode jsonl --param 'results=[
156
+ cypherlite query --database DB --mode jsonl --param 'results=[
155
157
  {"slug": "<slug>", "verdict": "pass", "failed_criteria": [], "outputs": {...},
156
158
  "started_at": "<iso>", "completed_at": "<iso>"},
157
159
  {"slug": "<slug>", "verdict": "fail", "failed_criteria": ["<criterion>"]}
@@ -186,15 +188,13 @@ user) changing branches in their own checkouts cannot race them.
186
188
 
187
189
  ## Step 3: Next wave
188
190
 
189
- If `.gbuild/` isn't ignored, commit the store in the feature worktree: `git -C FT add
190
- .gbuild/<feature>/db` and `git -C FT commit -m "<feature>: record wave <n>"`. Then claim again (step 2).
191
- Keep going until a claim returns no rows.
191
+ Claim again (step 2). Keep going until a claim returns no rows.
192
192
 
193
193
  ## Step 4: Report and stop
194
194
 
195
195
  ```
196
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
197
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
196
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
197
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
198
198
  ```
199
199
 
200
200
  Every `progress` row with `open: []` → the graph is done. Otherwise `attention` names what's stuck
@@ -3,16 +3,17 @@ description: Reports a gbuild feature's graph — frontier, blocked, in-flight,
3
3
  ---
4
4
 
5
5
  Report status for `$ARGUMENTS`. This skill only reads the store. `DB` below is the feature's store:
6
- `FT/.gbuild/<feature>/db`, where `FT` is the feature worktree at `<git-common-dir>/gbuild/<feature>/tree`
7
- (a feature charted before the worktree layout keeps its store at `.gbuild/<feature>/db` in the main
8
- tree). Status never creates or attaches worktrees — if neither store exists, say the feature's worktree
9
- is gone and that `git worktree add <git-common-dir>/gbuild/<feature>/tree <branch>` reattaches it.
6
+ `<git-common-dir>/gbuild/<feature>/db`, beside the feature worktree `FT` at
7
+ `<git-common-dir>/gbuild/<feature>/tree` — machine-local, never committed (a gbuild ≤ 0.7.1 store needs the
8
+ move in `reference/cypher.md`). Status never creates or attaches worktrees — if the store is missing,
9
+ the feature is gone (or was never charted here); say so.
10
10
 
11
11
  ## Store rules
12
12
 
13
13
  - `cypherlite --version` first. If it's missing, stop: gbuild needs it
14
14
  (`curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash`).
15
15
  - One `cypherlite` command at a time — never parallel tool calls on the same store.
16
+ - Always `--read-only`: status never writes, and a missing store fails fast instead of being created.
16
17
  - Always `--mode jsonl`: one JSON object per row, no output = no rows.
17
18
  - `storage locked` → another process (likely a running `/gbuild:run`) holds the store: wait a few
18
19
  seconds, retry up to 3 times, then say so. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
@@ -31,8 +32,8 @@ This is the human-facing report, so it's the one place that reads every node.
31
32
  ### 1. Load
32
33
 
33
34
  ```
34
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/status.cypher
35
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
35
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/status.cypher
36
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
36
37
  ```
37
38
 
38
39
  One call after the other. `status.cypher` gives one row per node with its derived `state`
@@ -80,11 +81,11 @@ don't let silence be ambiguous between "checked, clear" and "not checked."
80
81
 
81
82
  ## All-features mode
82
83
 
83
- Don't read every node of every feature. For each store found — `<git-common-dir>/gbuild/*/tree/.gbuild/*/db`,
84
- plus any legacy `.gbuild/*/db` in the main tree — one store at a time:
84
+ Don't read every node of every feature. For each store found — `<git-common-dir>/gbuild/*/db` — one
85
+ store at a time:
85
86
 
86
87
  ```
87
- cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
88
+ cypherlite query --read-only --database DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
88
89
  ```
89
90
 
90
91
  Print one line per feature: slug, node counts by state summed over its waves, and whether it's done
@@ -1,7 +1,7 @@
1
1
  // A worked 4-node diamond: A produces a value, B and C each consume it
2
2
  // independently, D joins both. This is exactly the script plan writes for a
3
3
  // new feature — one atomic statement, piped into the store:
4
- // cypherlite .gbuild/<slug>/db < plan.cypher
4
+ // cypherlite query --database <git-common-dir>/gbuild/<slug>/db < plan.cypher
5
5
  // Variables (f, a1, a, a_value, ...) are only scoped to this one statement, so
6
6
  // the whole graph is created in a single CREATE chain.
7
7
  .begin
@@ -54,4 +54,3 @@ CREATE (d)-[:INPUT]->(:Field {name: 'squared', shape: '<integer>'})-[:FROM]->(c_
54
54
  CREATE (d)-[:OUTPUT]->(:Field {name: 'sum', shape: '<integer>'})
55
55
  CREATE (d)-[:SATISFIES]->(a2);
56
56
  .commit
57
- .checkpoint