imprint-mcp 0.2.1 → 0.3.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 +165 -201
- package/examples/discoverandgo/README.md +1 -1
- package/examples/echo/README.md +1 -1
- package/examples/google-flights/README.md +28 -0
- package/examples/google-flights/_shared/batchexecute.ts +63 -0
- package/examples/google-flights/_shared/flights_request.ts +95 -0
- package/examples/google-flights/_shared/package.json +9 -0
- package/examples/google-flights/get_flight_booking_details/index.ts +159 -0
- package/examples/google-flights/get_flight_booking_details/package.json +9 -0
- package/examples/google-flights/get_flight_booking_details/parser.ts +182 -0
- package/examples/google-flights/get_flight_booking_details/playbook.yaml +138 -0
- package/examples/google-flights/get_flight_booking_details/request-transform.ts +86 -0
- package/examples/google-flights/get_flight_booking_details/workflow.json +98 -0
- package/examples/google-flights/get_flight_calendar_prices/index.ts +131 -0
- package/examples/google-flights/get_flight_calendar_prices/package.json +9 -0
- package/examples/google-flights/get_flight_calendar_prices/parser.ts +86 -0
- package/examples/google-flights/get_flight_calendar_prices/playbook.yaml +97 -0
- package/examples/google-flights/get_flight_calendar_prices/request-transform.ts +31 -0
- package/examples/google-flights/get_flight_calendar_prices/workflow.json +76 -0
- package/examples/google-flights/lookup_airport/index.ts +101 -0
- package/examples/google-flights/lookup_airport/package.json +9 -0
- package/examples/google-flights/lookup_airport/parser.ts +66 -0
- package/examples/google-flights/lookup_airport/playbook.yaml +47 -0
- package/examples/google-flights/lookup_airport/request-transform.ts +20 -0
- package/examples/google-flights/lookup_airport/workflow.json +57 -0
- package/examples/google-flights/search_flights/index.ts +219 -0
- package/examples/google-flights/search_flights/package.json +9 -0
- package/examples/google-flights/search_flights/parser.ts +169 -0
- package/examples/google-flights/search_flights/playbook.yaml +184 -0
- package/examples/google-flights/search_flights/request-transform.ts +119 -0
- package/examples/google-flights/search_flights/workflow.json +143 -0
- package/examples/google-hotels/README.md +29 -0
- package/examples/google-hotels/_shared/batchexecute.ts +73 -0
- package/examples/google-hotels/_shared/freq.ts +158 -0
- package/examples/google-hotels/_shared/package.json +9 -0
- package/examples/google-hotels/autocomplete_hotel_location/index.ts +80 -0
- package/examples/google-hotels/autocomplete_hotel_location/package.json +9 -0
- package/examples/google-hotels/autocomplete_hotel_location/parser.ts +71 -0
- package/examples/google-hotels/autocomplete_hotel_location/playbook.yaml +36 -0
- package/examples/google-hotels/autocomplete_hotel_location/request-transform.ts +37 -0
- package/examples/google-hotels/autocomplete_hotel_location/workflow.json +36 -0
- package/examples/google-hotels/get_hotel_booking_options/index.ts +143 -0
- package/examples/google-hotels/get_hotel_booking_options/package.json +9 -0
- package/examples/google-hotels/get_hotel_booking_options/parser.ts +271 -0
- package/examples/google-hotels/get_hotel_booking_options/playbook.yaml +154 -0
- package/examples/google-hotels/get_hotel_booking_options/request-transform.ts +154 -0
- package/examples/google-hotels/get_hotel_booking_options/workflow.json +84 -0
- package/examples/google-hotels/get_hotel_reviews/index.ts +81 -0
- package/examples/google-hotels/get_hotel_reviews/package.json +9 -0
- package/examples/google-hotels/get_hotel_reviews/parser.ts +128 -0
- package/examples/google-hotels/get_hotel_reviews/playbook.yaml +64 -0
- package/examples/google-hotels/get_hotel_reviews/request-transform.ts +42 -0
- package/examples/google-hotels/get_hotel_reviews/workflow.json +37 -0
- package/examples/google-hotels/search_hotels/index.ts +207 -0
- package/examples/google-hotels/search_hotels/package.json +9 -0
- package/examples/google-hotels/search_hotels/parser.ts +260 -0
- package/examples/google-hotels/search_hotels/playbook.yaml +87 -0
- package/examples/google-hotels/search_hotels/request-transform.ts +197 -0
- package/examples/google-hotels/search_hotels/workflow.json +127 -0
- package/package.json +3 -2
- package/prompts/audit-agent.md +71 -0
- package/prompts/build-planning.md +74 -0
- package/prompts/compile-agent.md +131 -27
- package/prompts/prereq-builder.md +64 -0
- package/prompts/prereq-planner.md +34 -0
- package/prompts/tool-planning.md +39 -0
- package/src/cli.ts +109 -2
- package/src/imprint/agent.ts +5 -0
- package/src/imprint/audit.ts +996 -0
- package/src/imprint/backend-ladder.ts +1214 -184
- package/src/imprint/build-plan.ts +1051 -0
- package/src/imprint/cdp-browser-fetch.ts +589 -0
- package/src/imprint/cdp-jar-cache.ts +320 -0
- package/src/imprint/chromium.ts +135 -0
- package/src/imprint/claude-cli-compile.ts +125 -25
- package/src/imprint/codex-cli-compile.ts +26 -23
- package/src/imprint/compile-agent-types.ts +38 -0
- package/src/imprint/compile-agent.ts +63 -25
- package/src/imprint/compile-tools.ts +1656 -64
- package/src/imprint/compile.ts +13 -1
- package/src/imprint/concurrency.ts +87 -0
- package/src/imprint/cron.ts +1 -0
- package/src/imprint/doctor.ts +39 -0
- package/src/imprint/freeform-redact.ts +5 -4
- package/src/imprint/integrations.ts +2 -2
- package/src/imprint/llm.ts +56 -8
- package/src/imprint/mcp-compile-server.ts +43 -10
- package/src/imprint/mcp-maintenance.ts +9 -101
- package/src/imprint/mcp-server.ts +73 -7
- package/src/imprint/multi-progress.ts +7 -2
- package/src/imprint/param-grounding.ts +367 -0
- package/src/imprint/paths.ts +29 -0
- package/src/imprint/playbook-runner.ts +101 -40
- package/src/imprint/prereq-builder.ts +651 -0
- package/src/imprint/probe-backends.ts +6 -3
- package/src/imprint/record.ts +10 -1
- package/src/imprint/redact.ts +30 -2
- package/src/imprint/replay-capture.ts +19 -18
- package/src/imprint/runtime.ts +19 -10
- package/src/imprint/session-diff.ts +79 -2
- package/src/imprint/session-merge.ts +9 -5
- package/src/imprint/stealth-chromium.ts +81 -0
- package/src/imprint/stealth-fetch.ts +309 -29
- package/src/imprint/stealth-token-cache.ts +88 -0
- package/src/imprint/teach-plan.ts +251 -0
- package/src/imprint/teach-state.ts +10 -0
- package/src/imprint/teach.ts +456 -142
- package/src/imprint/tool-candidates.ts +72 -14
- package/src/imprint/tool-plan.ts +313 -0
- package/src/imprint/tracing.ts +135 -6
- package/src/imprint/types.ts +61 -3
- package/examples/google-flights/search_google_flights/index.ts +0 -101
- package/examples/google-flights/search_google_flights/parser.test.ts +0 -140
- package/examples/google-flights/search_google_flights/parser.ts +0 -189
- package/examples/google-flights/search_google_flights/playbook.yaml +0 -130
- package/examples/google-flights/search_google_flights/workflow.json +0 -48
- package/examples/google-hotels/search_google_hotels/index.ts +0 -194
- package/examples/google-hotels/search_google_hotels/parser.test.ts +0 -168
- package/examples/google-hotels/search_google_hotels/parser.ts +0 -330
- package/examples/google-hotels/search_google_hotels/playbook.yaml +0 -125
- package/examples/google-hotels/search_google_hotels/workflow.json +0 -111
- package/examples/namecheap-domains/search_namecheap_domains/index.ts +0 -144
- package/examples/namecheap-domains/search_namecheap_domains/parser.ts +0 -380
- package/examples/namecheap-domains/search_namecheap_domains/playbook.yaml +0 -50
- package/examples/namecheap-domains/search_namecheap_domains/request-transform.ts +0 -136
- package/examples/namecheap-domains/search_namecheap_domains/workflow.json +0 -97
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan-prereqs step for multi-tool `imprint teach`.
|
|
3
|
+
*
|
|
4
|
+
* Runs once per teach, after candidate selection + the replay/diff join and
|
|
5
|
+
* before the per-tool compile fan-out, when ≥2 tools are selected. It:
|
|
6
|
+
* 1. generates a BuildPlan (shared modules + per-tool guidance + auth recipe),
|
|
7
|
+
* 2. builds + verifies the shared modules under `~/.imprint/<site>/_shared/`
|
|
8
|
+
* level-by-level (independent modules concurrently, dependents after their
|
|
9
|
+
* dependencies), so the files exist when the per-tool agents import them,
|
|
10
|
+
* 3. persists the plan to `.build-plan.json` and returns the manifest.
|
|
11
|
+
*
|
|
12
|
+
* A module the builder can't verify is marked unverified and pruned from every
|
|
13
|
+
* tool's `usesSharedModules`, so the per-tool import-assertion never fails on a
|
|
14
|
+
* module that was never written (tools fall back to inlining — today's behavior).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { join as pathJoin } from 'node:path';
|
|
19
|
+
import {
|
|
20
|
+
type BuildPlan,
|
|
21
|
+
type SharedModuleManifestEntry,
|
|
22
|
+
type SharedModuleSpec,
|
|
23
|
+
generateBuildPlan,
|
|
24
|
+
topoLevels,
|
|
25
|
+
writeBuildPlanSidecar,
|
|
26
|
+
} from './build-plan.ts';
|
|
27
|
+
import { mapLimit } from './concurrency.ts';
|
|
28
|
+
import type { ProviderName } from './llm.ts';
|
|
29
|
+
import { loadJsonFile } from './load-json.ts';
|
|
30
|
+
import { createLog } from './log.ts';
|
|
31
|
+
import { imprintHomeDir, localSharedDir } from './paths.ts';
|
|
32
|
+
import { buildSharedModule } from './prereq-builder.ts';
|
|
33
|
+
import { ensureImprintRuntimeLink } from './runtime-link.ts';
|
|
34
|
+
import type { ClassifiedValue } from './session-diff.ts';
|
|
35
|
+
import type { SharedCompileContext, ToolCandidate } from './tool-candidates.ts';
|
|
36
|
+
import { SessionSchema } from './types.ts';
|
|
37
|
+
|
|
38
|
+
const log = createLog('teach-plan');
|
|
39
|
+
|
|
40
|
+
/** Wall-clock cap on the single planner LLM call. A throttled/hung provider
|
|
41
|
+
* must not block the per-tool fan-out indefinitely; on timeout we degrade to
|
|
42
|
+
* independent per-tool compilation. */
|
|
43
|
+
const PLANNER_TIMEOUT_MS = 10 * 60_000;
|
|
44
|
+
|
|
45
|
+
/** Max shared modules built concurrently within one dependency level. Each build
|
|
46
|
+
* spawns an LLM child + `bun test` + `tsc`, so this is capped (matching the
|
|
47
|
+
* per-tool compile fan-out) to bound peak load and avoid provider throttling. */
|
|
48
|
+
const SHARED_BUILD_CONCURRENCY = 2;
|
|
49
|
+
|
|
50
|
+
interface PlanAndBuildPrereqsResult {
|
|
51
|
+
/** Absolute path to the persisted plan sidecar, or '' when planning was skipped. */
|
|
52
|
+
buildPlanPath: string;
|
|
53
|
+
/** Build manifest (one entry per shared module, with verified flags). */
|
|
54
|
+
sharedModules: SharedModuleManifestEntry[];
|
|
55
|
+
/** The plan that was used (after pruning unverified modules), if any. */
|
|
56
|
+
plan?: BuildPlan;
|
|
57
|
+
/** Set when planning was attempted but failed/timed out, so the caller can
|
|
58
|
+
* surface the reason in the TUI (not raw stderr). Absent on success and when
|
|
59
|
+
* planning was deliberately skipped (disabled / <2 tools). */
|
|
60
|
+
skippedReason?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function buildPlanDisabled(): boolean {
|
|
64
|
+
const v = process.env.IMPRINT_NO_BUILD_PLAN;
|
|
65
|
+
return !!v && !['0', 'false', 'no', 'off'].includes(v.toLowerCase());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function planAndBuildPrereqs(opts: {
|
|
69
|
+
site: string;
|
|
70
|
+
/** Redacted session path (also used as IMPRINT_SESSION_PATH when testing modules). */
|
|
71
|
+
redactedSessionPath: string;
|
|
72
|
+
candidates: ToolCandidate[];
|
|
73
|
+
sharedContext?: SharedCompileContext;
|
|
74
|
+
siteClassifications?: ClassifiedValue[];
|
|
75
|
+
providerName: ProviderName;
|
|
76
|
+
model?: string;
|
|
77
|
+
maxCyclesPerModule?: number;
|
|
78
|
+
onProgress?: (msg: string) => void;
|
|
79
|
+
}): Promise<PlanAndBuildPrereqsResult> {
|
|
80
|
+
// Gate: shared prereqs only make sense across ≥2 tools.
|
|
81
|
+
if (opts.candidates.length < 2) return { buildPlanPath: '', sharedModules: [] };
|
|
82
|
+
if (buildPlanDisabled()) {
|
|
83
|
+
log('IMPRINT_NO_BUILD_PLAN set — skipping build plan + shared prereqs');
|
|
84
|
+
return { buildPlanPath: '', sharedModules: [] };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const session = loadJsonFile(
|
|
88
|
+
opts.redactedSessionPath,
|
|
89
|
+
SessionSchema,
|
|
90
|
+
{
|
|
91
|
+
notFound: 'Redacted session file not found before build planning.',
|
|
92
|
+
badSchema: 'Redacted session file is malformed.',
|
|
93
|
+
},
|
|
94
|
+
'session',
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// 1. Plan. Bounded by a wall-clock timeout AND made non-fatal: a throttled or
|
|
98
|
+
// hung LLM provider (or a malformed plan) must never wedge or abort the
|
|
99
|
+
// whole multi-tool teach. On any failure we degrade to independent per-tool
|
|
100
|
+
// compilation (the pre-feature behavior) instead of shared modules.
|
|
101
|
+
opts.onProgress?.('Planning shared modules');
|
|
102
|
+
let generated: Awaited<ReturnType<typeof generateBuildPlan>>;
|
|
103
|
+
try {
|
|
104
|
+
generated = await generateBuildPlan({
|
|
105
|
+
session,
|
|
106
|
+
candidates: opts.candidates,
|
|
107
|
+
sharedContext: opts.sharedContext,
|
|
108
|
+
classifications: opts.siteClassifications,
|
|
109
|
+
llmConfig: { provider: opts.providerName, model: opts.model },
|
|
110
|
+
timeoutMs: PLANNER_TIMEOUT_MS,
|
|
111
|
+
onProgress: opts.onProgress,
|
|
112
|
+
});
|
|
113
|
+
} catch (err) {
|
|
114
|
+
return {
|
|
115
|
+
buildPlanPath: '',
|
|
116
|
+
sharedModules: [],
|
|
117
|
+
skippedReason: `Build planning failed or timed out (${err instanceof Error ? err.message : String(err)}) — compiling tools independently (no shared modules).`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const plan: BuildPlan = {
|
|
121
|
+
sharedModules: generated.sharedModules,
|
|
122
|
+
perTool: generated.perTool,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Persist immediately so a crash mid-build still leaves a readable plan.
|
|
126
|
+
const buildPlanPath = writeBuildPlanSidecar(opts.site, plan);
|
|
127
|
+
|
|
128
|
+
if (plan.sharedModules.length === 0) {
|
|
129
|
+
log('build plan declared no shared modules — per-tool guidance only');
|
|
130
|
+
return { buildPlanPath, sharedModules: [], plan };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 2. Prepare a clean _shared dir + its toolchain (a stale module from a
|
|
134
|
+
// differently-shaped prior run must not be silently imported).
|
|
135
|
+
const sharedDir = localSharedDir(opts.site);
|
|
136
|
+
rmSync(sharedDir, { recursive: true, force: true });
|
|
137
|
+
mkdirSync(sharedDir, { recursive: true });
|
|
138
|
+
ensureSharedDirToolchain(sharedDir);
|
|
139
|
+
|
|
140
|
+
// 3. Build the modules level-by-level. Modules in the same dependency level are
|
|
141
|
+
// independent, so each level builds concurrently (bounded by
|
|
142
|
+
// SHARED_BUILD_CONCURRENCY); a module that dependsOn another waits for its
|
|
143
|
+
// dependency's level. Only VERIFIED dependencies are accumulated into
|
|
144
|
+
// builtSpecs between levels, so a dependent of a pruned module degrades to
|
|
145
|
+
// inlining (today's behavior) rather than importing something never written.
|
|
146
|
+
const levels = topoLevels(plan.sharedModules);
|
|
147
|
+
const manifest: SharedModuleManifestEntry[] = [];
|
|
148
|
+
const builtSpecs: SharedModuleSpec[] = [];
|
|
149
|
+
for (const level of levels) {
|
|
150
|
+
const results = await mapLimit(level, SHARED_BUILD_CONCURRENCY, (module) => {
|
|
151
|
+
opts.onProgress?.(`Building ${module.path}`);
|
|
152
|
+
return buildSharedModule({
|
|
153
|
+
site: opts.site,
|
|
154
|
+
module,
|
|
155
|
+
session,
|
|
156
|
+
sessionPath: opts.redactedSessionPath,
|
|
157
|
+
sharedDir,
|
|
158
|
+
builtModules: builtSpecs,
|
|
159
|
+
llmConfig: { provider: opts.providerName, model: opts.model },
|
|
160
|
+
maxCycles: opts.maxCyclesPerModule,
|
|
161
|
+
onProgress: opts.onProgress,
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
for (const result of results) {
|
|
165
|
+
manifest.push({
|
|
166
|
+
path: result.module.path,
|
|
167
|
+
kind: result.module.kind,
|
|
168
|
+
verified: result.ok,
|
|
169
|
+
});
|
|
170
|
+
if (result.ok) {
|
|
171
|
+
builtSpecs.push(result.module);
|
|
172
|
+
log(`shared module ${result.module.path} built + verified in ${result.cycles} cycle(s)`);
|
|
173
|
+
} else {
|
|
174
|
+
log(
|
|
175
|
+
`shared module ${result.module.path} could not be verified — pruning from tools. Failures:\n${result.failures.join('\n')}`,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 4. Prune unverified modules from every tool, then re-persist.
|
|
182
|
+
const verifiedPaths = new Set(manifest.filter((m) => m.verified).map((m) => m.path));
|
|
183
|
+
const prunedPlan: BuildPlan = {
|
|
184
|
+
sharedModules: plan.sharedModules.filter((m) => verifiedPaths.has(m.path)),
|
|
185
|
+
perTool: plan.perTool.map((t) => ({
|
|
186
|
+
...t,
|
|
187
|
+
usesSharedModules: t.usesSharedModules.filter((p) => verifiedPaths.has(p)),
|
|
188
|
+
parserGuidance: correctGuidanceForPrunedModules(t.parserGuidance, verifiedPaths),
|
|
189
|
+
})),
|
|
190
|
+
};
|
|
191
|
+
writeBuildPlanSidecar(opts.site, prunedPlan);
|
|
192
|
+
|
|
193
|
+
return { buildPlanPath, sharedModules: manifest, plan: prunedPlan };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Shared-module reference pattern, mirrors build-plan.ts SHARED_MODULE_PATH_RE. */
|
|
197
|
+
const SHARED_MODULE_REF_RE = /_shared\/[A-Za-z0-9._-]+\.ts/g;
|
|
198
|
+
|
|
199
|
+
/** Append a correction note to a tool's free-text `parserGuidance` for any shared
|
|
200
|
+
* module the guidance still names but that was NOT verified/built (and therefore
|
|
201
|
+
* pruned). Without this, the planner's prose (e.g. "Call decodeBatchExecute from
|
|
202
|
+
* _shared/batchexecute.ts") reaches the compile LLM via read_build_plan and tells
|
|
203
|
+
* it to import a module that was never written. Pure + unit-testable; appends
|
|
204
|
+
* rather than rewrites, so still-valid guidance is preserved. */
|
|
205
|
+
export function correctGuidanceForPrunedModules(
|
|
206
|
+
guidance: string,
|
|
207
|
+
verifiedPaths: ReadonlySet<string>,
|
|
208
|
+
): string {
|
|
209
|
+
const referenced = new Set(guidance.match(SHARED_MODULE_REF_RE) ?? []);
|
|
210
|
+
const pruned = [...referenced].filter((p) => !verifiedPaths.has(p));
|
|
211
|
+
if (pruned.length === 0) return guidance;
|
|
212
|
+
const notes = pruned
|
|
213
|
+
.map(
|
|
214
|
+
(p) =>
|
|
215
|
+
`NOTE: shared module ${p} was NOT built — implement its logic inline in this tool's parser.ts; do not import it.`,
|
|
216
|
+
)
|
|
217
|
+
.join('\n');
|
|
218
|
+
return guidance ? `${guidance}\n\n${notes}` : notes;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ─── Toolchain bootstrap ────────────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
/** Bootstrap `_shared/` with the type deps + runtime symlink so `bun test`,
|
|
224
|
+
* `tsc`, and `imprint/*` imports resolve — mirrors the compile-agent tool-dir
|
|
225
|
+
* bootstrap. */
|
|
226
|
+
function ensureSharedDirToolchain(sharedDir: string): void {
|
|
227
|
+
ensureImprintRuntimeLink(imprintHomeDir());
|
|
228
|
+
const pkgPath = pathJoin(sharedDir, 'package.json');
|
|
229
|
+
if (!existsSync(pkgPath)) {
|
|
230
|
+
writeFileSync(
|
|
231
|
+
pkgPath,
|
|
232
|
+
`${JSON.stringify(
|
|
233
|
+
{
|
|
234
|
+
name: 'imprint-shared',
|
|
235
|
+
private: true,
|
|
236
|
+
devDependencies: {
|
|
237
|
+
'@types/bun': 'latest',
|
|
238
|
+
'@types/node': 'latest',
|
|
239
|
+
'bun-types': 'latest',
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
null,
|
|
243
|
+
2,
|
|
244
|
+
)}\n`,
|
|
245
|
+
'utf8',
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
if (!existsSync(pathJoin(sharedDir, 'node_modules'))) {
|
|
249
|
+
Bun.spawnSync(['bun', 'install'], { cwd: sharedDir });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
join as pathJoin,
|
|
23
23
|
resolve as pathResolve,
|
|
24
24
|
} from 'node:path';
|
|
25
|
+
import type { SharedModuleManifestEntry } from './build-plan.ts';
|
|
25
26
|
import {
|
|
26
27
|
localSessionsDir,
|
|
27
28
|
localSiteDir,
|
|
@@ -36,6 +37,7 @@ export const TEACH_STEPS = [
|
|
|
36
37
|
'replay-and-diff',
|
|
37
38
|
'triage',
|
|
38
39
|
'detect-candidates',
|
|
40
|
+
'plan-prereqs',
|
|
39
41
|
'generate',
|
|
40
42
|
'compile-playbook',
|
|
41
43
|
'emit',
|
|
@@ -55,6 +57,14 @@ export interface WorkflowState {
|
|
|
55
57
|
updatedAt: string;
|
|
56
58
|
candidate?: ToolCandidate;
|
|
57
59
|
sharedContext?: SharedCompileContext;
|
|
60
|
+
/** Site-relative path to the multi-tool build plan sidecar (.build-plan.json),
|
|
61
|
+
* set at the plan-prereqs step. Threaded into the per-tool compile drivers so
|
|
62
|
+
* each agent reads its slice via the read_build_plan tool. */
|
|
63
|
+
buildPlanPath?: string;
|
|
64
|
+
/** Shared modules built + verified before the per-tool fan-out. The verifier
|
|
65
|
+
* asserts a tool imports the modules the plan assigned it; entries with
|
|
66
|
+
* `verified: false` are excluded from that assertion. */
|
|
67
|
+
sharedModules?: SharedModuleManifestEntry[];
|
|
58
68
|
/** Non-fatal flags raised by upstream stages that downstream stages (and
|
|
59
69
|
* the user) should know about. Currently used by the redact stage to
|
|
60
70
|
* record `'credentials_not_paired'` when a password-shaped body field
|