@mjasnikovs/pi-task 0.37.6 → 0.38.0
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 +6 -3
- package/dist/shared/child-output.d.ts +19 -3
- package/dist/shared/child-output.js +21 -5
- package/dist/shared/git-runner.d.ts +39 -0
- package/dist/shared/git-runner.js +38 -0
- package/dist/task/accept-debt.d.ts +27 -58
- package/dist/task/accept-debt.js +60 -130
- package/dist/task/auto-orchestrator.d.ts +7 -57
- package/dist/task/auto-orchestrator.js +25 -499
- package/dist/task/child-runner.d.ts +2 -0
- package/dist/task/child-runner.js +74 -70
- package/dist/task/enforce-guidelines.d.ts +1 -1
- package/dist/task/enforce-guidelines.js +2 -2
- package/dist/task/external-context.d.ts +85 -7
- package/dist/task/external-context.js +100 -63
- package/dist/task/file-inventory.js +22 -41
- package/dist/task/final-gate.d.ts +80 -0
- package/dist/task/final-gate.js +102 -49
- package/dist/task/gate-deps.js +6 -23
- package/dist/task/git-state-guard.d.ts +1 -1
- package/dist/task/git-state-guard.js +1 -7
- package/dist/task/phases.js +40 -83
- package/dist/task/run-final-gate.d.ts +127 -0
- package/dist/task/run-final-gate.js +492 -0
- package/dist/task/task-gates.d.ts +20 -57
- package/dist/task/task-gates.js +11 -11
- package/dist/task/verify-work.d.ts +40 -32
- package/dist/task/verify-work.js +301 -241
- package/dist/workers/docs-core.d.ts +14 -0
- package/dist/workers/docs-core.js +28 -16
- package/dist/workers/fetch-core.d.ts +6 -1
- package/dist/workers/fetch-core.js +26 -33
- package/dist/workers/focused-extractor.d.ts +73 -0
- package/dist/workers/focused-extractor.js +72 -0
- package/dist/workers/pi-worker-docs.d.ts +1 -1
- package/dist/workers/pi-worker-docs.js +48 -42
- package/dist/workers/pi-worker-fetch.js +6 -8
- package/dist/workers/typeonly-log.d.ts +13 -0
- package/package.json +1 -1
package/dist/task/task-gates.js
CHANGED
|
@@ -3,6 +3,11 @@ import { SessionUI } from '../remote/bridge.js';
|
|
|
3
3
|
import { isYoloMode, yoloVerifyResolution, YOLO_STAMP } from './yolo.js';
|
|
4
4
|
import { extractFailingCommand, findRepairCandidate, summariseDefect } from './root-cause-repair.js';
|
|
5
5
|
import { attributeEnforceFailure } from './enforce-attribution.js';
|
|
6
|
+
// The debt ledger is reached through the injected `recordDebt` dep (so it stays
|
|
7
|
+
// absent-in-tests); only the origin TYPE and the cross-task-deletion reason SHAPE
|
|
8
|
+
// come from accept-debt.ts directly — the latter because its writer and its
|
|
9
|
+
// re-check-side parser (extractDeletedDebtPath) have to move together.
|
|
10
|
+
import { crossTaskDeletionReason } from './accept-debt.js';
|
|
6
11
|
/**
|
|
7
12
|
* How many times a verify FAIL may be auto-fixed UNATTENDED (the research
|
|
8
13
|
* recommended AUTOFIX, so pi re-runs the impl turn without prompting) before the
|
|
@@ -115,7 +120,7 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
115
120
|
});
|
|
116
121
|
if (!candidate)
|
|
117
122
|
return null;
|
|
118
|
-
await deps.
|
|
123
|
+
await deps.recordDebt?.(p.cwd, p.taskId, `${failReason} — ROOT CAUSE: \`${candidate.file}\` (introduced by ${candidate.owner}, not touched by this task)`, 'root-cause');
|
|
119
124
|
await deps.recordRepairCandidate?.(p.cwd, candidate);
|
|
120
125
|
await rec(`root-cause: FAIL attributed to \`${candidate.file}\` — a pre-existing defect in ${candidate.owner}'s file that this task never touched; `
|
|
121
126
|
+ 'recorded as durable debt and a scoped repair task queued');
|
|
@@ -223,7 +228,7 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
223
228
|
// final gate must surface it at run end (static-class: it auto-closes
|
|
224
229
|
// iff the run-end static check passes).
|
|
225
230
|
try {
|
|
226
|
-
await deps.
|
|
231
|
+
await deps.recordDebt?.(p.cwd, p.taskId, `${failReason} — ${frozenContradiction}`, 'frozen-blocked');
|
|
227
232
|
}
|
|
228
233
|
catch {
|
|
229
234
|
// recording must never break the gate sequence
|
|
@@ -310,12 +315,7 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
310
315
|
// Provenance splits here, mandatorily: an auto-pick writes the
|
|
311
316
|
// 'yolo-accepted' origin, never the plain 'accepted' one that
|
|
312
317
|
// asserts a human weighed the failing artifact.
|
|
313
|
-
|
|
314
|
-
await deps.recordYoloAcceptDebt?.(p.cwd, p.taskId, failReason);
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
await deps.recordAcceptDebt?.(p.cwd, p.taskId, failReason);
|
|
318
|
-
}
|
|
318
|
+
await deps.recordDebt?.(p.cwd, p.taskId, failReason, byYolo ? 'yolo-accepted' : 'accepted');
|
|
319
319
|
}
|
|
320
320
|
catch {
|
|
321
321
|
// recording must never break the gate sequence
|
|
@@ -331,7 +331,7 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
331
331
|
// the final gate re-checks them (mx5 run 12 PROMPT 2). Best-effort.
|
|
332
332
|
for (const del of verified.crossTaskDeletions ?? []) {
|
|
333
333
|
try {
|
|
334
|
-
await deps.
|
|
334
|
+
await deps.recordDebt?.(p.cwd, p.taskId, crossTaskDeletionReason(del), 'cross-task-deletion');
|
|
335
335
|
await rec(`accept-debt: cross-task deletion recorded — ${del.path} (${del.owner}'s deliverable)`);
|
|
336
336
|
}
|
|
337
337
|
catch {
|
|
@@ -581,7 +581,7 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
581
581
|
// Keeping the edits must NOT lose the finding — that was mx5 run
|
|
582
582
|
// 5's mistake. Same durability as the revert path; only the
|
|
583
583
|
// disposition of the edits differs.
|
|
584
|
-
await deps.
|
|
584
|
+
await deps.recordDebt?.(p.cwd, p.taskId, afterReason, 'enforce-kept');
|
|
585
585
|
// …and, when the named file is somebody else's committed work,
|
|
586
586
|
// queue the scoped repair so something actually FIXES it.
|
|
587
587
|
if (attribution.file && deps.introducedBy && deps.recordRepairCandidate) {
|
|
@@ -622,7 +622,7 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
622
622
|
// erasing it with the enforce edits buried the terminal fault 8.5h
|
|
623
623
|
// before run end. The final gate re-checks/surfaces it (static-class
|
|
624
624
|
// auto-closes if a later task fixed the statics; else stays open).
|
|
625
|
-
await deps.
|
|
625
|
+
await deps.recordDebt?.(p.cwd, p.taskId, after.reason ?? 'enforce re-verify failed', 'enforce-revert');
|
|
626
626
|
active.ui.notify(`${p.tag}: guideline fixes regressed verification on "${p.title}" (${(after.reason ?? 'now fails').slice(0, 120)}) — ${deps.revert ? 'reverted them, kept the verified work' : 'left in place (no revert available)'}.`, 'warning');
|
|
627
627
|
}
|
|
628
628
|
else {
|
|
@@ -44,43 +44,51 @@ export interface VerifyOutcome {
|
|
|
44
44
|
*/
|
|
45
45
|
export declare function extractSpecForVerification(taskBody: string): string | null;
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* ─────────────────────────── THE PROBE TABLE ───────────────────────────
|
|
48
|
+
*
|
|
49
|
+
* Every deterministic probe that sharpens this prompt used to cost the same
|
|
50
|
+
* ritual in four places: a `let x = []` + try/catch in runWorkVerification, a
|
|
51
|
+
* positional parameter on buildVerifyPrompt, a `const xBlock =` ternary, and a
|
|
52
|
+
* spread into the assembled prompt — plus its hand-numbered rule. Adding one
|
|
53
|
+
* meant editing all of them and hoping none was missed; the ninth would not
|
|
54
|
+
* even fit the signature (hence the `projectSurface` bag that used to group
|
|
55
|
+
* three of them).
|
|
50
56
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* language- and framework-agnostic.
|
|
57
|
+
* Each probe is now an ADAPTER: one row carrying only what is specific to it —
|
|
58
|
+
* the dep field it reads, the empty value it degrades to, how its raw result
|
|
59
|
+
* becomes finding lines, the notice block those lines produce, and the numbered
|
|
60
|
+
* rule the notice routes the child to. The loop owns the ritual. (Same shape as
|
|
61
|
+
* LOCKFILE_CHECKS in final-gate.ts, where a whole package ecosystem is one row.)
|
|
57
62
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* (
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* Guard: honest-clean fixture (prohibition in spec, probe silent) 5/5 PASS — no
|
|
69
|
-
* paranoia. Reverted-violation ≡ clean at the diff level (no entry → no finding).
|
|
63
|
+
* THIS PROMPT IS A MEASURED ARTIFACT — its wording is A/B-tested on the live
|
|
64
|
+
* local model and the verdicts are recorded in VALIDATION-DEBT.md, so the table
|
|
65
|
+
* must emit BYTE-IDENTICAL text for the same findings. Two orders are
|
|
66
|
+
* load-bearing and they are NOT the same order:
|
|
67
|
+
* - NOTICE BLOCKS are emitted in TABLE order (the order the rows appear below).
|
|
68
|
+
* - RULES are emitted sorted by `ruleId`, because the 4b…4g band was
|
|
69
|
+
* hand-numbered long before this table existed and its numbering is what the
|
|
70
|
+
* notices cite ("rule 4b applies").
|
|
71
|
+
* A row whose rule is woven into the numbered narrative elsewhere (3b inside the
|
|
72
|
+
* substitution rules, 3f, 5c) carries `ruleId` for the reader and no `rule` text.
|
|
70
73
|
*/
|
|
71
|
-
|
|
74
|
+
/** Stable identity of one probe channel: table row ↔ findings-bag key. */
|
|
75
|
+
export type ProbeKey = 'substitution' | 'prohibition' | 'crossTaskDeletion' | 'probeGaming' | 'skipEscape' | 'foreignPath' | 'scriptEscape' | 'runnerGlob' | 'testAssembly';
|
|
76
|
+
/** The finding lines each probe channel contributed. Absent/empty ⇒ no block. */
|
|
77
|
+
export type ProbeFindings = Partial<Record<ProbeKey, string[]>>;
|
|
72
78
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
79
|
+
* Build the verification child's prompt. Kept pure so the wording is unit-tested
|
|
80
|
+
* without spawning pi. The contract: run the spec's own verification in the real
|
|
81
|
+
* workspace, judge against ACCEPTANCE, and end on exactly one verdict line.
|
|
82
|
+
*
|
|
83
|
+
* `findings` is the probe bag: one key per PROBE_ADAPTERS row (see the table
|
|
84
|
+
* above for what each channel means and the A/B evidence behind it). A key that
|
|
85
|
+
* is absent or empty emits no block — the probes are independently optional.
|
|
76
86
|
*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
/** Colliding test-runner globs (rule 4g) — see runner-globs.ts. */
|
|
83
|
-
runnerGlobs?: string[];
|
|
87
|
+
export declare function buildVerifyPrompt(spec: string, findings?: ProbeFindings, context?: {
|
|
88
|
+
/** Environment facts earlier gate children discovered — see env-notes.ts. */
|
|
89
|
+
envNotes?: string;
|
|
90
|
+
/** Cross-slice interface facts the design pins — see contracts.ts. */
|
|
91
|
+
contracts?: string;
|
|
84
92
|
}): string;
|
|
85
93
|
/**
|
|
86
94
|
* Parse the child's verdict. Scans for the LAST `WORK-VERIFIED: PASS|FAIL|UNOBSERVED`
|