@phi-code-admin/phi-code 0.91.0 → 0.92.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.92.1] - 2026-07-12
|
|
4
|
+
|
|
5
|
+
### Docs
|
|
6
|
+
|
|
7
|
+
- README: document the execution-grounded modes (/plan, /debug, /build, /sandbox,
|
|
8
|
+
the sandbox_run oracle, per-phase model routing, the honest n=13 measurement)
|
|
9
|
+
and the one-command Alibaba Cloud Coding Plan setup — three releases of
|
|
10
|
+
features were undocumented.
|
|
11
|
+
|
|
12
|
+
## [0.92.0] - 2026-07-11
|
|
13
|
+
|
|
14
|
+
### Fixed — the two defects the n=13 SWE-bench measurement exposed
|
|
15
|
+
|
|
16
|
+
The measured head-to-head (baseline 7/13 vs /debug 6/13, official harness) traced
|
|
17
|
+
/debug's two lost points to concrete, reparable defects — both fixed here.
|
|
18
|
+
|
|
19
|
+
- **Hasty BLOCKED (sympy-11897, halted at 51s).** The generic /debug//build
|
|
20
|
+
driver now routes phase completion through the same pure decision machine as
|
|
21
|
+
/plan (`decidePhaseTransition`), gaining what it measurably lacked: a fatal
|
|
22
|
+
401 stops the run, a transient provider error (timeout / 5xx / 429 / broken
|
|
23
|
+
stream) retries the SAME phase once on the fallback model instead of being
|
|
24
|
+
swallowed, and — new — a BLOCKED verdict gets ONE second chance on the
|
|
25
|
+
fallback model (a different family re-checks the reproduction) before the
|
|
26
|
+
halt. A confirmed second BLOCKED still halts honestly: no fabricated fix.
|
|
27
|
+
REPRODUCE's instructions now state BLOCKED is a last resort — adjust and
|
|
28
|
+
retry once before concluding.
|
|
29
|
+
- **Timeout-blind VERIFY (sympy-11870, fix passed its repro but hung the real
|
|
30
|
+
suite for 900s).** VERIFY's instructions now treat a TIMEOUT of the
|
|
31
|
+
reproduction or the suite as a FAILURE of the candidate — a massive slowdown
|
|
32
|
+
or infinite loop IS a regression — with verdict BLOCKED, never FIXED. A
|
|
33
|
+
dramatic duration increase below the timeout is flagged as a red flag too.
|
|
34
|
+
|
|
35
|
+
8 integration tests cover the new behaviours (BLOCKED retry → honest halt,
|
|
36
|
+
BLOCKED retry → proceed on success, transient-error retry); full suite green
|
|
37
|
+
(1439).
|
|
38
|
+
|
|
3
39
|
## [0.91.0] - 2026-07-11
|
|
4
40
|
|
|
5
41
|
### Added — Alibaba Cloud Coding Plan, first-class and one-command
|
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ phi-code runs in four modes: interactive, print or JSON, RPC for process integra
|
|
|
16
16
|
|
|
17
17
|
- [Quick Start](#quick-start)
|
|
18
18
|
- [Providers & Models](#providers--models)
|
|
19
|
+
- [Execution-Grounded Modes (/plan, /debug, /build, /sandbox)](#execution-grounded-modes)
|
|
19
20
|
- [Interactive Mode](#interactive-mode)
|
|
20
21
|
- [Editor](#editor)
|
|
21
22
|
- [Commands](#commands)
|
|
@@ -103,13 +104,59 @@ For each built-in provider, phi maintains a list of tool-capable models, updated
|
|
|
103
104
|
- Xiaomi MiMo Token Plan (China)
|
|
104
105
|
- Xiaomi MiMo Token Plan (Amsterdam)
|
|
105
106
|
- Xiaomi MiMo Token Plan (Singapore)
|
|
107
|
+
- Alibaba Cloud Coding Plan (`qwen3.7-plus`, GLM, Kimi, MiniMax — subscription quota)
|
|
106
108
|
|
|
107
109
|
See [docs/providers.md](docs/providers.md) for detailed setup instructions.
|
|
108
110
|
|
|
111
|
+
**One-command setup for known providers:** `/keys set alibaba-codingplan sk-sp-…` (or `opencode-go <key>`) bootstraps the full provider entry — endpoint, protocol, model list — from just the API key, then validates it with `/keys test <id>`. The live catalog refreshes on session start.
|
|
112
|
+
|
|
109
113
|
**Custom providers & models:** Add providers via `~/.phi/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).
|
|
110
114
|
|
|
111
115
|
---
|
|
112
116
|
|
|
117
|
+
## Execution-Grounded Modes
|
|
118
|
+
|
|
119
|
+
Phi's multi-phase modes share one principle, learned the hard way on SWE-bench:
|
|
120
|
+
**execution is the only oracle**. A verdict must come from running real code —
|
|
121
|
+
never from a model reviewing its own output (which we measured approving wrong
|
|
122
|
+
code, even across model families). Full design:
|
|
123
|
+
[docs/design/plan-debug-build.md](docs/design/plan-debug-build.md).
|
|
124
|
+
|
|
125
|
+
| Command | Job | Pipeline |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `/plan <spec>` | Plan AND build a project | EXPLORE → PLAN → CODE → TEST → REVIEW |
|
|
128
|
+
| `/debug <failing test \| repro \| description>` | Turn a REAL failure green | REPRODUCE → LOCALIZE → FIX → VERIFY |
|
|
129
|
+
| `/build <spec>` | Build until it runs | EXPLORE → PLAN → CODE → BUILD-VERIFY (run recipe + acceptance + executable red-team) |
|
|
130
|
+
| `/sandbox [status\|prepare\|run <cmd>]` | Inspect the guaranteed environment | — |
|
|
131
|
+
|
|
132
|
+
**The execution sandbox.** Every oracle run goes through the `sandbox_run` tool:
|
|
133
|
+
a per-project Docker container (toolchain auto-detected — node/python/go/rust/ruby
|
|
134
|
+
or your `Dockerfile`; override anything in `.phi/sandbox.json`) that returns the
|
|
135
|
+
REAL exit code. No Docker and nothing to containerize → runs fall back to the
|
|
136
|
+
host; if an environment is demanded but unavailable, phases report `BLOCKED`
|
|
137
|
+
rather than fabricate a pass.
|
|
138
|
+
|
|
139
|
+
**Honesty guarantees** (each one exists because we measured its absence losing):
|
|
140
|
+
- `/debug` refuses to "fix" a failure it cannot reproduce — and a BLOCKED verdict
|
|
141
|
+
gets one second chance on a different model family before the halt.
|
|
142
|
+
- VERIFY requires the reproduction to pass AND the suite not to regress; a
|
|
143
|
+
TIMEOUT counts as a regression (a fix that hangs the suite is worse than none).
|
|
144
|
+
- `/build` reports `SUCCESS` only when a real run meets the acceptance criteria,
|
|
145
|
+
otherwise an honest `PARTIAL` listing what still fails.
|
|
146
|
+
|
|
147
|
+
**Per-phase model routing.** Each phase can run on its own model via
|
|
148
|
+
`~/.phi/agent/routing.json` (e.g. code on `alibaba-codingplan/qwen3.7-plus`,
|
|
149
|
+
verification on a different family so it does not share the coder's blind spot),
|
|
150
|
+
with automatic fallback on transient provider errors.
|
|
151
|
+
|
|
152
|
+
**Measured, honestly:** on a 13-instance SWE-bench-lite slice (official harness),
|
|
153
|
+
a strong single-shot baseline resolved 7/13 vs `/debug` 6/13 at ~2.5× the time —
|
|
154
|
+
with `/debug` producing smaller patches and zero toxic ones. These modes are
|
|
155
|
+
shipped as *tools with honest failure modes*, not as a claimed benchmark win;
|
|
156
|
+
the measurement lives in the repo and is re-runnable.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
113
160
|
## Interactive Mode
|
|
114
161
|
|
|
115
162
|
<p align="center"><img src="docs/images/interactive-mode.png" alt="Interactive Mode" width="600"></p>
|
|
@@ -284,6 +284,11 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
|
|
|
284
284
|
// Set true once this phase has been retried once (transient proxy failure /
|
|
285
285
|
// timeout / 0-tool-call). Hard cap of one retry per phase.
|
|
286
286
|
retried?: boolean;
|
|
287
|
+
// Generic driver (/debug, /build) only: set true once this phase was re-run
|
|
288
|
+
// after a BLOCKED verdict. One second chance on the fallback model — a hasty
|
|
289
|
+
// BLOCKED (measured: 51s on sympy-11897) is cheaper to re-check than to
|
|
290
|
+
// trust — then the halt is honest.
|
|
291
|
+
blockedRetried?: boolean;
|
|
287
292
|
// When true, switchModelForPhase resolves the fallback model first (used on retry
|
|
288
293
|
// to swap to a different model family rather than re-hit the one that just failed).
|
|
289
294
|
useFallback?: boolean;
|
|
@@ -1323,13 +1328,63 @@ Tag the note with relevant keywords for vector search.
|
|
|
1323
1328
|
phaseTimeoutId = null;
|
|
1324
1329
|
}
|
|
1325
1330
|
|
|
1326
|
-
//
|
|
1327
|
-
//
|
|
1331
|
+
// Route through the SAME pure decision machine as /plan so the generic
|
|
1332
|
+
// driver gets the protections it was measured to lack (sympy-11897, a 51s
|
|
1333
|
+
// hasty halt): fatal 401 stop, one retry on a transient provider error.
|
|
1328
1334
|
const structuredForThisPhase = currentPhaseResultKey === (currentPhase?.key ?? null) ? currentPhaseResult : null;
|
|
1329
1335
|
const outcome = resolvePhaseOutcome(structuredForThisPhase, null);
|
|
1330
|
-
|
|
1336
|
+
const decision = decidePhaseTransition({
|
|
1337
|
+
analysis,
|
|
1338
|
+
phase: currentPhase ? { key: currentPhase.key, retried: currentPhase.retried } : null,
|
|
1339
|
+
verdict: outcome.verdict,
|
|
1340
|
+
// The generic driver has no review-fix cycle; pass the cap as spent.
|
|
1341
|
+
reviewFixRounds: 1,
|
|
1342
|
+
maxToolCallsPerPhase: MAX_TOOL_CALLS_PER_PHASE,
|
|
1343
|
+
});
|
|
1344
|
+
|
|
1345
|
+
if (decision.action === "stop") {
|
|
1346
|
+
ctx.ui.notify(
|
|
1347
|
+
`\n❌ **/${orchestrationMode} aborted:** API authentication error (401). Check your API key.`,
|
|
1348
|
+
"error",
|
|
1349
|
+
);
|
|
1350
|
+
finishGenericOrchestration(ctx, `❌ **/${orchestrationMode} aborted (auth error).**`);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
if (decision.action === "retry-fallback" && currentPhase) {
|
|
1355
|
+
// Transient provider failure (timeout / 5xx / 429 / broken stream): retry
|
|
1356
|
+
// the SAME phase once on the fallback model before treating any of its
|
|
1357
|
+
// output as a real outcome.
|
|
1358
|
+
currentPhase.retried = true;
|
|
1359
|
+
currentPhase.useFallback = true;
|
|
1360
|
+
phaseQueue.unshift(currentPhase);
|
|
1361
|
+
phasePending = false;
|
|
1362
|
+
ctx.ui.notify(
|
|
1363
|
+
`\n🔁 **Transient provider error** in ${currentPhase.label} — retrying once on the fallback model.`,
|
|
1364
|
+
"warning",
|
|
1365
|
+
);
|
|
1366
|
+
sendNextGenericPhase(ctx);
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// BLOCKED (REPRODUCE cannot reproduce / VERIFY could not confirm): give the
|
|
1371
|
+
// phase ONE second chance on the fallback model — a hasty BLOCKED is cheaper
|
|
1372
|
+
// to re-check than to trust — then halt honestly. No fabricated success.
|
|
1373
|
+
if (decision.action === "pause-blocked" && currentPhase) {
|
|
1374
|
+
if (!currentPhase.blockedRetried) {
|
|
1375
|
+
currentPhase.blockedRetried = true;
|
|
1376
|
+
currentPhase.useFallback = true;
|
|
1377
|
+
phaseQueue.unshift(currentPhase);
|
|
1378
|
+
phasePending = false;
|
|
1379
|
+
ctx.ui.notify(
|
|
1380
|
+
`\n🔁 **${currentPhase.label} reported BLOCKED on the first attempt** — retrying once on the fallback model before halting. ${outcome.handoff || ""}`,
|
|
1381
|
+
"warning",
|
|
1382
|
+
);
|
|
1383
|
+
sendNextGenericPhase(ctx);
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1331
1386
|
ctx.ui.notify(
|
|
1332
|
-
`\n⏸️ **${currentPhase.label} reported BLOCKED.** ${outcome.handoff || "No reproducible/verifiable result."}`,
|
|
1387
|
+
`\n⏸️ **${currentPhase.label} reported BLOCKED (confirmed on retry).** ${outcome.handoff || "No reproducible/verifiable result."}`,
|
|
1333
1388
|
"warning",
|
|
1334
1389
|
);
|
|
1335
1390
|
finishGenericOrchestration(ctx, `⏸️ **/${orchestrationMode} stopped: BLOCKED at ${currentPhase.label}.**`);
|
|
@@ -59,7 +59,8 @@ ${failing}
|
|
|
59
59
|
- If it PASSES → STOP. Write \`BLOCKED: cannot reproduce — passes on current code\` with the run pasted. Do not invent a bug.
|
|
60
60
|
- If \`sandbox_run\` reports \`SANDBOX UNAVAILABLE\` → STOP. Write \`BLOCKED: no executable environment\`.
|
|
61
61
|
4. Do NOT edit any source yet. This phase only observes.
|
|
62
|
-
5. **
|
|
62
|
+
5. **BLOCKED is a last resort, not a first reaction.** If a run fails for an infrastructure-looking reason (tool error, missing file you guessed wrong, transient failure), adjust and retry at least once — e.g. locate the real test paths, try an alternative reproduction — before concluding. Only report BLOCKED after a genuine attempt showed the state is not reproducible or not runnable.
|
|
63
|
+
6. **Last action:** call \`phase_result\` — \`verdict: PASS\` if it reproduced (proceed to LOCALIZE), or \`verdict: BLOCKED\` with the reason if you stopped.` +
|
|
63
64
|
DEBUG_RULES,
|
|
64
65
|
|
|
65
66
|
localize: `You are the LOCALIZE agent (phase 2 of /debug). Drive from the REAL symptom the previous phase captured.
|
|
@@ -96,6 +97,7 @@ ${failing}
|
|
|
96
97
|
3. Verdict (from what \`sandbox_run\` returned, not from inspection):
|
|
97
98
|
- Both green → \`FIXED\`, and paste the before(fail)/after(pass) reproduction runs and the green suite as evidence.
|
|
98
99
|
- Reproduction still fails, or the suite regresses → \`BLOCKED\` with the closest diagnostic. Do NOT ship the least-bad patch; a wrong fix is worse than an honest BLOCKED.
|
|
100
|
+
- **A TIMEOUT counts as a FAILURE.** If the reproduction or the suite TIMES OUT with the fix applied (\`sandbox_run\` verdict TIMEOUT), the fix has introduced a massive slowdown or an infinite loop — that IS a regression (measured: a fix that passed its repro but made the real test suite hang for 900s). Verdict \`BLOCKED\`, never \`FIXED\`. Compare rough durations before/after: a check that got dramatically slower is a red flag even below the timeout.
|
|
99
101
|
4. Write the final verdict block, then call \`phase_result\` with \`verdict: PASS\` (FIXED) or \`verdict: BLOCKED\`, plus a one-line handoff:
|
|
100
102
|
\`\`\`
|
|
101
103
|
VERDICT: FIXED | BLOCKED
|