@gonrocca/zero-pi 0.1.20 → 0.1.21
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/extensions/autotune-extension.ts +2 -2
- package/extensions/autotune.ts +1 -1
- package/extensions/conversation-resume.ts +5 -5
- package/extensions/spec-merge-extension.ts +13 -13
- package/extensions/zero-models.ts +1 -1
- package/package.json +1 -1
- package/prompts/forge.md +5 -4
- package/prompts/orchestrator.md +72 -18
- package/prompts/phases/build.md +6 -1
- package/prompts/phases/explore.md +6 -1
- package/prompts/phases/plan.md +6 -1
- package/prompts/phases/veredicto.md +6 -1
- package/skills/sdd-routing/SKILL.md +2 -1
|
@@ -157,7 +157,7 @@ function evaluateAndTune(ctx: PiSessionContext): void {
|
|
|
157
157
|
if (data === null) {
|
|
158
158
|
// Absent or unparseable `zero.json` — no profile to safely tune. Skip with
|
|
159
159
|
// a single non-blocking warning; never synthesize a `models` map (AC 6.4).
|
|
160
|
-
notify("zero autotune: ~/.pi/zero.json
|
|
160
|
+
notify("zero autotune: ~/.pi/zero.json falta o no se puede leer — se omite", "warning");
|
|
161
161
|
return;
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -213,7 +213,7 @@ function evaluateAndTune(ctx: PiSessionContext): void {
|
|
|
213
213
|
);
|
|
214
214
|
for (const adj of pending) {
|
|
215
215
|
notify(
|
|
216
|
-
`zero autotune
|
|
216
|
+
`zero autotune sugiere: ${adj.phase} → ${adj.to} — corré /zero-models para aplicar`,
|
|
217
217
|
"info",
|
|
218
218
|
);
|
|
219
219
|
}
|
package/extensions/autotune.ts
CHANGED
|
@@ -526,7 +526,7 @@ export function decideAdjustments(
|
|
|
526
526
|
if (to === null) continue; // already at top tier, or untierable
|
|
527
527
|
|
|
528
528
|
const blame = phase === "build" ? "corregir" : "replantear";
|
|
529
|
-
const reason = `
|
|
529
|
+
const reason = `prom ${measure.toFixed(1)} ${blame}/run en ${stat.v2Samples} runs v2`;
|
|
530
530
|
|
|
531
531
|
adjustments.push({ phase, from: currentModel, to, reason });
|
|
532
532
|
}
|
|
@@ -368,21 +368,21 @@ export default function register(pi?: PiAPI): void {
|
|
|
368
368
|
|
|
369
369
|
try {
|
|
370
370
|
const path = writeFromContext(ctx, reason);
|
|
371
|
-
if (path) notify(ctx, `zero
|
|
371
|
+
if (path) notify(ctx, `zero: resumen guardado en ${path}`, "info");
|
|
372
372
|
} catch (err) {
|
|
373
|
-
notify(ctx, `zero
|
|
373
|
+
notify(ctx, `zero: falló el resumen — ${err instanceof Error ? err.message : String(err)}`, "warning");
|
|
374
374
|
}
|
|
375
375
|
});
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
if (typeof pi.registerCommand === "function") {
|
|
379
379
|
pi.registerCommand("zero-resume", {
|
|
380
|
-
description: "
|
|
380
|
+
description: "Escribe .pi/zero-resume.md con el comando de restauración y el final de la conversación",
|
|
381
381
|
handler: async (_args, ctx) => {
|
|
382
382
|
try {
|
|
383
383
|
const path = writeFromContext(ctx, "manual");
|
|
384
384
|
if (!path) {
|
|
385
|
-
notify(ctx, "zero-resume: no
|
|
385
|
+
notify(ctx, "zero-resume: no hay contexto de sesión persistido", "warning");
|
|
386
386
|
return;
|
|
387
387
|
}
|
|
388
388
|
const command = sessionFile(ctx)
|
|
@@ -390,7 +390,7 @@ export default function register(pi?: PiAPI): void {
|
|
|
390
390
|
: sessionId(ctx)
|
|
391
391
|
? `pi --session ${sessionId(ctx)}`
|
|
392
392
|
: "pi --resume";
|
|
393
|
-
notify(ctx, `zero-resume:
|
|
393
|
+
notify(ctx, `zero-resume: escrito ${path}\nrestaurar: ${command}`, "info");
|
|
394
394
|
} catch (err) {
|
|
395
395
|
notify(ctx, `zero-resume: ${err instanceof Error ? err.message : String(err)}`, "error");
|
|
396
396
|
}
|
|
@@ -121,12 +121,12 @@ function renderSyncReport(slug: string, date: string, summary: MergeSummary): st
|
|
|
121
121
|
/** Render the human-facing one-shot report of a `MergeSummary`. */
|
|
122
122
|
function describeSummary(summary: MergeSummary): string {
|
|
123
123
|
const lines: string[] = [];
|
|
124
|
-
if (summary.added.length > 0) lines.push(`
|
|
124
|
+
if (summary.added.length > 0) lines.push(` agregados: ${summary.added.join(", ")}`);
|
|
125
125
|
if (summary.modified.length > 0) {
|
|
126
|
-
lines.push(`
|
|
126
|
+
lines.push(` modificados: ${summary.modified.join(", ")} (reemplaza el texto de spec existente)`);
|
|
127
127
|
}
|
|
128
128
|
if (summary.removed.length > 0) {
|
|
129
|
-
lines.push(`
|
|
129
|
+
lines.push(` eliminados: ${summary.removed.join(", ")} (borra del store)`);
|
|
130
130
|
}
|
|
131
131
|
return lines.join("\n");
|
|
132
132
|
}
|
|
@@ -168,8 +168,8 @@ function runSync(args: string, ctx: PiCommandContext): void {
|
|
|
168
168
|
const slug = resolveSlug(args);
|
|
169
169
|
if (slug === null) {
|
|
170
170
|
notify(
|
|
171
|
-
"zero-sync: no
|
|
172
|
-
"
|
|
171
|
+
"zero-sync: no se dio slug de run y no hay un único candidato — " +
|
|
172
|
+
"corré /zero-sync <slug> (el slug del directorio .sdd/<slug>/ del run)",
|
|
173
173
|
"warning",
|
|
174
174
|
);
|
|
175
175
|
return;
|
|
@@ -181,7 +181,7 @@ function runSync(args: string, ctx: PiCommandContext): void {
|
|
|
181
181
|
// A legacy run produced no delta `spec.md` — nothing to sync. This is not
|
|
182
182
|
// an error: legacy runs finish in legacy mode (additive design).
|
|
183
183
|
notify(
|
|
184
|
-
`zero-sync: ${deltaPath}
|
|
184
|
+
`zero-sync: ${deltaPath} no existe — este run no produjo un spec.md delta, nada para sincronizar`,
|
|
185
185
|
"warning",
|
|
186
186
|
);
|
|
187
187
|
return;
|
|
@@ -190,7 +190,7 @@ function runSync(args: string, ctx: PiCommandContext): void {
|
|
|
190
190
|
// An empty delta (no blocks in any section) is valid — report and stop
|
|
191
191
|
// before touching the store.
|
|
192
192
|
if (isEmptyDelta(parseDelta(deltaText))) {
|
|
193
|
-
notify(`zero-sync:
|
|
193
|
+
notify(`zero-sync: delta vacío en ${deltaPath} — nada para sincronizar, store sin cambios`, "info");
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -204,7 +204,7 @@ function runSync(args: string, ctx: PiCommandContext): void {
|
|
|
204
204
|
// the store is flagged out of sync for a manual fix.
|
|
205
205
|
const detail = result.errors.map((e) => ` - [${e.kind}] ${e.message}`).join("\n");
|
|
206
206
|
notify(
|
|
207
|
-
`zero-sync: store
|
|
207
|
+
`zero-sync: store NO actualizado — el delta tiene errores de guardrail:\n${detail}`,
|
|
208
208
|
"error",
|
|
209
209
|
);
|
|
210
210
|
return;
|
|
@@ -219,7 +219,7 @@ function runSync(args: string, ctx: PiCommandContext): void {
|
|
|
219
219
|
renameSync(tmp, STORE_FILE);
|
|
220
220
|
} catch (err) {
|
|
221
221
|
notify(
|
|
222
|
-
`zero-sync:
|
|
222
|
+
`zero-sync: no se pudo escribir el store en ${STORE_FILE}: ${
|
|
223
223
|
err instanceof Error ? err.message : String(err)
|
|
224
224
|
}`,
|
|
225
225
|
"error",
|
|
@@ -240,16 +240,16 @@ function runSync(args: string, ctx: PiCommandContext): void {
|
|
|
240
240
|
if (existsSync(src)) copyFileSync(src, join(archiveDir, name));
|
|
241
241
|
}
|
|
242
242
|
writeFileSync(join(archiveDir, "sync.md"), renderSyncReport(slug, date, result.summary), "utf8");
|
|
243
|
-
archiveNote = `
|
|
243
|
+
archiveNote = `archivado en ${archiveDir}`;
|
|
244
244
|
} catch (err) {
|
|
245
|
-
archiveNote = `
|
|
245
|
+
archiveNote = `ATENCIÓN: store actualizado pero falló el archivado: ${
|
|
246
246
|
err instanceof Error ? err.message : String(err)
|
|
247
247
|
}`;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
const detail = describeSummary(result.summary);
|
|
251
251
|
notify(
|
|
252
|
-
`zero-sync:
|
|
252
|
+
`zero-sync: store canónico actualizado (${STORE_FILE})\n${detail}\n${archiveNote}`,
|
|
253
253
|
"info",
|
|
254
254
|
);
|
|
255
255
|
}
|
|
@@ -266,7 +266,7 @@ export default function register(pi?: PiExtensionAPI): void {
|
|
|
266
266
|
|
|
267
267
|
pi.registerCommand("zero-sync", {
|
|
268
268
|
description:
|
|
269
|
-
"
|
|
269
|
+
"Integra el spec.md delta de un run /forge al store canónico .sdd/specs/ — /zero-sync <slug>",
|
|
270
270
|
handler: (args: string, ctx: PiCommandContext): void => {
|
|
271
271
|
try {
|
|
272
272
|
if (!ctx || !ctx.ui || typeof ctx.ui.notify !== "function") return;
|
|
@@ -257,7 +257,7 @@ export default function register(pi?: PiExtensionAPI): void {
|
|
|
257
257
|
|
|
258
258
|
pi.registerCommand("zero-models", {
|
|
259
259
|
description:
|
|
260
|
-
"
|
|
260
|
+
"Muestra o cambia los modelos SDD por fase — /zero-models [<fase>=[<provider>/]<modelo>]",
|
|
261
261
|
handler: async (args: string, ctx: PiCommandContext): Promise<void> => {
|
|
262
262
|
try {
|
|
263
263
|
const data = readZeroJson();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gonrocca/zero-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
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/forge.md
CHANGED
|
@@ -14,10 +14,11 @@ claim success unless veredicto returned `pasa`.
|
|
|
14
14
|
If the request begins with `--continue [slug]`, resume that unfinished run from
|
|
15
15
|
its `.sdd/<slug>/` artifacts instead of starting fresh.
|
|
16
16
|
|
|
17
|
-
**
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
**Output and language.** Follow the orchestrator's `## Language Boundary` and
|
|
18
|
+
`## Output Contract`: user-facing chat in Spanish (natural Rioplatense voseo),
|
|
19
|
+
the bounded per-phase summary, no raw tool output, no agent listings, no
|
|
20
|
+
step-by-step narration — progress and the final verdict, never a log. The four
|
|
20
21
|
`zero-*` sub-agents already exist; delegate to them directly without running a
|
|
21
|
-
`subagent` listing.
|
|
22
|
+
`subagent` listing.
|
|
22
23
|
|
|
23
24
|
Feature request: $ARGUMENTS
|
package/prompts/orchestrator.md
CHANGED
|
@@ -112,30 +112,84 @@ start of a run and delegate each phase's sub-agent to its configured
|
|
|
112
112
|
provider + model. When the file is absent, a phase is missing, or its provider
|
|
113
113
|
entry is empty, fall back to the session's default model.
|
|
114
114
|
|
|
115
|
+
## Language Boundary
|
|
116
|
+
|
|
117
|
+
A zero SDD run has two language surfaces — keep them apart.
|
|
118
|
+
|
|
119
|
+
- **User-facing chat — Spanish.** Every message you print to the user is in
|
|
120
|
+
Spanish, in natural Rioplatense voseo: phase status lines, phase summaries,
|
|
121
|
+
the execution-mode question, the approval question, and the final verdict.
|
|
122
|
+
This holds in interactive and automatic mode alike.
|
|
123
|
+
- **Sub-agent briefs — English.** Write the briefs you hand to the `zero-*`
|
|
124
|
+
sub-agents in English, and expect their result envelopes back in English.
|
|
125
|
+
English keeps token use down and gives the executors one consistent
|
|
126
|
+
operating language. You translate and synthesize into Spanish for the user;
|
|
127
|
+
the sub-agents never address the user directly.
|
|
128
|
+
- **Fixed identifiers — verbatim.** Never translate identifiers. Keep verdict
|
|
129
|
+
values (`pasa`, `corregir`, `replantear`, `cap-reached`), feature slugs,
|
|
130
|
+
file and directory paths, model ids, and command names (`/forge`,
|
|
131
|
+
`/zero-sync`) exactly as they are, even inside Spanish text.
|
|
132
|
+
|
|
133
|
+
## Output Contract
|
|
134
|
+
|
|
135
|
+
What you print to the user is bounded. A zero SDD run reads as a short, calm
|
|
136
|
+
progress stream — not a log.
|
|
137
|
+
|
|
138
|
+
**Phase start.** When a phase begins, emit one short Spanish line with: the
|
|
139
|
+
phase name, the model and provider it runs on — read from `~/.pi/zero.json` as
|
|
140
|
+
`<modelo> (<provider>)`, or the session's default model when the file has no
|
|
141
|
+
entry for that phase — and a brief gloss of what the phase does. Inside the
|
|
142
|
+
build/veredicto loop, also include the round number. One line per phase:
|
|
143
|
+
|
|
144
|
+
- `Fase explore · <modelo> (<provider>) — exploro el código y junto hallazgos`
|
|
145
|
+
- `Fase plan · <modelo> (<provider>) — escribo requisitos, diseño y tareas`
|
|
146
|
+
- `Fase build · ronda <n> · <modelo> (<provider>) — implemento las tareas y corro los tests`
|
|
147
|
+
- `Fase veredicto · ronda <n> · <modelo> (<provider>) — reviso la build y doy el veredicto`
|
|
148
|
+
|
|
149
|
+
**Phase summary.** When a phase finishes, emit a bounded summary — never
|
|
150
|
+
free-form prose:
|
|
151
|
+
|
|
152
|
+
- `Estado:` one line — the phase and its outcome (for veredicto, the verdict).
|
|
153
|
+
- `Resumen:` at most two lines of what the phase produced, user-relevant only.
|
|
154
|
+
- `Artefactos:` the `.sdd/<slug>/` path(s) the phase wrote — the path, never
|
|
155
|
+
the file contents.
|
|
156
|
+
- `Siguiente:` the next phase, or that the run is ending.
|
|
157
|
+
|
|
158
|
+
When summarising the plan phase, also report the run's total changed-lines
|
|
159
|
+
forecast from the `## Review Workload` section of `tasks.md`, naming each
|
|
160
|
+
over-budget exception with its reason — or stating that every task is within
|
|
161
|
+
the per-task budget.
|
|
162
|
+
|
|
163
|
+
**Never noise.** Do not echo raw tool output, file dumps, full sub-agent result
|
|
164
|
+
envelopes, or a sub-agent discovery/listing into the chat, and do not narrate
|
|
165
|
+
your internal reasoning. Reference an artifact by its path; never paste its
|
|
166
|
+
contents. Summarize each sub-agent's result in one short message — synthesize,
|
|
167
|
+
do not relay.
|
|
168
|
+
|
|
169
|
+
**Approval question.** In interactive mode, after the phase summary, ask a
|
|
170
|
+
single Spanish question — `¿Continuamos?` — never a bilingual one. Accept
|
|
171
|
+
continue, stop, or feedback.
|
|
172
|
+
|
|
173
|
+
**Run end.** When the run ends, state the final verdict and say plainly whether
|
|
174
|
+
the result is **verificado** (a `pasa` verdict) or **no verificado** (the
|
|
175
|
+
iteration cap reached without `pasa`). Never claim success without a `pasa`.
|
|
176
|
+
|
|
177
|
+
**Always visible.** Trimming noise must never make the run look frozen: the
|
|
178
|
+
phase name is always stated at phase start, and the round number is always
|
|
179
|
+
stated inside the build/veredicto loop. A phase that runs long keeps showing
|
|
180
|
+
progress through the working indicator — never go silent for a long stretch.
|
|
181
|
+
|
|
115
182
|
## Execution mode
|
|
116
183
|
|
|
117
|
-
At the start of a run, ask the user which mode they want:
|
|
184
|
+
At the start of a run, ask the user — in Spanish — which mode they want:
|
|
118
185
|
|
|
119
|
-
- **interactive** (default): after each phase
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- **automatic**: run all phases back to back without pausing; show the final
|
|
124
|
-
result only.
|
|
186
|
+
- **interactive** (default): pause after each phase. Emit the phase summary
|
|
187
|
+
defined in the Output Contract, then ask `¿Continuamos?` before proceeding.
|
|
188
|
+
- **automatic**: run all phases back to back without pausing; show only the
|
|
189
|
+
final result.
|
|
125
190
|
|
|
126
191
|
Cache the mode for the run.
|
|
127
192
|
|
|
128
|
-
When summarising the plan phase, report the run's total changed-lines forecast
|
|
129
|
-
from the `## Review Workload` section of `tasks.md`, name each over-budget
|
|
130
|
-
exception with its reason, and — when there are no exceptions — state that all
|
|
131
|
-
tasks are within the per-task budget.
|
|
132
|
-
|
|
133
|
-
## Visibility
|
|
134
|
-
|
|
135
|
-
While a phase runs, keep the user informed of progress — never run silently for
|
|
136
|
-
a long stretch. The user must always be able to tell which phase and round the
|
|
137
|
-
run is in.
|
|
138
|
-
|
|
139
193
|
## Run memory
|
|
140
194
|
|
|
141
195
|
zero runs improve each other. The pipeline reads from and writes to Cortex —
|
package/prompts/phases/build.md
CHANGED
|
@@ -19,4 +19,9 @@ change within the plan's scope — do not expand it on your own initiative.
|
|
|
19
19
|
Run the test suite and make it pass before reporting the phase complete. Report
|
|
20
20
|
what you changed so the veredicto phase has something concrete to review.
|
|
21
21
|
|
|
22
|
-
**
|
|
22
|
+
**Return contract.** Return a concise result envelope to the orchestrator: your
|
|
23
|
+
phase's outcome (findings, plan, build result, or verdict with its concrete
|
|
24
|
+
reasoning) and the `.sdd/<slug>/` artifact path(s) you touched. No step-by-step
|
|
25
|
+
narration, no reasoning out loud, no echoed tool output, and no `subagent`
|
|
26
|
+
discovery or listing step. Write the envelope in English — the orchestrator
|
|
27
|
+
translates and synthesizes for the user; you never address the user directly.
|
|
@@ -21,4 +21,9 @@ If the orchestrator includes prior-run memory in your brief, use it: past runs
|
|
|
21
21
|
record what already broke in this code and which plans were sent back. Fold the
|
|
22
22
|
relevant points into the findings under a "Prior runs" heading.
|
|
23
23
|
|
|
24
|
-
**
|
|
24
|
+
**Return contract.** Return a concise result envelope to the orchestrator: your
|
|
25
|
+
phase's outcome (findings, plan, build result, or verdict with its concrete
|
|
26
|
+
reasoning) and the `.sdd/<slug>/` artifact path(s) you touched. No step-by-step
|
|
27
|
+
narration, no reasoning out loud, no echoed tool output, and no `subagent`
|
|
28
|
+
discovery or listing step. Write the envelope in English — the orchestrator
|
|
29
|
+
translates and synthesizes for the user; you never address the user directly.
|
package/prompts/phases/plan.md
CHANGED
|
@@ -81,4 +81,9 @@ means the same number on every run.
|
|
|
81
81
|
per-task estimates, and the over-budget exceptions list — state "none" when
|
|
82
82
|
there are no exceptions.
|
|
83
83
|
|
|
84
|
-
**
|
|
84
|
+
**Return contract.** Return a concise result envelope to the orchestrator: your
|
|
85
|
+
phase's outcome (findings, plan, build result, or verdict with its concrete
|
|
86
|
+
reasoning) and the `.sdd/<slug>/` artifact path(s) you touched. No step-by-step
|
|
87
|
+
narration, no reasoning out loud, no echoed tool output, and no `subagent`
|
|
88
|
+
discovery or listing step. Write the envelope in English — the orchestrator
|
|
89
|
+
translates and synthesizes for the user; you never address the user directly.
|
|
@@ -29,4 +29,9 @@ State the verdict's reasoning concretely — the specific defects for `corregir`
|
|
|
29
29
|
the specific plan flaw for `replantear`. The orchestrator persists that
|
|
30
30
|
reasoning to the run's memory trace, so future runs depend on it being precise.
|
|
31
31
|
|
|
32
|
-
**
|
|
32
|
+
**Return contract.** Return a concise result envelope to the orchestrator: your
|
|
33
|
+
phase's outcome (findings, plan, build result, or verdict with its concrete
|
|
34
|
+
reasoning) and the `.sdd/<slug>/` artifact path(s) you touched. No step-by-step
|
|
35
|
+
narration, no reasoning out loud, no echoed tool output, and no `subagent`
|
|
36
|
+
discovery or listing step. Write the envelope in English — the orchestrator
|
|
37
|
+
translates and synthesizes for the user; you never address the user directly.
|
|
@@ -35,7 +35,8 @@ the feature request. Pass that described work **verbatim** — do not rephrase,
|
|
|
35
35
|
summarize, translate, or interpret it. The existing `/forge` workflow does the
|
|
36
36
|
rest: an ordinary SDD run with all four phases (explore, plan, build,
|
|
37
37
|
veredicto), the round cap, and the veredicto verdict, exactly as an explicit
|
|
38
|
-
`/forge` invocation behaves
|
|
38
|
+
`/forge` invocation behaves — including its Spanish, low-noise output, governed
|
|
39
|
+
by the orchestrator's `## Language Boundary` and `## Output Contract`.
|
|
39
40
|
|
|
40
41
|
## When NOT to route — be conservative
|
|
41
42
|
|