@mjasnikovs/pi-task 0.17.19 → 0.17.20
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.
|
@@ -411,29 +411,55 @@ export async function planAuto(ctx, cwd, feature, deps) {
|
|
|
411
411
|
// natural EOS for an 18KB design doc) is nonempty, so the length guard below
|
|
412
412
|
// never fires and the whole run "completes" after one task. Judge the list
|
|
413
413
|
// against the feature with a no-tools child; on INCOMPLETE, re-run decompose
|
|
414
|
-
// with the missing areas as a hint.
|
|
415
|
-
// never replace a better list; best-effort so a triage fault never blocks
|
|
414
|
+
// with the missing areas as a hint. Best-effort so a triage fault never blocks
|
|
416
415
|
// planning (mirrors triageClarifyQuestion).
|
|
416
|
+
//
|
|
417
|
+
// A retry is adopted whenever it is NON-DEGENERATE — not only when it is
|
|
418
|
+
// strictly longer. The retry was generated WITH the judge's missing areas in
|
|
419
|
+
// its prompt, so it is the better-informed list, and the NEXT round's judge
|
|
420
|
+
// (not raw length) decides whether the gaps actually closed. Length survives
|
|
421
|
+
// only as a collapse floor against the one-task flake this gate exists for.
|
|
422
|
+
// mx5 run 5 (live): the hinted retry ADDED the flagged test-suite task but came
|
|
423
|
+
// back 29 titles vs the original 30 — strictly-longer discarded it, round 2
|
|
424
|
+
// re-judged the same unchanged list, and the known-incomplete plan shipped
|
|
425
|
+
// with no warning.
|
|
426
|
+
let unresolvedMissing = null;
|
|
417
427
|
for (let round = 0; round < MAX_COVERAGE_ROUNDS && planTitles.length > 0; round++) {
|
|
418
428
|
let verdict;
|
|
419
429
|
try {
|
|
420
430
|
verdict = parseCoverageVerdict(await deps.runChild('decompose-coverage', '', DECOMPOSE_COVERAGE_PROMPT(featureForModel, clarifications, planTitles)));
|
|
421
431
|
}
|
|
422
432
|
catch {
|
|
433
|
+
// Judge fault: unknown coverage, not known-missing — stay silent.
|
|
434
|
+
unresolvedMissing = null;
|
|
423
435
|
break;
|
|
424
436
|
}
|
|
425
437
|
if (verdict === null || verdict.kind === 'complete') {
|
|
438
|
+
unresolvedMissing = null;
|
|
426
439
|
logPlanDebug(cwd, `decompose-coverage round ${round + 1}: `
|
|
427
440
|
+ (verdict === null ? 'no verdict — accepting list' : 'COMPLETE'));
|
|
428
441
|
break;
|
|
429
442
|
}
|
|
443
|
+
unresolvedMissing = verdict.missing;
|
|
430
444
|
logPlanDebug(cwd, `decompose-coverage round ${round + 1}: INCOMPLETE — missing: `
|
|
431
445
|
+ verdict.missing.join('; ').slice(0, 300));
|
|
432
446
|
const retryRaw = await deps.runChild('auto-decompose', 'read', prependHint(coverageRepromptHint(verdict.missing), decomposePrompt));
|
|
433
447
|
const retryTitles = parseDecomposeList(retryRaw);
|
|
434
448
|
logPlanDebug(cwd, `decompose retry produced ${retryTitles.length} title(s)`);
|
|
435
|
-
if (retryTitles.length > planTitles.length)
|
|
449
|
+
if (retryTitles.length > 0 && retryTitles.length * 2 >= planTitles.length) {
|
|
436
450
|
planTitles = retryTitles;
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
logPlanDebug(cwd, `decompose retry discarded as degenerate (${retryTitles.length} vs ${planTitles.length} titles)`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Rounds exhausted with the last judgment still INCOMPLETE: the plan ships (the
|
|
457
|
+
// gate is best-effort), but silently shipping a KNOWN-gapped plan is how mx5
|
|
458
|
+
// run 5 lost its whole test suite — tell the user what the judge last flagged.
|
|
459
|
+
if (unresolvedMissing !== null) {
|
|
460
|
+
logPlanDebug(cwd, `decompose-coverage exhausted ${MAX_COVERAGE_ROUNDS} round(s) still INCOMPLETE — missing: `
|
|
461
|
+
+ unresolvedMissing.join('; ').slice(0, 300));
|
|
462
|
+
ctx.ui.notify(`/task-auto: plan may be missing coverage — ${unresolvedMissing.join('; ').slice(0, 200)} — review the plan before running.`, 'warning');
|
|
437
463
|
}
|
|
438
464
|
// Thread the feature's spec doc(s) into every title so each per-task
|
|
439
465
|
// pipeline — which only ever sees its title — reads the real spec instead of
|
package/dist/task/task-gates.js
CHANGED
|
@@ -212,7 +212,20 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
212
212
|
active.ui.notify(`${p.tag}: guideline edits on "${p.title}" failed repo health (${h.reason.slice(0, 120)}) — discarded before commit.`, 'warning');
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
|
-
if (mode === 'edit' && !enforceEditsBlocked) {
|
|
215
|
+
if (mode === 'edit' && !enforceEditsBlocked && editsMade === false) {
|
|
216
|
+
// KNOWN-clean tree (dirty dep ran and found no code edits): skip the
|
|
217
|
+
// enforce commit AND the differential re-verify outright. Without this
|
|
218
|
+
// gate the commit is never empty — the .pi-tasks gate-trail lines written
|
|
219
|
+
// above make it real — so mx5 run 5 burned a full model re-verify on an
|
|
220
|
+
// UNCHANGED tree for all ~29 tasks, and the 10 FAILs those re-verifies
|
|
221
|
+
// produced (all real, pre-existing defects) were "reverted" into the
|
|
222
|
+
// void: the revert dropped a bookkeeping-only commit and the defect
|
|
223
|
+
// reports were discarded while the tasks stayed PASS. No edits ⇒ nothing
|
|
224
|
+
// to guard ⇒ no commit, no re-verify, no revert. The trail lines ride
|
|
225
|
+
// along in the next ordinary commit.
|
|
226
|
+
await rec('enforce(edit): no code edits — enforce commit and re-verify skipped');
|
|
227
|
+
}
|
|
228
|
+
else if (mode === 'edit' && !enforceEditsBlocked) {
|
|
216
229
|
// Commit whatever the pass fixed as its own snapshot. A no-op when it made
|
|
217
230
|
// no edits (nothing to commit) — then there is nothing to re-verify/revert.
|
|
218
231
|
const enforceCommit = await deps.commit(p.cwd, `ENFORCE GUIDELINES: ${p.title} (${p.taskId})`);
|
package/dist/task/verify-work.js
CHANGED
|
@@ -144,8 +144,8 @@ export function buildVerifyPrompt(spec, probeFindings) {
|
|
|
144
144
|
'prove it by running the verification this task ships with.',
|
|
145
145
|
'',
|
|
146
146
|
'You have a `read` tool and a `bash` tool — nothing else. You can run any',
|
|
147
|
-
'command and read any file
|
|
148
|
-
'
|
|
147
|
+
'command and read any file. Your job is to VERIFY, not to fix: never modify',
|
|
148
|
+
'the project tree (rule 3d governs the scratch files a probe may need).',
|
|
149
149
|
'',
|
|
150
150
|
'THE TASK SPEC (its ACCEPTANCE criteria and VERIFY block are the contract):',
|
|
151
151
|
spec.trim(),
|
|
@@ -201,6 +201,17 @@ export function buildVerifyPrompt(spec, probeFindings) {
|
|
|
201
201
|
' If the tests patched a gap, report FAIL and name the missing production-side',
|
|
202
202
|
' change (e.g. the column no migration creates).',
|
|
203
203
|
'',
|
|
204
|
+
'3d. SELF-SUBSTITUTION: rules 3b/3c bind YOU as well. A small throwaway probe',
|
|
205
|
+
' script is fine, but it must (a) live in the system temp directory (/tmp),',
|
|
206
|
+
' NEVER inside the repository worktree, and (b) exercise the REAL shipped',
|
|
207
|
+
' artifact — import/require the real module, run the real entrypoint, hit the',
|
|
208
|
+
" real server. You must NEVER re-implement, copy, or paraphrase the artifact's",
|
|
209
|
+
' logic into a scratch file and test that copy: a green result on your own',
|
|
210
|
+
' copy proves only the copy, exactly like rule 3b. If the real artifact cannot',
|
|
211
|
+
' be exercised as shipped — its imports fail, the module will not load, the',
|
|
212
|
+
' server never starts, no entrypoint exists — that inability IS the defect:',
|
|
213
|
+
' report FAIL naming it. Do not stand up a substitute to get to green.',
|
|
214
|
+
'',
|
|
204
215
|
'4. Treat the ACCEPTANCE criteria as the bar. If a command fails, or its real output',
|
|
205
216
|
' contradicts an ACCEPTANCE criterion, the work has NOT verified.',
|
|
206
217
|
'',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.20",
|
|
4
4
|
"description": "Deterministic task planning and spec-orchestration for local models — crash-safe /task pipelines with verify/enforce gates, a real-time remote web view, and web/docs/fetch/worker subagent tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|