pi-adx-workflow 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +503 -2
- package/package.json +57 -4
- package/src/ask-user.ts +101 -0
- package/src/config.ts +104 -0
- package/src/executor.ts +924 -0
- package/src/index.ts +608 -0
- package/src/modes.ts +311 -0
- package/src/spec.ts +109 -0
- package/src/store.ts +468 -0
- package/src/subagent.ts +316 -0
- package/src/templates.ts +206 -0
- package/src/tools.ts +564 -0
- package/src/types.ts +141 -0
- package/src/widgets.ts +315 -0
- package/src/workflows.ts +86 -0
- package/workflows/build-verify.workflow.json +325 -0
- package/workflows/build.workflow.json +229 -0
- package/workflows/commit.workflow.json +83 -0
- package/workflows/pr-review.workflow.json +172 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 mossaab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,504 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pi-adx-workflow
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/pi-adx-workflow)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](https://github.com/earendil-works/pi)
|
|
6
|
+
|
|
7
|
+
**plan → build/verify → review → summarize** workflow for
|
|
8
|
+
[pi-coding-agent](https://github.com/earendil-works/pi), built as a pi extension with
|
|
9
|
+
**in-house sub-agent propagation**: flow children (verifier / code reviewer)
|
|
10
|
+
run as isolated `pi -p` child processes — no pi-subagents dependency.
|
|
11
|
+
|
|
12
|
+
It implements a complete working method:
|
|
13
|
+
|
|
14
|
+
1. **Plan mode** (read-only) — the planner explores and proposes **acceptance
|
|
15
|
+
criteria** (`flow_meta`, key `criteria`, status `pending`).
|
|
16
|
+
2. **Build mode** — you approve, then `/adx-run` starts the workflow:
|
|
17
|
+
the builder implements and marks criteria `completed`.
|
|
18
|
+
3. **Verify loop** — an isolated **verifier** sub-agent (fresh `pi -p` child
|
|
19
|
+
session) checks each criterion and sets `passed`/`failed`. Failures
|
|
20
|
+
send the builder back with a nudge carrying the verifier's findings.
|
|
21
|
+
4. **Code review** — an isolated **code reviewer** sub-agent reviews the git
|
|
22
|
+
diff and raises `review_findings`.
|
|
23
|
+
5. **Finalize loop** — the builder must resolve or dismiss every finding.
|
|
24
|
+
6. **Summarize** — final report + a "What to test" mini-tutorial.
|
|
25
|
+
|
|
26
|
+
The whole run is a declarative state machine: steps, ordered transitions,
|
|
27
|
+
metadata conditions, nudge re-entry, `maxIterations` safety cap,
|
|
28
|
+
`$blocked` handling, and persistence/resume.
|
|
29
|
+
|
|
30
|
+
## Contents
|
|
31
|
+
|
|
32
|
+
- [Requirements](#requirements)
|
|
33
|
+
- [Install](#install)
|
|
34
|
+
- [Usage](#usage)
|
|
35
|
+
- [Configuration](#configuration)
|
|
36
|
+
- [Never-stop (auto-continue)](#never-stop-auto-continue)
|
|
37
|
+
- [Tools](#tools)
|
|
38
|
+
- [Sub-agents](#sub-agents)
|
|
39
|
+
- [Workflows](#workflows)
|
|
40
|
+
- [Development](#development)
|
|
41
|
+
- [Contributing](#contributing)
|
|
42
|
+
- [Troubleshooting](#troubleshooting)
|
|
43
|
+
- [Project layout](#project-layout)
|
|
44
|
+
- [License](#license)
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
- pi-coding-agent **≥ 1.5** (the `pi` CLI is resolved from
|
|
49
|
+
`~/.pi/agent/bin/pi`, `ADX_PI_BIN`, or `PATH`)
|
|
50
|
+
- Node **≥ 22.19** (pi's own engine requirement)
|
|
51
|
+
|
|
52
|
+
pi-subagents is **not** required: children are plain `pi -p` processes that
|
|
53
|
+
load only this extension (child mode), so there is no retained-child state
|
|
54
|
+
and no "Agent is already processing" jams.
|
|
55
|
+
|
|
56
|
+
No `npm install` is needed for the extension itself: its runtime imports
|
|
57
|
+
(`typebox`, `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`) are
|
|
58
|
+
**host-provided** — pi maps them to its own copies, so the extension shares
|
|
59
|
+
pi's classes and registries (declared as `peerDependencies` with a `*` range,
|
|
60
|
+
per the pi package conventions).
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
Recommended: install as a [pi package](https://github.com/earendil-works/pi) from npm:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
pi install npm:pi-adx-workflow
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Variants:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
# project-local (written to .pi/settings.json, loads after project trust)
|
|
74
|
+
pi install --local npm:pi-adx-workflow
|
|
75
|
+
|
|
76
|
+
# from git (tracks the main branch)
|
|
77
|
+
pi install git:github.com/mossaab/pi-adx-workflow
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Manage the install:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
pi list # show configured packages
|
|
84
|
+
pi remove npm:pi-adx-workflow
|
|
85
|
+
pi update --extensions # reconcile git checkouts / npm specs
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Development install (symlink)
|
|
89
|
+
|
|
90
|
+
To develop the extension, clone the repo and symlink it into pi's global
|
|
91
|
+
extension directory (pi discovers `package.json` with a `pi.extensions`
|
|
92
|
+
field one level deep):
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
git clone https://github.com/mossaab/pi-adx-workflow.git
|
|
96
|
+
ln -sfn ~/path/to/pi-adx-workflow ~/.pi/agent/extensions/adx-workflow
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
No build step: pi loads `src/index.ts` through jiti. If you move the repo,
|
|
100
|
+
re-create the symlink.
|
|
101
|
+
|
|
102
|
+
## Usage
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
/adx-plan enter plan mode (read-only)
|
|
106
|
+
/adx-spec [path] enter spec mode (read-only brainstorm/research; writes a spec file, no build)
|
|
107
|
+
/adx-spec SPEC.md spec mode with a custom spec location (default: .pi/specs/<slug>.md)
|
|
108
|
+
/adx-approve approve the plan/spec: switch to build mode (turn plan/spec mode off, no launch)
|
|
109
|
+
/adx-run [workflow] [params] switch to build mode + launch a workflow (default: the configured build one)
|
|
110
|
+
/adx-run build-verify switch to build mode + launch the full build-verify workflow
|
|
111
|
+
/adx-run build-verify skip_review=true full workflow minus the code review step
|
|
112
|
+
/adx-run build-verify commit=true pipeline + commit & push at the end (auto-skips the "Commit changes?" picker)
|
|
113
|
+
/adx-run build-verify commit=false pipeline, changes left uncommitted (picker auto-skipped)
|
|
114
|
+
/adx-run build-verify commit=true message="feat: ..." commit phase with an explicit commit message
|
|
115
|
+
/adx-status show current workflow state
|
|
116
|
+
/adx-resume resume a blocked/waiting workflow
|
|
117
|
+
/adx-cancel cancel the current run
|
|
118
|
+
/adx-config show the effective config ("edit" menu / "set key=value")
|
|
119
|
+
Ctrl+Alt+A toggle plan/spec mode (spec mode exits; plan mode toggles)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Auto mode (unattended pipeline)
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
pi --adx-auto "Add a dark mode toggle: - toggle in settings, - persist to localStorage, - follow system preference"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`--adx-auto` runs the whole pipeline without any approval:
|
|
129
|
+
|
|
130
|
+
1. **Plan** — the planner refines the acceptance points you provided into
|
|
131
|
+
final criteria (no questions, no validation step) and adds them to the store.
|
|
132
|
+
2. **Build** — plan mode exits automatically and the build-verify workflow
|
|
133
|
+
launches (user steps like the work-location and commit pickers are
|
|
134
|
+
auto-skipped — in auto mode the work is left uncommitted by default).
|
|
135
|
+
3. **Verify → recap** — the verifier checks the criteria, then the summary
|
|
136
|
+
with "What to test" is printed. The code review step is skipped in auto
|
|
137
|
+
mode; use `/adx-run build-verify` for the full pipeline with review.
|
|
138
|
+
|
|
139
|
+
Manual mode (`/adx-plan` + `/adx-approve` / `/adx-run`) is unchanged.
|
|
140
|
+
|
|
141
|
+
When the planner finishes in interactive mode it calls `flow_plan_done`, which
|
|
142
|
+
shows a picker: **Build + verify (full pipeline)** / **Build (simple)** /
|
|
143
|
+
**Choose workspace** (current workspace or fresh worktree, then the pipeline) /
|
|
144
|
+
**Spec only — stop** (export the stored criteria as a spec document and stop —
|
|
145
|
+
no build is launched).
|
|
146
|
+
|
|
147
|
+
### Spec mode (brainstorm / research, no code)
|
|
148
|
+
|
|
149
|
+
`/adx-spec` is the "specs without dev" mode: pure brainstorming, research, and
|
|
150
|
+
spec writing — **zero coding, zero verification, zero review**.
|
|
151
|
+
|
|
152
|
+
- **Read-only workspace** — same gating as plan mode (edit/write disabled,
|
|
153
|
+
read-only bash allowlist). The single exception is the `spec_write` tool,
|
|
154
|
+
the only write channel: it writes the spec markdown file and nothing else.
|
|
155
|
+
- **Iterative reasoning** — the spec agent asks you 1-3 focused questions per
|
|
156
|
+
turn (`ask_user`), explores the codebase read-only, and researches on the
|
|
157
|
+
web (`web_search`, `fetch_content`, `source_check`).
|
|
158
|
+
- **Output = a spec document** — a markdown file with *Context & goal*,
|
|
159
|
+
*Research notes*, *Decisions & assumptions*, and an *Acceptance criteria*
|
|
160
|
+
checklist. Written to `.pi/specs/<slug>.md` by default (auto-generated
|
|
161
|
+
timestamp slug); pass a path to `/adx-spec` (e.g. `/adx-spec SPEC.md`) to
|
|
162
|
+
choose the location. `spec_write` is called exactly once, at the end.
|
|
163
|
+
- **No hand-off** — after the spec is saved the session simply ends in normal
|
|
164
|
+
build mode; nothing is launched, verified, or reviewed. Exit spec mode early
|
|
165
|
+
with `/adx-approve` or Ctrl+Alt+A (no launch). Spec mode is persisted per
|
|
166
|
+
session and restored on resume (unfinished spec → continue, then call
|
|
167
|
+
`spec_write` once).
|
|
168
|
+
|
|
169
|
+
After a regular plan, the `flow_plan_done` picker's **Spec only — stop**
|
|
170
|
+
option does the same export: it composes the spec from the stored criteria,
|
|
171
|
+
saves it to `.pi/specs/<slug>.md`, exits plan mode, and launches nothing.
|
|
172
|
+
|
|
173
|
+
### Typical session
|
|
174
|
+
|
|
175
|
+
1. `/adx-plan`
|
|
176
|
+
2. Ask for a feature: *"Add a dark mode toggle. Use flow_meta to define the
|
|
177
|
+
acceptance criteria."* — the planner explores (read-only) and adds
|
|
178
|
+
criteria. Review them in the widget (or edit with `flow_meta`).
|
|
179
|
+
3. `/adx-run` (quick: `build → summarize`) or `/adx-run build-verify`
|
|
180
|
+
(full: `work_location → build → verify → code_review → finalize → summarize`).
|
|
181
|
+
The widget tracks step, iteration, and criterion status; the footer shows
|
|
182
|
+
a compact status line.
|
|
183
|
+
4. When a criterion fails verification, the builder is nudged with the
|
|
184
|
+
verifier's findings and re-enters `build` until everything is `passed`.
|
|
185
|
+
5. The reviewer's findings are dispositioned in `finalize`, then the summary
|
|
186
|
+
with "What to test" is printed.
|
|
187
|
+
|
|
188
|
+
State lives **per pi session** in `.pi/adx-flow/state/<sessionId>.json`
|
|
189
|
+
(criteria, findings, execution state, plan-mode and spec-mode flags) — each session has its
|
|
190
|
+
own plan, and resuming a session restores exactly that session's plan/run.
|
|
191
|
+
A new session starts fresh. On the first per-session load, an in-flight run
|
|
192
|
+
still in the legacy shared `.pi/adx-flow/state.json` (status ≠ done) is
|
|
193
|
+
adopted into the new session's file once, so pre-existing runs keep working.
|
|
194
|
+
Flow sub-agents (verifier / code reviewer) write to the *parent's* state file
|
|
195
|
+
(passed via the `ADX_FLOW_STATE` env var) so their `flow_meta` updates land
|
|
196
|
+
in the driving session's store. It survives pi restarts — `session_start`
|
|
197
|
+
restores the resumed session's running run (and its plan/spec mode if the session
|
|
198
|
+
stopped mid-plan or mid-spec), and `/adx-resume` continues a blocked one.
|
|
199
|
+
|
|
200
|
+
## Configuration
|
|
201
|
+
|
|
202
|
+
The user config file is **created automatically on first run** with all
|
|
203
|
+
defaults, ready to edit:
|
|
204
|
+
|
|
205
|
+
- user: `~/.pi/agent/adx-workflow.json` (auto-created, all projects)
|
|
206
|
+
- project: `<cwd>/.pi/adx-workflow.json` (optional, overrides user per key)
|
|
207
|
+
|
|
208
|
+
All keys optional, unknown keys ignored, malformed file = defaults.
|
|
209
|
+
|
|
210
|
+
You can also manage it from inside pi:
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
/adx-config show the effective config + file paths
|
|
214
|
+
/adx-config edit interactive menu: pick the file (user/project),
|
|
215
|
+
then pick a setting row to TOGGLE it (booleans flip,
|
|
216
|
+
defaultBuildWorkflow cycles) — repeat, "Done" exits
|
|
217
|
+
/adx-config set defaultPlanMode=true one-shot update (user file)
|
|
218
|
+
/adx-config set showWidget=false project # write to the project file
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`showWidget`, `skipReview` and `defaultBuildWorkflow` apply immediately;
|
|
222
|
+
`defaultPlanMode` / `autoMode` apply from the next session.
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"defaultPlanMode": true,
|
|
227
|
+
"showWidget": true,
|
|
228
|
+
"autoMode": false,
|
|
229
|
+
"skipReview": false,
|
|
230
|
+
"defaultBuildWorkflow": "build"
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
| Key | Default | Effect |
|
|
235
|
+
|---|---|---|
|
|
236
|
+
| `defaultPlanMode` | `false` | Start every pi session in plan mode (no active run to restore) |
|
|
237
|
+
| `showWidget` | `true` | `false` hides the bottom flow/criteria widget entirely |
|
|
238
|
+
| `autoMode` | `false` | Persistent `--adx-auto`: unattended plan → build → verify → recap (the CLI flag still wins when passed) |
|
|
239
|
+
| `skipReview` | `false` | Default `skip_review=true` for the build-verify pipeline (picker + `/adx-run build-verify`); an explicit `skip_review=` in the command args wins |
|
|
240
|
+
| `defaultBuildWorkflow` | `"build"` | Which workflow `/adx-run` launches: `"build"` (simple) or `"build-verify"` (full) |
|
|
241
|
+
|
|
242
|
+
## Never-stop (auto-continue)
|
|
243
|
+
|
|
244
|
+
The workflow never parks itself on you:
|
|
245
|
+
|
|
246
|
+
- **Agent steps**: when a run ends on an active agent step without
|
|
247
|
+
`flow_step_done` (context pressure, stream stop, the model pausing
|
|
248
|
+
mid-reflection), the `agent_before_settle` hook appends a continuation
|
|
249
|
+
message — carrying the agent's **resume note** (written with `flow_meta`,
|
|
250
|
+
key `resume`), the criteria status, and the step reason — and requests one
|
|
251
|
+
more provider request. You never press "continue" (auto-continue /
|
|
252
|
+
`CONTINUE_PROMPT` behavior).
|
|
253
|
+
- **Context overflow**: pi's built-in auto-compaction keeps the context
|
|
254
|
+
usable between turns; the continuation message is what re-anchors the
|
|
255
|
+
agent after a compaction.
|
|
256
|
+
- **Sub-agents**: if an isolated verifier/reviewer child stops before
|
|
257
|
+
finishing (context pressure, timeout) and its run id is known, the executor
|
|
258
|
+
revives it once by re-spawning the persisted child session
|
|
259
|
+
(`pi -p --session <runId>` + "continue from where you stopped").
|
|
260
|
+
- **Safety**: 8 consecutive auto-continues on one step → the run blocks
|
|
261
|
+
(`/adx-resume`); `maxIterations` caps the whole run. Explicit user aborts
|
|
262
|
+
(Escape) are respected — `/adx-resume` continues from the persisted step.
|
|
263
|
+
- **Boot**: after a pi restart, `session_start` re-enters the current step of
|
|
264
|
+
any running run (boot auto-continuation).
|
|
265
|
+
|
|
266
|
+
## Tools
|
|
267
|
+
|
|
268
|
+
| Tool | Purpose |
|
|
269
|
+
| --- | --- |
|
|
270
|
+
| `flow_meta` | Shared workflow metadata store: `criteria`, `todos`, `review_findings`, `resume` (auto-continue notes) and `progress` (live display feed). Writes are atomic (per-process write chain + cross-process file lock — parent and `pi -p` children never lose updates); multi-item writes: `add_batch` (descriptions) / `update_batch` (items) |
|
|
271
|
+
| `flow_step_done` | Ends the current workflow step; the executor evaluates transitions and injects the next prompt (or a nudge) |
|
|
272
|
+
| `flow_plan_done` | Signals that planning is complete and hands off to the build pipeline (auto-launch in `--adx-auto`, picker in interactive mode — including **Spec only — stop**, which exports the criteria as a spec file and launches nothing) |
|
|
273
|
+
| `ask_user` | Structured question (choice / confirm / text) that pauses the turn for a user answer — plan/spec-mode clarification |
|
|
274
|
+
| `spec_write` | Writes the spec markdown document (spec mode only; `defaultActive: false`, so it is inactive in plan/build modes) — the single write channel while the workspace stays read-only |
|
|
275
|
+
|
|
276
|
+
## Sub-agents
|
|
277
|
+
|
|
278
|
+
Flow children are spawned **in-house** as isolated `pi -p` child processes
|
|
279
|
+
(`src/subagent.ts`), not through pi-subagents:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
pi -p --mode json --extension <adx-workflow> --no-extensions --no-mcp --no-skills
|
|
283
|
+
--tools "read,bash,flow_meta" --session-dir <cwd>/.pi/adx-flow/sessions
|
|
284
|
+
--session-id <runId> (fresh run) | --session <runId> (resume)
|
|
285
|
+
--append-system-prompt <agent role>
|
|
286
|
+
"<task>"
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
| Agent | Role |
|
|
290
|
+
| --- | --- |
|
|
291
|
+
| `adx-verifier` | Independent criterion verification; sets `passed`/`failed` via `flow_meta` |
|
|
292
|
+
| `adx-code-reviewer` | Reviews the git diff; manages `review_findings` via `flow_meta` |
|
|
293
|
+
|
|
294
|
+
- **Fresh session per run** (session files in `.pi/adx-flow/sessions/`) → no
|
|
295
|
+
retained in-process agent state → the "Agent is already processing" failure
|
|
296
|
+
class (stuck retained child blocking all subsequent spawns) is
|
|
297
|
+
structurally impossible.
|
|
298
|
+
- **Child mode** (`ADX_CHILD=1`): the child loads the extension with only the
|
|
299
|
+
`flow_meta` tool registered — no executor/commands/widgets, so the child can
|
|
300
|
+
update the shared store but never advance the workflow itself.
|
|
301
|
+
- **Bounded failures**: a 15-minute timeout kills the child process group;
|
|
302
|
+
provider hangs are recovered by the never-stop resume (persisted session).
|
|
303
|
+
- **Result contract**: the child updates `flow_meta` (criteria /
|
|
304
|
+
review_findings) and writes a report to `.pi/adx-flow/reports/<agent>.md`.
|
|
305
|
+
- **Model**: children use the user's default model; set `ADX_FLOW_MODEL`
|
|
306
|
+
(e.g. `litellm/qwen3.8-27b`) to pin a cheaper model for flow children, or a
|
|
307
|
+
per-step `"model"` field on any `sub_agent` step in a workflow file
|
|
308
|
+
(takes precedence over `ADX_FLOW_MODEL`) — e.g. a fast model for
|
|
309
|
+
verify/review on small projects.
|
|
310
|
+
- **Env overrides**: `ADX_PI_BIN` (pi CLI path), `ADX_EXTENSION_PATH`
|
|
311
|
+
(extension entry for the child).
|
|
312
|
+
|
|
313
|
+
### Performance: no redundant verification
|
|
314
|
+
|
|
315
|
+
The executor keeps verification cheap in three ways:
|
|
316
|
+
|
|
317
|
+
- **Re-run short-circuit** — after a successful verify pass the executor
|
|
318
|
+
records a content hash of the project files (`.pi/`, `node_modules/`,
|
|
319
|
+
`.git/`, build dirs excluded). On re-entry to the verify step, if the hash
|
|
320
|
+
is unchanged AND the step's metadata gate is now met (e.g. the store
|
|
321
|
+
caught up after a lost write), the expensive verifier pass is skipped and
|
|
322
|
+
the previous report is reused — a small project no longer pays 3-4 full
|
|
323
|
+
verifier passes to re-converge on the same verdict.
|
|
324
|
+
- **Proportional effort** — verify prompts get `{{projectFileCount}}` /
|
|
325
|
+
`{{projectLines}}` template variables and instruct the verifier to scale
|
|
326
|
+
the effort to the project size (small project: focused read + one smoke
|
|
327
|
+
run, not an exhaustive test suite).
|
|
328
|
+
- **Atomic store** — the state file is protected by a cross-process lock
|
|
329
|
+
(parent + children) and `flow_meta` mutations are atomic read-modify-writes;
|
|
330
|
+
the verifier records all criterion verdicts in a single `update_batch` call,
|
|
331
|
+
so "the verifier said PASS but the store disagrees" re-loops can't happen.
|
|
332
|
+
|
|
333
|
+
## Workflows
|
|
334
|
+
|
|
335
|
+
Workflow files are plain JSON state machines: `workflows/*.workflow.json`
|
|
336
|
+
(bundled), overridable per project in `.pi/adx-workflows/` (highest
|
|
337
|
+
precedence) and per user in `~/.pi/agent/workflows/`.
|
|
338
|
+
|
|
339
|
+
Four workflows are bundled:
|
|
340
|
+
|
|
341
|
+
- `build` — **simple**: `work_location → build → commit? → summarize`. No
|
|
342
|
+
automated verification, no code review; the builder self-checks before
|
|
343
|
+
marking criteria complete. Launched by `/adx-run`.
|
|
344
|
+
- `build-verify` — **the full pipeline** (launched with `/adx-run build-verify`):
|
|
345
|
+
`work_location → build → verify → code_review → finalize → commit? →
|
|
346
|
+
summarize`.
|
|
347
|
+
|
|
348
|
+
Both build pipelines end with an optional **commit & push** phase (`commit?`
|
|
349
|
+
above), controlled by the `commit` launch parameter: `commit=true` runs the
|
|
350
|
+
commit & push step automatically (the "Commit changes?" picker is skipped),
|
|
351
|
+
`commit=false` skips it, and without the parameter an interactive
|
|
352
|
+
"Commit changes?" picker is shown (auto mode skips it — no commit by
|
|
353
|
+
default). The step stages only the session's files (never `git add -A`),
|
|
354
|
+
commits with a clear message, and pushes (rebase onto origin if rejected).
|
|
355
|
+
An optional `message` launch parameter sets the exact commit message
|
|
356
|
+
verbatim (without it, the agent derives one from the staged diff).
|
|
357
|
+
In a **fresh worktree** (the `worklocation=new` path) it commits on the
|
|
358
|
+
`adx/<slug>` branch and pushes that branch only — `git push -u origin
|
|
359
|
+
adx/<slug>` — with **no merge into the base branch**: the merge stays manual
|
|
360
|
+
(open a PR or `git merge adx/<slug>` later), and the worktree + branch are
|
|
361
|
+
kept in place for follow-up work.
|
|
362
|
+
- `pr-review` — PR review + fixes + squash-merge (requires `gh`), launched
|
|
363
|
+
with `/adx-run pr-review pr_number=123`.
|
|
364
|
+
- `commit` — **commit & push**: `check_status → stage → commit → push →
|
|
365
|
+
summarize`. Stages only the session's files (never `git add -A`), commits
|
|
366
|
+
with a clear message, and rebases onto origin if the push is rejected.
|
|
367
|
+
Launched with `/adx-run commit` (optional `message="..."` param to set
|
|
368
|
+
the commit message explicitly).
|
|
369
|
+
|
|
370
|
+
### Authoring reference (short)
|
|
371
|
+
|
|
372
|
+
- **Steps**: `agent` (in-session LLM turn; must end with `flow_step_done`),
|
|
373
|
+
`sub_agent` (isolated child by `subAgentType`), `shell` (branch on exit
|
|
374
|
+
code), `user` (pause; buttons derived from `step_result` transitions + a
|
|
375
|
+
`Continue` for the `always` transition).
|
|
376
|
+
- **Transitions**: ordered, first match wins. Conditions: `step_result`,
|
|
377
|
+
`metadata_all_match`, `metadata_all_in` (empty list ⇒ true), `always`.
|
|
378
|
+
`goto` targets a step id, `$done`, or `$blocked`.
|
|
379
|
+
- **Templates**: `{{workdir}}`, `{{reason}}`, `{{criteriaCount}}`,
|
|
380
|
+
`{{pendingCount}}`, `{{criteriaList}}`, `{{modifiedFiles}}`,
|
|
381
|
+
`{{stepOutput.<key>}}` (incl. `content`, `stdout`, `stderr`, `exitCode`),
|
|
382
|
+
`{{params}}` / individual launch parameters.
|
|
383
|
+
- **Shell trust boundary**: `shell` step commands run via `sh -c`, and
|
|
384
|
+
`{{params.*}}` / `{{workdir}}` are interpolated **verbatim (unquoted)**.
|
|
385
|
+
Launch parameters are trusted shell input: a value like
|
|
386
|
+
`message="a; rm -rf ~"` is executed as shell code, and word-splitting
|
|
387
|
+
applies (a param `args="a b"` becomes two words). Quote values yourself when
|
|
388
|
+
composing commands from params. This is a deliberate trust assumption,
|
|
389
|
+
not a bug — workflow JSON and launch args are authored by the user running
|
|
390
|
+
the workflow.
|
|
391
|
+
- **Semantics**: `settings.maxIterations` caps the whole run (default 50);
|
|
392
|
+
no matching transition ⇒ `$blocked`; agent steps re-enter with
|
|
393
|
+
`nudgePrompt` when their transition condition is unmet; state is persisted
|
|
394
|
+
on every transition.
|
|
395
|
+
|
|
396
|
+
Full semantics: this extension is a self-contained declarative workflow
|
|
397
|
+
engine — steps, ordered transitions, metadata conditions, nudge re-entry,
|
|
398
|
+
`maxIterations` safety cap, `$blocked` handling, persistence and resume.
|
|
399
|
+
|
|
400
|
+
## Development
|
|
401
|
+
|
|
402
|
+
```sh
|
|
403
|
+
git clone https://github.com/mossaab/pi-adx-workflow.git
|
|
404
|
+
cd pi-adx-workflow
|
|
405
|
+
npm install # dev dependencies (typescript, @types/node, jiti, typebox,
|
|
406
|
+
# @earendil-works/pi-ai + pi-coding-agent for the test scripts)
|
|
407
|
+
npm run setup-dev # link host-provided packages (typebox, @earendil-works/*)
|
|
408
|
+
# from your pi install into node_modules
|
|
409
|
+
|
|
410
|
+
npm run smoke # jiti-load the extension with a fake ExtensionAPI
|
|
411
|
+
npm run e2e # drive the full build-verify pipeline with fake pi + fake sub-agents
|
|
412
|
+
npm run typecheck # tsc --noEmit (strict)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
`npm run setup-dev` replicates pi's runtime resolution: it symlinks the
|
|
416
|
+
host-provided packages (`typebox`, `@earendil-works/*`) from your pi install
|
|
417
|
+
into the local `node_modules/`, so the dev commands work from a fresh clone.
|
|
418
|
+
Re-run it if your pi install location changes (or use `ADX_FLOW_JITI` below).
|
|
419
|
+
|
|
420
|
+
The test scripts load TypeScript the same way pi does (via jiti). They find
|
|
421
|
+
jiti from your pi install — `~/.pi/agent/install/releases/<newest>/node_modules/jiti` —
|
|
422
|
+
with no hard-coded paths. Override the lookup with
|
|
423
|
+
`ADX_FLOW_JITI=/path/to/node_modules/jiti` if your layout is unusual.
|
|
424
|
+
|
|
425
|
+
Extension development loop: symlink the repo into
|
|
426
|
+
`~/.pi/agent/extensions/` (see [Install](#development-install-symlink)), edit
|
|
427
|
+
`src/*.ts`, and restart pi (or `/reload`) — jiti loads the TypeScript
|
|
428
|
+
directly, no build step.
|
|
429
|
+
|
|
430
|
+
### CI/CD
|
|
431
|
+
|
|
432
|
+
- **CI** (`.github/workflows/ci.yml`): on every push to `main` and on pull
|
|
433
|
+
requests, GitHub Actions runs `npm ci` → `typecheck` → `smoke` → `e2e` →
|
|
434
|
+
`e2e:lock` on Node 22. The test scripts' jiti lookup is pointed at the
|
|
435
|
+
devDependency copy via `ADX_FLOW_JITI` (runners have no pi install).
|
|
436
|
+
- **Publish** (`.github/workflows/npm-publish.yml`): publishing a
|
|
437
|
+
[GitHub release](https://github.com/mossaab/pi-adx-workflow/releases)
|
|
438
|
+
(or the manual `workflow_dispatch`) runs the typecheck + smoke checks, then
|
|
439
|
+
`npm publish --provenance`. Configure the repo secret **`NPM_TOKEN`** with
|
|
440
|
+
an npm automation token (fine-grained or classic with publish access);
|
|
441
|
+
`--provenance` additionally requires the GitHub OIDC token, which the
|
|
442
|
+
workflow requests via the `id-token: write` permission.
|
|
443
|
+
|
|
444
|
+
## Contributing
|
|
445
|
+
|
|
446
|
+
Contributions are welcome — fork, branch, and open a pull request.
|
|
447
|
+
|
|
448
|
+
- **TypeScript, strict mode, no build step** — the extension ships as
|
|
449
|
+
TypeScript loaded by pi's jiti; keep it that way.
|
|
450
|
+
- **Workflow engine changes**: extend `scripts/e2e-executor.mjs` — it drives
|
|
451
|
+
the whole pipeline (nudge loops, verify/review sub-agents, resume,
|
|
452
|
+
maxIterations blocking) against a fake pi, so it catches regressions fast.
|
|
453
|
+
- **New workflows**: plain JSON state machines in `workflows/` (schema in
|
|
454
|
+
`src/types.ts`); see the [authoring reference](#authoring-reference-short).
|
|
455
|
+
- **Docs**: README sections mirror the feature set — update both together.
|
|
456
|
+
|
|
457
|
+
## Troubleshooting
|
|
458
|
+
|
|
459
|
+
- **`pi` CLI not found** — point the extension at it: `export ADX_PI_BIN=/path/to/pi`
|
|
460
|
+
(or install pi-coding-agent so `~/.pi/agent/bin/pi` exists).
|
|
461
|
+
- **Flow children using a model you don't want** — pin one:
|
|
462
|
+
`export ADX_FLOW_MODEL=<provider/model>`.
|
|
463
|
+
- **Config not taking effect** — run `/adx-config` to see the effective
|
|
464
|
+
config and which files were read. Note: `defaultPlanMode` / `autoMode`
|
|
465
|
+
apply from the *next* session; the rest apply immediately.
|
|
466
|
+
- **"Agent is already processing"** — structurally impossible here: flow
|
|
467
|
+
children are isolated `pi -p` processes with fresh sessions, so no stuck
|
|
468
|
+
retained child can block later spawns. A hung child is killed by the
|
|
469
|
+
15-minute timeout and revived by the never-stop resume.
|
|
470
|
+
- **Package install fails at startup** (e.g. offline) — pi warns, skips the
|
|
471
|
+
package, and retries on the next start or `/reload`; `pi update --extensions`
|
|
472
|
+
reports the failure explicitly.
|
|
473
|
+
- **Dev scripts can't find jiti** — set `ADX_FLOW_JITI` to your jiti install
|
|
474
|
+
path (see [Development](#development)).
|
|
475
|
+
|
|
476
|
+
## Project layout
|
|
477
|
+
|
|
478
|
+
```
|
|
479
|
+
src/
|
|
480
|
+
├── index.ts # entry: tools, commands, events, wiring
|
|
481
|
+
├── types.ts # workflow schema types
|
|
482
|
+
├── store.ts # flow_meta store + execution state (file-backed)
|
|
483
|
+
├── templates.ts # template variable resolution
|
|
484
|
+
├── modes.ts # plan/build tool gating, bash allowlist, prompt sections
|
|
485
|
+
├── subagent.ts # in-house child-process propagation (pi -p spawn/resume)
|
|
486
|
+
├── executor.ts # the workflow state machine
|
|
487
|
+
├── tools.ts # flow_meta + flow_step_done tool definitions
|
|
488
|
+
├── widgets.ts # TUI widget (criteria checklist, step, findings)
|
|
489
|
+
└── workflows.ts # workflow loading (project > user > bundled)
|
|
490
|
+
workflows/
|
|
491
|
+
├── build.workflow.json
|
|
492
|
+
├── build-verify.workflow.json
|
|
493
|
+
├── commit.workflow.json
|
|
494
|
+
└── pr-review.workflow.json
|
|
495
|
+
scripts/
|
|
496
|
+
├── find-jiti.mjs # locate jiti in your pi install (used by the dev scripts)
|
|
497
|
+
├── setup-dev.mjs # npm run setup-dev (link host-provided packages)
|
|
498
|
+
├── smoke-load.mjs # npm run smoke
|
|
499
|
+
└── e2e-executor.mjs # npm run e2e
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## License
|
|
503
|
+
|
|
504
|
+
[MIT](./LICENSE) © mossaab
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-adx-workflow",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Declarative plan → build → verify → review workflow for pi-coding-agent, with in-house isolated sub-agents and never-stop auto-continue.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "mossaab",
|
|
8
|
+
"homepage": "https://github.com/mossaab/pi-adx-workflow",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/mossaab/pi-adx-workflow.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/mossaab/pi-adx-workflow/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"pi",
|
|
18
|
+
"pi-coding-agent",
|
|
19
|
+
"pi-extension",
|
|
20
|
+
"pi-package",
|
|
21
|
+
"pi-adx-workflow",
|
|
22
|
+
"workflow",
|
|
23
|
+
"subagent",
|
|
24
|
+
"acceptance-criteria",
|
|
25
|
+
"planning",
|
|
26
|
+
"verification",
|
|
27
|
+
"code-review"
|
|
28
|
+
],
|
|
29
|
+
"files": [
|
|
30
|
+
"src",
|
|
31
|
+
"workflows",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"setup-dev": "node scripts/setup-dev.mjs",
|
|
36
|
+
"smoke": "node scripts/smoke-load.mjs",
|
|
37
|
+
"e2e": "node scripts/e2e-executor.mjs",
|
|
38
|
+
"e2e:lock": "node scripts/e2e-lock.mjs",
|
|
39
|
+
"typecheck": "tsc --noEmit"
|
|
40
|
+
},
|
|
41
|
+
"pi": {
|
|
42
|
+
"extensions": [
|
|
43
|
+
"./src/index.ts"
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@earendil-works/pi-ai": "*",
|
|
48
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
49
|
+
"typebox": "*"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@earendil-works/pi-ai": "^1.5.2",
|
|
53
|
+
"@earendil-works/pi-coding-agent": "^1.5.2",
|
|
54
|
+
"@types/node": "^26.6.6",
|
|
55
|
+
"jiti": "^2.7.0",
|
|
56
|
+
"typebox": "^1.4.6",
|
|
57
|
+
"typescript": "^7.0.2"
|
|
58
|
+
}
|
|
59
|
+
}
|