@gonrocca/zero-pi 0.1.21 → 0.1.23
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 +224 -217
- package/extensions/startup-banner.ts +49 -6
- package/package.json +1 -1
- package/prompts/orchestrator.md +5 -0
package/README.md
CHANGED
|
@@ -7,290 +7,297 @@
|
|
|
7
7
|
╚══════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
+
<div align="center">
|
|
11
|
+
|
|
10
12
|
# @gonrocca/zero-pi
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
**The zero spec-driven development workflow, packaged for [pi](https://pi.dev).**
|
|
15
|
+
|
|
16
|
+
[](https://www.npmjs.com/package/@gonrocca/zero-pi)
|
|
17
|
+
[](./LICENSE)
|
|
18
|
+
[](https://nodejs.org)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
---
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
zero-pi adds the **`/forge`** SDD pipeline, skill auto-learning, adaptive
|
|
25
|
+
per-phase models, a metered-billing guard, and an animated `ZERO` banner —
|
|
26
|
+
**without modifying pi itself**. Same idea as `gentle-pi`: pi stays untouched;
|
|
27
|
+
zero-pi is a package pi loads. Every prompt, skill, extension and theme below
|
|
28
|
+
ships inside this one package.
|
|
17
29
|
|
|
18
|
-
##
|
|
30
|
+
## Contents
|
|
19
31
|
|
|
20
|
-
|
|
32
|
+
- [Install](#-install)
|
|
33
|
+
- [The SDD workflow](#-the-sdd-workflow)
|
|
34
|
+
- [Quality-of-life extensions](#-quality-of-life-extensions)
|
|
35
|
+
- [Commands](#-commands)
|
|
36
|
+
- [Environment variables](#-environment-variables)
|
|
37
|
+
- [Files it reads & writes](#-files-it-reads--writes)
|
|
38
|
+
- [Relationship to `zero`](#-relationship-to-zero)
|
|
39
|
+
- [Development](#-development)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 📦 Install
|
|
44
|
+
|
|
45
|
+
```
|
|
21
46
|
pi install npm:@gonrocca/zero-pi
|
|
22
47
|
```
|
|
23
48
|
|
|
24
49
|
That registers zero-pi in `~/.pi/agent/settings.json` and makes its prompts,
|
|
25
|
-
skills, and
|
|
50
|
+
skills, theme, and extensions available in every pi session.
|
|
26
51
|
|
|
27
|
-
|
|
52
|
+
| Requirement | Detail |
|
|
53
|
+
| ----------- | ------ |
|
|
54
|
+
| `pi-subagents` | **Required** — the SDD pipeline delegates each phase to a sub-agent. Install with `pi install npm:pi-subagents`. |
|
|
55
|
+
| Node | ≥ 20.6 — pi loads the TypeScript extensions directly. |
|
|
56
|
+
| After upgrade | Restart pi for the new version to take effect. |
|
|
28
57
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
58
|
+
Remove it with `pi remove npm:@gonrocca/zero-pi`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🛠 The SDD workflow
|
|
63
|
+
|
|
64
|
+
### `/forge` — the four-phase pipeline
|
|
65
|
+
|
|
66
|
+
A spec-driven development run, driven through four phases in order:
|
|
67
|
+
|
|
68
|
+
| Phase | Does |
|
|
69
|
+
| ----- | ---- |
|
|
70
|
+
| **explore** | Investigate the codebase read-only; produce findings. |
|
|
71
|
+
| **plan** | Write requirements, design, and an ordered task list. |
|
|
72
|
+
| **build** | Implement the plan. |
|
|
73
|
+
| **veredicto** | Review the build adversarially and record a verdict. |
|
|
74
|
+
|
|
75
|
+
Start it with `/forge <feature>`. The orchestrator drives phase order and
|
|
76
|
+
enforces a hard build/veredicto iteration cap — a `corregir` verdict re-runs
|
|
77
|
+
`build`, a `replantear` re-runs `plan`, and when the cap is reached without a
|
|
78
|
+
`pasa` the run stops and reports the result as **not verified**.
|
|
79
|
+
`/forge --continue [slug]` resumes an interrupted run from its `.sdd/<slug>/`
|
|
80
|
+
artifacts.
|
|
81
|
+
|
|
82
|
+
A run can also start from natural language: describe the work and signal SDD
|
|
83
|
+
intent — "hacelo con sdd", "usá el pipeline" — and the `sdd-routing` skill
|
|
84
|
+
routes it into `/forge`. It triggers only on a clear signal phrase; `/forge`
|
|
85
|
+
stays the primary, explicit entry point.
|
|
32
86
|
|
|
33
|
-
|
|
87
|
+
### Language & output
|
|
34
88
|
|
|
35
|
-
|
|
89
|
+
A `/forge` run reads as a short, calm progress stream, in Spanish:
|
|
36
90
|
|
|
37
|
-
|
|
91
|
+
- **Language Boundary** — every user-facing message is in Spanish (Rioplatense
|
|
92
|
+
voseo); sub-agent briefs stay in English for token efficiency; identifiers
|
|
93
|
+
(verdicts, slugs, paths, model ids, commands) are kept verbatim.
|
|
94
|
+
- **Output Contract** — each phase reports a bounded summary
|
|
95
|
+
(`Estado` / `Resumen` / `Artefactos` / `Siguiente`), never free-form prose.
|
|
96
|
+
No raw tool output, file dumps, sub-agent listings, or triple-backtick code
|
|
97
|
+
fences reach the chat. The phase-start line names the model and provider the
|
|
98
|
+
phase runs on plus a brief gloss of what it does — so a slow phase reads as
|
|
99
|
+
working, not frozen. The run ends stating `verificado` or `no verificado`.
|
|
38
100
|
|
|
39
|
-
|
|
40
|
-
2. **plan** — write requirements, design, and an ordered task list.
|
|
41
|
-
3. **build** — implement the plan.
|
|
42
|
-
4. **veredicto** — review the build adversarially and record a verdict
|
|
43
|
-
(`pasa`, `corregir`, or `replantear`).
|
|
101
|
+
### Review Workload Forecast
|
|
44
102
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
103
|
+
The `plan` phase keeps tasks reviewable. Every planned task carries a
|
|
104
|
+
`review: ~N changed lines` estimate, and `tasks.md` gains a `## Review Workload`
|
|
105
|
+
section with a bold run total. Tasks are sized against a fixed budget of
|
|
106
|
+
**400 changed lines per task** (borrowed from gentle-ai). A task over budget is
|
|
107
|
+
split; one that genuinely cannot be split stays whole and is recorded as an
|
|
108
|
+
over-budget exception with a reason.
|
|
48
109
|
|
|
49
|
-
|
|
50
|
-
natural language: describe the work and signal SDD intent — e.g. "hacelo con
|
|
51
|
-
sdd" or "usá el pipeline" — and the `sdd-routing` skill routes the request into
|
|
52
|
-
`/forge` for you. It triggers only on a clear signal phrase and stays out of the
|
|
53
|
-
way for ordinary requests; `/forge` remains the primary, explicit entry point.
|
|
110
|
+
### SDD sub-agents — `sdd-agents.ts`
|
|
54
111
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
split into smaller, individually verifiable tasks; one that genuinely cannot be
|
|
62
|
-
split stays whole and is recorded as an over-budget exception with a reason. The
|
|
63
|
-
orchestrator's plan-phase summary reports the run total and any exceptions.
|
|
112
|
+
`pi-subagents` discovers agents from `~/.pi/agent/agents/**/*.md`, but a
|
|
113
|
+
`pi install` ships only the phase *prompts*. This extension closes the gap: on
|
|
114
|
+
every load it generates the four `zero-<phase>` agent files under
|
|
115
|
+
`~/.pi/agent/agents/zero/` from the package's phase prompts and the per-phase
|
|
116
|
+
models in `~/.pi/zero.json`, so they stay in sync with the prompts and with
|
|
117
|
+
`/zero-models`.
|
|
64
118
|
|
|
65
|
-
### Per-phase models
|
|
119
|
+
### Per-phase models — `/zero-models`
|
|
66
120
|
|
|
67
|
-
|
|
68
|
-
|
|
121
|
+
A real pi command — a code handler, not an LLM prompt — for the SDD models. Run
|
|
122
|
+
it with no argument for the **provider-aware** interactive picker
|
|
123
|
+
(**phase → provider → model**, sourced from pi's model registry), or set one
|
|
69
124
|
directly:
|
|
70
125
|
|
|
71
126
|
```
|
|
72
|
-
/zero-models
|
|
73
|
-
/zero-models build=claude-opus-4-7
|
|
74
|
-
/zero-models build=codex/gpt-5-codex
|
|
127
|
+
/zero-models interactive picker
|
|
128
|
+
/zero-models build=claude-opus-4-7 set one phase
|
|
129
|
+
/zero-models build=codex/gpt-5-codex set one phase with an explicit provider
|
|
75
130
|
```
|
|
76
131
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
(anthropic, codex, opencode, …) and its models are offered — not a hardcoded
|
|
80
|
-
list. An `— otro provider —` / `— otro modelo —` entry still lets you type
|
|
81
|
-
anything by hand.
|
|
132
|
+
It reads and writes `~/.pi/zero.json` — a `models` map and a parallel
|
|
133
|
+
`providers` map. The orchestrator picks the change up on the next `/forge` run.
|
|
82
134
|
|
|
83
|
-
|
|
84
|
-
parallel `providers` map. The orchestrator picks the change up on the next
|
|
85
|
-
`/forge` run. The `zero` CLI also writes this file when it installs the layer.
|
|
135
|
+
### Run memory — Cortex
|
|
86
136
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
137
|
+
Every run reads from and writes to Cortex, the persistent-memory MCP server.
|
|
138
|
+
Before exploring, the orchestrator recalls prior `zero-run/*` traces; when the
|
|
139
|
+
run ends it saves a run-trace — verdict, correction rounds, gotchas — under
|
|
140
|
+
`topic_key: zero-run/<slug>`. The next run starts from what the last one
|
|
141
|
+
learned. With `--no-mcp`, or when Cortex is unreachable, the loop degrades
|
|
142
|
+
silently and never blocks a run.
|
|
93
143
|
|
|
94
144
|
### Canonical specs & `/zero-sync`
|
|
95
145
|
|
|
96
146
|
zero keeps a **canonical, project-wide spec store** that accumulates accepted
|
|
97
|
-
requirements across runs, so each `/forge` run builds on the last
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
invokes `/zero-sync <slug>` automatically — a `corregir`, `replantear`, or
|
|
126
|
-
cap-reached run never syncs.
|
|
127
|
-
|
|
128
|
-
**The archive — `.sdd/archive/`.** Each successful sync appends a dated,
|
|
129
|
-
slug-named entry `.sdd/archive/<YYYY-MM-DD>-<slug>/` containing a copy of the
|
|
130
|
-
run's `proposal.md` and `spec.md` plus a `sync.md` report listing every added,
|
|
131
|
-
modified, and removed requirement. The archive is append-only — a new entry
|
|
132
|
-
never rewrites a prior one — so it is a full audit trail of how the canonical
|
|
133
|
-
store evolved.
|
|
134
|
-
|
|
135
|
-
### Adaptive model profiles
|
|
136
|
-
|
|
137
|
-
zero learns which model fits each SDD phase from your own run history and can
|
|
138
|
-
re-tune `~/.pi/zero.json` for you.
|
|
139
|
-
|
|
140
|
-
**The metrics log — `~/.pi/zero-runs.jsonl`.** Every completed SDD run appends
|
|
141
|
-
one JSON line to this file: the feature slug, the per-phase models the run used,
|
|
142
|
-
the final verdict, the build/veredicto round count, and the ordered per-round
|
|
143
|
-
verdict sequence. It is append-only and never rewritten. This local log is the
|
|
144
|
-
only thing zero learns from — a run abandoned before it reaches a verdict adds
|
|
145
|
-
no line.
|
|
146
|
-
|
|
147
|
-
**Phase attribution (v2).** The per-round verdict sequence makes blame precise:
|
|
148
|
-
a `corregir` round re-runs — and so blames — the `build` phase, and a
|
|
149
|
-
`replantear` round blames the `plan` phase. Autotune aggregates that sequence
|
|
150
|
-
per phase and upgrades **only the phase at fault**, one tier at a time — a
|
|
151
|
-
`build` problem no longer drags `plan` up with it. The `explore` and `veredicto`
|
|
152
|
-
phases are never tuned.
|
|
153
|
-
|
|
154
|
-
**Autotune modes.** At each pi session start zero aggregates the log and, once a
|
|
155
|
-
phase has accumulated enough run data to cross a confidence threshold, decides
|
|
156
|
-
whether that phase's model should change. Until a phase has accumulated enough
|
|
157
|
-
v2 runs of its own, autotune deliberately stays quiet — a one-time, silent
|
|
158
|
-
cold-start after upgrading, not a regression. The `autotune` mode in
|
|
159
|
-
`~/.pi/zero.json` controls what happens next:
|
|
147
|
+
requirements across runs, so each `/forge` run builds on the last.
|
|
148
|
+
|
|
149
|
+
- **The store** — `.sdd/specs/requirements.md`: a `# ` title followed by
|
|
150
|
+
`### REQ: <name>` blocks. The `plan` phase reads it as the baseline.
|
|
151
|
+
- **The plan artifacts** — every run's `plan` phase writes `proposal.md`,
|
|
152
|
+
`spec.md` (the **delta**: `## ADDED` / `## MODIFIED` / `## REMOVED`),
|
|
153
|
+
`design.md`, and `tasks.md` into `.sdd/<slug>/`.
|
|
154
|
+
- **`/zero-sync <slug>`** — a deterministic, unit-tested merge that folds the
|
|
155
|
+
delta into the store atomically. Guardrails reject a bad delta before
|
|
156
|
+
anything is written. The orchestrator invokes it automatically after a `pasa`
|
|
157
|
+
verdict — never on `corregir`, `replantear`, or a cap-reached run.
|
|
158
|
+
- **The archive** — `.sdd/archive/<YYYY-MM-DD>-<slug>/`: an append-only audit
|
|
159
|
+
trail of every sync.
|
|
160
|
+
|
|
161
|
+
### Adaptive model profiles — autotune
|
|
162
|
+
|
|
163
|
+
zero learns which model fits each SDD phase from your own run history.
|
|
164
|
+
|
|
165
|
+
- **The metrics log** — `~/.pi/zero-runs.jsonl`: every completed run appends one
|
|
166
|
+
JSON line (slug, per-phase models, verdict, round count, per-round verdict
|
|
167
|
+
sequence). Append-only.
|
|
168
|
+
- **Phase attribution** — a `corregir` round blames `build`, a `replantear`
|
|
169
|
+
blames `plan`. Autotune upgrades **only the phase at fault**, one tier at a
|
|
170
|
+
time. `explore` and `veredicto` are never tuned.
|
|
171
|
+
- **Cross-machine sync** — each run pushes its metrics to Cortex; `/forge`
|
|
172
|
+
pulls the shared log back, so autotune sees runs from other machines too.
|
|
173
|
+
|
|
174
|
+
The `autotune` mode in `~/.pi/zero.json` controls what happens:
|
|
160
175
|
|
|
161
176
|
| Mode | Behaviour |
|
|
162
177
|
| ---- | --------- |
|
|
163
|
-
| `auto` _(default)_ |
|
|
164
|
-
| `ask` |
|
|
165
|
-
| `off` |
|
|
178
|
+
| `auto` _(default)_ | Applies the adjustment to `~/.pi/zero.json` and notifies you what changed. |
|
|
179
|
+
| `ask` | Records the recommendation; you apply it from `/zero-models`. |
|
|
180
|
+
| `off` | Records run metrics, but never changes or recommends anything. |
|
|
166
181
|
|
|
167
|
-
|
|
168
|
-
|
|
182
|
+
Set it with `/zero-models autotune=<auto\|ask\|off>`. In `ask` mode a waiting
|
|
183
|
+
recommendation shows as a leading `★ aplicar sugerencia` entry in `/zero-models`.
|
|
169
184
|
|
|
170
|
-
|
|
171
|
-
`/zero-models` menu (which shows the current mode as its own entry):
|
|
185
|
+
### Skill auto-learning — `skill-loop`
|
|
172
186
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
187
|
+
Gives the agent a closed learning loop — distill a reusable skill from a
|
|
188
|
+
substantial task, store it, surface relevant skills on a new task, refine an
|
|
189
|
+
existing skill instead of duplicating it — so solutions are reused, not
|
|
190
|
+
re-derived.
|
|
176
191
|
|
|
177
|
-
|
|
178
|
-
waiting, running `/zero-models` shows a leading `★ aplicar sugerencia` entry;
|
|
179
|
-
selecting it applies the change and clears the pending suggestion. Note that a
|
|
180
|
-
pending suggestion is *refreshed* — an unactioned suggestion is overwritten by
|
|
181
|
-
the next `ask`-mode session with fresher data, so `/zero-models` always reflects
|
|
182
|
-
the most recent recommendation.
|
|
192
|
+
---
|
|
183
193
|
|
|
184
|
-
|
|
194
|
+
## ✨ Quality-of-life extensions
|
|
185
195
|
|
|
186
|
-
`
|
|
187
|
-
instead of re-derived.
|
|
196
|
+
### Provider guard — `provider-guard.ts`
|
|
188
197
|
|
|
189
|
-
|
|
198
|
+
pi reaches the same Claude models through two providers: `pi-claude-cli` (billed
|
|
199
|
+
against your subscription's plan limits) and `anthropic` (the direct API, billed
|
|
200
|
+
per token from your metered extra-usage pool). The guard watches model switches:
|
|
201
|
+
on a deliberate switch to a metered provider it offers — via a confirmation
|
|
202
|
+
dialog — to redirect you to the equivalent model on `pi-claude-cli`. Say no and
|
|
203
|
+
you stay put, no nagging. Switching to a subscription provider is a no-op.
|
|
190
204
|
|
|
191
|
-
|
|
192
|
-
palette with cyan, amber, mint, rose, and violet accents tuned for SDD work.
|
|
193
|
-
Select it from `/settings`, or set `"theme": "zero-sdd"` in Pi settings.
|
|
205
|
+
### Startup banner — `startup-banner.ts`
|
|
194
206
|
|
|
195
|
-
|
|
207
|
+
Renders the `ZERO` wordmark as ASCII-safe Tetris cells in pure ANSI 24-bit
|
|
208
|
+
colour, no runtime dependencies. The cells assemble from the bottom up, settle,
|
|
209
|
+
then run a short **sparkle pass** — a few cells glint bright for about a second.
|
|
210
|
+
The render runs synchronously before pi draws its UI.
|
|
196
211
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
212
|
+
| `ZERO_BANNER` | Effect |
|
|
213
|
+
| ------------- | ------ |
|
|
214
|
+
| _(unset)_ / `shimmer` | Animated assembly + sparkle, then settle (default) |
|
|
215
|
+
| `static` | Completed banner only, no animation |
|
|
216
|
+
| `off` | Render nothing |
|
|
201
217
|
|
|
202
|
-
|
|
203
|
-
fights pi's renderer.
|
|
218
|
+
Colour is skipped automatically when `NO_COLOR` is set or output is not a TTY.
|
|
204
219
|
|
|
205
|
-
### Working-phrase ticker
|
|
220
|
+
### Working-phrase ticker — `working-phrases.ts`
|
|
206
221
|
|
|
207
|
-
|
|
208
|
-
|
|
222
|
+
Replaces pi's static `Working...` line with a context-aware, rotating Spanish
|
|
223
|
+
phrase — tool-specific while a tool runs (`Leyendo archivos…`), the SDD phase
|
|
224
|
+
while a sub-agent runs (`Planeando la solución…`), playful verbs while the model
|
|
225
|
+
thinks (`Maquinando…`) — plus a theme-tinted braille spinner.
|
|
209
226
|
|
|
210
|
-
|
|
211
|
-
`Ejecutando comandos…`, `Buscando en el código…`. MCP tools are named by
|
|
212
|
-
server (`Consultando un MCP…`).
|
|
213
|
-
- **While a zero sub-agent runs** — the SDD phase it owns:
|
|
214
|
-
`Explorando el código…`, `Planeando la solución…`,
|
|
215
|
-
`Construyendo la implementación…`, `Revisando el veredicto…`.
|
|
216
|
-
- **While the model thinks** — a rotation of playful verbs (`Maquinando…`,
|
|
217
|
-
`Rumiando…`, `Cocinando…`). Once a `/forge` run is detected the rotation
|
|
218
|
-
biases toward SDD vocabulary.
|
|
227
|
+
### Conversation resume — `conversation-resume.ts`
|
|
219
228
|
|
|
220
|
-
|
|
221
|
-
the
|
|
222
|
-
|
|
223
|
-
|
|
229
|
+
When pi exits normally, writes a local handoff note at `.pi/zero-resume.md` —
|
|
230
|
+
the exact restore command for the persisted session plus a concise conversation
|
|
231
|
+
tail. Generate it any time with `/zero-resume`. zero-pi creates `.pi/.gitignore`
|
|
232
|
+
so conversation context is never committed. Set `ZERO_RESUME=off` to disable the
|
|
233
|
+
automatic write.
|
|
224
234
|
|
|
225
|
-
|
|
235
|
+
### Windows process-tree kill — `win-tree-kill.ts`
|
|
226
236
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
| `off` | Render nothing |
|
|
237
|
+
On Windows, `kill()` terminates only the target process — so aborting a turn can
|
|
238
|
+
leave an orphaned `claude` process streaming (Esc appears to do nothing). This
|
|
239
|
+
extension patches `child_process.spawn` so every later subprocess tree-kills via
|
|
240
|
+
`taskkill /T /F`. No-op on non-Windows. **Keep it enabled on Windows.**
|
|
232
241
|
|
|
233
|
-
|
|
234
|
-
TTY.
|
|
242
|
+
### ZERO terminal theme — `themes/zero-sdd.json`
|
|
235
243
|
|
|
236
|
-
|
|
244
|
+
A dark, high-contrast pi theme with cyan, amber, mint, rose, and violet accents
|
|
245
|
+
tuned for SDD work. Select it from `/settings`, or set `"theme": "zero-sdd"`.
|
|
237
246
|
|
|
238
|
-
|
|
239
|
-
provider. When you switch to a model on the `anthropic` provider — which bills
|
|
240
|
-
per token and draws down your metered extra-usage pool — the guard offers to
|
|
241
|
-
redirect you to the equivalent model on `pi-claude-cli`, the provider backed by
|
|
242
|
-
your subscription's limits.
|
|
247
|
+
---
|
|
243
248
|
|
|
244
|
-
|
|
245
|
-
escape hatch: say "yes" and the guard switches you to the subscription-backed
|
|
246
|
-
equivalent; say "no" (or cancel) and you stay on the metered `anthropic`
|
|
247
|
-
provider with no further nagging. When there is no equivalent model on
|
|
248
|
-
`pi-claude-cli`, and when a model is restored on session start rather than
|
|
249
|
-
switched deliberately, the guard skips the modal and just shows a one-line
|
|
250
|
-
warning. Switching to a subscription provider is a complete no-op — no dialog,
|
|
251
|
-
no notification, no noise.
|
|
249
|
+
## ⌨️ Commands
|
|
252
250
|
|
|
253
|
-
|
|
251
|
+
| Command | What it does |
|
|
252
|
+
| ------- | ------------ |
|
|
253
|
+
| `/forge <feature>` | Run the four-phase SDD pipeline for a feature. |
|
|
254
|
+
| `/forge --continue [slug]` | Resume an interrupted SDD run. |
|
|
255
|
+
| `/zero-models [<phase>=[<provider>/]<model>]` | Show or set the per-phase SDD models. |
|
|
256
|
+
| `/zero-models autotune=<auto\|ask\|off>` | Set the autotune mode. |
|
|
257
|
+
| `/zero-sync <slug>` | Fold a run's delta `spec.md` into the canonical store. |
|
|
258
|
+
| `/zero-resume` | Write `.pi/zero-resume.md` now. |
|
|
254
259
|
|
|
255
|
-
|
|
260
|
+
## 🔧 Environment variables
|
|
256
261
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
262
|
+
| Variable | Effect |
|
|
263
|
+
| -------- | ------ |
|
|
264
|
+
| `ZERO_BANNER` | `shimmer` (default) · `static` · `off` — startup-banner mode. |
|
|
265
|
+
| `ZERO_RESUME` | `off` / `0` disables the automatic conversation-resume write. |
|
|
266
|
+
| `NO_COLOR` | Standard — disables banner colour. |
|
|
260
267
|
|
|
261
|
-
|
|
268
|
+
## 📂 Files it reads & writes
|
|
262
269
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
270
|
+
| Path | Role |
|
|
271
|
+
| ---- | ---- |
|
|
272
|
+
| `~/.pi/zero.json` | Per-phase `models` / `providers` and the `autotune` mode. |
|
|
273
|
+
| `~/.pi/zero-runs.jsonl` | Append-only run-metrics log autotune learns from. |
|
|
274
|
+
| `~/.pi/agent/agents/zero/` | Generated `zero-<phase>` sub-agent files. |
|
|
275
|
+
| `.sdd/<slug>/` | Per-run plan artifacts. |
|
|
276
|
+
| `.sdd/specs/requirements.md` | The canonical, project-wide spec store. |
|
|
277
|
+
| `.sdd/archive/` | Append-only audit trail of every `/zero-sync`. |
|
|
278
|
+
| `.pi/zero-resume.md` | Local session handoff note. |
|
|
266
279
|
|
|
267
|
-
|
|
280
|
+
## 🔗 Relationship to `zero`
|
|
268
281
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
282
|
+
`zero-pi` is the pi-specific layer of the
|
|
283
|
+
**[zero](https://github.com/gonzalonicolasr/zero)** integrator. The `zero` CLI
|
|
284
|
+
installs this layer onto pi (bootstrapping pi.dev itself when missing) and
|
|
285
|
+
writes the per-phase model configuration. You can also install `zero-pi`
|
|
286
|
+
directly if you only want the pi layer.
|
|
272
287
|
|
|
273
|
-
|
|
274
|
-
keeps a concise conversation tail, enough to remember the last user intent and
|
|
275
|
-
assistant progress without replacing pi's real session history.
|
|
288
|
+
## 🧪 Development
|
|
276
289
|
|
|
277
|
-
|
|
290
|
+
Dependency-free, no build step — pi loads the TypeScript extensions directly.
|
|
291
|
+
Run the test suite with:
|
|
278
292
|
|
|
279
|
-
```
|
|
280
|
-
|
|
293
|
+
```
|
|
294
|
+
npm test
|
|
281
295
|
```
|
|
282
296
|
|
|
283
|
-
|
|
284
|
-
conversation context is not accidentally committed.
|
|
285
|
-
|
|
286
|
-
## Relationship to `zero`
|
|
287
|
-
|
|
288
|
-
`zero-pi` is the pi-specific layer of the **[zero](https://github.com/gonzalonicolasr/zero)**
|
|
289
|
-
integrator. The `zero` CLI installs this layer onto pi (bootstrapping pi.dev
|
|
290
|
-
itself when it is missing) and writes the per-phase model configuration. You
|
|
291
|
-
can also install `zero-pi` directly with `pi install npm:@gonrocca/zero-pi` if
|
|
292
|
-
you only want the pi layer.
|
|
297
|
+
---
|
|
293
298
|
|
|
294
|
-
|
|
299
|
+
<div align="center">
|
|
295
300
|
|
|
296
301
|
MIT © Gonzalo Rocca
|
|
302
|
+
|
|
303
|
+
</div>
|
|
@@ -119,7 +119,12 @@ function colorForPiece(piece: string, row: number, rank: number, active: boolean
|
|
|
119
119
|
return lerpColor(base, COLORS.peak, heightWarmth * 0.18 + rankPulse);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
function paintMatrixLine(
|
|
122
|
+
function paintMatrixLine(
|
|
123
|
+
matrix: Matrix,
|
|
124
|
+
row: number,
|
|
125
|
+
visibleCells: number,
|
|
126
|
+
sparkles?: ReadonlySet<string>,
|
|
127
|
+
): string {
|
|
123
128
|
let out = "";
|
|
124
129
|
const line = matrix.rows[row] ?? "";
|
|
125
130
|
for (let col = 0; col < matrix.width; col++) {
|
|
@@ -128,16 +133,31 @@ function paintMatrixLine(matrix: Matrix, row: number, visibleCells: number): str
|
|
|
128
133
|
out += " ";
|
|
129
134
|
continue;
|
|
130
135
|
}
|
|
131
|
-
const
|
|
136
|
+
const key = `${row}:${col}`;
|
|
137
|
+
const rank = matrix.ranks.get(key) ?? Number.POSITIVE_INFINITY;
|
|
132
138
|
if (rank >= visibleCells) {
|
|
133
139
|
out += " ";
|
|
134
140
|
continue;
|
|
135
141
|
}
|
|
136
|
-
|
|
142
|
+
// A cell glints when it is the assembly's leading cell or when this
|
|
143
|
+
// sparkle frame picked it.
|
|
144
|
+
const glint = rank === visibleCells - 1 || (sparkles?.has(key) ?? false);
|
|
145
|
+
out += ansiFg(colorForPiece(piece, row, rank, glint), "[]");
|
|
137
146
|
}
|
|
138
147
|
return out;
|
|
139
148
|
}
|
|
140
149
|
|
|
150
|
+
/** Pick a handful of distinct settled cells to glint for one sparkle frame. */
|
|
151
|
+
function pickSparkles(matrix: Matrix, count: number, rand: () => number): Set<string> {
|
|
152
|
+
const keys = Array.from(matrix.ranks.keys());
|
|
153
|
+
const chosen = new Set<string>();
|
|
154
|
+
const target = Math.min(Math.max(0, count), keys.length);
|
|
155
|
+
for (let guard = 0; chosen.size < target && guard < target * 8; guard++) {
|
|
156
|
+
chosen.add(keys[Math.floor(rand() * keys.length)]);
|
|
157
|
+
}
|
|
158
|
+
return chosen;
|
|
159
|
+
}
|
|
160
|
+
|
|
141
161
|
interface OutStream {
|
|
142
162
|
write(chunk: string): unknown;
|
|
143
163
|
isTTY?: boolean;
|
|
@@ -178,6 +198,10 @@ export interface RenderOptions {
|
|
|
178
198
|
text?: string;
|
|
179
199
|
frames?: number;
|
|
180
200
|
frameMs?: number;
|
|
201
|
+
/** Number of post-settle sparkle frames (shimmer mode). `0` disables it. */
|
|
202
|
+
sparkleFrames?: number;
|
|
203
|
+
/** Delay between sparkle frames, in milliseconds. */
|
|
204
|
+
sparkleMs?: number;
|
|
181
205
|
stream?: OutStream;
|
|
182
206
|
}
|
|
183
207
|
|
|
@@ -201,6 +225,14 @@ export function renderBanner(options: RenderOptions = {}): void {
|
|
|
201
225
|
|
|
202
226
|
stream.write("\n" + Array.from({ length: ROWS }, () => "").join("\n") + "\n");
|
|
203
227
|
|
|
228
|
+
// Repaint the six rows in place; optionally with this frame's sparkle set.
|
|
229
|
+
const paintRows = (sparkles?: ReadonlySet<string>): void => {
|
|
230
|
+
stream.write(`\x1b[${ROWS}A\r`);
|
|
231
|
+
for (let r = 0; r < ROWS; r++) {
|
|
232
|
+
stream.write("\x1b[2K" + paintMatrixLine(matrix, r, matrix.totalCells, sparkles) + "\n");
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
204
236
|
if (mode === "shimmer") {
|
|
205
237
|
const frames = Math.max(2, options.frames ?? 42);
|
|
206
238
|
const frameMs = Math.max(1, options.frameMs ?? 18);
|
|
@@ -215,10 +247,21 @@ export function renderBanner(options: RenderOptions = {}): void {
|
|
|
215
247
|
}
|
|
216
248
|
}
|
|
217
249
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
250
|
+
// Settle on the completed wordmark.
|
|
251
|
+
paintRows();
|
|
252
|
+
|
|
253
|
+
// Sparkle pass — a few settled cells glint bright each frame, then a clean
|
|
254
|
+
// final settle. Shimmer only; `sparkleFrames: 0` disables it.
|
|
255
|
+
if (mode === "shimmer") {
|
|
256
|
+
const sparkleFrames = Math.max(0, options.sparkleFrames ?? 22);
|
|
257
|
+
const sparkleMs = Math.max(1, options.sparkleMs ?? 36);
|
|
258
|
+
for (let f = 0; f < sparkleFrames; f++) {
|
|
259
|
+
paintRows(pickSparkles(matrix, 3 + (f % 4), Math.random));
|
|
260
|
+
sleepSync(sparkleMs);
|
|
261
|
+
}
|
|
262
|
+
if (sparkleFrames > 0) paintRows();
|
|
221
263
|
}
|
|
264
|
+
|
|
222
265
|
stream.write("\n");
|
|
223
266
|
}
|
|
224
267
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gonrocca/zero-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "zero-pi — an installable layer for pi (pi.dev): the zero spec-driven development workflow, skill auto-learning, and an animated ZERO startup banner. Adds capability to pi without modifying pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
package/prompts/orchestrator.md
CHANGED
|
@@ -166,6 +166,11 @@ your internal reasoning. Reference an artifact by its path; never paste its
|
|
|
166
166
|
contents. Summarize each sub-agent's result in one short message — synthesize,
|
|
167
167
|
do not relay.
|
|
168
168
|
|
|
169
|
+
**Formatting.** pi's chat shows a triple-backtick fenced code block with the
|
|
170
|
+
backticks rendered literally — never use one. Present commands, paths, and
|
|
171
|
+
snippets as plain lines indented two spaces, or inline with single backticks.
|
|
172
|
+
Keep the rest plain text; bold and single-backtick inline code render fine.
|
|
173
|
+
|
|
169
174
|
**Approval question.** In interactive mode, after the phase summary, ask a
|
|
170
175
|
single Spanish question — `¿Continuamos?` — never a bilingual one. Accept
|
|
171
176
|
continue, stop, or feedback.
|