@mjasnikovs/pi-task 0.18.12 → 0.18.14
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/dist/config/config.d.ts +17 -0
- package/dist/config/config.js +12 -1
- package/dist/config/extension-list.d.ts +40 -0
- package/dist/config/extension-list.js +66 -0
- package/dist/config/register.d.ts +10 -0
- package/dist/config/register.js +49 -10
- package/dist/shared/child-extensions.d.ts +28 -0
- package/dist/shared/child-extensions.js +47 -0
- package/dist/shared/child-process.d.ts +11 -0
- package/dist/shared/child-process.js +18 -0
- package/dist/task/accept-debt.d.ts +28 -9
- package/dist/task/accept-debt.js +0 -0
- package/dist/task/auto-orchestrator.d.ts +2 -2
- package/dist/task/auto-orchestrator.js +31 -7
- package/dist/task/child-runner.js +3 -2
- package/dist/task/final-gate.d.ts +32 -3
- package/dist/task/final-gate.js +181 -15
- package/dist/task/gate-deps.d.ts +6 -0
- package/dist/task/gate-deps.js +20 -1
- package/dist/task/git-state-guard.js +58 -4
- package/dist/task/launch-contract.d.ts +31 -0
- package/dist/task/launch-contract.js +162 -0
- package/dist/task/task-gates.d.ts +8 -0
- package/dist/task/task-gates.js +7 -0
- package/dist/workers/docs-core.js +4 -3
- package/dist/workers/fetch-core.js +4 -3
- package/dist/workers/pi-worker-core.d.ts +8 -1
- package/dist/workers/pi-worker-core.js +4 -3
- package/dist/workers/pi-worker-docs.js +5 -4
- package/package.json +1 -1
|
@@ -127,6 +127,14 @@ export interface GateDeps {
|
|
|
127
127
|
* and surfaces it if still open. Best-effort; absent in tests → no ledger written.
|
|
128
128
|
*/
|
|
129
129
|
recordAcceptDebt?: (cwd: string, taskId: string, reason: string) => Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Record a durable ENFORCE-REVERT debt (mx5 run 10 item 3): the enforce re-verify
|
|
132
|
+
* FAILED and the enforce edits were reverted, but the FAIL indicts the ORIGINAL
|
|
133
|
+
* work (run 10 TASK_0004: "Missing server entry point … the Hono server cannot be
|
|
134
|
+
* started"). Without this the diagnosis dies with the revert; recorded, the final
|
|
135
|
+
* gate re-checks and surfaces it like an accept-debt. Best-effort; absent in tests.
|
|
136
|
+
*/
|
|
137
|
+
recordEnforceRevertDebt?: (cwd: string, taskId: string, reason: string) => Promise<void>;
|
|
130
138
|
/**
|
|
131
139
|
* The concrete paths this task's spec forbids modifying (its `Do NOT modify`
|
|
132
140
|
* CONSTRAINTS — see frozen-path-guard.ts / prohibition-probe.ts). Used to
|
package/dist/task/task-gates.js
CHANGED
|
@@ -332,6 +332,13 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
332
332
|
if (deps.revert)
|
|
333
333
|
await deps.revert(p.cwd);
|
|
334
334
|
await rec(`enforce: fixes committed but re-verify FAILED (${(after.reason ?? 'now fails').slice(0, 200)}) — ${deps.revert ? 'REVERTED' : 'left in place (no revert available)'}`);
|
|
335
|
+
// Persist the FAIL as a durable defect (mx5 run 10 item 3). The
|
|
336
|
+
// revert restores the tree the ORIGINAL verify already blessed, so
|
|
337
|
+
// this re-verify caught a defect that verify's earlier PASS missed —
|
|
338
|
+
// erasing it with the enforce edits buried the terminal fault 8.5h
|
|
339
|
+
// before run end. The final gate re-checks/surfaces it (static-class
|
|
340
|
+
// auto-closes if a later task fixed the statics; else stays open).
|
|
341
|
+
await deps.recordEnforceRevertDebt?.(p.cwd, p.taskId, after.reason ?? 'enforce re-verify failed');
|
|
335
342
|
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');
|
|
336
343
|
}
|
|
337
344
|
else {
|
|
@@ -8,7 +8,8 @@ import { resolvePackage as defaultResolvePackage, ResolveError, detectTypesRedir
|
|
|
8
8
|
import { retrieveChunks as defaultRetrieveChunks } from './docs-retrieve.js';
|
|
9
9
|
import { npmVersionLookup as defaultNpmVersionLookup } from './npm-version.js';
|
|
10
10
|
import { getPiInvocation } from '../shared/pi-invocation.js';
|
|
11
|
-
import {
|
|
11
|
+
import { runChild } from '../shared/child-process.js';
|
|
12
|
+
import { childBaseArgs } from '../shared/child-extensions.js';
|
|
12
13
|
import { parseChildOutput, isExcerptInContent, formatResultText as formatResultTextShared } from '../shared/child-output.js';
|
|
13
14
|
const DEFAULT_LIMIT = 8;
|
|
14
15
|
const DEFAULT_BUDGET = 24_000;
|
|
@@ -16,7 +17,7 @@ const NO_CACHE_HEAD = 25_000;
|
|
|
16
17
|
const NO_CACHE_TAIL = 5_000;
|
|
17
18
|
const NO_CACHE_TOTAL = NO_CACHE_HEAD + NO_CACHE_TAIL;
|
|
18
19
|
const NO_CACHE_MARKER = '\n\n[...content continues, truncated...]\n\n';
|
|
19
|
-
const
|
|
20
|
+
const childArgs = () => [...childBaseArgs(), '--no-tools'];
|
|
20
21
|
export function extractParentPackage(moduleName) {
|
|
21
22
|
if (moduleName.startsWith('@')) {
|
|
22
23
|
const parts = moduleName.split('/');
|
|
@@ -423,7 +424,7 @@ export async function docsFocused(input) {
|
|
|
423
424
|
const { pkg, chunks, hitCache, indexingMs } = rawResult;
|
|
424
425
|
const concatenated = chunks.map(c => c.content).join('\n\n');
|
|
425
426
|
const prompt = buildPrompt(pkg, input.query, concatenated);
|
|
426
|
-
const invocation = getPiInvocation(
|
|
427
|
+
const invocation = getPiInvocation(childArgs(), prompt);
|
|
427
428
|
const child = await runChild(spawn, invocation, input.cwd, input.signal);
|
|
428
429
|
const parsed = parseChildOutput(child.stdout);
|
|
429
430
|
const excerptVerified = parsed.excerpt ? isExcerptInContent(parsed.excerpt, concatenated) : undefined;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { spawn as defaultSpawn } from 'node:child_process';
|
|
2
2
|
import { fetchAndClean as defaultFetchAndClean } from './html-clean.js';
|
|
3
3
|
import { getPiInvocation } from '../shared/pi-invocation.js';
|
|
4
|
-
import {
|
|
4
|
+
import { runChild } from '../shared/child-process.js';
|
|
5
|
+
import { childBaseArgs } from '../shared/child-extensions.js';
|
|
5
6
|
import { parseChildOutput, isExcerptInContent, formatResultText as formatResultTextShared } from '../shared/child-output.js';
|
|
6
7
|
const CONTENT_BUDGET = 30_000;
|
|
7
8
|
const HEAD_CHARS = 25_000;
|
|
8
9
|
const TAIL_CHARS = 5_000;
|
|
9
10
|
const TRUNCATION_MARKER = '\n\n[...page continues, truncated...]\n\n';
|
|
10
|
-
const
|
|
11
|
+
const childArgs = () => [...childBaseArgs(), '--no-tools'];
|
|
11
12
|
export async function fetchRaw(input) {
|
|
12
13
|
const fetchAndCleanFn = input.fetchAndClean ?? defaultFetchAndClean;
|
|
13
14
|
const cleaned = await fetchAndCleanFn(input.url, { signal: input.signal });
|
|
@@ -24,7 +25,7 @@ export async function fetchFocused(input) {
|
|
|
24
25
|
title: cleaned.title,
|
|
25
26
|
content: truncated
|
|
26
27
|
});
|
|
27
|
-
const invocation = getPiInvocation(
|
|
28
|
+
const invocation = getPiInvocation(childArgs(), prompt);
|
|
28
29
|
const childResult = await runChild(spawnFn, invocation, input.cwd, input.signal);
|
|
29
30
|
if (childResult.aborted) {
|
|
30
31
|
return {
|
|
@@ -7,10 +7,17 @@ export interface RunWorkerInput {
|
|
|
7
7
|
spawn?: SpawnFn;
|
|
8
8
|
/** Comma-separated tool whitelist passed to `pi --tools`. Defaults to read,grep,find,ls. */
|
|
9
9
|
tools?: string;
|
|
10
|
-
/**
|
|
10
|
+
/** Internal extension entry-point paths to load via `-e <path>` (see childBaseArgs). */
|
|
11
11
|
extensions?: string[];
|
|
12
12
|
/** Called for each tool execution start and text-writing event inside the worker. */
|
|
13
13
|
onLine?: (line: string) => void;
|
|
14
|
+
/** Called when a tool call FINISHES, with its (truncatable) result — lets a caller
|
|
15
|
+
* log tool OUTPUTS, not just the command (mx5 run 10 item 6). */
|
|
16
|
+
onToolResult?: (result: {
|
|
17
|
+
name: string;
|
|
18
|
+
isError: boolean;
|
|
19
|
+
text: string;
|
|
20
|
+
}) => void;
|
|
14
21
|
/**
|
|
15
22
|
* Called for each context_usage snapshot the child emits (same `--mode json`
|
|
16
23
|
* stream the phase children parse). Lets a caller's status widget show the
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getPiInvocation } from '../shared/pi-invocation.js';
|
|
2
|
-
import {
|
|
2
|
+
import { runChildDefault } from '../shared/child-process.js';
|
|
3
|
+
import { childBaseArgs } from '../shared/child-extensions.js';
|
|
3
4
|
import { LoopDetector } from '../task/loop-detector.js';
|
|
4
5
|
import { LOOP_WINDOW, LOOP_THRESHOLD, MAX_LOOP_RESTARTS, formatLoopHint } from '../task/child-runner.js';
|
|
5
6
|
import { detectLeakedToolCall, leakedToolCallHint, MAX_LEAK_RETRIES } from '../shared/leaked-tool-call.js';
|
|
@@ -70,8 +71,7 @@ function workerTimeout(external, ms) {
|
|
|
70
71
|
}
|
|
71
72
|
export async function runWorker(input) {
|
|
72
73
|
const tools = input.tools ?? DEFAULT_TOOLS;
|
|
73
|
-
const
|
|
74
|
-
const baseArgs = [...extensionArgs, ...CHILD_BASE_ARGS, '--mode', 'json', '--tools', tools];
|
|
74
|
+
const baseArgs = [...childBaseArgs(input.extensions ?? []), '--mode', 'json', '--tools', tools];
|
|
75
75
|
const timeoutMs = input.timeoutMs ?? RESEARCH_WORKER_TIMEOUT_MS;
|
|
76
76
|
let hint = null;
|
|
77
77
|
// Loop-kill and timeout share one restart budget, mirroring
|
|
@@ -124,6 +124,7 @@ export async function runWorker(input) {
|
|
|
124
124
|
return hit;
|
|
125
125
|
},
|
|
126
126
|
onLine: input.onLine,
|
|
127
|
+
onToolResult: input.onToolResult,
|
|
127
128
|
onContextUsage: input.onContextUsage
|
|
128
129
|
}, input.spawn);
|
|
129
130
|
}
|
|
@@ -4,13 +4,14 @@ import { openCache as defaultOpenCache } from './docs-cache.js';
|
|
|
4
4
|
import { retrieveChunks as defaultRetrieveChunks } from './docs-retrieve.js';
|
|
5
5
|
import { docsRaw, formatResultText, buildPrompt, buildVersionBanner } from './docs-core.js';
|
|
6
6
|
import { formatNpmVersionSection } from './npm-version.js';
|
|
7
|
-
import { runChild
|
|
7
|
+
import { runChild } from '../shared/child-process.js';
|
|
8
|
+
import { childBaseArgs } from '../shared/child-extensions.js';
|
|
8
9
|
import { parseChildOutput, isExcerptInContent } from '../shared/child-output.js';
|
|
9
10
|
import { getPiInvocation } from '../shared/pi-invocation.js';
|
|
10
11
|
import { formatChildFailure, makeWorkerTool } from './shared.js';
|
|
11
12
|
import { normalizeQuery } from './research-cache.js';
|
|
12
13
|
import { projectDocsRaw, buildProjectPrompt } from './docs-project.js';
|
|
13
|
-
const
|
|
14
|
+
const childArgs = () => [...childBaseArgs(), '--no-tools'];
|
|
14
15
|
const RENDER_QUERY_MAX = 100;
|
|
15
16
|
const Params = Type.Object({
|
|
16
17
|
module: Type.String({
|
|
@@ -105,7 +106,7 @@ export function registerPiWorkerDocs(pi, internals = {}) {
|
|
|
105
106
|
};
|
|
106
107
|
const concatenated = chunks.map(c => c.content).join('\n\n');
|
|
107
108
|
const prompt = buildProjectPrompt(projectName, params.query, concatenated);
|
|
108
|
-
const invocation = getPiInvocation(
|
|
109
|
+
const invocation = getPiInvocation(childArgs(), prompt);
|
|
109
110
|
const child = await runChild(spawn, invocation, ctx.cwd, signal);
|
|
110
111
|
const failure = formatChildFailure(child, 'Project docs lookup aborted.');
|
|
111
112
|
if (failure !== null) {
|
|
@@ -207,7 +208,7 @@ export function registerPiWorkerDocs(pi, internals = {}) {
|
|
|
207
208
|
};
|
|
208
209
|
const concatenated = chunks.map(c => c.content).join('\n\n');
|
|
209
210
|
const prompt = buildPrompt(pkg, params.query, concatenated);
|
|
210
|
-
const invocation = getPiInvocation(
|
|
211
|
+
const invocation = getPiInvocation(childArgs(), prompt);
|
|
211
212
|
const child = await runChild(spawn, invocation, ctx.cwd, signal);
|
|
212
213
|
const failure = formatChildFailure(child, 'Docs lookup aborted.');
|
|
213
214
|
if (failure !== null) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.14",
|
|
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",
|