@otto-code/brain 0.7.5
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/bin/otto-brain +2 -0
- package/dist/bench/context-corpus.d.ts +58 -0
- package/dist/bench/context-corpus.js +210 -0
- package/dist/bench/corpus.d.ts +31 -0
- package/dist/bench/corpus.js +379 -0
- package/dist/bench/curated-repos.d.ts +35 -0
- package/dist/bench/curated-repos.js +41 -0
- package/dist/bench/health.d.ts +50 -0
- package/dist/bench/health.js +112 -0
- package/dist/bench/index.d.ts +103 -0
- package/dist/bench/index.js +209 -0
- package/dist/bench/mine.d.ts +32 -0
- package/dist/bench/mine.js +101 -0
- package/dist/bench/repo-task.d.ts +93 -0
- package/dist/bench/repo-task.js +380 -0
- package/dist/bench/repo.d.ts +125 -0
- package/dist/bench/repo.js +195 -0
- package/dist/bench/rescore.d.ts +41 -0
- package/dist/bench/rescore.js +127 -0
- package/dist/bench/tasks.d.ts +124 -0
- package/dist/bench/tasks.js +1249 -0
- package/dist/bench/verify.d.ts +142 -0
- package/dist/bench/verify.js +350 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +72 -0
- package/dist/commands/bench.d.ts +20 -0
- package/dist/commands/bench.js +222 -0
- package/dist/commands/calibrate.d.ts +19 -0
- package/dist/commands/calibrate.js +75 -0
- package/dist/commands/catalog.d.ts +32 -0
- package/dist/commands/catalog.js +48 -0
- package/dist/commands/config.d.ts +13 -0
- package/dist/commands/config.js +90 -0
- package/dist/commands/lifecycle.d.ts +29 -0
- package/dist/commands/lifecycle.js +194 -0
- package/dist/commands/pull.d.ts +22 -0
- package/dist/commands/pull.js +135 -0
- package/dist/commands/report.d.ts +10 -0
- package/dist/commands/report.js +34 -0
- package/dist/commands/rescore.d.ts +11 -0
- package/dist/commands/rescore.js +48 -0
- package/dist/commands/runtime.d.ts +21 -0
- package/dist/commands/runtime.js +62 -0
- package/dist/commands/scan.d.ts +24 -0
- package/dist/commands/scan.js +55 -0
- package/dist/commands/search.d.ts +31 -0
- package/dist/commands/search.js +135 -0
- package/dist/commands/share.d.ts +26 -0
- package/dist/commands/share.js +148 -0
- package/dist/commands/sweep.d.ts +21 -0
- package/dist/commands/sweep.js +69 -0
- package/dist/commands/ui.d.ts +9 -0
- package/dist/commands/ui.js +28 -0
- package/dist/config/env.d.ts +10 -0
- package/dist/config/env.js +48 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.js +9 -0
- package/dist/config/otto-home.d.ts +2 -0
- package/dist/config/otto-home.js +24 -0
- package/dist/config/paths.d.ts +20 -0
- package/dist/config/paths.js +33 -0
- package/dist/config/private-files.d.ts +3 -0
- package/dist/config/private-files.js +32 -0
- package/dist/config/profiles.d.ts +34 -0
- package/dist/config/profiles.js +116 -0
- package/dist/config/schema.d.ts +1035 -0
- package/dist/config/schema.js +191 -0
- package/dist/config/store.d.ts +11 -0
- package/dist/config/store.js +73 -0
- package/dist/gguf.d.ts +61 -0
- package/dist/gguf.js +231 -0
- package/dist/gpu.d.ts +12 -0
- package/dist/gpu.js +49 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +13 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +5 -0
- package/dist/models/dirs.d.ts +9 -0
- package/dist/models/dirs.js +21 -0
- package/dist/models/download.d.ts +31 -0
- package/dist/models/download.js +105 -0
- package/dist/models/enrich.d.ts +36 -0
- package/dist/models/enrich.js +68 -0
- package/dist/models/hf.d.ts +62 -0
- package/dist/models/hf.js +114 -0
- package/dist/models/index.d.ts +15 -0
- package/dist/models/index.js +49 -0
- package/dist/models/manage.d.ts +27 -0
- package/dist/models/manage.js +112 -0
- package/dist/models/pick.d.ts +3 -0
- package/dist/models/pick.js +36 -0
- package/dist/models/scan.d.ts +13 -0
- package/dist/models/scan.js +185 -0
- package/dist/ops/archive.d.ts +34 -0
- package/dist/ops/archive.js +105 -0
- package/dist/ops/calibrate.d.ts +49 -0
- package/dist/ops/calibrate.js +74 -0
- package/dist/ops/report.d.ts +26 -0
- package/dist/ops/report.js +532 -0
- package/dist/ops/results.d.ts +207 -0
- package/dist/ops/results.js +250 -0
- package/dist/ops/sweep.d.ts +77 -0
- package/dist/ops/sweep.js +126 -0
- package/dist/output/index.d.ts +5 -0
- package/dist/output/index.js +5 -0
- package/dist/output/render.d.ts +4 -0
- package/dist/output/render.js +96 -0
- package/dist/output/types.d.ts +52 -0
- package/dist/output/types.js +9 -0
- package/dist/output/with-output.d.ts +3 -0
- package/dist/output/with-output.js +42 -0
- package/dist/run.d.ts +5 -0
- package/dist/run.js +19 -0
- package/dist/runtime/args.d.ts +21 -0
- package/dist/runtime/args.js +71 -0
- package/dist/runtime/index.d.ts +13 -0
- package/dist/runtime/index.js +41 -0
- package/dist/runtime/lmstudio.d.ts +10 -0
- package/dist/runtime/lmstudio.js +88 -0
- package/dist/runtime/managed.d.ts +26 -0
- package/dist/runtime/managed.js +148 -0
- package/dist/service/model-selector.d.ts +36 -0
- package/dist/service/model-selector.js +123 -0
- package/dist/service/pid-lock.d.ts +18 -0
- package/dist/service/pid-lock.js +50 -0
- package/dist/service/router.d.ts +144 -0
- package/dist/service/router.js +746 -0
- package/dist/service/scheduler.d.ts +74 -0
- package/dist/service/scheduler.js +110 -0
- package/dist/service/serve.d.ts +41 -0
- package/dist/service/serve.js +278 -0
- package/dist/service/supervisor.d.ts +67 -0
- package/dist/service/supervisor.js +222 -0
- package/dist/service/tailscale.d.ts +19 -0
- package/dist/service/tailscale.js +62 -0
- package/dist/service/tls.d.ts +77 -0
- package/dist/service/tls.js +192 -0
- package/dist/sysmon.d.ts +50 -0
- package/dist/sysmon.js +103 -0
- package/dist/tui/app.d.ts +208 -0
- package/dist/tui/app.js +1801 -0
- package/dist/tui/screen.d.ts +72 -0
- package/dist/tui/screen.js +176 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.js +7 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +8 -0
- package/dist/vram.d.ts +67 -0
- package/dist/vram.js +132 -0
- package/package.json +58 -0
package/bin/otto-brain
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A window-sized synthetic codebase for the `context-stress` benchmark task.
|
|
3
|
+
*
|
|
4
|
+
* The point of this task is the opposite of a clever puzzle: it is a *volume*
|
|
5
|
+
* test. A staged pipeline has N modules, each of which returns its input
|
|
6
|
+
* unchanged (a placeholder). The real rule each stage must implement -- an
|
|
7
|
+
* operation and an operand -- lives ONLY in the specification, which is split
|
|
8
|
+
* across `docs/spec/part_XX.md` and generated verbose enough to fill a target
|
|
9
|
+
* fraction of the model's context window. So the model cannot fix any stage
|
|
10
|
+
* without reading the spec, and it cannot fix ALL of them without holding most
|
|
11
|
+
* of the window at once.
|
|
12
|
+
*
|
|
13
|
+
* That is the design guarantee: a run that scores well on the hidden per-stage
|
|
14
|
+
* oracle MUST have held (read and kept in context) at least the target fraction
|
|
15
|
+
* of the window. A run that shortcuts scores low AND shows low held context --
|
|
16
|
+
* which is exactly the signal a 1-2%-held long-horizon task fails to give.
|
|
17
|
+
*
|
|
18
|
+
* Everything here is deterministic (seeded by stage index, never `Math.random`)
|
|
19
|
+
* so the corpus, the reference fix, and the oracle all agree across runs. All
|
|
20
|
+
* arithmetic is bounded mod 1000 so the JavaScript-computed expectations match
|
|
21
|
+
* Python's integer semantics exactly (no bignum drift through a long pipeline).
|
|
22
|
+
*/
|
|
23
|
+
/** One stage's fully-resolved rule: the op, its operand, and a probe/expected. */
|
|
24
|
+
export interface StageSpec {
|
|
25
|
+
index: number;
|
|
26
|
+
op: "add" | "mul" | "shift";
|
|
27
|
+
operand: number;
|
|
28
|
+
/** A small fixed probe input for this stage's oracle test. */
|
|
29
|
+
sample: number;
|
|
30
|
+
/** The correct `apply(sample)`, computed here so the oracle is self-consistent. */
|
|
31
|
+
expected: number;
|
|
32
|
+
}
|
|
33
|
+
/** The generated corpus: what the model sees, the hidden oracle, and the fix. */
|
|
34
|
+
export interface ContextCorpus {
|
|
35
|
+
/** Files shown to the model: docs (read-only) + buggy Python modules. */
|
|
36
|
+
files: Record<string, string>;
|
|
37
|
+
/** The correct Python modules, kept ONLY for the unit test's oracle check. */
|
|
38
|
+
reference: Record<string, string>;
|
|
39
|
+
/** The hidden per-stage oracle (`test_pipeline.py`), never shown to the model. */
|
|
40
|
+
hiddenTest: string;
|
|
41
|
+
/** Basenames of the runnable Python modules (no docs), for the test harness. */
|
|
42
|
+
pyFiles: string[];
|
|
43
|
+
/** The spec doc paths, in order. */
|
|
44
|
+
specFiles: string[];
|
|
45
|
+
/** The resolved stage rules. */
|
|
46
|
+
stages: StageSpec[];
|
|
47
|
+
/** The approximate character budget the docs were padded to. */
|
|
48
|
+
docChars: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generate a window-sized staged-pipeline corpus whose spec fills roughly
|
|
52
|
+
* `targetTokens` (estimated at ~4 chars/token). Returns the buggy corpus the
|
|
53
|
+
* model works on, the reference fix, and the hidden oracle.
|
|
54
|
+
*/
|
|
55
|
+
export declare function generateContextCorpus({ targetTokens }: {
|
|
56
|
+
targetTokens: number;
|
|
57
|
+
}): ContextCorpus;
|
|
58
|
+
//# sourceMappingURL=context-corpus.d.ts.map
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A window-sized synthetic codebase for the `context-stress` benchmark task.
|
|
3
|
+
*
|
|
4
|
+
* The point of this task is the opposite of a clever puzzle: it is a *volume*
|
|
5
|
+
* test. A staged pipeline has N modules, each of which returns its input
|
|
6
|
+
* unchanged (a placeholder). The real rule each stage must implement -- an
|
|
7
|
+
* operation and an operand -- lives ONLY in the specification, which is split
|
|
8
|
+
* across `docs/spec/part_XX.md` and generated verbose enough to fill a target
|
|
9
|
+
* fraction of the model's context window. So the model cannot fix any stage
|
|
10
|
+
* without reading the spec, and it cannot fix ALL of them without holding most
|
|
11
|
+
* of the window at once.
|
|
12
|
+
*
|
|
13
|
+
* That is the design guarantee: a run that scores well on the hidden per-stage
|
|
14
|
+
* oracle MUST have held (read and kept in context) at least the target fraction
|
|
15
|
+
* of the window. A run that shortcuts scores low AND shows low held context --
|
|
16
|
+
* which is exactly the signal a 1-2%-held long-horizon task fails to give.
|
|
17
|
+
*
|
|
18
|
+
* Everything here is deterministic (seeded by stage index, never `Math.random`)
|
|
19
|
+
* so the corpus, the reference fix, and the oracle all agree across runs. All
|
|
20
|
+
* arithmetic is bounded mod 1000 so the JavaScript-computed expectations match
|
|
21
|
+
* Python's integer semantics exactly (no bignum drift through a long pipeline).
|
|
22
|
+
*/
|
|
23
|
+
/** Neutral spec-prose filler, used to pad each part to its character budget so
|
|
24
|
+
* the corpus reaches the target window fraction. Deterministic by index. */
|
|
25
|
+
const FILLER = [
|
|
26
|
+
"This constraint is load-bearing: downstream stages assume the transform has already been applied, so skipping it silently corrupts every later result.",
|
|
27
|
+
"The operand was chosen during calibration and must not be inferred from the code, which deliberately carries no hint of its value.",
|
|
28
|
+
"Reviewers should treat this section as normative; where the prose and a placeholder disagree, the prose wins.",
|
|
29
|
+
"Historically this rule lived in the module itself, but colocating it with the code led to drift, so it was moved here and the code reset to a passthrough.",
|
|
30
|
+
"Note that the ordering of stages is significant only through the running total; each stage's own rule is independent of its neighbours.",
|
|
31
|
+
"A conforming implementation returns an integer in the range produced by the bounded arithmetic described below, never a float.",
|
|
32
|
+
"The specification is intentionally verbose so that a reader must carry it in working memory rather than pattern-matching a single line.",
|
|
33
|
+
"When in doubt, re-read the operand: transcription errors here are the most common cause of a failing stage.",
|
|
34
|
+
];
|
|
35
|
+
function operandFor(index) {
|
|
36
|
+
// Knuth multiplicative hash, kept well under 2^53 for any realistic N, mapped
|
|
37
|
+
// to a readable 3-digit operand so the spec prose can name it plainly.
|
|
38
|
+
return 100 + ((index * 2654435761) % 900);
|
|
39
|
+
}
|
|
40
|
+
function opFor(index) {
|
|
41
|
+
return ["add", "mul", "shift"][index % 3];
|
|
42
|
+
}
|
|
43
|
+
/** Apply a stage's rule, bounded mod 1000 (matches the generated Python). */
|
|
44
|
+
function applyRule(op, operand, x) {
|
|
45
|
+
if (op === "mul")
|
|
46
|
+
return (x * operand) % 1000;
|
|
47
|
+
if (op === "shift")
|
|
48
|
+
return (x + operand * 2) % 1000;
|
|
49
|
+
return (x + operand) % 1000;
|
|
50
|
+
}
|
|
51
|
+
/** The Python expression body for a stage's correct `apply`, matching applyRule. */
|
|
52
|
+
function pyExpr(op, operand) {
|
|
53
|
+
if (op === "mul")
|
|
54
|
+
return `(x * ${operand}) % 1000`;
|
|
55
|
+
if (op === "shift")
|
|
56
|
+
return `(x + ${operand * 2}) % 1000`;
|
|
57
|
+
return `(x + ${operand}) % 1000`;
|
|
58
|
+
}
|
|
59
|
+
/** A human-readable rule description for the spec prose. */
|
|
60
|
+
function ruleProse(op, operand) {
|
|
61
|
+
if (op === "mul")
|
|
62
|
+
return `multiply the running value by operand **${operand}**, then take the result modulo 1000`;
|
|
63
|
+
if (op === "shift")
|
|
64
|
+
return `add **twice** operand ${operand} (that is, ${operand * 2}) to the running value, then take the result modulo 1000`;
|
|
65
|
+
return `add operand **${operand}** to the running value, then take the result modulo 1000`;
|
|
66
|
+
}
|
|
67
|
+
function stageModuleName(index) {
|
|
68
|
+
return `stage_${String(index).padStart(2, "0")}`;
|
|
69
|
+
}
|
|
70
|
+
function buggyStage(index) {
|
|
71
|
+
const name = stageModuleName(index);
|
|
72
|
+
return (`"""${name}: one stage of the pipeline.\n\n` +
|
|
73
|
+
`This module is a PLACEHOLDER. It must apply the rule documented for stage ` +
|
|
74
|
+
`${index} in the specification under docs/spec/. Until then it returns its\n` +
|
|
75
|
+
`input unchanged, which the oracle test for this stage will reject.\n"""\n\n\n` +
|
|
76
|
+
`def apply(x):\n` +
|
|
77
|
+
` # TODO: implement stage ${index} per docs/spec/.\n` +
|
|
78
|
+
` return x\n`);
|
|
79
|
+
}
|
|
80
|
+
function referenceStage(index, op, operand) {
|
|
81
|
+
const name = stageModuleName(index);
|
|
82
|
+
return (`"""${name}: one stage of the pipeline (reference implementation)."""\n\n\n` +
|
|
83
|
+
`def apply(x):\n` +
|
|
84
|
+
` return ${pyExpr(op, operand)}\n`);
|
|
85
|
+
}
|
|
86
|
+
function pipelineModule(count) {
|
|
87
|
+
const names = Array.from({ length: count }, (_, i) => stageModuleName(i));
|
|
88
|
+
const imports = names.map((n) => `import ${n}`).join("\n");
|
|
89
|
+
const list = names.join(", ");
|
|
90
|
+
return (`"""The staged pipeline. Applies every stage's apply() in order.\n\n` +
|
|
91
|
+
`Each stage is implemented in its own module; the rules live in docs/spec/.\n"""\n` +
|
|
92
|
+
`${imports}\n\n` +
|
|
93
|
+
`STAGES = [${list}]\n\n\n` +
|
|
94
|
+
`def run(x):\n` +
|
|
95
|
+
` total = x\n` +
|
|
96
|
+
` for stage in STAGES:\n` +
|
|
97
|
+
` total = stage.apply(total)\n` +
|
|
98
|
+
` return total\n`);
|
|
99
|
+
}
|
|
100
|
+
const PIPELINE_START = 5;
|
|
101
|
+
function endToEnd(stages) {
|
|
102
|
+
let total = PIPELINE_START;
|
|
103
|
+
for (const s of stages)
|
|
104
|
+
total = applyRule(s.op, s.operand, total);
|
|
105
|
+
return total;
|
|
106
|
+
}
|
|
107
|
+
function hiddenTest(stages) {
|
|
108
|
+
const imports = stages.map((s) => `import ${stageModuleName(s.index)}`).join("\n");
|
|
109
|
+
const perStage = stages
|
|
110
|
+
.map((s) => ` def test_${stageModuleName(s.index)}(self):\n` +
|
|
111
|
+
` self.assertEqual(${stageModuleName(s.index)}.apply(${s.sample}), ${s.expected})\n`)
|
|
112
|
+
.join("\n");
|
|
113
|
+
const final = endToEnd(stages);
|
|
114
|
+
return (`import unittest\n\n` +
|
|
115
|
+
`${imports}\n` +
|
|
116
|
+
`import pipeline\n\n\n` +
|
|
117
|
+
`class TestPipeline(unittest.TestCase):\n` +
|
|
118
|
+
`${perStage}\n` +
|
|
119
|
+
` def test_pipeline_end_to_end(self):\n` +
|
|
120
|
+
` self.assertEqual(pipeline.run(${PIPELINE_START}), ${final})\n\n\n` +
|
|
121
|
+
`if __name__ == "__main__":\n` +
|
|
122
|
+
` unittest.main()\n`);
|
|
123
|
+
}
|
|
124
|
+
/** Pad `body` with deterministic filler prose until it reaches `budgetChars`. */
|
|
125
|
+
function padTo(body, budgetChars, seed) {
|
|
126
|
+
let out = body;
|
|
127
|
+
let i = seed;
|
|
128
|
+
while (out.length < budgetChars) {
|
|
129
|
+
out += `\n\n${FILLER[i % FILLER.length]}`;
|
|
130
|
+
i += 1;
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
/** Build one spec part covering `stages`, padded to `budgetChars`. */
|
|
135
|
+
function specPart(partIndex, stages, budgetChars) {
|
|
136
|
+
const heading = `# Pipeline specification — part ${String(partIndex).padStart(2, "0")}\n\n` +
|
|
137
|
+
`This part defines the rule for stages ${stages[0].index}–${stages[stages.length - 1].index}. ` +
|
|
138
|
+
`Each stage's module in the working copy is a passthrough placeholder; implement its \`apply(x)\` ` +
|
|
139
|
+
`exactly as written here. All arithmetic is bounded modulo 1000 and returns an integer.\n`;
|
|
140
|
+
const entries = stages
|
|
141
|
+
.map((s) => `\n## Stage ${s.index}\n\n` +
|
|
142
|
+
`Module: \`${stageModuleName(s.index)}.py\`. Rule: ${ruleProse(s.op, s.operand)}. ` +
|
|
143
|
+
`Equivalently, \`apply(x)\` must return \`${pyExpr(s.op, s.operand)}\`.\n`)
|
|
144
|
+
.join("");
|
|
145
|
+
return padTo(heading + entries, budgetChars, partIndex * 31 + stages[0].index);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Generate a window-sized staged-pipeline corpus whose spec fills roughly
|
|
149
|
+
* `targetTokens` (estimated at ~4 chars/token). Returns the buggy corpus the
|
|
150
|
+
* model works on, the reference fix, and the hidden oracle.
|
|
151
|
+
*/
|
|
152
|
+
export function generateContextCorpus({ targetTokens }) {
|
|
153
|
+
// ~3000 tokens of spec per stage keeps the stage count sane while letting the
|
|
154
|
+
// docs carry the volume; clamp so tiny windows still get a real pipeline and
|
|
155
|
+
// huge windows do not generate an unbounded number of modules.
|
|
156
|
+
const stageCount = Math.max(12, Math.min(48, Math.round(targetTokens / 3000)));
|
|
157
|
+
const docChars = Math.max(2000, targetTokens * 4);
|
|
158
|
+
const stages = Array.from({ length: stageCount }, (_, index) => {
|
|
159
|
+
const op = opFor(index);
|
|
160
|
+
const operand = operandFor(index);
|
|
161
|
+
const sample = 3 + (index % 7);
|
|
162
|
+
return { index, op, operand, sample, expected: applyRule(op, operand, sample) };
|
|
163
|
+
});
|
|
164
|
+
// Split stages across doc parts (~6 per part), each padded to an equal share
|
|
165
|
+
// of the doc budget so the whole spec sums to ~docChars.
|
|
166
|
+
const partCount = Math.min(stageCount, Math.max(3, Math.round(stageCount / 6)));
|
|
167
|
+
const perPartBudget = Math.floor(docChars / partCount);
|
|
168
|
+
const partStride = Math.ceil(stageCount / partCount);
|
|
169
|
+
const files = {};
|
|
170
|
+
const reference = {};
|
|
171
|
+
const specFiles = [];
|
|
172
|
+
files["README.md"] =
|
|
173
|
+
"# staged-pipeline\n\nA numeric pipeline built from independent stages. Every stage " +
|
|
174
|
+
"module under the working root is a placeholder that returns its input unchanged; the " +
|
|
175
|
+
"rule each one must implement is specified in `docs/spec/`. Fix every stage, then run " +
|
|
176
|
+
"`python -m unittest test_pipeline`.\n";
|
|
177
|
+
files["docs/OVERVIEW.md"] =
|
|
178
|
+
"# Specification overview\n\nThe pipeline applies each stage's `apply(x)` in order, starting " +
|
|
179
|
+
`from ${PIPELINE_START}. There are ${stageCount} stages. The rule for each stage — its ` +
|
|
180
|
+
"operation and operand — is defined in the numbered parts under `docs/spec/`. The code carries " +
|
|
181
|
+
"no hint of the operands; you must read the spec.\n";
|
|
182
|
+
for (let p = 0; p < partCount; p += 1) {
|
|
183
|
+
const slice = stages.slice(p * partStride, (p + 1) * partStride);
|
|
184
|
+
if (!slice.length)
|
|
185
|
+
continue;
|
|
186
|
+
const path = `docs/spec/part_${String(p).padStart(2, "0")}.md`;
|
|
187
|
+
files[path] = specPart(p, slice, perPartBudget);
|
|
188
|
+
specFiles.push(path);
|
|
189
|
+
}
|
|
190
|
+
const pyFiles = [];
|
|
191
|
+
for (const s of stages) {
|
|
192
|
+
const file = `${stageModuleName(s.index)}.py`;
|
|
193
|
+
files[file] = buggyStage(s.index);
|
|
194
|
+
reference[file] = referenceStage(s.index, s.op, s.operand);
|
|
195
|
+
pyFiles.push(file);
|
|
196
|
+
}
|
|
197
|
+
files["pipeline.py"] = pipelineModule(stageCount);
|
|
198
|
+
reference["pipeline.py"] = files["pipeline.py"];
|
|
199
|
+
pyFiles.push("pipeline.py");
|
|
200
|
+
return {
|
|
201
|
+
files,
|
|
202
|
+
reference,
|
|
203
|
+
hiddenTest: hiddenTest(stages),
|
|
204
|
+
pyFiles,
|
|
205
|
+
specFiles,
|
|
206
|
+
stages,
|
|
207
|
+
docChars,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=context-corpus.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A self-contained codebase for the extra-long-horizon benchmark task.
|
|
3
|
+
*
|
|
4
|
+
* The bug in `pricing.py` cannot be fixed correctly by reading the code alone:
|
|
5
|
+
* the two rules the fix must honour (discounts apply to the ORIGINAL subtotal,
|
|
6
|
+
* and the combined discount is capped at 50%) live only in `docs/SPEC.md`. So a
|
|
7
|
+
* model has to explore the tree, find and read the spec, and only then produce a
|
|
8
|
+
* fix that passes the hidden oracle. Reading widely is the point - it is what
|
|
9
|
+
* fills context on a long-horizon task.
|
|
10
|
+
*
|
|
11
|
+
* The markdown is deliberately verbose: the more a model reads to locate the two
|
|
12
|
+
* load-bearing rules, the more of its context window it fills, which the task
|
|
13
|
+
* reports. Expand the corpus to push the context bar higher.
|
|
14
|
+
*/
|
|
15
|
+
/** The reference fix, kept only so the task's own unit test can sanity-check the
|
|
16
|
+
* oracle. Never shown to the model. */
|
|
17
|
+
export declare const PRICING_PY_REFERENCE = "\"\"\"Order pricing: apply discount rules to a subtotal.\"\"\"\nfrom rules import PercentRule # noqa: F401\n\n\ndef compute_total(subtotal_cents, rules):\n ordered = sorted(rules, key=lambda r: r.priority, reverse=True)\n discount = 0\n for rule in ordered:\n discount += rule.discount(subtotal_cents)\n cap = subtotal_cents // 2\n if discount > cap:\n discount = cap\n return subtotal_cents - discount\n";
|
|
18
|
+
/** The hidden oracle - never shown to the model, written only at test time. Its
|
|
19
|
+
* expectations encode docs/SPEC.md exactly. */
|
|
20
|
+
export declare const EXTRA_HIDDEN_TEST = "import unittest\n\nfrom pricing import compute_total\nfrom rules import PercentRule, FixedRule\n\n\nclass TestPricing(unittest.TestCase):\n def test_empty_rules(self):\n self.assertEqual(compute_total(10000, []), 10000)\n\n def test_single_percent(self):\n self.assertEqual(compute_total(10000, [PercentRule(\"a\", 20)]), 8000)\n\n def test_two_rules_do_not_compound(self):\n # 30% + 40% of the ORIGINAL 10000 = 3000 + 4000 = 7000, capped at 5000.\n rules = [PercentRule(\"a\", 30), PercentRule(\"b\", 40)]\n self.assertEqual(compute_total(10000, rules), 5000)\n\n def test_combined_cap(self):\n # A single 60% rule is capped at 50%.\n self.assertEqual(compute_total(10000, [PercentRule(\"big\", 60)]), 5000)\n\n def test_under_cap(self):\n # 10% + 15% = 2500 discount, below the cap.\n rules = [PercentRule(\"a\", 10), PercentRule(\"b\", 15)]\n self.assertEqual(compute_total(10000, rules), 7500)\n\n def test_fixed_and_percent_capped(self):\n # 4000 fixed + 30% (3000) = 7000, capped at 5000.\n rules = [FixedRule(\"f\", 4000), PercentRule(\"p\", 30)]\n self.assertEqual(compute_total(10000, rules), 5000)\n\n\nif __name__ == \"__main__\":\n unittest.main()\n";
|
|
21
|
+
/**
|
|
22
|
+
* The files the model can see and explore. Python modules are the working copy it
|
|
23
|
+
* edits; markdown is read-only reference. The hidden test is intentionally NOT
|
|
24
|
+
* here.
|
|
25
|
+
*/
|
|
26
|
+
export declare const EXTRA_CORPUS: Record<string, string>;
|
|
27
|
+
/** The Python modules that make up the runnable working copy (no docs). */
|
|
28
|
+
export declare const EXTRA_PY_FILES: string[];
|
|
29
|
+
/** The one file the model is meant to fix. */
|
|
30
|
+
export declare const EXTRA_TARGET_FILE = "pricing.py";
|
|
31
|
+
//# sourceMappingURL=corpus.d.ts.map
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A self-contained codebase for the extra-long-horizon benchmark task.
|
|
3
|
+
*
|
|
4
|
+
* The bug in `pricing.py` cannot be fixed correctly by reading the code alone:
|
|
5
|
+
* the two rules the fix must honour (discounts apply to the ORIGINAL subtotal,
|
|
6
|
+
* and the combined discount is capped at 50%) live only in `docs/SPEC.md`. So a
|
|
7
|
+
* model has to explore the tree, find and read the spec, and only then produce a
|
|
8
|
+
* fix that passes the hidden oracle. Reading widely is the point - it is what
|
|
9
|
+
* fills context on a long-horizon task.
|
|
10
|
+
*
|
|
11
|
+
* The markdown is deliberately verbose: the more a model reads to locate the two
|
|
12
|
+
* load-bearing rules, the more of its context window it fills, which the task
|
|
13
|
+
* reports. Expand the corpus to push the context bar higher.
|
|
14
|
+
*/
|
|
15
|
+
/** The buggy engine the model must fix. Applies discounts to the RUNNING total
|
|
16
|
+
* (so they compound) and never caps them - both wrong per docs/SPEC.md. */
|
|
17
|
+
const PRICING_PY = `"""Order pricing: apply discount rules to a subtotal.
|
|
18
|
+
|
|
19
|
+
See docs/SPEC.md for the discount rules this module is supposed to implement, and
|
|
20
|
+
docs/ARCHITECTURE.md for how it fits with rules.py and money.py.
|
|
21
|
+
"""
|
|
22
|
+
from rules import PercentRule # noqa: F401 (re-exported for callers)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def compute_total(subtotal_cents, rules):
|
|
26
|
+
"""Return the order total in cents after applying every discount rule.
|
|
27
|
+
|
|
28
|
+
subtotal_cents: the pre-discount total, in integer cents.
|
|
29
|
+
rules: a list of rule objects, each with a .discount(amount_cents) method.
|
|
30
|
+
"""
|
|
31
|
+
total = subtotal_cents
|
|
32
|
+
for rule in rules:
|
|
33
|
+
total -= rule.discount(total)
|
|
34
|
+
return total
|
|
35
|
+
`;
|
|
36
|
+
/** The reference fix, kept only so the task's own unit test can sanity-check the
|
|
37
|
+
* oracle. Never shown to the model. */
|
|
38
|
+
export const PRICING_PY_REFERENCE = `"""Order pricing: apply discount rules to a subtotal."""
|
|
39
|
+
from rules import PercentRule # noqa: F401
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def compute_total(subtotal_cents, rules):
|
|
43
|
+
ordered = sorted(rules, key=lambda r: r.priority, reverse=True)
|
|
44
|
+
discount = 0
|
|
45
|
+
for rule in ordered:
|
|
46
|
+
discount += rule.discount(subtotal_cents)
|
|
47
|
+
cap = subtotal_cents // 2
|
|
48
|
+
if discount > cap:
|
|
49
|
+
discount = cap
|
|
50
|
+
return subtotal_cents - discount
|
|
51
|
+
`;
|
|
52
|
+
const RULES_PY = `"""Discount rule types.
|
|
53
|
+
|
|
54
|
+
A rule exposes .discount(amount_cents) -> int and a .priority (higher runs
|
|
55
|
+
first, per docs/SPEC.md "Ordering"). Discounts are integer cents; fractional
|
|
56
|
+
cents are floored, matching money.floor_cents.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class PercentRule:
|
|
61
|
+
"""A flat percentage off the amount it is given."""
|
|
62
|
+
|
|
63
|
+
def __init__(self, name, percent, priority=0):
|
|
64
|
+
self.name = name
|
|
65
|
+
self.percent = percent
|
|
66
|
+
self.priority = priority
|
|
67
|
+
|
|
68
|
+
def discount(self, amount_cents):
|
|
69
|
+
return amount_cents * self.percent // 100
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class FixedRule:
|
|
73
|
+
"""A fixed number of cents off, never more than the amount."""
|
|
74
|
+
|
|
75
|
+
def __init__(self, name, cents, priority=0):
|
|
76
|
+
self.name = name
|
|
77
|
+
self.cents = cents
|
|
78
|
+
self.priority = priority
|
|
79
|
+
|
|
80
|
+
def discount(self, amount_cents):
|
|
81
|
+
return min(self.cents, amount_cents)
|
|
82
|
+
`;
|
|
83
|
+
const MONEY_PY = `"""Money helpers. All amounts are integer cents; never use floats for money.
|
|
84
|
+
|
|
85
|
+
docs/SPEC.md "Rounding" governs how any ratio is turned back into cents.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def to_cents(dollars):
|
|
90
|
+
return int(round(dollars * 100))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def floor_cents(amount_cents):
|
|
94
|
+
return int(amount_cents)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def format_money(amount_cents):
|
|
98
|
+
return "$%d.%02d" % (amount_cents // 100, amount_cents % 100)
|
|
99
|
+
`;
|
|
100
|
+
const MODELS_PY = `"""Cart and line-item value objects. The pricing engine works on the cart's
|
|
101
|
+
subtotal (see cart_subtotal), not on individual lines.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class LineItem:
|
|
106
|
+
def __init__(self, sku, unit_cents, quantity):
|
|
107
|
+
self.sku = sku
|
|
108
|
+
self.unit_cents = unit_cents
|
|
109
|
+
self.quantity = quantity
|
|
110
|
+
|
|
111
|
+
def line_total(self):
|
|
112
|
+
return self.unit_cents * self.quantity
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Cart:
|
|
116
|
+
def __init__(self, items=None):
|
|
117
|
+
self.items = items or []
|
|
118
|
+
|
|
119
|
+
def add(self, item):
|
|
120
|
+
self.items.append(item)
|
|
121
|
+
|
|
122
|
+
def subtotal(self):
|
|
123
|
+
return sum(item.line_total() for item in self.items)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def cart_subtotal(cart):
|
|
127
|
+
return cart.subtotal()
|
|
128
|
+
`;
|
|
129
|
+
const CATALOG_PY = `"""A tiny in-memory product catalog. Not used by the pricing math, but the
|
|
130
|
+
handlers look products up here before building a cart.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
CATALOG = {
|
|
134
|
+
"BOOK-01": 1999,
|
|
135
|
+
"MUG-07": 1250,
|
|
136
|
+
"PEN-42": 399,
|
|
137
|
+
"DESK-99": 18900,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def price_of(sku):
|
|
142
|
+
return CATALOG.get(sku)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def known_skus():
|
|
146
|
+
return sorted(CATALOG)
|
|
147
|
+
`;
|
|
148
|
+
const README_MD = `# orderkit
|
|
149
|
+
|
|
150
|
+
A small order-pricing library. An order's total is its cart subtotal with a set
|
|
151
|
+
of discount **rules** applied.
|
|
152
|
+
|
|
153
|
+
## Where things live
|
|
154
|
+
|
|
155
|
+
- \`pricing.py\` - the engine: \`compute_total(subtotal_cents, rules)\`.
|
|
156
|
+
- \`rules.py\` - the rule types (\`PercentRule\`, \`FixedRule\`).
|
|
157
|
+
- \`money.py\` - integer-cents money helpers.
|
|
158
|
+
- \`models.py\` - \`Cart\` / \`LineItem\`.
|
|
159
|
+
- \`catalog.py\` - a demo product catalog.
|
|
160
|
+
- \`docs/SPEC.md\` - **the authoritative pricing rules.** If the code and the
|
|
161
|
+
spec disagree, the spec is right and the code is a bug.
|
|
162
|
+
- \`docs/ARCHITECTURE.md\` - how the modules fit together.
|
|
163
|
+
- \`docs/CHANGELOG.md\` - what changed and when.
|
|
164
|
+
|
|
165
|
+
## Running the tests
|
|
166
|
+
|
|
167
|
+
\`python -m unittest test_pricing\`
|
|
168
|
+
|
|
169
|
+
If a test fails, read \`docs/SPEC.md\` before changing the math - the intended
|
|
170
|
+
behaviour is defined there, not inferable from the current code.
|
|
171
|
+
`;
|
|
172
|
+
const SPEC_MD = `# Pricing specification
|
|
173
|
+
|
|
174
|
+
This document is authoritative. \`pricing.py\` must implement exactly what is
|
|
175
|
+
written here; where the code differs, the code is wrong.
|
|
176
|
+
|
|
177
|
+
## Inputs
|
|
178
|
+
|
|
179
|
+
\`compute_total(subtotal_cents, rules)\` receives:
|
|
180
|
+
|
|
181
|
+
- \`subtotal_cents\`: the pre-discount order total, a non-negative integer in
|
|
182
|
+
cents.
|
|
183
|
+
- \`rules\`: a list of discount rules, each exposing \`discount(amount_cents)\`
|
|
184
|
+
and an integer \`priority\`.
|
|
185
|
+
|
|
186
|
+
It returns the final total in cents, a non-negative integer.
|
|
187
|
+
|
|
188
|
+
## Rule application
|
|
189
|
+
|
|
190
|
+
### Ordering
|
|
191
|
+
|
|
192
|
+
Rules are applied in **descending priority** (highest \`priority\` first). Two
|
|
193
|
+
rules with equal priority may be applied in any order; the specification is
|
|
194
|
+
written so that the result does not depend on the order of equal-priority rules.
|
|
195
|
+
|
|
196
|
+
### Base amount — the load-bearing rule
|
|
197
|
+
|
|
198
|
+
Every rule's discount is computed against the **original subtotal**, NOT against
|
|
199
|
+
the running total after earlier rules. Discounts do **not** compound. A 30% rule
|
|
200
|
+
and a 40% rule on a $100.00 order remove \`$30.00 + $40.00 = $70.00\`, they do
|
|
201
|
+
**not** remove 30% and then 40% of what remains ($58.00 off).
|
|
202
|
+
|
|
203
|
+
This is the single most common mistake when re-implementing the engine: applying
|
|
204
|
+
each discount to the amount left by the previous one. Do not do that.
|
|
205
|
+
|
|
206
|
+
### Combined cap — the other load-bearing rule
|
|
207
|
+
|
|
208
|
+
The **sum** of all rule discounts is capped at **50% of the original subtotal**.
|
|
209
|
+
Once the accumulated discount reaches half the subtotal, no further discount is
|
|
210
|
+
applied. So \`$30.00 + $40.00 = $70.00\` of discount on a $100.00 order is capped
|
|
211
|
+
to \`$50.00\`, giving a total of \`$50.00\`, never \`$30.00\`.
|
|
212
|
+
|
|
213
|
+
The cap is on the *combined* discount, applied after summing every rule, not per
|
|
214
|
+
rule.
|
|
215
|
+
|
|
216
|
+
## Result
|
|
217
|
+
|
|
218
|
+
\`total = subtotal_cents - min(sum_of_discounts, subtotal_cents // 2)\`
|
|
219
|
+
|
|
220
|
+
The total is therefore always between 50% and 100% of the subtotal, inclusive,
|
|
221
|
+
and is a non-negative integer number of cents.
|
|
222
|
+
|
|
223
|
+
## Rounding
|
|
224
|
+
|
|
225
|
+
All arithmetic is in integer cents. A percentage discount floors fractional
|
|
226
|
+
cents (integer division), per \`money.floor_cents\`. No banker's rounding is
|
|
227
|
+
needed because the cap and the discounts are all integer-cents operations.
|
|
228
|
+
|
|
229
|
+
## Empty input
|
|
230
|
+
|
|
231
|
+
With an empty \`rules\` list the total equals the subtotal unchanged.
|
|
232
|
+
`;
|
|
233
|
+
const ARCHITECTURE_MD = `# Architecture
|
|
234
|
+
|
|
235
|
+
\`\`\`
|
|
236
|
+
catalog.py ──▶ handlers build a Cart (models.py)
|
|
237
|
+
│
|
|
238
|
+
▼
|
|
239
|
+
cart.subtotal() ── integer cents
|
|
240
|
+
│
|
|
241
|
+
▼
|
|
242
|
+
pricing.compute_total(subtotal, rules) ──▶ final total
|
|
243
|
+
▲
|
|
244
|
+
│
|
|
245
|
+
rules.py (PercentRule, FixedRule)
|
|
246
|
+
money.py (integer-cents helpers)
|
|
247
|
+
\`\`\`
|
|
248
|
+
|
|
249
|
+
## Module responsibilities
|
|
250
|
+
|
|
251
|
+
- **catalog.py** owns product prices. Nothing downstream mutates it.
|
|
252
|
+
- **models.py** turns line items into a subtotal. The pricing engine never sees
|
|
253
|
+
individual lines, only the subtotal - this keeps the discount rules independent
|
|
254
|
+
of how the cart was built.
|
|
255
|
+
- **rules.py** defines discount rules. A rule is a pure function of the amount it
|
|
256
|
+
is handed; it does not know about ordering or caps. Those are the *engine's*
|
|
257
|
+
responsibility, defined in docs/SPEC.md, not the rule's.
|
|
258
|
+
- **money.py** keeps everything in integer cents. Floats never touch money.
|
|
259
|
+
- **pricing.py** is the only place the SPEC's ordering + cap rules are enforced.
|
|
260
|
+
|
|
261
|
+
## Invariant
|
|
262
|
+
|
|
263
|
+
Because rules are pure and stateless, the engine must not let one rule's output
|
|
264
|
+
feed the next rule's input. Read docs/SPEC.md "Base amount" - each rule sees the
|
|
265
|
+
original subtotal. A bug here looks like discounts that are slightly too small
|
|
266
|
+
(because they compound) and totals that drop below half the subtotal (because the
|
|
267
|
+
cap is missing).
|
|
268
|
+
`;
|
|
269
|
+
const CHANGELOG_MD = `# Changelog
|
|
270
|
+
|
|
271
|
+
## Unreleased
|
|
272
|
+
|
|
273
|
+
- Nothing yet.
|
|
274
|
+
|
|
275
|
+
## v3.0
|
|
276
|
+
|
|
277
|
+
- **Spec:** clarified that the 50% combined cap applies to the *sum* of
|
|
278
|
+
discounts, not per rule. No code change was landed for this - see the open bug
|
|
279
|
+
where large discounts still drive totals below 50%.
|
|
280
|
+
|
|
281
|
+
## v2.0
|
|
282
|
+
|
|
283
|
+
- Added the **50% combined discount cap** to docs/SPEC.md. Previously discounts
|
|
284
|
+
were uncapped. The engine was supposed to be updated to enforce it.
|
|
285
|
+
- Added \`FixedRule\`.
|
|
286
|
+
|
|
287
|
+
## v1.1
|
|
288
|
+
|
|
289
|
+
- Established that discounts apply to the **original subtotal**, so multiple
|
|
290
|
+
rules do not compound. Documented under docs/SPEC.md "Base amount".
|
|
291
|
+
|
|
292
|
+
## v1.0
|
|
293
|
+
|
|
294
|
+
- Initial engine: \`compute_total\`, \`PercentRule\`, integer-cents money.
|
|
295
|
+
`;
|
|
296
|
+
const HANDLERS_PY = `"""Request handlers. Build a cart from SKUs, then price it. These are here so
|
|
297
|
+
the module graph looks like a real service; the pricing math lives in pricing.py.
|
|
298
|
+
"""
|
|
299
|
+
from catalog import price_of
|
|
300
|
+
from models import Cart, LineItem
|
|
301
|
+
from pricing import compute_total
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def price_order(skus_with_qty, rules):
|
|
305
|
+
cart = Cart()
|
|
306
|
+
for sku, qty in skus_with_qty:
|
|
307
|
+
unit = price_of(sku)
|
|
308
|
+
if unit is None:
|
|
309
|
+
raise KeyError("unknown sku: %s" % sku)
|
|
310
|
+
cart.add(LineItem(sku, unit, qty))
|
|
311
|
+
return compute_total(cart.subtotal(), rules)
|
|
312
|
+
`;
|
|
313
|
+
/** The hidden oracle - never shown to the model, written only at test time. Its
|
|
314
|
+
* expectations encode docs/SPEC.md exactly. */
|
|
315
|
+
export const EXTRA_HIDDEN_TEST = `import unittest
|
|
316
|
+
|
|
317
|
+
from pricing import compute_total
|
|
318
|
+
from rules import PercentRule, FixedRule
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class TestPricing(unittest.TestCase):
|
|
322
|
+
def test_empty_rules(self):
|
|
323
|
+
self.assertEqual(compute_total(10000, []), 10000)
|
|
324
|
+
|
|
325
|
+
def test_single_percent(self):
|
|
326
|
+
self.assertEqual(compute_total(10000, [PercentRule("a", 20)]), 8000)
|
|
327
|
+
|
|
328
|
+
def test_two_rules_do_not_compound(self):
|
|
329
|
+
# 30% + 40% of the ORIGINAL 10000 = 3000 + 4000 = 7000, capped at 5000.
|
|
330
|
+
rules = [PercentRule("a", 30), PercentRule("b", 40)]
|
|
331
|
+
self.assertEqual(compute_total(10000, rules), 5000)
|
|
332
|
+
|
|
333
|
+
def test_combined_cap(self):
|
|
334
|
+
# A single 60% rule is capped at 50%.
|
|
335
|
+
self.assertEqual(compute_total(10000, [PercentRule("big", 60)]), 5000)
|
|
336
|
+
|
|
337
|
+
def test_under_cap(self):
|
|
338
|
+
# 10% + 15% = 2500 discount, below the cap.
|
|
339
|
+
rules = [PercentRule("a", 10), PercentRule("b", 15)]
|
|
340
|
+
self.assertEqual(compute_total(10000, rules), 7500)
|
|
341
|
+
|
|
342
|
+
def test_fixed_and_percent_capped(self):
|
|
343
|
+
# 4000 fixed + 30% (3000) = 7000, capped at 5000.
|
|
344
|
+
rules = [FixedRule("f", 4000), PercentRule("p", 30)]
|
|
345
|
+
self.assertEqual(compute_total(10000, rules), 5000)
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
if __name__ == "__main__":
|
|
349
|
+
unittest.main()
|
|
350
|
+
`;
|
|
351
|
+
/**
|
|
352
|
+
* The files the model can see and explore. Python modules are the working copy it
|
|
353
|
+
* edits; markdown is read-only reference. The hidden test is intentionally NOT
|
|
354
|
+
* here.
|
|
355
|
+
*/
|
|
356
|
+
export const EXTRA_CORPUS = {
|
|
357
|
+
"README.md": README_MD,
|
|
358
|
+
"docs/SPEC.md": SPEC_MD,
|
|
359
|
+
"docs/ARCHITECTURE.md": ARCHITECTURE_MD,
|
|
360
|
+
"docs/CHANGELOG.md": CHANGELOG_MD,
|
|
361
|
+
"pricing.py": PRICING_PY,
|
|
362
|
+
"rules.py": RULES_PY,
|
|
363
|
+
"money.py": MONEY_PY,
|
|
364
|
+
"models.py": MODELS_PY,
|
|
365
|
+
"catalog.py": CATALOG_PY,
|
|
366
|
+
"handlers.py": HANDLERS_PY,
|
|
367
|
+
};
|
|
368
|
+
/** The Python modules that make up the runnable working copy (no docs). */
|
|
369
|
+
export const EXTRA_PY_FILES = [
|
|
370
|
+
"pricing.py",
|
|
371
|
+
"rules.py",
|
|
372
|
+
"money.py",
|
|
373
|
+
"models.py",
|
|
374
|
+
"catalog.py",
|
|
375
|
+
"handlers.py",
|
|
376
|
+
];
|
|
377
|
+
/** The one file the model is meant to fix. */
|
|
378
|
+
export const EXTRA_TARGET_FILE = "pricing.py";
|
|
379
|
+
//# sourceMappingURL=corpus.js.map
|