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.
- package/README.md +49 -37
- package/agents/gbuild-auditor.md +1 -1
- package/agents/gbuild-reviewer.md +17 -10
- package/cypher/attention.cypher +20 -0
- package/cypher/dispatch.cypher +31 -0
- package/cypher/feature.cypher +16 -0
- package/cypher/node.cypher +41 -0
- package/cypher/progress.cypher +25 -0
- package/cypher/record.cypher +38 -0
- package/cypher/schema.cypher +45 -0
- package/cypher/set-status.cypher +14 -0
- package/cypher/status.cypher +33 -0
- package/cypher/validate.cypher +105 -0
- package/package.json +2 -2
- package/reference/checklist.md +16 -16
- package/reference/cypher.md +107 -0
- package/reference/failure-policies.md +6 -6
- package/reference/graph-format.md +129 -196
- package/reference/queries.md +37 -0
- package/reference/shapes.md +10 -9
- package/skills/plan/SKILL.md +115 -102
- package/skills/pr/SKILL.md +5 -3
- package/skills/review/SKILL.md +25 -7
- package/skills/run/SKILL.md +113 -67
- package/skills/status/SKILL.md +48 -46
- package/templates/example.cypher +57 -0
- package/scripts/__pycache__/graph.cpython-314.pyc +0 -0
- package/scripts/__pycache__/test_graph.cpython-314.pyc +0 -0
- package/scripts/__pycache__/validate_format.cpython-314.pyc +0 -0
- package/scripts/graph.py +0 -239
- package/scripts/test_graph.py +0 -403
- package/scripts/validate_format.py +0 -378
- package/templates/graph.json +0 -110
package/skills/run/SKILL.md
CHANGED
|
@@ -1,100 +1,146 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Executes a gbuild graph — dispatches every ready-and-independent node in the current wave concurrently, reviews each node's output with gbuild-reviewer before
|
|
2
|
+
description: Executes a gbuild graph — dispatches every ready-and-independent node in the current wave concurrently, reviews each node's output with gbuild-reviewer before 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 `.gbuild/$ARGUMENTS/db
|
|
5
|
+
Run the graph in `.gbuild/$ARGUMENTS/db` (the feature slug is `$ARGUMENTS`; `DB` below).
|
|
6
6
|
|
|
7
7
|
**CRITICAL: this skill must run in the main context, not inside a forked agent.** It dispatches its own
|
|
8
|
-
subagents per node; a subagent cannot itself fan out further subagents reliably.
|
|
8
|
+
subagents per node; a subagent cannot itself fan out further subagents reliably. It is also the store's
|
|
9
|
+
**only writer**: subagents never run `cypherlite` — they get what they need in their prompt and report
|
|
10
|
+
back in their final message, and this skill records it.
|
|
9
11
|
|
|
10
|
-
##
|
|
12
|
+
## Store rules
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
`
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
- `cypherlite --version` first. If it's missing, stop: gbuild needs it
|
|
15
|
+
(`curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash`).
|
|
16
|
+
- One `cypherlite` command at a time against `DB` — never parallel tool calls on it, never from a subagent.
|
|
17
|
+
- Always `--mode jsonl`: one JSON object per row, no output = no rows. Every `--param` value is JSON,
|
|
18
|
+
single-quoted for the shell (`--param 'slugs=["a","b"]'`).
|
|
19
|
+
- `storage locked` → another process holds the store: wait a few seconds, retry up to 3 times, then stop.
|
|
20
|
+
Exit code 1 = failure; read stderr. Anything beyond the scripts below: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
|
|
21
|
+
- Never re-read what you already hold. The claimed wave's definitions stay valid for its retries.
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/validate_format.py .gbuild/<feature>/db/graph.json
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
If it prints `invalid: ...`, stop and report — do not attempt to run a graph `plan` didn't finish
|
|
22
|
-
correctly. Then take the frontier:
|
|
23
|
+
## Step 0: Check and recover
|
|
23
24
|
|
|
24
25
|
```
|
|
25
|
-
|
|
26
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
|
|
27
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
- `validate` printing anything → stop and report the rows; do not run a graph `plan` didn't finish
|
|
31
|
+
correctly.
|
|
32
|
+
- `attention` rows with reason `in_progress` are left over from an interrupted run (this skill is the
|
|
33
|
+
only writer and records every node before finishing). Check `git log` for commits their agents already
|
|
34
|
+
made, then reset them all in one call so they re-dispatch, and mention it in the report:
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
```
|
|
37
|
+
cypherlite DB --mode jsonl --param 'slugs=["<slug>", ...]' --param 'status="pending"' \
|
|
38
|
+
< ${CLAUDE_PLUGIN_ROOT}/cypher/set-status.cypher
|
|
39
|
+
```
|
|
34
40
|
|
|
35
41
|
## Step 1: Establish VCS facts
|
|
36
42
|
|
|
37
|
-
Default to `git`. `git check-ignore -q .gbuild/` tells you whether to
|
|
43
|
+
Default to `git`. `git check-ignore -q .gbuild/` tells you whether to commit the store at all.
|
|
38
44
|
|
|
39
45
|
## Step 2: Pick a backend
|
|
40
46
|
|
|
41
47
|
**Workflow tool**, if this session has opted into multi-agent orchestration (ultracode, or the user
|
|
42
|
-
asked for a workflow explicitly) — translate
|
|
43
|
-
node is an `agent()` implement call, immediately followed by a `gbuild-reviewer` `agent()` review
|
|
44
|
-
scoped to that node's
|
|
45
|
-
|
|
46
|
-
Controlled-cycle clusters become a bounded `while` loop per `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md`'s
|
|
47
|
-
`model_tier: strong` nodes via `opts.model` where the harness supports an override.
|
|
48
|
+
asked for a workflow explicitly) — translate each claimed wave into a `pipeline()`/`parallel()` script:
|
|
49
|
+
each node is an `agent()` implement call, immediately followed by a `gbuild-reviewer` `agent()` review
|
|
50
|
+
call scoped to that node's outputs + `acceptance`, using `schema` for the pass/fail verdict. Code nodes
|
|
51
|
+
touching files that could conflict with a concurrent sibling get `isolation: 'worktree'`.
|
|
52
|
+
Controlled-cycle clusters become a bounded `while` loop per `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md`'s
|
|
53
|
+
round cap. Route `model_tier: strong` nodes via `opts.model` where the harness supports an override. The
|
|
54
|
+
script never touches the store: collect the results and record them from the main context (step 3.4).
|
|
48
55
|
|
|
49
56
|
**Fallback** (default — no opt-in required, and always what step 3 below assumes): fire one `Agent`
|
|
50
|
-
tool call per node
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
## Step 3:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
57
|
+
tool call per claimed node, **all in a single message** — this is what makes the fan-out real rather
|
|
58
|
+
than claimed. Do not dispatch them one at a time across separate messages; that's exactly the serial
|
|
59
|
+
behavior this plugin replaces.
|
|
60
|
+
|
|
61
|
+
## Step 3: One wave
|
|
62
|
+
|
|
63
|
+
1. **CLAIM.**
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/dispatch.cypher
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
It moves the whole frontier to `in_progress` and prints one row per claimed node with everything its
|
|
70
|
+
agent needs: `slug`, `title`, `type`, `acceptance`, `failure_policy`, `model_tier`, `verify`,
|
|
71
|
+
`inputs` (an input with a `value` came from an upstream node; one without is external — its `shape`
|
|
72
|
+
says where to find it), and `outputs`. **No rows** → nothing is ready: go to step 5.
|
|
73
|
+
|
|
74
|
+
2. **IMPLEMENT.** In one message, spawn one `Agent` per claimed node with its row. Tell it to:
|
|
75
|
+
- actually do the work — for `code`/`test`/`chore` nodes make the change in the working tree (not
|
|
76
|
+
describe it) and commit it, message `<feature>/<slug>: <what changed>`;
|
|
77
|
+
- produce a value for every output field: a scalar or a list of scalars, JSON-encoding anything
|
|
78
|
+
nested into a string;
|
|
79
|
+
- record its own UTC start and finish (`date -u +%Y-%m-%dT%H:%M:%SZ`) and end its final message with
|
|
80
|
+
`{"started_at": "...", "completed_at": "...", "outputs": {...}}`;
|
|
81
|
+
- **not** run `cypherlite` or touch `.gbuild/`.
|
|
82
|
+
|
|
83
|
+
3. **REVIEW.** Once IMPLEMENT returns, spawn a `gbuild-reviewer` per node, again all in one message
|
|
84
|
+
(`agents/gbuild-reviewer.md` — this plugin's own copy, gbuild does not depend on hone-ai being
|
|
85
|
+
installed). Give it the node's row, the agent's reported outputs, and where the diff is. Never let
|
|
86
|
+
the implementing agent review its own work.
|
|
87
|
+
|
|
88
|
+
4. **RECORD** the whole wave in one call — one result per node, `verdict` from the reviewer's
|
|
89
|
+
`VERDICT:` line, `failed_criteria` from its `[fail]` lines:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
cypherlite DB --mode jsonl --param 'results=[
|
|
93
|
+
{"slug": "<slug>", "verdict": "pass", "failed_criteria": [], "outputs": {...},
|
|
94
|
+
"started_at": "<iso>", "completed_at": "<iso>"},
|
|
95
|
+
{"slug": "<slug>", "verdict": "fail", "failed_criteria": ["<criterion>"]}
|
|
96
|
+
]' < ${CLAUDE_PLUGIN_ROOT}/cypher/record.cypher
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Each returned row says whether that node `completed`. A slug missing from the output was not
|
|
100
|
+
recorded (it wasn't `in_progress`) — find out why before moving on. `InvalidPropertyType` means an
|
|
101
|
+
output value was a map; the whole batch was rejected — JSON-encode it and send the batch again.
|
|
102
|
+
|
|
103
|
+
5. **FAILURES.** For each row with `completed: false` (a failed review, or a pass `record` downgraded
|
|
104
|
+
because `missing_outputs` is non-empty), apply the node's `failure_policy`
|
|
105
|
+
(`${CLAUDE_PLUGIN_ROOT}/reference/failure-policies.md`), using its `attempt` as the count:
|
|
106
|
+
- `retry` / `repair` → re-dispatch implement → review with the failed criteria fed back in, reusing
|
|
107
|
+
the row you already hold, then record just those nodes. Bounded: 2 attempts.
|
|
108
|
+
- `fallback` → dispatch the named alternate approach the same way.
|
|
109
|
+
- `skip` → `cancelled`; `escalate` (or an exhausted retry/repair) → `failed`, its dependents stay
|
|
110
|
+
blocked while siblings elsewhere keep going; `stop` → `failed` and halt the entire run. One
|
|
111
|
+
`set-status.cypher` call per status, with every slug that gets it.
|
|
112
|
+
- A completed router (`decision` choosing a branch) → cancel the unselected branches with
|
|
113
|
+
`set-status.cypher` before the next claim.
|
|
114
|
+
|
|
115
|
+
Nodes in the same wave never read each other's outputs, so true concurrent dispatch is safe by
|
|
116
|
+
construction — only the store calls are serialized.
|
|
76
117
|
|
|
77
118
|
## Step 4: Next wave
|
|
78
119
|
|
|
79
|
-
|
|
80
|
-
|
|
120
|
+
If `.gbuild/` isn't ignored, commit the store: `git add .gbuild/<feature>/db` and
|
|
121
|
+
`git commit -m "<feature>: record wave <n>"`. Then claim again (step 3). Keep going until a claim
|
|
122
|
+
returns no rows.
|
|
81
123
|
|
|
82
124
|
## Step 5: Report and stop
|
|
83
125
|
|
|
84
|
-
|
|
85
|
-
|
|
126
|
+
```
|
|
127
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
|
|
128
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Every `progress` row with `open: []` → the graph is done. Otherwise `attention` names what's stuck
|
|
132
|
+
(`failed` nodes with their last failed criteria, and what they block).
|
|
86
133
|
|
|
87
|
-
|
|
134
|
+
Report: which nodes ran this invocation, which passed review outright vs. needed a repair pass, and any
|
|
135
|
+
`failed` nodes needing a decision. Close with the next step:
|
|
88
136
|
|
|
89
|
-
- **Graph fully done**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- **Work remains** (
|
|
93
|
-
`next: /gbuild:status <feature>`.
|
|
137
|
+
- **Graph fully done** → say so plainly, then `next: /gbuild:review <feature>` — the per-node reviews
|
|
138
|
+
graded each node against its own contract; nothing has yet looked at what the accumulated diff did to
|
|
139
|
+
the codebase.
|
|
140
|
+
- **Work remains** (nodes `failed` awaiting a decision) → `next: /gbuild:status <feature>`.
|
|
94
141
|
|
|
95
142
|
## Resuming
|
|
96
143
|
|
|
97
|
-
Re-invoking `/gbuild:run <feature>` after an interruption re-runs step 0 fresh:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
the memory.
|
|
144
|
+
Re-invoking `/gbuild:run <feature>` after an interruption re-runs step 0 fresh: nodes an interrupted
|
|
145
|
+
wave left `in_progress` are reset, and the next claim picks up exactly the remaining frontier. Nothing
|
|
146
|
+
needs to be told what already finished — the store is the memory.
|
package/skills/status/SKILL.md
CHANGED
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
description: Reports a gbuild feature's graph — frontier, blocked, in-flight, completed, each node's review verdict, and the cluster shapes with evidence of what actually ran concurrently. Use to check progress or diagnose a stuck run.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Report status for `$ARGUMENTS`.
|
|
5
|
+
Report status for `$ARGUMENTS`. This skill only reads the store; `DB` below is `.gbuild/<feature>/db`.
|
|
6
|
+
|
|
7
|
+
## Store rules
|
|
8
|
+
|
|
9
|
+
- `cypherlite --version` first. If it's missing, stop: gbuild needs it
|
|
10
|
+
(`curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash`).
|
|
11
|
+
- One `cypherlite` command at a time — never parallel tool calls on the same store.
|
|
12
|
+
- Always `--mode jsonl`: one JSON object per row, no output = no rows.
|
|
13
|
+
- `storage locked` → another process (likely a running `/gbuild:run`) holds the store: wait a few
|
|
14
|
+
seconds, retry up to 3 times, then say so. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
|
|
6
15
|
|
|
7
16
|
## Mode
|
|
8
17
|
|
|
@@ -13,73 +22,66 @@ Report status for `$ARGUMENTS`.
|
|
|
13
22
|
|
|
14
23
|
## Single feature
|
|
15
24
|
|
|
16
|
-
|
|
25
|
+
This is the human-facing report, so it's the one place that reads every node.
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
are linked by `DEPENDS_ON` relationships; feature-level acceptance is `Acceptance` nodes linked by
|
|
20
|
-
`HAS_ACCEPTANCE`/`SATISFIES`) and every `.gbuild/<feature>/nodes/*.json` checkpoint (keyed by slug; the
|
|
21
|
-
`nodes/` dir is a sibling of the `db/` graph folder). This is a small, bounded read — status doesn't
|
|
22
|
-
scale with graph size the way loading full node prose would.
|
|
23
|
-
|
|
24
|
-
### 2. Compute
|
|
27
|
+
### 1. Load
|
|
25
28
|
|
|
26
29
|
```
|
|
27
|
-
|
|
30
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/status.cypher
|
|
31
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
|
|
28
32
|
```
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
One call after the other. `status.cypher` gives one row per node with its derived `state`
|
|
35
|
+
(`frontier` / `blocked` / `in_progress` / `completed` / `cancelled` / `failed`), `wave`, `waiting_on`,
|
|
36
|
+
review summary and timestamps — don't re-derive any of these by hand.
|
|
32
37
|
|
|
33
|
-
###
|
|
38
|
+
### 2. Render the graph
|
|
34
39
|
|
|
35
|
-
Draw the DAG with a marker per node
|
|
40
|
+
Draw the DAG with a marker per node state:
|
|
36
41
|
|
|
37
42
|
```
|
|
38
|
-
✓ completed ◐ in_progress ○
|
|
43
|
+
✓ completed ◐ in_progress ○ frontier ● blocked ✗ failed – cancelled
|
|
39
44
|
```
|
|
40
45
|
|
|
41
|
-
Annotate blocked nodes with what they're waiting on:
|
|
46
|
+
Annotate blocked nodes with what they're waiting on (`waiting_on`):
|
|
47
|
+
`● d-join-and-sum ← b-consume-doubled, c-consume-squared`.
|
|
42
48
|
|
|
43
|
-
Group by wave
|
|
49
|
+
Group by `wave` so fan-out is visible in the layout, not just in the dependency list.
|
|
44
50
|
|
|
45
|
-
###
|
|
51
|
+
### 3. Review verdicts
|
|
46
52
|
|
|
47
|
-
For every `completed` node, one line:
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
For every `completed` node, one line: passed outright (`review_attempts: 1`), or passed after N repair
|
|
54
|
+
attempts. For `failed` nodes, `last_failed_criteria` verbatim — this is what a human needs to make the
|
|
55
|
+
`escalate`/`stop` call.
|
|
50
56
|
|
|
51
|
-
###
|
|
57
|
+
### 4. Concurrency evidence
|
|
52
58
|
|
|
53
|
-
For each wave with more than one node, compare `started_at`
|
|
54
|
-
Report whether they actually overlapped (real concurrent dispatch) or ran
|
|
55
|
-
the same wave (a sign the fallback backend was invoked one node at a time —
|
|
56
|
-
driven, not a graph problem).
|
|
59
|
+
For each wave with more than one completed node, compare the implementing agents' `started_at` /
|
|
60
|
+
`completed_at` intervals. Report whether they actually overlapped (real concurrent dispatch) or ran
|
|
61
|
+
back-to-back despite being in the same wave (a sign the fallback backend was invoked one node at a time —
|
|
62
|
+
a bug in how `run` was driven, not a graph problem).
|
|
57
63
|
|
|
58
|
-
###
|
|
64
|
+
### 5. Next action
|
|
59
65
|
|
|
60
66
|
One priority-ordered list: what `/gbuild:run <feature>` would do next (the current frontier), and
|
|
61
|
-
anything needing a human decision first (`failed
|
|
62
|
-
nodes
|
|
67
|
+
anything needing a human decision first (`failed` nodes, an empty frontier with incomplete nodes
|
|
68
|
+
remaining, `in_progress` nodes when no run is active — an interrupted wave `run` will reset).
|
|
63
69
|
|
|
64
|
-
###
|
|
70
|
+
### 6. Invariant checks
|
|
65
71
|
|
|
66
|
-
|
|
72
|
+
`validate.cypher` is the invariant check — it covers non-empty acceptance, acceptance coverage,
|
|
73
|
+
acyclicity, completed nodes without a passing review or missing an output value, orphan chores, and the
|
|
74
|
+
`FROM` cut test. Report every row it returned, numbered. If it returned nothing, say so in one line —
|
|
75
|
+
don't let silence be ambiguous between "checked, clear" and "not checked."
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
validation — report if a node manages to lack it anyway, since that means the file was hand-edited or
|
|
70
|
-
written by something other than `plan`).
|
|
71
|
-
2. Every `Acceptance` node is `SATISFIES`-covered by at least one GbuildNode (enforced by
|
|
72
|
-
`validate_format.py` — report if one slips through anyway).
|
|
73
|
-
3. `DEPENDS_ON` is acyclic (validated by `validate_format.py`/`graph.py` already; report if it somehow
|
|
74
|
-
wasn't checked).
|
|
75
|
-
4. No `completed` node's checkpoint is missing a `review` field with `verdict: pass` — a node marked
|
|
76
|
-
complete without a passing review means `run` skipped the review step.
|
|
77
|
-
5. Every `chore`-type GbuildNode is the target of at least one `DEPENDS_ON` edge.
|
|
77
|
+
## All-features mode
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
"not checked."
|
|
79
|
+
Don't read every node of every feature. For each `.gbuild/<slug>/db` found, one store at a time:
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
```
|
|
82
|
+
cypherlite .gbuild/<slug>/db --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
|
|
83
|
+
```
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
Print one line per feature: slug, node counts by state summed over its waves, and whether it's done
|
|
86
|
+
(every `open` empty), has ready work (`frontier` > 0), or is stuck. Point at `/gbuild:status <slug>` for
|
|
87
|
+
detail.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// A worked 4-node diamond: A produces a value, B and C each consume it
|
|
2
|
+
// independently, D joins both. This is exactly the script plan writes for a
|
|
3
|
+
// new feature — one atomic statement, piped into the store:
|
|
4
|
+
// cypherlite .gbuild/<slug>/db < plan.cypher
|
|
5
|
+
// Variables (f, a1, a, a_value, ...) are only scoped to this one statement, so
|
|
6
|
+
// the whole graph is created in a single CREATE chain.
|
|
7
|
+
.begin
|
|
8
|
+
CREATE (f:Feature {
|
|
9
|
+
feature: 'example-diamond',
|
|
10
|
+
destination: 'A tiny worked example: A produces a shared value, B and C each consume it independently, D joins both.',
|
|
11
|
+
context: "Ships with the plugin as the toy graph used in gbuild's own tests. Not a real feature.",
|
|
12
|
+
out_of_scope: ['Anything beyond demonstrating fan-out and join scheduling.']
|
|
13
|
+
})
|
|
14
|
+
CREATE (a1:Acceptance {id: 'a-1', text: 'run dispatches B and C concurrently, not one after the other'})
|
|
15
|
+
CREATE (a2:Acceptance {id: 'a-2', text: 'D does not start until both B and C are recorded completed'})
|
|
16
|
+
CREATE (f)-[:HAS_ACCEPTANCE]->(a1), (f)-[:HAS_ACCEPTANCE]->(a2)
|
|
17
|
+
|
|
18
|
+
CREATE (a:GbuildNode:Chore {
|
|
19
|
+
slug: 'a-produce-shared-value', title: 'Produce the shared value B and C both need', type: 'chore',
|
|
20
|
+
acceptance: ['output.value is a single integer'],
|
|
21
|
+
failure_policy: 'retry', model_tier: 'cheap', status: 'pending'
|
|
22
|
+
})
|
|
23
|
+
CREATE (a)-[:OUTPUT]->(a_value:Field {name: 'value', shape: '<integer>'})
|
|
24
|
+
|
|
25
|
+
CREATE (b:GbuildNode:Code {
|
|
26
|
+
slug: 'b-consume-doubled', title: 'Consume the shared value, produce its double', type: 'code',
|
|
27
|
+
acceptance: ['output.doubled equals input.value multiplied by 2'],
|
|
28
|
+
failure_policy: 'repair', model_tier: 'cheap', status: 'pending'
|
|
29
|
+
})
|
|
30
|
+
CREATE (b)-[:DEPENDS_ON]->(a)
|
|
31
|
+
CREATE (b)-[:INPUT]->(:Field {name: 'value', shape: '<integer>'})-[:FROM]->(a_value)
|
|
32
|
+
CREATE (b)-[:OUTPUT]->(b_doubled:Field {name: 'doubled', shape: '<integer>'})
|
|
33
|
+
CREATE (b)-[:SATISFIES]->(a1)
|
|
34
|
+
|
|
35
|
+
CREATE (c:GbuildNode:Code {
|
|
36
|
+
slug: 'c-consume-squared', title: 'Consume the shared value, produce its square', type: 'code',
|
|
37
|
+
acceptance: ['output.squared equals input.value raised to the power of 2'],
|
|
38
|
+
failure_policy: 'repair', model_tier: 'cheap', status: 'pending'
|
|
39
|
+
})
|
|
40
|
+
CREATE (c)-[:DEPENDS_ON]->(a)
|
|
41
|
+
CREATE (c)-[:INPUT]->(:Field {name: 'value', shape: '<integer>'})-[:FROM]->(a_value)
|
|
42
|
+
CREATE (c)-[:OUTPUT]->(c_squared:Field {name: 'squared', shape: '<integer>'})
|
|
43
|
+
CREATE (c)-[:SATISFIES]->(a1)
|
|
44
|
+
|
|
45
|
+
CREATE (d:GbuildNode:Code {
|
|
46
|
+
slug: 'd-join-and-sum', title: 'Join B and C, produce their sum', type: 'code',
|
|
47
|
+
acceptance: ['output.sum equals input.doubled plus input.squared',
|
|
48
|
+
'only runs after both b-consume-doubled and c-consume-squared are recorded completed'],
|
|
49
|
+
failure_policy: 'repair', model_tier: 'cheap', status: 'pending'
|
|
50
|
+
})
|
|
51
|
+
CREATE (d)-[:DEPENDS_ON]->(b), (d)-[:DEPENDS_ON]->(c)
|
|
52
|
+
CREATE (d)-[:INPUT]->(:Field {name: 'doubled', shape: '<integer>'})-[:FROM]->(b_doubled)
|
|
53
|
+
CREATE (d)-[:INPUT]->(:Field {name: 'squared', shape: '<integer>'})-[:FROM]->(c_squared)
|
|
54
|
+
CREATE (d)-[:OUTPUT]->(:Field {name: 'sum', shape: '<integer>'})
|
|
55
|
+
CREATE (d)-[:SATISFIES]->(a2);
|
|
56
|
+
.commit
|
|
57
|
+
.checkpoint
|
|
Binary file
|
|
Binary file
|
|
Binary file
|