@mjasnikovs/pi-task 0.16.4 → 0.17.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/dist/task/phases.d.ts +8 -0
- package/dist/task/phases.js +62 -10
- package/dist/task/prompts.d.ts +1 -1
- package/dist/task/prompts.js +2 -2
- package/package.json +1 -1
package/dist/task/phases.d.ts
CHANGED
|
@@ -42,6 +42,14 @@ export interface PhaseConfig {
|
|
|
42
42
|
export declare function extractToolingCommands(research: string): string[] | null;
|
|
43
43
|
/** Replace the TOOLING section in a research string with a VERIFIED-TOOLING section. */
|
|
44
44
|
export declare function replaceToolingWithVerified(research: string, verifiedCommands: string[]): string;
|
|
45
|
+
/**
|
|
46
|
+
* Manifest + config content (orientation tiers 0–1) for refine, with the preserve
|
|
47
|
+
* directive. Reuses the SAME orientation machinery research feeds its workers — not
|
|
48
|
+
* a parallel reader — scoped to the "accumulative" files a from-scratch rewrite
|
|
49
|
+
* silently destroys. '' (non-git/empty/orientation-off) leaves refine unchanged, so
|
|
50
|
+
* a genuinely greenfield task is still free to create.
|
|
51
|
+
*/
|
|
52
|
+
export declare function refineExistingFilesBlock(deps: PhaseDeps): Promise<string>;
|
|
45
53
|
export declare const phaseRefine: (deps: PhaseDeps, raw: string, planContext?: string) => Promise<string>;
|
|
46
54
|
export declare function phaseVerifyTooling(deps: PhaseDeps, research: string): Promise<string>;
|
|
47
55
|
export interface PhaseResearchDeps extends ExternalContextDeps {
|
package/dist/task/phases.js
CHANGED
|
@@ -11,7 +11,7 @@ import { search as defaultSearch } from '../workers/search-core.js';
|
|
|
11
11
|
import { extractEnrichTargets } from './enrichment.js';
|
|
12
12
|
import { isIntegrationUnknown } from './unknown-routing.js';
|
|
13
13
|
import { getFileInventory } from './file-inventory.js';
|
|
14
|
-
import { buildOrientation } from './orientation.js';
|
|
14
|
+
import { buildOrientation, orientationTier } from './orientation.js';
|
|
15
15
|
import { getConfig } from '../config/config.js';
|
|
16
16
|
import { readFile } from 'node:fs/promises';
|
|
17
17
|
import { resolve } from 'node:path';
|
|
@@ -63,15 +63,67 @@ export function replaceToolingWithVerified(research, verifiedCommands) {
|
|
|
63
63
|
return replaced;
|
|
64
64
|
}
|
|
65
65
|
// ─── Phase functions ─────────────────────────────────────────────────────────
|
|
66
|
-
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
// the
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
|
|
66
|
+
// Authoritative directive that travels with the refine orientation block. Refine
|
|
67
|
+
// runs BEFORE research, so on a "Scaffold project with package.json…" title it has
|
|
68
|
+
// no signal the file already exists and authors greenfield strip-constraints
|
|
69
|
+
// ("bun-plugin-tailwind the only dependency", "exactly N scripts") that compose
|
|
70
|
+
// then obeys over the research facts — the implementer executes a wholesale
|
|
71
|
+
// rewrite that drops every existing dependency and script (mx5 TASK_0001 emptied
|
|
72
|
+
// package.json; the REAL pipeline reproduced it 3/3 even with research surfacing
|
|
73
|
+
// the deps). Handing refine the manifest/config CONTENT up front, with this
|
|
74
|
+
// reframe, fixes it at the origin (A/B: 1/5 → 5/5 preserve, 5/5 end-to-end).
|
|
75
|
+
const REFINE_PRESERVE_DIRECTIVE = 'EXISTING FILES ON DISK — AUTHORITATIVE (overrides any "scaffold / create / set '
|
|
76
|
+
+ 'up / initialize / from scratch / only / exactly / minimal" wording in the task '
|
|
77
|
+
+ 'below): the files shown in the PROJECT ORIENTATION block ALREADY EXIST. When '
|
|
78
|
+
+ 'the task says to scaffold, create, set up, initialize, or configure a file that '
|
|
79
|
+
+ 'already exists, your GOAL and CONSTRAINTS MUST frame it as an in-place UPDATE '
|
|
80
|
+
+ 'that PRESERVES every existing dependency, devDependency, script, field, and '
|
|
81
|
+
+ "compiler option — adding or changing only the task's explicit delta. Do NOT "
|
|
82
|
+
+ 'author any constraint that empties, reduces to a fixed/minimal set, renames, '
|
|
83
|
+
+ 'recreates, or drops existing entries (no "X is the only dependency", no '
|
|
84
|
+
+ '"exactly N scripts", no "produce exactly N files from scratch"). An existing '
|
|
85
|
+
+ 'entry is NEVER scope drift and is never removed because it "belongs to a later step".';
|
|
86
|
+
/**
|
|
87
|
+
* Manifest + config content (orientation tiers 0–1) for refine, with the preserve
|
|
88
|
+
* directive. Reuses the SAME orientation machinery research feeds its workers — not
|
|
89
|
+
* a parallel reader — scoped to the "accumulative" files a from-scratch rewrite
|
|
90
|
+
* silently destroys. '' (non-git/empty/orientation-off) leaves refine unchanged, so
|
|
91
|
+
* a genuinely greenfield task is still free to create.
|
|
92
|
+
*/
|
|
93
|
+
export async function refineExistingFilesBlock(deps) {
|
|
94
|
+
if (!getConfig().orientation)
|
|
95
|
+
return '';
|
|
96
|
+
const inventoryRaw = await getFileInventory(deps.cwd, deps.signal).catch(() => '');
|
|
97
|
+
if (inventoryRaw.length === 0)
|
|
98
|
+
return '';
|
|
99
|
+
const paths = inventoryRaw
|
|
100
|
+
.split('\n')
|
|
101
|
+
.map(l => l.trim())
|
|
102
|
+
.filter(l => l.length > 0 && (orientationTier(l) === 0 || orientationTier(l) === 1));
|
|
103
|
+
if (paths.length === 0)
|
|
104
|
+
return '';
|
|
105
|
+
const { block } = await buildOrientation(paths, async (p) => {
|
|
106
|
+
try {
|
|
107
|
+
return await readFile(resolve(deps.cwd, p), 'utf8');
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return block.trim().length === 0 ? '' : `${REFINE_PRESERVE_DIRECTIVE}\n\n${block.trim()}`;
|
|
114
|
+
}
|
|
115
|
+
export const phaseRefine = async (deps, raw, planContext) => {
|
|
116
|
+
const existingFiles = await refineExistingFilesBlock(deps).catch(() => '');
|
|
117
|
+
return runPhaseWithLoopGuard(deps, 'refine', 'read', hint => prependHint(hint, appendNoThink(REFINE_PROMPT(raw, planContext, existingFiles))),
|
|
118
|
+
// refine's deliverable is a 4-section text rewrite that never strictly
|
|
119
|
+
// needs a successful read — on a test-writing task against a large
|
|
120
|
+
// existing codebase the model over-explores (re-reads source hunting for
|
|
121
|
+
// the impl) and burns the loop budget. Degrade to a no-tools final
|
|
122
|
+
// attempt instead of hard-failing the whole run. See TASK_0016 (mx5):
|
|
123
|
+
// refine looped 3×/resume forever; the deliverable was always producible
|
|
124
|
+
// from the title + design doc alone.
|
|
125
|
+
{ degradeOnExhaustion: true });
|
|
126
|
+
};
|
|
75
127
|
export async function phaseVerifyTooling(deps, research) {
|
|
76
128
|
const commands = extractToolingCommands(research);
|
|
77
129
|
if (!commands || commands.length === 0) {
|
package/dist/task/prompts.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export declare const COMPRESS_LABEL_PROMPT: (title: string, maxChars: number) =>
|
|
|
47
47
|
* "Scaffold …" title re-expands the entire design into one task (validated: a real
|
|
48
48
|
* /task-auto run implemented all 24 steps under step 1).
|
|
49
49
|
*/
|
|
50
|
-
declare const REFINE_PROMPT: (raw: string, planContext?: string) => string;
|
|
50
|
+
declare const REFINE_PROMPT: (raw: string, planContext?: string, existingFiles?: string) => string;
|
|
51
51
|
declare const RESEARCH_READ_ONLY_CONSTRAINT = "IMPORTANT: You are ONLY allowed to READ. Do NOT create, modify, or delete any files. Use the read, grep, find, and ls tools to inspect the repo.";
|
|
52
52
|
declare const RESEARCH_FILES_PROMPT: (refined: string) => string;
|
|
53
53
|
declare const RESEARCH_APIS_PROMPT: (refined: string) => string;
|
package/dist/task/prompts.js
CHANGED
|
@@ -61,7 +61,7 @@ ${title}`;
|
|
|
61
61
|
* "Scaffold …" title re-expands the entire design into one task (validated: a real
|
|
62
62
|
* /task-auto run implemented all 24 steps under step 1).
|
|
63
63
|
*/
|
|
64
|
-
const REFINE_PROMPT = (raw, planContext) => `${planContext ? planContext + '\n\n---\n\n' : ''}You receive a user's task description for an AI coding agent. Rewrite it to be unambiguous and actionable.
|
|
64
|
+
const REFINE_PROMPT = (raw, planContext, existingFiles) => `${planContext ? planContext + '\n\n---\n\n' : ''}You receive a user's task description for an AI coding agent. Rewrite it to be unambiguous and actionable.
|
|
65
65
|
|
|
66
66
|
Output structure (four sections, exact headings, in this order):
|
|
67
67
|
|
|
@@ -87,7 +87,7 @@ Rules:
|
|
|
87
87
|
- Do not invent requirements not implied by the input.
|
|
88
88
|
- If the task references a design/spec document (an @-path or a named spec file), READ it and treat it as authoritative. Carry its concrete schema verbatim into GOAL/CONSTRAINTS — table and column names, types, endpoint methods and paths, enum values. The task title is only a pointer into that spec: where the title and the spec disagree, follow the spec, and never introduce a table, column, endpoint, or dependency the spec does not define.
|
|
89
89
|
- Do not output any preamble, commentary, or markdown headings beyond the four sections above.
|
|
90
|
-
|
|
90
|
+
${existingFiles && existingFiles.trim() ? `\n${existingFiles.trim()}\n` : ''}
|
|
91
91
|
Task: ${raw}`;
|
|
92
92
|
// ─── Research fan-out prompts ─────────────────────────────────────────────────
|
|
93
93
|
const RESEARCH_READ_ONLY_CONSTRAINT = `IMPORTANT: You are ONLY allowed to READ. Do NOT create, modify, or delete any files. Use the read, grep, find, and ls tools to inspect the repo.`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
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",
|