@mjasnikovs/pi-task 0.14.10 → 0.14.11
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.
|
@@ -57,6 +57,16 @@ export declare class TaskRunner {
|
|
|
57
57
|
* finally block's call. */
|
|
58
58
|
private _disposeWidget;
|
|
59
59
|
private _deliverSpec;
|
|
60
|
+
/**
|
|
61
|
+
* The spec as the implementer should receive it (Layer B). Layer A strips phantom
|
|
62
|
+
* specifiers from the upstream pipeline text, but a residual affirmative can survive
|
|
63
|
+
* into the composed spec, or arrive when pi expands an `@design.md` the spec
|
|
64
|
+
* references — and the implementer is told that doc is authoritative. Prepend a
|
|
65
|
+
* VERIFIED API OVERRIDES banner that outranks the spec for any specifier the
|
|
66
|
+
* deterministic check proves does not exist. No-op (returns the spec unchanged) when
|
|
67
|
+
* nothing is flagged or the runtime's types aren't installed.
|
|
68
|
+
*/
|
|
69
|
+
private _specForDelivery;
|
|
60
70
|
}
|
|
61
71
|
export interface RunSingleTaskOptions {
|
|
62
72
|
/** Await the session going idle after the spec is delivered, so the caller
|
|
@@ -26,6 +26,7 @@ import { startWidget } from './widget.js';
|
|
|
26
26
|
import { publishViewer, publishNotify, registerBridgeCommand, getBridge } from '../remote/bridge.js';
|
|
27
27
|
import { pushNotify } from '../remote/push.js';
|
|
28
28
|
import { parseVerifyBlock } from './spec-validation.js';
|
|
29
|
+
import { findDeliveryPhantoms, formatApiOverrideBanner } from '../workers/phantom-imports.js';
|
|
29
30
|
import { titleForDisplay } from './parsers.js';
|
|
30
31
|
import { formatTimings } from './timings.js';
|
|
31
32
|
import { getParentContextWindow, resolveContextUsage } from './context-usage.js';
|
|
@@ -261,20 +262,38 @@ export class TaskRunner {
|
|
|
261
262
|
this._stopWidget = null;
|
|
262
263
|
}
|
|
263
264
|
async _deliverSpec(ctx) {
|
|
265
|
+
const spec = this._specForDelivery();
|
|
264
266
|
if (this._sendSpec) {
|
|
265
|
-
await this._sendSpec(
|
|
267
|
+
await this._sendSpec(spec);
|
|
266
268
|
return;
|
|
267
269
|
}
|
|
268
270
|
if (!piApi) {
|
|
269
271
|
throw new Error('extension not initialised (no ExtensionAPI captured)');
|
|
270
272
|
}
|
|
271
273
|
if (ctx.isIdle()) {
|
|
272
|
-
piApi.sendUserMessage(
|
|
274
|
+
piApi.sendUserMessage(spec);
|
|
273
275
|
}
|
|
274
276
|
else {
|
|
275
|
-
piApi.sendUserMessage(
|
|
277
|
+
piApi.sendUserMessage(spec, { deliverAs: 'followUp' });
|
|
276
278
|
}
|
|
277
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* The spec as the implementer should receive it (Layer B). Layer A strips phantom
|
|
282
|
+
* specifiers from the upstream pipeline text, but a residual affirmative can survive
|
|
283
|
+
* into the composed spec, or arrive when pi expands an `@design.md` the spec
|
|
284
|
+
* references — and the implementer is told that doc is authoritative. Prepend a
|
|
285
|
+
* VERIFIED API OVERRIDES banner that outranks the spec for any specifier the
|
|
286
|
+
* deterministic check proves does not exist. No-op (returns the spec unchanged) when
|
|
287
|
+
* nothing is flagged or the runtime's types aren't installed.
|
|
288
|
+
*/
|
|
289
|
+
_specForDelivery() {
|
|
290
|
+
const phantoms = findDeliveryPhantoms(this._pc.spec, this._cwd);
|
|
291
|
+
const banner = formatApiOverrideBanner(phantoms);
|
|
292
|
+
if (!banner)
|
|
293
|
+
return this._pc.spec;
|
|
294
|
+
this._deps.logDebug?.(`impl-handoff API override banner prepended for: ${phantoms.map(p => p.spec).join(', ')}`);
|
|
295
|
+
return `${banner}\n\n${this._pc.spec}`;
|
|
296
|
+
}
|
|
278
297
|
}
|
|
279
298
|
/** Dialog copy for the post-interrupt steering prompt. */
|
|
280
299
|
const STEER_TITLE = 'Paused — steer the model';
|
|
@@ -36,6 +36,25 @@ export declare function loadRuntimeTypeText(runtime: string, cwd: string): strin
|
|
|
36
36
|
export declare function findPhantomImports(text: string, cwd: string, loadText?: (runtime: string, cwd: string) => string | null): PhantomImport[];
|
|
37
37
|
/** Render flagged phantoms as an authoritative research section, or '' if none. */
|
|
38
38
|
export declare function formatApiCorrections(phantoms: PhantomImport[]): string;
|
|
39
|
+
/**
|
|
40
|
+
* A top-of-handoff override banner (Layer B). The deterministic check has proven —
|
|
41
|
+
* against the installed type definitions — that the spec, or a design doc it
|
|
42
|
+
* references, names an API that does NOT exist. The implementer is told the spec/doc
|
|
43
|
+
* is authoritative, so a residual affirmative that survived into the composed spec, or
|
|
44
|
+
* one re-injected when pi expands an `@design.md` the spec references, can still push it
|
|
45
|
+
* to write `bun:sql` / a `declare module` shim. This banner sits ABOVE the spec and is
|
|
46
|
+
* declared to outrank it for these specifiers only. Empty when nothing is flagged.
|
|
47
|
+
*/
|
|
48
|
+
export declare function formatApiOverrideBanner(phantoms: PhantomImport[]): string;
|
|
49
|
+
/**
|
|
50
|
+
* The phantoms the IMPLEMENTER would actually encounter: those named in the delivered
|
|
51
|
+
* spec text itself, PLUS those in any @-file the spec references (pi expands that
|
|
52
|
+
* mention at send time, re-injecting the doc's affirmative). Concatenates the spec with
|
|
53
|
+
* each readable referenced doc and runs the standard deterministic check over the whole.
|
|
54
|
+
* Unreadable mentions are skipped; silent when types are absent or nothing is flagged.
|
|
55
|
+
* Drives the impl-handoff override banner (Layer B).
|
|
56
|
+
*/
|
|
57
|
+
export declare function findDeliveryPhantoms(spec: string, cwd: string): PhantomImport[];
|
|
39
58
|
/**
|
|
40
59
|
* Subtractively rewrite every flagged phantom specifier in `text` to the canonical
|
|
41
60
|
* import the installed types prove, so NO affirmative occurrence of the non-existent
|
|
@@ -186,6 +186,56 @@ export function formatApiCorrections(phantoms) {
|
|
|
186
186
|
const lines = phantoms.map(p => ` - ${p.suggestion}`);
|
|
187
187
|
return `API CORRECTIONS\n${lines.join('\n')}`;
|
|
188
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* A top-of-handoff override banner (Layer B). The deterministic check has proven —
|
|
191
|
+
* against the installed type definitions — that the spec, or a design doc it
|
|
192
|
+
* references, names an API that does NOT exist. The implementer is told the spec/doc
|
|
193
|
+
* is authoritative, so a residual affirmative that survived into the composed spec, or
|
|
194
|
+
* one re-injected when pi expands an `@design.md` the spec references, can still push it
|
|
195
|
+
* to write `bun:sql` / a `declare module` shim. This banner sits ABOVE the spec and is
|
|
196
|
+
* declared to outrank it for these specifiers only. Empty when nothing is flagged.
|
|
197
|
+
*/
|
|
198
|
+
export function formatApiOverrideBanner(phantoms) {
|
|
199
|
+
if (phantoms.length === 0)
|
|
200
|
+
return '';
|
|
201
|
+
const lines = phantoms.map(p => ` - ${p.suggestion}`);
|
|
202
|
+
return ('VERIFIED API OVERRIDES — checked against the installed type definitions. These '
|
|
203
|
+
+ 'SUPERSEDE the spec below and any design/spec document it references: the doc is '
|
|
204
|
+
+ 'WRONG about these specifiers, so do NOT follow it here.\n'
|
|
205
|
+
+ lines.join('\n')
|
|
206
|
+
+ '\nUse the corrected import shown for each. Never write the phantom specifier, '
|
|
207
|
+
+ 'and never add a `declare module` shim to make it resolve.');
|
|
208
|
+
}
|
|
209
|
+
// An @-file mention in a spec ("@DESIGN/foo.md", path until whitespace) minus the
|
|
210
|
+
// trailing prose punctuation a sentence adds. Mirrors auto-orchestrator's mention
|
|
211
|
+
// rules so we read the same docs pi re-expands when delivering the spec.
|
|
212
|
+
const MENTION_RE = /(?:^|\s)@([^\s]+)/g;
|
|
213
|
+
const MENTION_TRAILING_PUNCT = /[.,;:!?)\]}>"']+$/;
|
|
214
|
+
/**
|
|
215
|
+
* The phantoms the IMPLEMENTER would actually encounter: those named in the delivered
|
|
216
|
+
* spec text itself, PLUS those in any @-file the spec references (pi expands that
|
|
217
|
+
* mention at send time, re-injecting the doc's affirmative). Concatenates the spec with
|
|
218
|
+
* each readable referenced doc and runs the standard deterministic check over the whole.
|
|
219
|
+
* Unreadable mentions are skipped; silent when types are absent or nothing is flagged.
|
|
220
|
+
* Drives the impl-handoff override banner (Layer B).
|
|
221
|
+
*/
|
|
222
|
+
export function findDeliveryPhantoms(spec, cwd) {
|
|
223
|
+
let text = spec;
|
|
224
|
+
const seen = new Set();
|
|
225
|
+
for (const m of spec.matchAll(MENTION_RE)) {
|
|
226
|
+
const rel = m[1].replace(MENTION_TRAILING_PUNCT, '');
|
|
227
|
+
if (rel === '' || seen.has(rel))
|
|
228
|
+
continue;
|
|
229
|
+
seen.add(rel);
|
|
230
|
+
try {
|
|
231
|
+
text += '\n' + fs.readFileSync(path.resolve(cwd, rel), 'utf8');
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// not a readable file — leave the @token, skip it
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return findPhantomImports(text, cwd);
|
|
238
|
+
}
|
|
189
239
|
/**
|
|
190
240
|
* Subtractively rewrite every flagged phantom specifier in `text` to the canonical
|
|
191
241
|
* import the installed types prove, so NO affirmative occurrence of the non-existent
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.11",
|
|
4
4
|
"description": "Deterministic spec-orchestration for local models, with a bundled real-time remote web view and web/docs/fetch/worker subagent tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|