@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.
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/agentSdkRunner.d.ts +64 -0
- package/dist/agentSdkRunner.d.ts.map +1 -0
- package/dist/agentSdkRunner.js +158 -0
- package/dist/agentSdkRunner.js.map +1 -0
- package/dist/assembleStage.d.ts +41 -0
- package/dist/assembleStage.d.ts.map +1 -0
- package/dist/assembleStage.js +33 -0
- package/dist/assembleStage.js.map +1 -0
- package/dist/authorStage.d.ts +123 -0
- package/dist/authorStage.d.ts.map +1 -0
- package/dist/authorStage.js +284 -0
- package/dist/authorStage.js.map +1 -0
- package/dist/cloneRepo.d.ts +72 -0
- package/dist/cloneRepo.d.ts.map +1 -0
- package/dist/cloneRepo.js +104 -0
- package/dist/cloneRepo.js.map +1 -0
- package/dist/flagship.d.ts +62 -0
- package/dist/flagship.d.ts.map +1 -0
- package/dist/flagship.js +216 -0
- package/dist/flagship.js.map +1 -0
- package/dist/generateLab.d.ts +151 -0
- package/dist/generateLab.d.ts.map +1 -0
- package/dist/generateLab.js +291 -0
- package/dist/generateLab.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/intake.d.ts +31 -0
- package/dist/intake.d.ts.map +1 -0
- package/dist/intake.js +45 -0
- package/dist/intake.js.map +1 -0
- package/dist/live.d.ts +2 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +213 -0
- package/dist/live.js.map +1 -0
- package/dist/mapStage.d.ts +84 -0
- package/dist/mapStage.d.ts.map +1 -0
- package/dist/mapStage.js +241 -0
- package/dist/mapStage.js.map +1 -0
- package/dist/pass1.d.ts +85 -0
- package/dist/pass1.d.ts.map +1 -0
- package/dist/pass1.js +81 -0
- package/dist/pass1.js.map +1 -0
- package/dist/pipeline.d.ts +73 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +70 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/planStage.d.ts +141 -0
- package/dist/planStage.d.ts.map +1 -0
- package/dist/planStage.js +275 -0
- package/dist/planStage.js.map +1 -0
- package/dist/progress.d.ts +45 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +2 -0
- package/dist/progress.js.map +1 -0
- package/dist/repoCommit.d.ts +41 -0
- package/dist/repoCommit.d.ts.map +1 -0
- package/dist/repoCommit.js +84 -0
- package/dist/repoCommit.js.map +1 -0
- package/dist/repoSize.d.ts +23 -0
- package/dist/repoSize.d.ts.map +1 -0
- package/dist/repoSize.js +74 -0
- package/dist/repoSize.js.map +1 -0
- package/dist/resolveAnchors.d.ts +142 -0
- package/dist/resolveAnchors.d.ts.map +1 -0
- package/dist/resolveAnchors.js +242 -0
- package/dist/resolveAnchors.js.map +1 -0
- package/dist/verifyStage.d.ts +150 -0
- package/dist/verifyStage.d.ts.map +1 -0
- package/dist/verifyStage.js +461 -0
- package/dist/verifyStage.js.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RampLab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @ramplab/generator
|
|
2
|
+
|
|
3
|
+
The RampLab pipeline: it reads a repository, writes an edition of it, and
|
|
4
|
+
mechanically resolves every code anchor against the source so nothing
|
|
5
|
+
unverifiable survives.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @ramplab/generator
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Most people want [`@ramplab/cli`](https://www.npmjs.com/package/@ramplab/cli)
|
|
12
|
+
instead, which wraps this with a command line, credential handling and
|
|
13
|
+
progress reporting. Use this directly if you are embedding the press in
|
|
14
|
+
something of your own.
|
|
15
|
+
|
|
16
|
+
`resolveAnchors(spec, repoDir)` is the part worth knowing about even if you
|
|
17
|
+
never press anything: it is pure over (spec, repository directory), checks that
|
|
18
|
+
every anchored file, line range and symbol really exists, and fingerprints the
|
|
19
|
+
region it resolved. Grounding is enforced structurally rather than promised.
|
|
20
|
+
|
|
21
|
+
## Licence
|
|
22
|
+
|
|
23
|
+
MIT. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ModelRunner } from './pipeline.js';
|
|
2
|
+
/**
|
|
3
|
+
* Which credential a live run will spend (founder, 2026-07-25). Populating
|
|
4
|
+
* the library used to mean an API key and a metered bill — around $17-21 a
|
|
5
|
+
* pressing at recent Caddy sizes. The SDK's CLI will just as happily use the
|
|
6
|
+
* Claude Code login, which spends session allowance instead of API credit, so
|
|
7
|
+
* both are allowed and the run says out loud which one it took.
|
|
8
|
+
*/
|
|
9
|
+
export type AuthMode = 'api-key' | 'claude-code';
|
|
10
|
+
export interface AuthDescription {
|
|
11
|
+
mode: AuthMode;
|
|
12
|
+
/** One line for the run banner. */
|
|
13
|
+
label: string;
|
|
14
|
+
/**
|
|
15
|
+
* True when the run bills the Anthropic API account — i.e. when a reported
|
|
16
|
+
* `costUsd` is real money. False on the Claude Code credential, where the
|
|
17
|
+
* SDK's cost figure is a token-priced estimate nobody is invoiced for.
|
|
18
|
+
*/
|
|
19
|
+
billedToApiAccount: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Report the credential the SDK will resolve, without spending anything. A
|
|
23
|
+
* non-empty `ANTHROPIC_API_KEY` wins because that is the CLI's own precedence;
|
|
24
|
+
* everything else falls through to the Claude Code login (which may still not
|
|
25
|
+
* exist — that surfaces as an SDK auth error on the first stage, not here).
|
|
26
|
+
*/
|
|
27
|
+
export declare function describeAuth(env?: NodeJS.ProcessEnv): AuthDescription;
|
|
28
|
+
export interface AgentSdkRunnerOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Cap on agentic turns per stage call — a cost guard, not a tuning knob.
|
|
31
|
+
* @default 50
|
|
32
|
+
*/
|
|
33
|
+
maxTurns?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Abort a stage that has gone completely silent for this long. A working
|
|
36
|
+
* session streams messages continuously; one that stops yielding has
|
|
37
|
+
* stalled on a network read and will never resume on its own.
|
|
38
|
+
* @default 15 minutes
|
|
39
|
+
*/
|
|
40
|
+
stallTimeoutMs?: number;
|
|
41
|
+
}
|
|
42
|
+
/** 15 minutes: far longer than a healthy turn, far shorter than a hang. */
|
|
43
|
+
export declare const DEFAULT_STALL_TIMEOUT_MS: number;
|
|
44
|
+
export interface StallWatchdog {
|
|
45
|
+
/** (Re)start the countdown — call on every sign of life. */
|
|
46
|
+
arm(): void;
|
|
47
|
+
/** Stop the countdown for good. */
|
|
48
|
+
disarm(): void;
|
|
49
|
+
/** True once the countdown expired and `onStall` fired. */
|
|
50
|
+
get stalled(): boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A dead-man's switch for a streaming session (founder, 2026-07-26).
|
|
54
|
+
*
|
|
55
|
+
* A Caddy eval sat in pass-1 authoring for 5h24m having burned 16 seconds of
|
|
56
|
+
* CPU: the SDK session stopped yielding and `for await` waited forever, with
|
|
57
|
+
* `maxTurns` no help because a turn cap is not a clock. Nothing downstream
|
|
58
|
+
* had a wall-clock guard either, so the whole run hung until it was killed by
|
|
59
|
+
* hand. This watchdog is the missing clock — idle-based rather than total, so
|
|
60
|
+
* a legitimately long stage is never cut off, only a silent one.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createStallWatchdog(timeoutMs: number, onStall: () => void): StallWatchdog;
|
|
63
|
+
export declare function createAgentSdkRunner(options?: AgentSdkRunnerOptions): ModelRunner;
|
|
64
|
+
//# sourceMappingURL=agentSdkRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentSdkRunner.d.ts","sourceRoot":"","sources":["../src/agentSdkRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,eAAe,CAAC;AAgC9E;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,CAgBlF;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,QAAiB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,GAAG,IAAI,IAAI,CAAC;IACZ,mCAAmC;IACnC,MAAM,IAAI,IAAI,CAAC;IACf,2DAA2D;IAC3D,IAAI,OAAO,IAAI,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,aAAa,CAsBzF;AAWD,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,WAAW,CAqFrF"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The live `ModelRunner`: runs a stage as a Claude Agent SDK session over
|
|
3
|
+
* the repository directory with read-only tools.
|
|
4
|
+
*
|
|
5
|
+
* CI never touches this module's runtime path — tests inject fakes at the
|
|
6
|
+
* `ModelRunner` seam — so the SDK import is lazy: `@ramplab/generator` can
|
|
7
|
+
* be loaded (and everything else tested) without the SDK spawning anything.
|
|
8
|
+
*
|
|
9
|
+
* Auth: the SDK spawns the Claude Code CLI, which resolves credentials the
|
|
10
|
+
* way Claude Code itself does — `ANTHROPIC_API_KEY` first, then
|
|
11
|
+
* `CLAUDE_CODE_OAUTH_TOKEN`, then the stored Claude Code login. Both paths
|
|
12
|
+
* generate identical labs; they differ in who pays. See {@link describeAuth},
|
|
13
|
+
* which the live entry points print so a run always says which one it is on.
|
|
14
|
+
*/
|
|
15
|
+
/** The agent may look, not touch: exploration tools only. */
|
|
16
|
+
const READ_ONLY_TOOLS = ['Read', 'Glob', 'Grep'];
|
|
17
|
+
/** Everything with side effects or network reach is denied outright. */
|
|
18
|
+
const DENIED_TOOLS = [
|
|
19
|
+
'Bash',
|
|
20
|
+
'Write',
|
|
21
|
+
'Edit',
|
|
22
|
+
'NotebookEdit',
|
|
23
|
+
'WebFetch',
|
|
24
|
+
'WebSearch',
|
|
25
|
+
'Task',
|
|
26
|
+
'TodoWrite',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Report the credential the SDK will resolve, without spending anything. A
|
|
30
|
+
* non-empty `ANTHROPIC_API_KEY` wins because that is the CLI's own precedence;
|
|
31
|
+
* everything else falls through to the Claude Code login (which may still not
|
|
32
|
+
* exist — that surfaces as an SDK auth error on the first stage, not here).
|
|
33
|
+
*/
|
|
34
|
+
export function describeAuth(env = process.env) {
|
|
35
|
+
const apiKey = env['ANTHROPIC_API_KEY'];
|
|
36
|
+
if (apiKey !== undefined && apiKey.length > 0) {
|
|
37
|
+
return {
|
|
38
|
+
mode: 'api-key',
|
|
39
|
+
label: 'ANTHROPIC_API_KEY — billed to the Anthropic API account',
|
|
40
|
+
billedToApiAccount: true,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
mode: 'claude-code',
|
|
45
|
+
label: 'Claude Code credential (no ANTHROPIC_API_KEY set) — spends session ' +
|
|
46
|
+
'allowance, not API credit; reported costs are estimates, not charges',
|
|
47
|
+
billedToApiAccount: false,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** 15 minutes: far longer than a healthy turn, far shorter than a hang. */
|
|
51
|
+
export const DEFAULT_STALL_TIMEOUT_MS = 15 * 60 * 1000;
|
|
52
|
+
/**
|
|
53
|
+
* A dead-man's switch for a streaming session (founder, 2026-07-26).
|
|
54
|
+
*
|
|
55
|
+
* A Caddy eval sat in pass-1 authoring for 5h24m having burned 16 seconds of
|
|
56
|
+
* CPU: the SDK session stopped yielding and `for await` waited forever, with
|
|
57
|
+
* `maxTurns` no help because a turn cap is not a clock. Nothing downstream
|
|
58
|
+
* had a wall-clock guard either, so the whole run hung until it was killed by
|
|
59
|
+
* hand. This watchdog is the missing clock — idle-based rather than total, so
|
|
60
|
+
* a legitimately long stage is never cut off, only a silent one.
|
|
61
|
+
*/
|
|
62
|
+
export function createStallWatchdog(timeoutMs, onStall) {
|
|
63
|
+
let timer;
|
|
64
|
+
let stalled = false;
|
|
65
|
+
return {
|
|
66
|
+
arm() {
|
|
67
|
+
if (stalled)
|
|
68
|
+
return;
|
|
69
|
+
if (timer !== undefined)
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
timer = setTimeout(() => {
|
|
72
|
+
stalled = true;
|
|
73
|
+
onStall();
|
|
74
|
+
}, timeoutMs);
|
|
75
|
+
// Never hold the process open on the watchdog's account.
|
|
76
|
+
timer.unref?.();
|
|
77
|
+
},
|
|
78
|
+
disarm() {
|
|
79
|
+
if (timer !== undefined)
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
timer = undefined;
|
|
82
|
+
},
|
|
83
|
+
get stalled() {
|
|
84
|
+
return stalled;
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export function createAgentSdkRunner(options = {}) {
|
|
89
|
+
const maxTurns = options.maxTurns ?? 50;
|
|
90
|
+
const stallTimeoutMs = options.stallTimeoutMs ?? DEFAULT_STALL_TIMEOUT_MS;
|
|
91
|
+
return {
|
|
92
|
+
async runStage(request) {
|
|
93
|
+
const { query } = await import('@anthropic-ai/claude-agent-sdk');
|
|
94
|
+
// The CLI's dying words. A bare "exited with code 1" cost a day of
|
|
95
|
+
// guessing (2026-07-13); keep the tail and attach it to any failure.
|
|
96
|
+
let stderrTail = '';
|
|
97
|
+
const withStderr = (message) => stderrTail.length > 0 ? `${message}\nCLI stderr (tail):\n${stderrTail.trim()}` : message;
|
|
98
|
+
const abortController = new AbortController();
|
|
99
|
+
const watchdog = createStallWatchdog(stallTimeoutMs, () => abortController.abort());
|
|
100
|
+
const session = query({
|
|
101
|
+
prompt: request.prompt,
|
|
102
|
+
options: {
|
|
103
|
+
model: request.model,
|
|
104
|
+
cwd: request.repoDir,
|
|
105
|
+
allowedTools: READ_ONLY_TOOLS,
|
|
106
|
+
disallowedTools: DENIED_TOOLS,
|
|
107
|
+
permissionMode: 'bypassPermissions',
|
|
108
|
+
// Zero infra assumptions: never load user/project settings.
|
|
109
|
+
settingSources: [],
|
|
110
|
+
maxTurns,
|
|
111
|
+
abortController,
|
|
112
|
+
stderr: (data) => {
|
|
113
|
+
stderrTail = `${stderrTail}${data}`.slice(-2000);
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
const stalledError = () => new Error(withStderr(`Agent SDK session for stage "${request.stage}" produced no output for ` +
|
|
118
|
+
`${Math.round(stallTimeoutMs / 60000)} minute(s) and was aborted. The ` +
|
|
119
|
+
`session had stalled, not slowed: raise stallTimeoutMs only if a healthy ` +
|
|
120
|
+
`stage genuinely goes silent that long.`));
|
|
121
|
+
let result;
|
|
122
|
+
try {
|
|
123
|
+
watchdog.arm();
|
|
124
|
+
for await (const message of session) {
|
|
125
|
+
watchdog.arm(); // any message is a sign of life
|
|
126
|
+
const candidate = message;
|
|
127
|
+
if (candidate.type === 'result') {
|
|
128
|
+
result = candidate;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (cause) {
|
|
133
|
+
// An abort we caused reads as a generic cancellation; say what it was.
|
|
134
|
+
if (watchdog.stalled)
|
|
135
|
+
throw stalledError();
|
|
136
|
+
throw new Error(withStderr(cause.message), { cause });
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
watchdog.disarm();
|
|
140
|
+
}
|
|
141
|
+
// A stall can also surface as a clean end-of-iteration after the abort.
|
|
142
|
+
if (watchdog.stalled)
|
|
143
|
+
throw stalledError();
|
|
144
|
+
if (result === undefined) {
|
|
145
|
+
throw new Error(withStderr(`Agent SDK session for stage "${request.stage}" ended without a result message.`));
|
|
146
|
+
}
|
|
147
|
+
if (result.is_error === true || result.subtype !== 'success') {
|
|
148
|
+
throw new Error(withStderr(`Agent SDK session for stage "${request.stage}" failed` +
|
|
149
|
+
`${result.subtype !== undefined ? ` (${result.subtype})` : ''}.`));
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
output: result.result ?? '',
|
|
153
|
+
...(result.total_cost_usd !== undefined ? { costUsd: result.total_cost_usd } : {}),
|
|
154
|
+
};
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=agentSdkRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentSdkRunner.js","sourceRoot":"","sources":["../src/agentSdkRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type LabModule, type LabSpec } from '@ramplab/spec';
|
|
2
|
+
import { type ResolutionPolicy, type ResolutionReport } from './resolveAnchors.js';
|
|
3
|
+
/**
|
|
4
|
+
* The assemble stage (PLAN.md §4): merge the map stage's overview module and
|
|
5
|
+
* the authored modules — in plan order — into one lab spec, revalidate the
|
|
6
|
+
* whole thing against `@ramplab/spec`, and run anchor resolution per policy.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately **mechanical**: no model call. Every creative decision was
|
|
9
|
+
* made upstream (map named the lab, plan ordered the modules, authors wrote
|
|
10
|
+
* the content); assembly only merges, validates, and grounds. Module ids are
|
|
11
|
+
* already stable — `repo-overview` from the map stage, plan ids for authored
|
|
12
|
+
* modules — so overlay entries and learner progress survive regeneration.
|
|
13
|
+
*/
|
|
14
|
+
export interface AssembleOptions {
|
|
15
|
+
/** @default 'drop' */
|
|
16
|
+
policy?: ResolutionPolicy;
|
|
17
|
+
/**
|
|
18
|
+
* Id of the authored module that opens the lab (issue #18, iteration 2):
|
|
19
|
+
* concrete-before-abstract applies to the curriculum too, so the flagship
|
|
20
|
+
* trace goes first and the map's overview module follows as the zoom-out.
|
|
21
|
+
* Undefined or unmatched keeps the map's modules first.
|
|
22
|
+
*/
|
|
23
|
+
leadModuleId?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface AssembleResult {
|
|
26
|
+
/** The merged, validated, anchor-resolved lab spec. */
|
|
27
|
+
spec: LabSpec;
|
|
28
|
+
/** Full anchor-resolution report over the merged spec. */
|
|
29
|
+
report: ResolutionReport;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Merge `authoredModules` (already in plan order) with the map spec's own
|
|
33
|
+
* modules and revalidate. The module named by `leadModuleId` — the flagship
|
|
34
|
+
* trace — is pulled to the front so the learner meets walked code before the
|
|
35
|
+
* map's architectural overview; the remaining authored modules keep plan
|
|
36
|
+
* order after it. Throws `LabSpecParseError` if the merge violates the spec
|
|
37
|
+
* schema — e.g. a duplicate module id, which upstream stages are built to
|
|
38
|
+
* prevent.
|
|
39
|
+
*/
|
|
40
|
+
export declare function assembleLab(mapSpec: LabSpec, authoredModules: readonly LabModule[], repoDir: string, options?: AssembleOptions): AssembleResult;
|
|
41
|
+
//# sourceMappingURL=assembleStage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assembleStage.d.ts","sourceRoot":"","sources":["../src/assembleStage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,IAAI,EAAE,OAAO,CAAC;IACd,0DAA0D;IAC1D,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,SAAS,SAAS,EAAE,EACrC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,eAAoB,GAC5B,cAAc,CAsBhB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { parseLabSpec } from '@ramplab/spec';
|
|
2
|
+
import { resolveAnchors, } from './resolveAnchors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Merge `authoredModules` (already in plan order) with the map spec's own
|
|
5
|
+
* modules and revalidate. The module named by `leadModuleId` — the flagship
|
|
6
|
+
* trace — is pulled to the front so the learner meets walked code before the
|
|
7
|
+
* map's architectural overview; the remaining authored modules keep plan
|
|
8
|
+
* order after it. Throws `LabSpecParseError` if the merge violates the spec
|
|
9
|
+
* schema — e.g. a duplicate module id, which upstream stages are built to
|
|
10
|
+
* prevent.
|
|
11
|
+
*/
|
|
12
|
+
export function assembleLab(mapSpec, authoredModules, repoDir, options = {}) {
|
|
13
|
+
const lead = authoredModules.filter((m) => m.id === options.leadModuleId);
|
|
14
|
+
const rest = authoredModules.filter((m) => m.id !== options.leadModuleId);
|
|
15
|
+
const candidate = {
|
|
16
|
+
schemaVersion: mapSpec.schemaVersion,
|
|
17
|
+
id: mapSpec.id,
|
|
18
|
+
title: mapSpec.title,
|
|
19
|
+
...(mapSpec.repo !== undefined ? { repo: mapSpec.repo } : {}),
|
|
20
|
+
base: {
|
|
21
|
+
modules: [...lead, ...mapSpec.base.modules, ...rest],
|
|
22
|
+
},
|
|
23
|
+
overlay: mapSpec.overlay,
|
|
24
|
+
};
|
|
25
|
+
// Single validation path: a JSON round-trip plus parseLabSpec guarantees
|
|
26
|
+
// the merged spec is exactly what a consumer would load from disk.
|
|
27
|
+
const merged = parseLabSpec(JSON.parse(JSON.stringify(candidate)));
|
|
28
|
+
const { spec, report } = resolveAnchors(merged, repoDir, {
|
|
29
|
+
policy: options.policy ?? 'drop',
|
|
30
|
+
});
|
|
31
|
+
return { spec, report };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=assembleStage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assembleStage.js","sourceRoot":"","sources":["../src/assembleStage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgC,MAAM,eAAe,CAAC;AAC3E,OAAO,EACL,cAAc,GAGf,MAAM,qBAAqB,CAAC;AAiC7B;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CACzB,OAAgB,EAChB,eAAqC,EACrC,OAAe,EACf,UAA2B,EAAE;IAE7B,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG;QAChB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,IAAI,EAAE;YACJ,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;SACrD;QACD,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;IAEF,yEAAyE;IACzE,mEAAmE;IACnE,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAEnE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE;QACvD,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,MAAM;KACjC,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { type LabModule } from '@ramplab/spec';
|
|
2
|
+
import { type ModelRunner } from './pipeline.js';
|
|
3
|
+
import type { CurriculumPlan, PlannedModule } from './planStage.js';
|
|
4
|
+
/**
|
|
5
|
+
* The author stage (PLAN.md §4, pass 2): fan out one authoring agent per
|
|
6
|
+
* planned module, in parallel under a small concurrency cap. Each agent
|
|
7
|
+
* writes a full module — a mix of anchored widgets (callouts, code
|
|
8
|
+
* walkthroughs, code figures, diagrams, and a closing quiz) — validated
|
|
9
|
+
* against `@ramplab/spec`'s module schema with the same bounded retry the
|
|
10
|
+
* other stages use.
|
|
11
|
+
*
|
|
12
|
+
* Diagrams are budgeted, not left over (founder, 2026-07-25): the Edition v2
|
|
13
|
+
* threads gave every module several prose obligations inside an unchanged
|
|
14
|
+
* 4-to-8 widget budget, and the only widget family described as optional —
|
|
15
|
+
* the diagrams — is what got squeezed out. Live editions pressed on 2026-07-13
|
|
16
|
+
* carried 3-5 system maps; those pressed on 2026-07-14 carried 1-2, with the
|
|
17
|
+
* callout share climbing from 29% to 50% across the same five editions. The
|
|
18
|
+
* range now starts higher, the diagram catalogue sits above code-figure and
|
|
19
|
+
* quiz rather than last, and {@link SHAPE_CONTRACT} states the expectation
|
|
20
|
+
* outright. The escape hatch stays honest: no diagram where the code has no
|
|
21
|
+
* shape, and every node still carries its own anchor.
|
|
22
|
+
*
|
|
23
|
+
* Narrative continuity without serializing the fan-out (issue #18): each
|
|
24
|
+
* author prompt carries its module's **learner-state ledger slice** — what
|
|
25
|
+
* the learner has already seen (`assumes`, plus the titles of earlier
|
|
26
|
+
* modules it may reference), and what this module must add (`teaches`) —
|
|
27
|
+
* plus the **style contract** (concrete before abstract, jargon defined at
|
|
28
|
+
* first use, analogies anchored, mechanism-and-why over structural survey).
|
|
29
|
+
*
|
|
30
|
+
* Failure policy (deliberate, documented): a module that is still
|
|
31
|
+
* schema-invalid after its retries **fails the whole stage** with an error
|
|
32
|
+
* naming the module — there is no silent-skip mode. A planned module is a
|
|
33
|
+
* curriculum commitment; dropping it quietly would ship a lab with a hole
|
|
34
|
+
* the lead never sees. Other in-flight modules finish before the error is
|
|
35
|
+
* raised, so all failures are reported at once.
|
|
36
|
+
*/
|
|
37
|
+
/** Default cap on concurrent authoring agents. */
|
|
38
|
+
export declare const DEFAULT_AUTHOR_CONCURRENCY = 4;
|
|
39
|
+
/**
|
|
40
|
+
* Widgets per authored chapter. The floor clears the module's mandatory prose
|
|
41
|
+
* — a quiz, the capability callout, the "when it breaks" warning, the threads
|
|
42
|
+
* the plan assigned — so a diagram has somewhere to go.
|
|
43
|
+
*/
|
|
44
|
+
export declare const DEFAULT_WIDGET_RANGE: {
|
|
45
|
+
readonly min: 6;
|
|
46
|
+
readonly max: 10;
|
|
47
|
+
};
|
|
48
|
+
/** Widgets per chapter for repos deep enough to earn a 7-module plan. */
|
|
49
|
+
export declare const DEEP_WIDGET_RANGE: {
|
|
50
|
+
readonly min: 7;
|
|
51
|
+
readonly max: 12;
|
|
52
|
+
};
|
|
53
|
+
export interface AuthorStageOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Widget count guidance interpolated into the prompt. Bigger repos earn
|
|
56
|
+
* deeper chapters, not only more of them. The floor has to clear the
|
|
57
|
+
* module's mandatory prose (a quiz, the capability callout, the "when it
|
|
58
|
+
* breaks" warning, the threads the plan assigned) before a diagram can fit
|
|
59
|
+
* at all — see the module comment. @default 6 to 10
|
|
60
|
+
*/
|
|
61
|
+
widgetRange?: {
|
|
62
|
+
min: number;
|
|
63
|
+
max: number;
|
|
64
|
+
};
|
|
65
|
+
model: string;
|
|
66
|
+
plan: CurriculumPlan;
|
|
67
|
+
/**
|
|
68
|
+
* How many times to re-prompt a single module after schema-invalid output.
|
|
69
|
+
* @default 1
|
|
70
|
+
*/
|
|
71
|
+
maxRetries?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Max authoring agents in flight at once.
|
|
74
|
+
* @default 4
|
|
75
|
+
*/
|
|
76
|
+
concurrency?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Titles of chapters the reader meets BEFORE this plan's modules in the
|
|
79
|
+
* finished lab. Prepended to every module's ledger slice. Needed when a
|
|
80
|
+
* plan covers only part of the book — re-authoring the overview chapter
|
|
81
|
+
* passes the flagship trace's title here, so the overview is told to build
|
|
82
|
+
* on the trace instead of being mistaken for the opening chapter (which is
|
|
83
|
+
* what an empty ledger means).
|
|
84
|
+
*/
|
|
85
|
+
precedingTitles?: readonly string[];
|
|
86
|
+
/**
|
|
87
|
+
* Called as soon as each module validates — while other modules are still
|
|
88
|
+
* in flight. This is the fan-out's progress seam: `generateLab` and pass 1
|
|
89
|
+
* forward it as `module-authored` events. Invoked synchronously and not
|
|
90
|
+
* awaited; completion order follows the fan-out, not plan order.
|
|
91
|
+
*/
|
|
92
|
+
onModuleAuthored?: (authored: AuthoredModule) => void;
|
|
93
|
+
}
|
|
94
|
+
export interface AuthoredModule {
|
|
95
|
+
/** A valid lab module — not yet anchor-resolved. */
|
|
96
|
+
module: LabModule;
|
|
97
|
+
/** Attempts spent on this module (1 = no retry needed). */
|
|
98
|
+
attempts: number;
|
|
99
|
+
}
|
|
100
|
+
export interface AuthorStageResult {
|
|
101
|
+
/** One authored module per planned module, in plan order. */
|
|
102
|
+
modules: AuthoredModule[];
|
|
103
|
+
/** Summed cost across all modules and attempts, if the runner reports cost. */
|
|
104
|
+
costUsd: number | undefined;
|
|
105
|
+
}
|
|
106
|
+
/** One module's terminal failure inside the author stage. */
|
|
107
|
+
export interface AuthorModuleFailure {
|
|
108
|
+
moduleId: string;
|
|
109
|
+
attempts: number;
|
|
110
|
+
lastFailure: string;
|
|
111
|
+
}
|
|
112
|
+
/** Raised when at least one planned module never produced a valid module. */
|
|
113
|
+
export declare class AuthorStageError extends Error {
|
|
114
|
+
readonly failures: readonly AuthorModuleFailure[];
|
|
115
|
+
constructor(failures: readonly AuthorModuleFailure[]);
|
|
116
|
+
}
|
|
117
|
+
export declare function runAuthorStage(runner: ModelRunner, repoDir: string, options: AuthorStageOptions): Promise<AuthorStageResult>;
|
|
118
|
+
/** Exported for prompt-contract tests; not part of the stage's runtime API. */
|
|
119
|
+
export declare function buildAuthorPrompt(planned: PlannedModule, earlierTitles: readonly string[], range: {
|
|
120
|
+
min: number;
|
|
121
|
+
max: number;
|
|
122
|
+
}): string;
|
|
123
|
+
//# sourceMappingURL=authorStage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorStage.d.ts","sourceRoot":"","sources":["../src/authorStage.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EAAsB,KAAK,WAAW,EAAsB,MAAM,eAAe,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,kDAAkD;AAClD,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;CAA+B,CAAC;AAEjE,yEAAyE;AACzE,eAAO,MAAM,iBAAiB;;;CAA+B,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,MAAM,EAAE,SAAS,CAAC;IAClB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,6DAA6D;IAC7D,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAC;gBAEtC,QAAQ,EAAE,SAAS,mBAAmB,EAAE;CAerD;AASD,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAkC5B;AA4KD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAClC,MAAM,CAuDR"}
|