@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
@@ -0,0 +1,216 @@
1
+ import { hasIntakeAnswers } from './intake.js';
2
+ import { LANDING_MODULE_ID, plannedModuleSchema, } from './planStage.js';
3
+ /** Raised when the map offers nothing teachable to author. */
4
+ export class FlagshipSelectionError extends Error {
5
+ constructor(message) {
6
+ super(`Flagship selection failed: ${message}`);
7
+ this.name = 'FlagshipSelectionError';
8
+ }
9
+ }
10
+ export function selectFlagshipModule(mapSpec, intake, traceCandidates) {
11
+ const fromTrace = selectTraceFlagship(traceCandidates, intake);
12
+ if (fromTrace !== undefined)
13
+ return fromTrace;
14
+ return selectCentralityFlagship(mapSpec, intake);
15
+ }
16
+ // ---------------------------------------------------------------------------
17
+ // Trace-based selection (the primary path)
18
+ // ---------------------------------------------------------------------------
19
+ /**
20
+ * Select the flagship trace from the map's candidate actions, or `undefined`
21
+ * when there are no candidates (callers fall back to centrality). Exported
22
+ * separately because pass 2 uses it too: the plan stage pins its module 1 to
23
+ * the same selection pass 1 previewed.
24
+ */
25
+ export function selectTraceFlagship(traceCandidates, intake) {
26
+ if (traceCandidates === undefined || traceCandidates.length === 0)
27
+ return undefined;
28
+ const searchable = traceCandidates.map((candidate) => ({
29
+ candidate,
30
+ searchText: [
31
+ candidate.id,
32
+ candidate.action,
33
+ candidate.description ?? '',
34
+ ...candidate.keyFiles,
35
+ ]
36
+ .join(' ')
37
+ .toLowerCase(),
38
+ }));
39
+ const fromIntake = matchIntakeHints(searchable, intake);
40
+ if (fromIntake !== undefined) {
41
+ return toTraceSelection(fromIntake.matched.candidate, 'trace-intake', intake, fromIntake.hint);
42
+ }
43
+ // Map order is the representativeness ranking (see the map prompt).
44
+ const first = traceCandidates[0];
45
+ return toTraceSelection(first, 'trace', intake);
46
+ }
47
+ /**
48
+ * Ids owned by other parts of the pipeline: the map stage's overview module
49
+ * and the plan stage's mandated landing module. A colliding candidate id is
50
+ * suffixed rather than rejected.
51
+ */
52
+ function traceModuleId(candidateId) {
53
+ return candidateId === 'repo-overview' || candidateId === LANDING_MODULE_ID
54
+ ? `${candidateId}-trace`
55
+ : candidateId;
56
+ }
57
+ function toTraceSelection(candidate, basis, intake, matchedHint) {
58
+ const focusParts = [
59
+ `This module is the lab's opening trace: follow ONE real user action end to ` +
60
+ `end through the code. The action: ${candidate.action}.`,
61
+ ];
62
+ if (candidate.description !== undefined) {
63
+ focusParts.push(candidate.description);
64
+ }
65
+ focusParts.push(`Start at the entry point and walk the exact path the action takes — file by ` +
66
+ `file, layer by layer — teaching each mechanism concretely as the action ` +
67
+ `reaches it, before naming any abstraction it exemplifies.`, `Widget order is part of the pedagogy: the module MUST open with a ` +
68
+ `code-walkthrough stepping through this action's entry point — the learner's ` +
69
+ `first contact is real code being walked, never a diagram. A system-map of ` +
70
+ `the path may appear only after the walkthroughs, as a recap of ground ` +
71
+ `already covered.`, basis === 'trace-intake'
72
+ ? `The onboarding lead's intake singled this area out ("${matchedHint ?? ''}").`
73
+ : `The map stage judged this the most representative front-door action of this codebase.`);
74
+ const intakeLine = renderIntakeFocusLine(intake);
75
+ if (intakeLine !== undefined)
76
+ focusParts.push(intakeLine);
77
+ const plannedModule = plannedModuleSchema.parse({
78
+ id: traceModuleId(candidate.id),
79
+ title: `End to end: ${candidate.action}`,
80
+ focus: focusParts.join(' '),
81
+ keyFiles: candidate.keyFiles,
82
+ assumes: [],
83
+ teaches: [
84
+ `how "${candidate.action}" flows end to end through this codebase`,
85
+ 'the files and layers along that path, and why each exists',
86
+ ],
87
+ });
88
+ return {
89
+ basis,
90
+ traceAction: candidate.action,
91
+ ...(matchedHint !== undefined ? { matchedHint } : {}),
92
+ plannedModule,
93
+ };
94
+ }
95
+ function selectCentralityFlagship(mapSpec, intake) {
96
+ const systemMap = findSystemMap(mapSpec);
97
+ if (systemMap === undefined) {
98
+ throw new FlagshipSelectionError('the map spec contains no system-map widget.');
99
+ }
100
+ const candidates = systemMap.nodes
101
+ .map((node) => toNodeCandidate(node, systemMap.edges))
102
+ .filter((candidate) => candidate.keyFiles.length > 0);
103
+ if (candidates.length === 0) {
104
+ throw new FlagshipSelectionError('no system-map node carries an anchor (directly or via an incident edge), ' +
105
+ 'so there are no key files to author from.');
106
+ }
107
+ const fromIntake = matchIntakeHints(candidates, intake);
108
+ if (fromIntake !== undefined) {
109
+ return toNodeSelection(fromIntake.matched, 'intake', intake, fromIntake.hint);
110
+ }
111
+ let best = candidates[0];
112
+ for (const candidate of candidates) {
113
+ if (candidate.degree > best.degree)
114
+ best = candidate; // ties keep map order
115
+ }
116
+ return toNodeSelection(best, 'centrality', intake);
117
+ }
118
+ function findSystemMap(mapSpec) {
119
+ for (const module of mapSpec.base.modules) {
120
+ for (const widget of module.widgets) {
121
+ if (widget.type === 'system-map')
122
+ return widget;
123
+ }
124
+ }
125
+ return undefined;
126
+ }
127
+ function toNodeCandidate(node, edges) {
128
+ const incident = edges.filter((edge) => edge.from === node.id || edge.to === node.id);
129
+ const keyFiles = [
130
+ ...new Set([...(node.anchors ?? []), ...incident.flatMap((edge) => edge.anchors ?? [])].map((anchor) => anchor.file)),
131
+ ];
132
+ const searchText = [node.id, node.label, node.description ?? '', ...keyFiles]
133
+ .join(' ')
134
+ .toLowerCase();
135
+ return { node, degree: incident.length, keyFiles, searchText };
136
+ }
137
+ /** The map stage owns `repo-overview`; a colliding node id gets suffixed. */
138
+ function flagshipModuleId(nodeId) {
139
+ return nodeId === 'repo-overview' ? 'repo-overview-flagship' : nodeId;
140
+ }
141
+ function toNodeSelection(candidate, basis, intake, matchedHint) {
142
+ const { node, degree, keyFiles } = candidate;
143
+ const focusParts = [
144
+ `Teach "${node.label}" as this repository's flagship subsystem — the single ` +
145
+ `deepest first look a new engineer gets.`,
146
+ ];
147
+ if (node.description !== undefined) {
148
+ focusParts.push(node.description);
149
+ }
150
+ focusParts.push(basis === 'intake'
151
+ ? `The onboarding lead's intake singled this area out ("${matchedHint ?? ''}").`
152
+ : `It was chosen by subsystem centrality: ${degree} edge${degree === 1 ? '' : 's'} ` +
153
+ `of the system map touch it.`);
154
+ const intakeLine = renderIntakeFocusLine(intake);
155
+ if (intakeLine !== undefined)
156
+ focusParts.push(intakeLine);
157
+ const plannedModule = plannedModuleSchema.parse({
158
+ id: flagshipModuleId(node.id),
159
+ title: node.label,
160
+ focus: focusParts.join(' '),
161
+ keyFiles,
162
+ assumes: [],
163
+ teaches: [`how the "${node.label}" subsystem works and its role in the system`],
164
+ });
165
+ return {
166
+ basis,
167
+ nodeId: node.id,
168
+ degree,
169
+ ...(matchedHint !== undefined ? { matchedHint } : {}),
170
+ plannedModule,
171
+ };
172
+ }
173
+ // ---------------------------------------------------------------------------
174
+ // Shared intake-hint matching
175
+ // ---------------------------------------------------------------------------
176
+ /**
177
+ * A hint matches an item when any of its words (4+ characters, so "the"/"a"
178
+ * never match) appears in the item's search text. Hints are scanned in
179
+ * intake priority order; items in map order.
180
+ */
181
+ function matchIntakeHints(items, intake) {
182
+ if (!hasIntakeAnswers(intake))
183
+ return undefined;
184
+ const hints = [...(intake.weekOneMastery ?? []), ...(intake.activeDevelopment ?? [])];
185
+ for (const hint of hints) {
186
+ const words = hint
187
+ .toLowerCase()
188
+ .split(/[^a-z0-9]+/)
189
+ .filter((word) => word.length >= 4);
190
+ if (words.length === 0)
191
+ continue;
192
+ for (const matched of items) {
193
+ if (words.some((word) => matched.searchText.includes(word))) {
194
+ return { matched, hint };
195
+ }
196
+ }
197
+ }
198
+ return undefined;
199
+ }
200
+ /** The intake summary appended to every flagship brief, when present. */
201
+ function renderIntakeFocusLine(intake) {
202
+ if (!hasIntakeAnswers(intake))
203
+ return undefined;
204
+ const inline = [];
205
+ if ((intake.weekOneMastery?.length ?? 0) > 0) {
206
+ inline.push(`week-one hires must master: ${intake.weekOneMastery.join('; ')}`);
207
+ }
208
+ if ((intake.activeDevelopment?.length ?? 0) > 0) {
209
+ inline.push(`under active development: ${intake.activeDevelopment.join('; ')}`);
210
+ }
211
+ if ((intake.gotchas?.length ?? 0) > 0) {
212
+ inline.push(`known gotchas to call out: ${intake.gotchas.join('; ')}`);
213
+ }
214
+ return `Lead intake — ${inline.join('. ')}.`;
215
+ }
216
+ //# sourceMappingURL=flagship.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flagship.js","sourceRoot":"","sources":["../src/flagship.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,aAAa,CAAC;AAEhE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,gBAAgB,CAAC;AAkDxB,8DAA8D;AAC9D,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB,CAClC,OAAgB,EAChB,MAAmB,EACnB,eAA2C;IAE3C,MAAM,SAAS,GAAG,mBAAmB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAC/D,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,eAAsD,EACtD,MAAmB;IAEnB,IAAI,eAAe,KAAK,SAAS,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEpF,MAAM,UAAU,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACrD,SAAS;QACT,UAAU,EAAE;YACV,SAAS,CAAC,EAAE;YACZ,SAAS,CAAC,MAAM;YAChB,SAAS,CAAC,WAAW,IAAI,EAAE;YAC3B,GAAG,SAAS,CAAC,QAAQ;SACtB;aACE,IAAI,CAAC,GAAG,CAAC;aACT,WAAW,EAAE;KACjB,CAAC,CAAC,CAAC;IAEJ,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACxD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACjG,CAAC;IACD,oEAAoE;IACpE,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAmB,CAAC;IACnD,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,WAAmB;IACxC,OAAO,WAAW,KAAK,eAAe,IAAI,WAAW,KAAK,iBAAiB;QACzE,CAAC,CAAC,GAAG,WAAW,QAAQ;QACxB,CAAC,CAAC,WAAW,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CACvB,SAAyB,EACzB,KAA+B,EAC/B,MAA8B,EAC9B,WAAoB;IAEpB,MAAM,UAAU,GAAa;QAC3B,6EAA6E;YAC3E,qCAAqC,SAAS,CAAC,MAAM,GAAG;KAC3D,CAAC;IACF,IAAI,SAAS,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACxC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC;IACD,UAAU,CAAC,IAAI,CACb,8EAA8E;QAC5E,0EAA0E;QAC1E,2DAA2D,EAC7D,oEAAoE;QAClE,8EAA8E;QAC9E,4EAA4E;QAC5E,wEAAwE;QACxE,kBAAkB,EACpB,KAAK,KAAK,cAAc;QACtB,CAAC,CAAC,wDAAwD,WAAW,IAAI,EAAE,KAAK;QAChF,CAAC,CAAC,uFAAuF,CAC5F,CAAC;IACF,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,SAAS;QAAE,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE1D,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC;QAC9C,EAAE,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,KAAK,EAAE,eAAe,SAAS,CAAC,MAAM,EAAE;QACxC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3B,QAAQ,EAAE,SAAS,CAAC,QAAQ;QAC5B,OAAO,EAAE,EAAE;QACX,OAAO,EAAE;YACP,QAAQ,SAAS,CAAC,MAAM,0CAA0C;YAClE,2DAA2D;SAC5D;KACF,CAAC,CAAC;IACH,OAAO;QACL,KAAK;QACL,WAAW,EAAE,SAAS,CAAC,MAAM;QAC7B,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,aAAa;KACd,CAAC;AACJ,CAAC;AAeD,SAAS,wBAAwB,CAC/B,OAAgB,EAChB,MAAmB;IAEnB,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,sBAAsB,CAAC,6CAA6C,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK;SAC/B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;SACrD,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,sBAAsB,CAC9B,2EAA2E;YACzE,2CAA2C,CAC9C,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACxD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,eAAe,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,IAAI,GAAG,UAAU,CAAC,CAAC,CAAkB,CAAC;IAC1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;YAAE,IAAI,GAAG,SAAS,CAAC,CAAC,sBAAsB;IAC9E,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB;IACrC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC1C,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY;gBAAE,OAAO,MAAM,CAAC;QAClD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,IAAmB,EAAE,KAA+B;IAC3E,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAG;QACf,GAAG,IAAI,GAAG,CACR,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAC9E,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CACxB,CACF;KACF,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE,EAAE,GAAG,QAAQ,CAAC;SAC1E,IAAI,CAAC,GAAG,CAAC;SACT,WAAW,EAAE,CAAC;IACjB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AACjE,CAAC;AAED,6EAA6E;AAC7E,SAAS,gBAAgB,CAAC,MAAc;IACtC,OAAO,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,MAAM,CAAC;AACxE,CAAC;AAED,SAAS,eAAe,CACtB,SAAwB,EACxB,KAA8B,EAC9B,MAA8B,EAC9B,WAAoB;IAEpB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAE7C,MAAM,UAAU,GAAa;QAC3B,UAAU,IAAI,CAAC,KAAK,yDAAyD;YAC3E,yCAAyC;KAC5C,CAAC;IACF,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IACD,UAAU,CAAC,IAAI,CACb,KAAK,KAAK,QAAQ;QAChB,CAAC,CAAC,wDAAwD,WAAW,IAAI,EAAE,KAAK;QAChF,CAAC,CAAC,0CAA0C,MAAM,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;YAChF,6BAA6B,CACpC,CAAC;IACF,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,SAAS;QAAE,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE1D,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC;QAC9C,EAAE,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3B,QAAQ;QACR,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,CAAC,YAAY,IAAI,CAAC,KAAK,8CAA8C,CAAC;KAChF,CAAC,CAAC;IACH,OAAO;QACL,KAAK;QACL,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,MAAM;QACN,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,aAAa;KACd,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,8BAA8B;AAC9B,8EAA8E;AAE9E;;;;GAIG;AACH,SAAS,gBAAgB,CACvB,KAAmB,EACnB,MAA8B;IAE9B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;IACtF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI;aACf,WAAW,EAAE;aACb,KAAK,CAAC,YAAY,CAAC;aACnB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yEAAyE;AACzE,SAAS,qBAAqB,CAAC,MAA8B;IAC3D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,cAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,iBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,OAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,151 @@
1
+ import type { LabSpec } from '@ramplab/spec';
2
+ import type { LeadIntake } from './intake.js';
3
+ import { type MapStageResult } from './mapStage.js';
4
+ import { type GenerationStageName, type ModelRunner, type StageModelConfig } from './pipeline.js';
5
+ import { type CurriculumBudget, type CurriculumPlan, type PlannedModule } from './planStage.js';
6
+ import type { ProgressCallback } from './progress.js';
7
+ import { type ResolutionPolicy, type ResolutionReport } from './resolveAnchors.js';
8
+ import { type VerificationReport } from './verifyStage.js';
9
+ /**
10
+ * `generateLab(repoDir, config)` — the generator entry point (PLAN.md §4).
11
+ *
12
+ * Two modes on the same config/runner plumbing:
13
+ *
14
+ * - **Tracer (default, `full` unset/false):** the map stage only — agent
15
+ * explores the repo (read-only), emits a system-map widget plus one module
16
+ * of anchored callouts. Predates the two-pass runtime; for the streamed
17
+ * pass-1 preview (map + flagship module) use `generateLabPass1` in
18
+ * `pass1.ts`. The tracer emits no progress events.
19
+ * - **Full pipeline (`full: true`) — pass 2 of the two-pass runtime:**
20
+ * map → curriculum plan → author (parallel per planned module,
21
+ * concurrency-capped) → assemble → verify. The plan stage plans a
22
+ * dependency-ordered journey (issue #18) within `config.budget` (a config
23
+ * cap, never repo size), steered by the lead's `config.intake` answers
24
+ * when present: module 1 is pinned to the flagship trace when the map
25
+ * proposed candidates, every module carries an `assumes`/`teaches`
26
+ * learner-state ledger, and the final module is always "your first
27
+ * contribution". Each planned module is authored by its own agent call
28
+ * (with its ledger slice and the style contract in the prompt); assembly
29
+ * merges everything into one spec, revalidates, and runs anchor resolution
30
+ * per policy; the verify stage then adversarially checks every surviving
31
+ * claim against its anchored code and drops what it cannot verify
32
+ * (PLAN.md §3).
33
+ *
34
+ * **Map reuse (`config.mapResult`):** pass 2 normally runs right after pass 1
35
+ * on the same repo snapshot, so callers hand pass 1's `mapResult` in and the
36
+ * map stage is skipped entirely — no second map agent call. The reused map's
37
+ * cost is NOT re-counted in this run's `costUsd` (it was paid in pass 1).
38
+ * The pass-1 **flagship module is deliberately re-authored, not reused**:
39
+ * the plan stage owns pass 2's curriculum (ids, ordering, briefs), and
40
+ * splicing a module authored against pass 1's ad-hoc brief into it would
41
+ * make the draft's shape depend on which pass wrote which module. Pass 1 is
42
+ * a preview; pass 2 is the canonical draft.
43
+ *
44
+ * **Progress (`config.onProgress`):** full-pipeline runs emit typed events
45
+ * (see `progress.ts`) tagged `pass: 'pass2'` — stage boundaries,
46
+ * per-module authoring, and `spec-updated` snapshots that are always valid
47
+ * and anchor-resolved, so a caller can render each one as it lands.
48
+ *
49
+ * Zero infra assumptions: the input is a plain local directory. No cloning,
50
+ * no network beyond the model API (and none at all with an injected fake
51
+ * runner).
52
+ */
53
+ export interface GenerateLabConfig {
54
+ /**
55
+ * Run the full pipeline (map → plan → author → assemble → verify) instead
56
+ * of the map-only tracer.
57
+ * @default false
58
+ */
59
+ full?: boolean;
60
+ /**
61
+ * Per-stage model map. Every stage defaults to `claude-sonnet-5`;
62
+ * overrides are honored per stage (PLAN.md §10).
63
+ */
64
+ models?: StageModelConfig;
65
+ /**
66
+ * Curriculum budget for the plan stage (full pipeline only): max module
67
+ * count and scope hints. Caps lab scope by config, not repo size.
68
+ */
69
+ budget?: CurriculumBudget;
70
+ /**
71
+ * The lead's 2-minute intake (PLAN.md §4 curation loop). Threaded into the
72
+ * curriculum-plan prompt so the answers steer module selection/ordering,
73
+ * and into pass 1's flagship choice (see `flagship.ts`).
74
+ */
75
+ intake?: LeadIntake;
76
+ /**
77
+ * Progress-event callback — the streaming seam (see `progress.ts`).
78
+ * Full-pipeline runs emit `pass: 'pass2'` events; the tracer emits none.
79
+ */
80
+ onProgress?: ProgressCallback;
81
+ /**
82
+ * A previous map-stage result (typically pass 1's `result.mapResult`).
83
+ * When present, the map stage is skipped and this output is used verbatim;
84
+ * its cost is not re-counted. Full pipeline only.
85
+ */
86
+ mapResult?: MapStageResult;
87
+ /**
88
+ * Millisecond clock for timing measurements, injectable for tests.
89
+ * Only the live path should rely on the `Date.now` default.
90
+ * @default Date.now
91
+ */
92
+ clock?: () => number;
93
+ /**
94
+ * Max authoring agents in flight at once (full pipeline only).
95
+ * @default 4
96
+ */
97
+ concurrency?: number;
98
+ /**
99
+ * What to do with teachable units whose anchors fail to resolve:
100
+ * `drop` (default) removes them; `flag` keeps them and only reports.
101
+ */
102
+ resolutionPolicy?: ResolutionPolicy;
103
+ /**
104
+ * The agent-invocation boundary. Defaults to the real Claude Agent SDK
105
+ * runner; tests inject a fake so CI never makes live API calls.
106
+ */
107
+ runner?: ModelRunner;
108
+ /**
109
+ * Bounded retries per stage (and per authored module) when the model's
110
+ * output is schema-invalid.
111
+ * @default 1
112
+ */
113
+ maxRetries?: number;
114
+ /** Lab id override; defaults to a slug of the repo directory name. */
115
+ labId?: string;
116
+ }
117
+ export interface GenerateLabResult {
118
+ /** The validated, anchor-resolved lab spec. */
119
+ spec: LabSpec;
120
+ /** Full anchor-resolution report (what resolved, dropped, or flagged). */
121
+ resolution: ResolutionReport;
122
+ /** The fully-resolved per-stage model map used for this run. */
123
+ models: Record<GenerationStageName, string>;
124
+ /** Total model cost in USD across all stages, when the runner reports cost. */
125
+ costUsd: number | undefined;
126
+ /** Map-stage attempts (1 = first output was already valid). */
127
+ attempts: number;
128
+ /** The curriculum plan, present only on full-pipeline runs. */
129
+ plan?: CurriculumPlan;
130
+ /** Per-module authoring attempts, present only on full-pipeline runs. */
131
+ authorAttempts?: Record<string, number>;
132
+ /**
133
+ * Adversarial verification report (per-claim verdicts, pass rate, drops),
134
+ * present only on full-pipeline runs.
135
+ */
136
+ verification?: VerificationReport;
137
+ /** Per-module verifier attempts, present only on full-pipeline runs. */
138
+ verifyAttempts?: Record<string, number>;
139
+ }
140
+ export declare function generateLab(repoDir: string, config?: GenerateLabConfig): Promise<GenerateLabResult>;
141
+ /** The map stage's zoom-out chapter — a stable id learner progress keys off. */
142
+ export declare const OVERVIEW_MODULE_ID = "repo-overview";
143
+ /**
144
+ * Build the planned-module brief for the zoom-out chapter: what the reader
145
+ * already walked (the flagship trace's `teaches`), and what this chapter owes
146
+ * them. Exported for tests — the brief IS the fix, so it is worth pinning.
147
+ */
148
+ export declare function plannedOverviewModule(mapSpec: LabSpec, plan: CurriculumPlan): PlannedModule | undefined;
149
+ export declare function sumCosts(...costs: (number | undefined)[]): number | undefined;
150
+ export declare function assertDirectory(repoDir: string): void;
151
+ //# sourceMappingURL=generateLab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateLab.d.ts","sourceRoot":"","sources":["../src/generateLab.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAK7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAC5C,+EAA+E;IAC/E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,iBAAsB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAsM5B;AAED,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAkBlD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,cAAc,GACnB,aAAa,GAAG,SAAS,CAkC3B;AAyDD,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,GAAG,SAAS,CAQ7E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAUrD"}