@ramplab/generator 0.1.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/agentSdkRunner.d.ts +64 -0
  4. package/dist/agentSdkRunner.d.ts.map +1 -0
  5. package/dist/agentSdkRunner.js +158 -0
  6. package/dist/agentSdkRunner.js.map +1 -0
  7. package/dist/assembleStage.d.ts +41 -0
  8. package/dist/assembleStage.d.ts.map +1 -0
  9. package/dist/assembleStage.js +33 -0
  10. package/dist/assembleStage.js.map +1 -0
  11. package/dist/authorStage.d.ts +123 -0
  12. package/dist/authorStage.d.ts.map +1 -0
  13. package/dist/authorStage.js +284 -0
  14. package/dist/authorStage.js.map +1 -0
  15. package/dist/cloneRepo.d.ts +72 -0
  16. package/dist/cloneRepo.d.ts.map +1 -0
  17. package/dist/cloneRepo.js +104 -0
  18. package/dist/cloneRepo.js.map +1 -0
  19. package/dist/flagship.d.ts +62 -0
  20. package/dist/flagship.d.ts.map +1 -0
  21. package/dist/flagship.js +216 -0
  22. package/dist/flagship.js.map +1 -0
  23. package/dist/generateLab.d.ts +151 -0
  24. package/dist/generateLab.d.ts.map +1 -0
  25. package/dist/generateLab.js +291 -0
  26. package/dist/generateLab.js.map +1 -0
  27. package/dist/index.d.ts +22 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +21 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/intake.d.ts +31 -0
  32. package/dist/intake.d.ts.map +1 -0
  33. package/dist/intake.js +45 -0
  34. package/dist/intake.js.map +1 -0
  35. package/dist/live.d.ts +2 -0
  36. package/dist/live.d.ts.map +1 -0
  37. package/dist/live.js +213 -0
  38. package/dist/live.js.map +1 -0
  39. package/dist/mapStage.d.ts +84 -0
  40. package/dist/mapStage.d.ts.map +1 -0
  41. package/dist/mapStage.js +241 -0
  42. package/dist/mapStage.js.map +1 -0
  43. package/dist/pass1.d.ts +85 -0
  44. package/dist/pass1.d.ts.map +1 -0
  45. package/dist/pass1.js +81 -0
  46. package/dist/pass1.js.map +1 -0
  47. package/dist/pipeline.d.ts +73 -0
  48. package/dist/pipeline.d.ts.map +1 -0
  49. package/dist/pipeline.js +70 -0
  50. package/dist/pipeline.js.map +1 -0
  51. package/dist/planStage.d.ts +141 -0
  52. package/dist/planStage.d.ts.map +1 -0
  53. package/dist/planStage.js +275 -0
  54. package/dist/planStage.js.map +1 -0
  55. package/dist/progress.d.ts +45 -0
  56. package/dist/progress.d.ts.map +1 -0
  57. package/dist/progress.js +2 -0
  58. package/dist/progress.js.map +1 -0
  59. package/dist/repoCommit.d.ts +41 -0
  60. package/dist/repoCommit.d.ts.map +1 -0
  61. package/dist/repoCommit.js +84 -0
  62. package/dist/repoCommit.js.map +1 -0
  63. package/dist/repoSize.d.ts +23 -0
  64. package/dist/repoSize.d.ts.map +1 -0
  65. package/dist/repoSize.js +74 -0
  66. package/dist/repoSize.js.map +1 -0
  67. package/dist/resolveAnchors.d.ts +142 -0
  68. package/dist/resolveAnchors.d.ts.map +1 -0
  69. package/dist/resolveAnchors.js +242 -0
  70. package/dist/resolveAnchors.js.map +1 -0
  71. package/dist/verifyStage.d.ts +150 -0
  72. package/dist/verifyStage.d.ts.map +1 -0
  73. package/dist/verifyStage.js +461 -0
  74. package/dist/verifyStage.js.map +1 -0
  75. package/package.json +47 -0
package/dist/live.js ADDED
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Live-run entry for the generator — the documented real-model path.
3
+ *
4
+ * Usage (from the repo root):
5
+ *
6
+ * ANTHROPIC_API_KEY=... pnpm --filter @ramplab/generator run live -- <repoDir> [outFile] [--pass1 | --full]
7
+ *
8
+ * The key is optional. With `ANTHROPIC_API_KEY` unset the Agent SDK falls
9
+ * through to the Claude Code login, which spends session allowance instead of
10
+ * API credit — the way to populate the library without a metered bill. Either
11
+ * way the run prints which credential it took before it starts. Note that a
12
+ * shell which sources this repo's `.env` has the key set: unset it deliberately.
13
+ *
14
+ * Runs against the given plain local directory with the real Claude Agent
15
+ * SDK, prints progress and a resolution summary to stderr, and writes the
16
+ * resulting lab-spec JSON to `outFile` (default `lab-spec.json` in the
17
+ * current directory) — ready to load into the playground.
18
+ *
19
+ * Modes (the two-pass runtime, PLAN.md §4):
20
+ * - default: the map-stage tracer (repo map + intro module).
21
+ * - `--pass1`: pass 1 — map + ONE flagship module: the most representative
22
+ * front-door trace action the map proposed (intake can override; subsystem
23
+ * centrality is the fallback), lightly verified (anchor resolution only).
24
+ * Streams progress events, prints which trace action was selected and why
25
+ * (basis), and prints the measured pass-1 timing.
26
+ * - `--full`: pass 2 — the full pipeline (map → curriculum plan → parallel
27
+ * authoring → assemble → adversarial verification), printing progress
28
+ * events as they arrive.
29
+ *
30
+ * Optional env:
31
+ * - RAMPLAB_MAP_MODEL / RAMPLAB_PLAN_MODEL / RAMPLAB_AUTHOR_MODEL /
32
+ * RAMPLAB_VERIFY_MODEL override the per-stage models.
33
+ * - RAMPLAB_MAX_MODULES caps the curriculum budget (full mode; default 6).
34
+ */
35
+ import { writeFileSync } from 'node:fs';
36
+ import { resolve } from 'node:path';
37
+ import { createAgentSdkRunner, describeAuth } from './agentSdkRunner.js';
38
+ import { generateLab } from './generateLab.js';
39
+ import { generateLabPass1 } from './pass1.js';
40
+ /**
41
+ * One line naming the selected flagship and its basis — trace action first
42
+ * (the issue-#18 design), node fallback spelled out — so iteration reviews
43
+ * know exactly what pass 1 chose and why.
44
+ */
45
+ function describeFlagship(flagship) {
46
+ const why = {
47
+ trace: 'most representative front-door action proposed by the map',
48
+ 'trace-intake': `intake hint "${flagship.matchedHint ?? ''}" matched this action`,
49
+ intake: `no usable trace candidates — node fallback; ` +
50
+ `intake hint "${flagship.matchedHint ?? ''}" matched this node`,
51
+ centrality: `no usable trace candidates — node fallback by subsystem centrality ` +
52
+ `(degree ${flagship.degree ?? 0})`,
53
+ }[flagship.basis];
54
+ return flagship.traceAction !== undefined
55
+ ? `Flagship trace: "${flagship.traceAction}" → module "${flagship.plannedModule.id}" ` +
56
+ `(basis: ${flagship.basis} — ${why}).`
57
+ : `Flagship: module "${flagship.plannedModule.id}" (node ${flagship.nodeId ?? '?'}, ` +
58
+ `basis: ${flagship.basis} — ${why}).`;
59
+ }
60
+ function printProgress(event) {
61
+ switch (event.type) {
62
+ case 'stage-started':
63
+ console.error(`[${event.pass}] ${event.stage}: started`);
64
+ break;
65
+ case 'stage-completed':
66
+ console.error(`[${event.pass}] ${event.stage}: completed`);
67
+ break;
68
+ case 'module-authored':
69
+ console.error(`[${event.pass}] authored module "${event.moduleId}" ` +
70
+ `(${event.attempts} attempt${event.attempts === 1 ? '' : 's'})`);
71
+ break;
72
+ case 'spec-updated':
73
+ console.error(`[${event.pass}] spec updated — ${event.spec.base.modules.length} module(s) renderable`);
74
+ break;
75
+ }
76
+ }
77
+ /** Read `--flag N` out of argv as a positive integer. */
78
+ function numericFlag(args, flag) {
79
+ const at = args.indexOf(flag);
80
+ if (at === -1)
81
+ return { ok: true, value: undefined };
82
+ const raw = args[at + 1];
83
+ const value = Number(raw);
84
+ if (raw === undefined || !Number.isInteger(value) || value < 1) {
85
+ return { ok: false, error: `${flag} needs a positive integer, got "${raw ?? ''}".` };
86
+ }
87
+ return { ok: true, value };
88
+ }
89
+ async function main() {
90
+ const args = process.argv.slice(2);
91
+ const full = args.includes('--full');
92
+ const pass1 = args.includes('--pass1');
93
+ // The same two guards the eval harness raises by default (its tier-1
94
+ // findings): the SDK's 50-turn default gets exhausted by one authoring
95
+ // session on a real repo, and author-stage schema drift occasionally needs
96
+ // a second retry. This entry could not reach either until now, so a
97
+ // single-repo pressing was the one path still running on the low cap.
98
+ const turns = numericFlag(args, '--max-turns');
99
+ const retries = numericFlag(args, '--max-retries');
100
+ for (const parsed of [turns, retries]) {
101
+ if (!parsed.ok) {
102
+ console.error(parsed.error);
103
+ process.exitCode = 2;
104
+ return;
105
+ }
106
+ }
107
+ const maxTurns = turns.ok ? turns.value : undefined;
108
+ const maxRetries = retries.ok ? retries.value : undefined;
109
+ const positional = args.filter((arg, index) => !arg.startsWith('--') &&
110
+ // Drop the value that followed a numeric flag, not every matching token.
111
+ !(index > 0 && (args[index - 1] === '--max-turns' || args[index - 1] === '--max-retries')));
112
+ const [repoDirArg, outArg] = positional;
113
+ if (repoDirArg === undefined || (full && pass1)) {
114
+ console.error('Usage: pnpm --filter @ramplab/generator run live -- <repoDir> [outFile] ' +
115
+ '[--pass1 | --full] [--max-turns N] [--max-retries N]');
116
+ process.exitCode = 2;
117
+ return;
118
+ }
119
+ // Either credential runs the pipeline; the run just has to say which.
120
+ console.error(`Auth: ${describeAuth().label}`);
121
+ const repoDir = resolve(repoDirArg);
122
+ const outFile = resolve(outArg ?? 'lab-spec.json');
123
+ const models = {};
124
+ if (process.env['RAMPLAB_MAP_MODEL'] !== undefined) {
125
+ models.map = process.env['RAMPLAB_MAP_MODEL'];
126
+ }
127
+ if (process.env['RAMPLAB_PLAN_MODEL'] !== undefined) {
128
+ models.plan = process.env['RAMPLAB_PLAN_MODEL'];
129
+ }
130
+ if (process.env['RAMPLAB_AUTHOR_MODEL'] !== undefined) {
131
+ models.author = process.env['RAMPLAB_AUTHOR_MODEL'];
132
+ }
133
+ if (process.env['RAMPLAB_VERIFY_MODEL'] !== undefined) {
134
+ models.verify = process.env['RAMPLAB_VERIFY_MODEL'];
135
+ }
136
+ const maxModulesEnv = process.env['RAMPLAB_MAX_MODULES'];
137
+ const maxModules = maxModulesEnv !== undefined ? Number(maxModulesEnv) : undefined;
138
+ if (maxModules !== undefined && (!Number.isInteger(maxModules) || maxModules < 1)) {
139
+ console.error(`RAMPLAB_MAX_MODULES must be a positive integer, got "${maxModulesEnv}".`);
140
+ process.exitCode = 2;
141
+ return;
142
+ }
143
+ // A raised cap is still a hard guard, just a roomier one.
144
+ const runner = maxTurns !== undefined ? createAgentSdkRunner({ maxTurns }) : undefined;
145
+ if (maxTurns !== undefined || maxRetries !== undefined) {
146
+ console.error(`Guards: max-turns=${maxTurns ?? 'default'}, max-retries=${maxRetries ?? 'default'}`);
147
+ }
148
+ if (pass1) {
149
+ console.error(`Generating pass-1 preview lab for ${repoDir} ...`);
150
+ const result = await generateLabPass1(repoDir, {
151
+ ...(Object.keys(models).length > 0 ? { models } : {}),
152
+ ...(runner !== undefined ? { runner } : {}),
153
+ ...(maxRetries !== undefined ? { maxRetries } : {}),
154
+ onProgress: printProgress,
155
+ });
156
+ writeFileSync(outFile, `${JSON.stringify(result.spec, null, 2)}\n`, 'utf8');
157
+ const seconds = (result.timing.durationMs / 1000).toFixed(1);
158
+ console.error(`Pass 1 done in ${seconds}s (map attempts: ${result.attempts}).`);
159
+ console.error(`Models: map=${result.models.map}, author=${result.models.author}`);
160
+ console.error(describeFlagship(result.flagship));
161
+ const { summary } = result.resolution;
162
+ console.error(`Anchors: ${summary.resolvedAnchors}/${summary.totalAnchors} resolved; ` +
163
+ `units: ${summary.resolvedUnits}/${summary.totalUnits} kept, ` +
164
+ `${summary.unresolvedUnits} dropped.`);
165
+ console.error(result.costUsd !== undefined
166
+ ? `Cost: $${result.costUsd.toFixed(4)}`
167
+ : 'Cost: not reported by the runner.');
168
+ console.error(`Spec written to ${outFile} — load it in apps/playground to view.`);
169
+ return;
170
+ }
171
+ const config = {
172
+ full,
173
+ ...(Object.keys(models).length > 0 ? { models } : {}),
174
+ ...(maxModules !== undefined ? { budget: { maxModules } } : {}),
175
+ ...(runner !== undefined ? { runner } : {}),
176
+ ...(maxRetries !== undefined ? { maxRetries } : {}),
177
+ ...(full ? { onProgress: printProgress } : {}),
178
+ };
179
+ console.error(`Generating ${full ? 'full-pipeline' : 'map-stage'} lab for ${repoDir} ...`);
180
+ const started = Date.now();
181
+ const result = await generateLab(repoDir, config);
182
+ const seconds = ((Date.now() - started) / 1000).toFixed(1);
183
+ writeFileSync(outFile, `${JSON.stringify(result.spec, null, 2)}\n`, 'utf8');
184
+ const { summary } = result.resolution;
185
+ console.error(`Done in ${seconds}s (map attempts: ${result.attempts}).`);
186
+ console.error(full
187
+ ? `Models: map=${result.models.map}, plan=${result.models.plan}, ` +
188
+ `author=${result.models.author}, verify=${result.models.verify}`
189
+ : `Model (map stage): ${result.models.map}`);
190
+ if (result.plan !== undefined) {
191
+ console.error(`Plan: ${result.plan.modules.length} module(s) — ` +
192
+ result.plan.modules.map((m) => m.id).join(', '));
193
+ }
194
+ console.error(`Anchors: ${summary.resolvedAnchors}/${summary.totalAnchors} resolved; ` +
195
+ `units: ${summary.resolvedUnits}/${summary.totalUnits} kept, ` +
196
+ `${summary.unresolvedUnits} dropped.`);
197
+ if (result.verification !== undefined) {
198
+ const v = result.verification;
199
+ console.error(`Verification: ${v.summary.verified}/${v.summary.totalClaims} claims verified ` +
200
+ `(pass rate ${(v.summary.passRate * 100).toFixed(1)}%); dropped ` +
201
+ `${v.drops.widgets.length} widget(s), ${v.drops.questions.length} quiz question(s), ` +
202
+ `${v.drops.modules.length} emptied module(s).`);
203
+ }
204
+ console.error(result.costUsd !== undefined
205
+ ? `Cost: $${result.costUsd.toFixed(4)}`
206
+ : 'Cost: not reported by the runner.');
207
+ console.error(`Spec written to ${outFile} — load it in apps/playground to view.`);
208
+ }
209
+ main().catch((error) => {
210
+ console.error(error instanceof Error ? error.message : error);
211
+ process.exitCode = 1;
212
+ });
213
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { z } from 'zod';
2
+ import { type LabSpec } from '@ramplab/spec';
3
+ import type { ModelRunner } from './pipeline.js';
4
+ /**
5
+ * The map stage (PLAN.md §4, pass 1): an agent explores the repository and
6
+ * produces (a) a system-map widget of the architecture, (b) one module of
7
+ * anchored callouts introducing the repo, and (c) 2–3 candidate "front door"
8
+ * trace actions — real user-triggered entry-point scenarios ("an HTTP
9
+ * request is served", "a file is sent") with the files along each action's
10
+ * path. The candidates seed flagship selection (issue #18): the lab's
11
+ * opening module traces one of them end to end.
12
+ *
13
+ * The model returns a small JSON payload; this module owns the output
14
+ * contract (prompt), the payload → LabSpec assembly, and the bounded retry
15
+ * on schema-invalid output. Validation is a single path: the assembled spec
16
+ * must pass `parseLabSpec` — there is no separate payload schema to drift
17
+ * out of sync with `@ramplab/spec`. Trace candidates are deliberately
18
+ * advisory: a malformed candidate is dropped (flagship selection has a
19
+ * mechanical fallback), never a reason to reject the whole map.
20
+ */
21
+ export interface MapStageOptions {
22
+ model: string;
23
+ /** Lab id; defaults to a slug of the repo directory name. */
24
+ labId?: string;
25
+ /**
26
+ * How many times to re-prompt after schema-invalid output.
27
+ * @default 1
28
+ */
29
+ maxRetries?: number;
30
+ }
31
+ /**
32
+ * One candidate "front door" user action proposed by the map agent — an
33
+ * entry-point scenario a real user triggers, with the files along its path.
34
+ * Pipeline-internal (never part of the lab spec): it exists to seed the
35
+ * flagship trace selection in `flagship.ts`.
36
+ */
37
+ export declare const traceCandidateSchema: z.ZodObject<{
38
+ id: z.ZodString;
39
+ action: z.ZodString;
40
+ description: z.ZodOptional<z.ZodString>;
41
+ keyFiles: z.ZodArray<z.ZodString>;
42
+ }, z.core.$strip>;
43
+ export type TraceCandidate = z.infer<typeof traceCandidateSchema>;
44
+ export interface MapStageResult {
45
+ /** A valid lab spec — not yet anchor-resolved. */
46
+ spec: LabSpec;
47
+ /** Total attempts made (1 = no retry needed). */
48
+ attempts: number;
49
+ /** Summed cost across attempts, if the runner reports cost. */
50
+ costUsd: number | undefined;
51
+ /**
52
+ * Candidate front-door trace actions, most representative first. Always
53
+ * present (possibly empty) on fresh runs; optional so map results captured
54
+ * before issue #18 (e.g. a reused `config.mapResult`) remain valid — every
55
+ * consumer must treat a missing/empty list as "no candidates" and fall
56
+ * back mechanically.
57
+ */
58
+ traceCandidates?: TraceCandidate[];
59
+ }
60
+ /** Raised when the model's output stays schema-invalid after all retries. */
61
+ export declare class MapStageError extends Error {
62
+ readonly attempts: number;
63
+ /** The validation failure of the final attempt. */
64
+ readonly lastFailure: string;
65
+ constructor(attempts: number, lastFailure: string);
66
+ }
67
+ export declare function runMapStage(runner: ModelRunner, repoDir: string, options: MapStageOptions): Promise<MapStageResult>;
68
+ /**
69
+ * Lenient trace-candidate parsing: keep every entry that satisfies
70
+ * {@link traceCandidateSchema} (first occurrence wins on a duplicate id),
71
+ * silently drop the rest. Advisory data gets advisory validation — flagship
72
+ * selection falls back to centrality when nothing usable survives, so a
73
+ * sloppy candidate must never fail (or force a retry of) the map stage.
74
+ */
75
+ export declare function parseTraceCandidates(payload: Record<string, unknown>): TraceCandidate[];
76
+ /**
77
+ * Pull a JSON value out of agent output that may wrap it in prose or a
78
+ * markdown fence. Tries, in order: the raw text, the last ```json fence,
79
+ * and the outermost `{...}` span.
80
+ */
81
+ export declare function extractJson(output: string): unknown;
82
+ /** Turn a directory name into a schema-valid kebab-case lab id. */
83
+ export declare function slugify(name: string): string;
84
+ //# sourceMappingURL=mapStage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapStage.d.ts","sourceRoot":"","sources":["../src/mapStage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA8B,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAEhE;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;iBAW/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,IAAI,EAAE,OAAO,CAAC;IACd,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,6EAA6E;AAC7E,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CASlD;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAqCzB;AAsDD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,EAAE,CAYvF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAuBnD;AAqFD,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C"}
@@ -0,0 +1,241 @@
1
+ import { basename } from 'node:path';
2
+ import { z } from 'zod';
3
+ import { idSchema, safeParseLabSpec } from '@ramplab/spec';
4
+ /**
5
+ * One candidate "front door" user action proposed by the map agent — an
6
+ * entry-point scenario a real user triggers, with the files along its path.
7
+ * Pipeline-internal (never part of the lab spec): it exists to seed the
8
+ * flagship trace selection in `flagship.ts`.
9
+ */
10
+ export const traceCandidateSchema = z.object({
11
+ /** Stable kebab-case id — becomes the trace module's id when selected. */
12
+ id: idSchema,
13
+ /** The user-visible action, e.g. "an HTTP request is served". */
14
+ action: z.string().min(1, 'trace candidate action must be non-empty'),
15
+ /** Optional one-liner: where the action enters and what it passes through. */
16
+ description: z.string().min(1).optional(),
17
+ /** Repo-relative files along the action's path, entry point first. */
18
+ keyFiles: z
19
+ .array(z.string().min(1))
20
+ .min(1, 'a trace candidate needs at least one key file'),
21
+ });
22
+ /** Raised when the model's output stays schema-invalid after all retries. */
23
+ export class MapStageError extends Error {
24
+ attempts;
25
+ /** The validation failure of the final attempt. */
26
+ lastFailure;
27
+ constructor(attempts, lastFailure) {
28
+ super(`Map stage failed: model output did not produce a valid lab spec after ` +
29
+ `${attempts} attempt${attempts === 1 ? '' : 's'}.\nLast failure:\n${lastFailure}`);
30
+ this.name = 'MapStageError';
31
+ this.attempts = attempts;
32
+ this.lastFailure = lastFailure;
33
+ }
34
+ }
35
+ export async function runMapStage(runner, repoDir, options) {
36
+ const maxRetries = options.maxRetries ?? 1;
37
+ const maxAttempts = 1 + Math.max(0, maxRetries);
38
+ const labId = options.labId ?? slugify(basename(repoDir));
39
+ const basePrompt = buildMapPrompt();
40
+ let costUsd;
41
+ let lastFailure = 'no attempt was made';
42
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
43
+ const prompt = attempt === 1 ? basePrompt : `${basePrompt}\n\n${retryPreamble(lastFailure)}`;
44
+ const response = await runner.runStage({
45
+ stage: 'map',
46
+ model: options.model,
47
+ repoDir,
48
+ prompt,
49
+ attempt,
50
+ });
51
+ if (response.costUsd !== undefined) {
52
+ costUsd = (costUsd ?? 0) + response.costUsd;
53
+ }
54
+ const outcome = assembleSpec(response.output, labId);
55
+ if (outcome.ok) {
56
+ return {
57
+ spec: outcome.spec,
58
+ attempts: attempt,
59
+ costUsd,
60
+ traceCandidates: outcome.traceCandidates,
61
+ };
62
+ }
63
+ lastFailure = outcome.failure;
64
+ }
65
+ throw new MapStageError(maxAttempts, lastFailure);
66
+ }
67
+ /**
68
+ * Parse the model's text output as the map-stage payload and assemble the
69
+ * lab spec around it. Any problem — unparseable JSON, wrong envelope, or a
70
+ * spec-schema violation — becomes a `failure` string that feeds the retry
71
+ * prompt verbatim.
72
+ */
73
+ function assembleSpec(output, labId) {
74
+ const json = extractJson(output);
75
+ if (json === undefined) {
76
+ return { ok: false, failure: 'The output did not contain a parseable JSON object.' };
77
+ }
78
+ if (typeof json !== 'object' || json === null || Array.isArray(json)) {
79
+ return { ok: false, failure: 'The output JSON must be an object.' };
80
+ }
81
+ const payload = json;
82
+ const callouts = Array.isArray(payload['callouts']) ? payload['callouts'] : [];
83
+ const candidate = {
84
+ schemaVersion: 1,
85
+ id: labId,
86
+ title: payload['title'],
87
+ base: {
88
+ modules: [
89
+ {
90
+ id: 'repo-overview',
91
+ title: payload['moduleTitle'],
92
+ ...(typeof payload['moduleSummary'] === 'string'
93
+ ? { summary: payload['moduleSummary'] }
94
+ : {}),
95
+ widgets: [payload['systemMap'], ...callouts],
96
+ },
97
+ ],
98
+ },
99
+ overlay: [],
100
+ };
101
+ const parsed = safeParseLabSpec(candidate);
102
+ if (!parsed.success) {
103
+ return { ok: false, failure: parsed.error };
104
+ }
105
+ return { ok: true, spec: parsed.data, traceCandidates: parseTraceCandidates(payload) };
106
+ }
107
+ /**
108
+ * Lenient trace-candidate parsing: keep every entry that satisfies
109
+ * {@link traceCandidateSchema} (first occurrence wins on a duplicate id),
110
+ * silently drop the rest. Advisory data gets advisory validation — flagship
111
+ * selection falls back to centrality when nothing usable survives, so a
112
+ * sloppy candidate must never fail (or force a retry of) the map stage.
113
+ */
114
+ export function parseTraceCandidates(payload) {
115
+ const raw = payload['traceCandidates'];
116
+ if (!Array.isArray(raw))
117
+ return [];
118
+ const seen = new Set();
119
+ const candidates = [];
120
+ for (const entry of raw) {
121
+ const parsed = traceCandidateSchema.safeParse(entry);
122
+ if (!parsed.success || seen.has(parsed.data.id))
123
+ continue;
124
+ seen.add(parsed.data.id);
125
+ candidates.push(parsed.data);
126
+ }
127
+ return candidates;
128
+ }
129
+ /**
130
+ * Pull a JSON value out of agent output that may wrap it in prose or a
131
+ * markdown fence. Tries, in order: the raw text, the last ```json fence,
132
+ * and the outermost `{...}` span.
133
+ */
134
+ export function extractJson(output) {
135
+ const candidates = [output.trim()];
136
+ const fences = [...output.matchAll(/```(?:json)?\s*\n([\s\S]*?)```/g)];
137
+ const lastFence = fences[fences.length - 1];
138
+ if (lastFence?.[1] !== undefined) {
139
+ candidates.push(lastFence[1].trim());
140
+ }
141
+ const first = output.indexOf('{');
142
+ const last = output.lastIndexOf('}');
143
+ if (first !== -1 && last > first) {
144
+ candidates.push(output.slice(first, last + 1));
145
+ }
146
+ for (const candidate of candidates) {
147
+ try {
148
+ return JSON.parse(candidate);
149
+ }
150
+ catch {
151
+ // try the next extraction strategy
152
+ }
153
+ }
154
+ return undefined;
155
+ }
156
+ // ---------------------------------------------------------------------------
157
+ // Prompting
158
+ // ---------------------------------------------------------------------------
159
+ function retryPreamble(failure) {
160
+ return (`IMPORTANT — your previous attempt was rejected because it did not ` +
161
+ `validate against the lab spec schema:\n\n${failure}\n\n` +
162
+ `Fix these problems and respond again with ONLY the corrected JSON object.`);
163
+ }
164
+ function buildMapPrompt() {
165
+ return `You are analyzing the repository in your working directory to build the "map" stage of a codebase onboarding lab: an architecture overview a new hire sees first.
166
+
167
+ Explore the repository using the read-only tools available to you (Read, Glob, Grep). Do not modify anything.
168
+
169
+ When you are done exploring, respond with ONLY a single JSON object (no prose before or after) with exactly this shape:
170
+
171
+ {
172
+ "title": "<the project's REAL name, verbatim, followed by ' Onboarding Lab' — e.g. 'Caddy Onboarding Lab'>",
173
+ "moduleTitle": "<title for the intro module>",
174
+ "moduleSummary": "<2-3 sentence orientation for a new engineer>",
175
+ "systemMap": {
176
+ "id": "system-map",
177
+ "type": "system-map",
178
+ "title": "<diagram title>",
179
+ "nodes": [
180
+ {
181
+ "id": "<kebab-case-id>",
182
+ "label": "<short label>",
183
+ "description": "<what this part does>",
184
+ "anchors": [{ "file": "<repo-relative path>", "symbol": "<identifier in that file>", "lines": { "start": N, "end": M } }]
185
+ }
186
+ ],
187
+ "edges": [
188
+ { "from": "<node-id>", "to": "<node-id>", "label": "<what flows here>", "anchors": [{ "file": "...", "symbol": "..." }] }
189
+ ]
190
+ },
191
+ "callouts": [
192
+ {
193
+ "id": "<kebab-case-id>",
194
+ "type": "callout",
195
+ "kind": "why" | "warning" | "connects-to",
196
+ "title": "<optional short title>",
197
+ "body": "<one teachable insight about this codebase>",
198
+ "anchors": [{ "file": "<repo-relative path>", "symbol": "<identifier>", "lines": { "start": N, "end": M } }]
199
+ }
200
+ ],
201
+ "traceCandidates": [
202
+ {
203
+ "id": "<kebab-case-id>",
204
+ "action": "<a 'front door' user action, e.g. 'an HTTP request is served', 'a file is sent'>",
205
+ "description": "<one sentence: where the action enters and what it passes through>",
206
+ "keyFiles": ["<repo-relative file on the action's path, entry point first>", "..."]
207
+ }
208
+ ]
209
+ }
210
+
211
+ Trace candidates — the lab's opening module will follow ONE real user action end to end through the code, and you are proposing the candidates:
212
+ - Propose 2 or 3, each a scenario a real user actually triggers from outside (a request served, a file sent, a command run) — not an internal subroutine.
213
+ - Order them most representative first: the first candidate should be the action whose path exercises the most of this codebase's core.
214
+ - "keyFiles" lists 2-6 files you actually read, in the order the action reaches them, entry point first.
215
+ - Candidates are advisory: a malformed candidate is dropped rather than causing rejection, so keep them simple and real.
216
+
217
+ Hard requirements — the JSON is machine-validated and rejected on any violation:
218
+ - The "title" MUST use the project's REAL name exactly as it appears in the repository — take it verbatim from the "name" field in package.json, the project title in the README, or failing those the repository/directory name — then append " Onboarding Lab". Do NOT invent, guess, abbreviate, translate, rebrand, or otherwise alter the name (for example, never turn "cal.com" into "Cal.diy"). Copy the real name character for character; a wrong project name is a credibility failure on a customer's own repo.
219
+ - Every "id" is kebab-case: lowercase letters, digits, and hyphens, starting with a letter or digit.
220
+ - The system map has at least one node; every edge's "from"/"to" names an existing node id; node ids are unique.
221
+ - Any node with a "description" and any edge with a "label" MUST carry at least one anchor. Bare structural nodes/edges (no description/label) may omit anchors.
222
+ - Every callout MUST carry at least one anchor. Produce 3 to 6 callouts introducing the repo (why it is structured this way, warnings about gotchas, how parts connect).
223
+ - Anchors are mechanically verified against the repository:
224
+ - "file" is a repo-relative path to a file that exists.
225
+ - "lines", if given, is a 1-based inclusive range within the file's real line count.
226
+ - "symbol", if given, appears as a whole token inside the anchored region.
227
+ Only anchor code you actually read. Content whose anchors fail verification is dropped from the lab.
228
+ - Do not include a "fingerprint" field on any anchor.
229
+ - In every prose string (node "description"s, edge "label"s, callout "body"s and "title"s), wrap each code identifier, symbol, type, function, file path, and package name in backticks the moment it appears — e.g. \`ServeHTTP\`, \`caddyhttp.Server\`, \`internal/caddyhttp/server.go\`. The renderer sets backticked spans as inline code.
230
+ - Strings are non-empty. "kind" is exactly one of "why", "warning", "connects-to".`;
231
+ }
232
+ // ---------------------------------------------------------------------------
233
+ /** Turn a directory name into a schema-valid kebab-case lab id. */
234
+ export function slugify(name) {
235
+ const slug = name
236
+ .toLowerCase()
237
+ .replace(/[^a-z0-9]+/g, '-')
238
+ .replace(/^-+|-+$/g, '');
239
+ return slug.length > 0 ? slug : 'generated-lab';
240
+ }
241
+ //# sourceMappingURL=mapStage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapStage.js","sourceRoot":"","sources":["../src/mapStage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { LabSpec } from '@ramplab/spec';
2
+ import { type FlagshipSelection } from './flagship.js';
3
+ import { type GenerateLabConfig } from './generateLab.js';
4
+ import { type MapStageResult } from './mapStage.js';
5
+ import { type GenerationStageName } from './pipeline.js';
6
+ import { type ResolutionReport } from './resolveAnchors.js';
7
+ /**
8
+ * `generateLabPass1(repoDir, config)` — pass 1 of the two-pass runtime
9
+ * (PLAN.md §4): the ~3–5 minute streamed preview, the self-serve "whoa"
10
+ * moment. Map the repo, pick ONE flagship module — the most representative
11
+ * front-door trace action the map proposed, authored as "follow this action
12
+ * end to end through the code"; intake hints can override, and subsystem
13
+ * centrality remains the fallback when the map yields no usable candidates
14
+ * (see `flagship.ts`) — author only that module, and assemble a small valid
15
+ * lab spec: the system-map overview module plus the flagship module.
16
+ *
17
+ * **A separate entry point, not another `generateLab` flag — deliberately.**
18
+ * `generateLab` already multiplexes tracer/full on one result type via
19
+ * optional fields; a third mode would make every field's presence contingent
20
+ * on flag combinations. Pass 1 has its own result shape (flagship selection,
21
+ * timing, a `mapResult` to hand to pass 2) and its own verification
22
+ * semantics, so it gets its own function with non-optional fields. Both
23
+ * entry points share `GenerateLabConfig` (minus the pass-2-only knobs) and
24
+ * all stage plumbing.
25
+ *
26
+ * **Lightly verified (the plan's words):** validation + anchor resolution
27
+ * only — every claim in the preview provably points at real code (unresolved
28
+ * units are dropped/flagged per policy), but the adversarial verifier agent
29
+ * does NOT run. That is pass 2's job; spending verifier calls here would
30
+ * blow the 3–5 minute target for content pass 2 re-authors anyway.
31
+ *
32
+ * **Streaming:** progress surfaces through `config.onProgress` (see
33
+ * `progress.ts`) tagged `pass: 'pass1'` — the callback IS the streaming
34
+ * seam; no network transport in this slice. `spec-updated` fires first with
35
+ * the overview-only spec (renderable the moment the map lands) and again
36
+ * with the final two-module spec.
37
+ *
38
+ * **Timing:** measured with `config.clock` (injected in tests; defaults to
39
+ * `Date.now` on the live path) and reported as `timing` in the result.
40
+ */
41
+ export type GenerateLabPass1Config = Omit<GenerateLabConfig, 'full' | 'budget' | 'concurrency' | 'mapResult'>;
42
+ /** One stage's share of a pass's wall clock (and spend, when reported). */
43
+ export interface StageTiming {
44
+ stage: 'map' | 'author' | 'assemble';
45
+ durationMs: number;
46
+ costUsd?: number;
47
+ }
48
+ export interface Pass1Timing {
49
+ /** `clock()` at entry. */
50
+ startedAtMs: number;
51
+ /** Total wall-clock duration of pass 1 in milliseconds. */
52
+ durationMs: number;
53
+ /**
54
+ * Per-stage split (#31): committed telemetry used to record only the total,
55
+ * so a 40-minute run couldn't say whether the map or the author ate it —
56
+ * the A/B in `evals/results/pass1-timing.md` had to be hand-timed. Now every
57
+ * run is attributable.
58
+ */
59
+ stages: StageTiming[];
60
+ }
61
+ export interface GenerateLabPass1Result {
62
+ /** The validated, anchor-resolved preview spec: overview + flagship. */
63
+ spec: LabSpec;
64
+ /** Anchor-resolution report over the assembled preview spec. */
65
+ resolution: ResolutionReport;
66
+ /** The fully-resolved per-stage model map used for this run. */
67
+ models: Record<GenerationStageName, string>;
68
+ /** Total model cost in USD (map + flagship authoring), when reported. */
69
+ costUsd: number | undefined;
70
+ /** Map-stage attempts (1 = first output was already valid). */
71
+ attempts: number;
72
+ /** Which system-map node became the flagship module, and why. */
73
+ flagship: FlagshipSelection;
74
+ /** Authoring attempts for the flagship module. */
75
+ authorAttempts: Record<string, number>;
76
+ /** Wall-clock timing of the whole pass (PLAN.md's 3–5 minute target). */
77
+ timing: Pass1Timing;
78
+ /**
79
+ * The raw map-stage output. Hand it to pass 2 as `config.mapResult` so the
80
+ * full pipeline skips its map stage instead of re-mapping the repo.
81
+ */
82
+ mapResult: MapStageResult;
83
+ }
84
+ export declare function generateLabPass1(repoDir: string, config?: GenerateLabPass1Config): Promise<GenerateLabPass1Result>;
85
+ //# sourceMappingURL=pass1.d.ts.map