sdkproof 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 +192 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +201 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/classify.d.ts +4 -0
- package/dist/core/classify.js +72 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/model.d.ts +30 -0
- package/dist/core/model.js +27 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/prompt.d.ts +4 -0
- package/dist/core/prompt.js +43 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/score.d.ts +3 -0
- package/dist/core/score.js +37 -0
- package/dist/core/score.js.map +1 -0
- package/dist/core/stats.d.ts +99 -0
- package/dist/core/stats.js +121 -0
- package/dist/core/stats.js.map +1 -0
- package/dist/core/types.d.ts +162 -0
- package/dist/core/types.js +11 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/verify.d.ts +33 -0
- package/dist/core/verify.js +191 -0
- package/dist/core/verify.js.map +1 -0
- package/dist/drift.d.ts +87 -0
- package/dist/drift.js +105 -0
- package/dist/drift.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +33 -0
- package/dist/models.js +186 -0
- package/dist/models.js.map +1 -0
- package/dist/registry.d.ts +65 -0
- package/dist/registry.js +98 -0
- package/dist/registry.js.map +1 -0
- package/dist/report.d.ts +26 -0
- package/dist/report.js +240 -0
- package/dist/report.js.map +1 -0
- package/dist/run.d.ts +36 -0
- package/dist/run.js +188 -0
- package/dist/run.js.map +1 -0
- package/dist/surface.d.ts +95 -0
- package/dist/surface.js +281 -0
- package/dist/surface.js.map +1 -0
- package/dist/tarball.d.ts +7 -0
- package/dist/tarball.js +66 -0
- package/dist/tarball.js.map +1 -0
- package/dist/tasks.d.ts +41 -0
- package/dist/tasks.js +199 -0
- package/dist/tasks.js.map +1 -0
- package/dist/workspace.d.ts +42 -0
- package/dist/workspace.js +251 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { writeFile, rm } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
// A tsc "--pretty false" primary diagnostic line:
|
|
7
|
+
// path/candidate.ts(4,22): error TS2551: Property 'createOne' does not exist ...
|
|
8
|
+
const DIAG_RE = /^(.+?)\((\d+),(\d+)\):\s+error\s+(TS\d+):\s+(.*)$/;
|
|
9
|
+
// Error codes that indicate misuse of an API surface (a hallucinated/wrong/
|
|
10
|
+
// removed member or signature) rather than a generic JS mistake.
|
|
11
|
+
export const API_SHAPE_CODES = new Set([
|
|
12
|
+
"TS2339", // property does not exist on type
|
|
13
|
+
"TS2551", // property does not exist — did you mean X
|
|
14
|
+
"TS2353", // object literal may only specify known properties (invented field)
|
|
15
|
+
"TS2561", // did you mean to write X
|
|
16
|
+
"TS2554", // wrong number of arguments
|
|
17
|
+
"TS2345", // argument type not assignable
|
|
18
|
+
"TS2322", // type not assignable
|
|
19
|
+
"TS2559", // type has no properties in common with
|
|
20
|
+
"TS2307", // cannot find module (bad import path)
|
|
21
|
+
"TS2724", // module has no exported member — did you mean X
|
|
22
|
+
"TS2305", // module has no exported member (the member moved entrypoint)
|
|
23
|
+
"TS1192", // module has no default export (the default export was removed)
|
|
24
|
+
"TS2694", // namespace has no exported member
|
|
25
|
+
// The call/type-argument shape changed under the model's feet. All four were
|
|
26
|
+
// landing in the residual bucket while being exactly the thing this harness
|
|
27
|
+
// measures: TS2314 alone accounts for more diagnostics across the bench than
|
|
28
|
+
// any other code, and TS2558 is the third error in the README's own
|
|
29
|
+
// TanStack Table example.
|
|
30
|
+
"TS2769", // no overload matches this call
|
|
31
|
+
"TS2314", // generic type requires N type argument(s)
|
|
32
|
+
"TS2558", // expected N type arguments, but got M
|
|
33
|
+
"TS2707", // generic type requires between N and M type arguments
|
|
34
|
+
"TS2347", // untyped function calls may not accept type arguments
|
|
35
|
+
]);
|
|
36
|
+
/**
|
|
37
|
+
* Type-check a model-generated candidate against the real installed package,
|
|
38
|
+
* inside the library's sandbox fixture. A candidate "passes" iff it compiles
|
|
39
|
+
* clean under the fixture's strict tsconfig.
|
|
40
|
+
*/
|
|
41
|
+
export async function verify(candidate, spec, opts) {
|
|
42
|
+
// An empty or bodyless candidate compiles clean, so without this it scores as
|
|
43
|
+
// a PASS — a generation failure recorded as a perfect answer. Found on the
|
|
44
|
+
// first Stripe run (2026-08-04): four of fifteen candidates came back empty
|
|
45
|
+
// because the model hit max_tokens, lost its closing fence, and extraction
|
|
46
|
+
// returned nothing. All four "passed" and the library scored 100/100.
|
|
47
|
+
//
|
|
48
|
+
// Every task skeleton asks for an export, so a candidate with no `export`
|
|
49
|
+
// has not answered. That is a harness failure, not model drift, and it is
|
|
50
|
+
// reported with a code outside API_SHAPE_CODES so it can never be counted as
|
|
51
|
+
// a library-drift finding.
|
|
52
|
+
// A candidate may not redefine the library it is being measured against.
|
|
53
|
+
// TypeScript module augmentation ADDS the declared members to the module's
|
|
54
|
+
// exports, so `declare module "react-router" { interface AppLoadContext {} }`
|
|
55
|
+
// re-creates a type v8 deleted and the accompanying import resolves — a
|
|
56
|
+
// candidate written entirely against the REMOVED API compiles clean and
|
|
57
|
+
// scores as a PASS. Found 2026-08-17 probing react-router v8: two of five
|
|
58
|
+
// candidates that reached for the deleted `AppLoadContext` passed, purely
|
|
59
|
+
// because they also wrote the augmentation. The third, which imported it
|
|
60
|
+
// without augmenting, failed with TS2305 as it should.
|
|
61
|
+
//
|
|
62
|
+
// This is the same failure class as an empty candidate passing: the harness
|
|
63
|
+
// converts "the model used the old API" into "the model got it right".
|
|
64
|
+
// SDKP002 is deliberately outside API_SHAPE_CODES so it can never be counted
|
|
65
|
+
// as library drift either.
|
|
66
|
+
const augmented = augmentsLibrary(candidate.code, spec.packageName);
|
|
67
|
+
if (augmented) {
|
|
68
|
+
return {
|
|
69
|
+
taskId: candidate.taskId,
|
|
70
|
+
model: candidate.model,
|
|
71
|
+
passed: false,
|
|
72
|
+
errors: [{ code: "SDKP002", message: augmented, line: 0, column: 0, libraryRelated: false }],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Runs BEFORE the empty-candidate check on purpose: augmentation is the more
|
|
76
|
+
// specific diagnosis, and emptyCandidate's `declare` strip is line-oriented in
|
|
77
|
+
// intent but its [^;]* spans newlines, so a multi-line `declare module` block
|
|
78
|
+
// swallows the rest of the candidate and reports SDKP001 instead.
|
|
79
|
+
const empty = emptyCandidate(candidate.code);
|
|
80
|
+
if (empty) {
|
|
81
|
+
return {
|
|
82
|
+
taskId: candidate.taskId,
|
|
83
|
+
model: candidate.model,
|
|
84
|
+
passed: false,
|
|
85
|
+
errors: [{ code: "SDKP001", message: empty, line: 0, column: 0, libraryRelated: false }],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const candidatePath = path.join(spec.fixtureDir, spec.candidateFile ?? "candidate.ts");
|
|
89
|
+
const tsconfigPath = path.join(spec.fixtureDir, "tsconfig.json");
|
|
90
|
+
await writeFile(candidatePath, candidate.code, "utf8");
|
|
91
|
+
try {
|
|
92
|
+
const output = await runTsc(opts.tscEntry, tsconfigPath);
|
|
93
|
+
const errors = parseDiagnostics(output, spec);
|
|
94
|
+
return {
|
|
95
|
+
taskId: candidate.taskId,
|
|
96
|
+
model: candidate.model,
|
|
97
|
+
passed: errors.length === 0,
|
|
98
|
+
errors,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
await rm(candidatePath, { force: true });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Detect a candidate that augments the module it is supposed to be USING.
|
|
107
|
+
* Matches the package itself and any subpath entrypoint of it, so
|
|
108
|
+
* `declare module "@apollo/client/react"` is caught as well as
|
|
109
|
+
* `declare module "@apollo/client"`.
|
|
110
|
+
*
|
|
111
|
+
* Deliberately conservative: it fires on ANY augmentation of the library's own
|
|
112
|
+
* module, not only ones that redeclare a removed symbol. Telling those apart
|
|
113
|
+
* needs type introspection, and the cost of being wrong is asymmetric — a
|
|
114
|
+
* false positive costs one task, a false negative silently inflates a
|
|
115
|
+
* published score. Measured before shipping: `declare module` appears in 0 of
|
|
116
|
+
* 35 stored candidate files, so this fires on nothing that has ever been run.
|
|
117
|
+
*/
|
|
118
|
+
export function augmentsLibrary(code, packageName) {
|
|
119
|
+
const pkg = packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
120
|
+
const re = new RegExp(`declare\\s+module\\s+["'\`]${pkg}(?:/[^"'\`]*)?["'\`]`);
|
|
121
|
+
const m = re.exec(code);
|
|
122
|
+
return m
|
|
123
|
+
? `module augmentation: the candidate redefines "${packageName}" (${m[0].trim()}), which can re-create an API the package removed`
|
|
124
|
+
: null;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Reject candidates that cannot possibly be an answer. Returns a reason string
|
|
128
|
+
* when the candidate is unusable, or null when it is worth compiling.
|
|
129
|
+
*/
|
|
130
|
+
export function emptyCandidate(code) {
|
|
131
|
+
const trimmed = code.trim();
|
|
132
|
+
if (!trimmed)
|
|
133
|
+
return "empty candidate: the model returned no code";
|
|
134
|
+
// Strip comments and single-line imports; what remains must contain an export.
|
|
135
|
+
//
|
|
136
|
+
// The character class excludes newlines, which the original did not. `[^;]*`
|
|
137
|
+
// spans lines, so a candidate written WITHOUT SEMICOLONS had its entire body
|
|
138
|
+
// swallowed by the import strip and was reported as an empty candidate —
|
|
139
|
+
// a complete, correct answer recorded as a generation failure. It cost
|
|
140
|
+
// zustand a task on 2026-08-04 (`shallow-equality`, a 78-line answer scored
|
|
141
|
+
// as "no implementation") and every candidate of the first @sanity/client run
|
|
142
|
+
// through the CLI on 2026-08-22, because that model writes semicolon-free TS.
|
|
143
|
+
//
|
|
144
|
+
// A multi-line import is now left in place rather than stripped, which is the
|
|
145
|
+
// safe direction: it only ever makes `body` non-empty, so the candidate goes
|
|
146
|
+
// to the compiler and tsc decides instead of this heuristic.
|
|
147
|
+
const body = trimmed
|
|
148
|
+
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
149
|
+
.replace(/^\s*\/\/.*$/gm, "")
|
|
150
|
+
.replace(/^\s*import\s[^;\n]*;?\s*$/gm, "")
|
|
151
|
+
.replace(/^\s*declare\s[^;\n]*;?\s*$/gm, "")
|
|
152
|
+
.trim();
|
|
153
|
+
if (!body)
|
|
154
|
+
return "empty candidate: only imports and comments, no implementation";
|
|
155
|
+
if (!/\bexport\b/.test(body))
|
|
156
|
+
return "no export: the candidate does not implement the requested export";
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
async function runTsc(tscEntry, tsconfigPath) {
|
|
160
|
+
try {
|
|
161
|
+
const { stdout } = await execFileAsync(process.execPath, [tscEntry, "-p", tsconfigPath, "--pretty", "false"], { maxBuffer: 16 * 1024 * 1024 });
|
|
162
|
+
return stdout;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
// tsc exits non-zero when it reports errors; diagnostics are on stdout.
|
|
166
|
+
const e = err;
|
|
167
|
+
return (e.stdout ?? "") + (e.stderr ?? "");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** Parse tsc "--pretty false" output into structured errors for the candidate. */
|
|
171
|
+
export function parseDiagnostics(output, spec) {
|
|
172
|
+
const errors = [];
|
|
173
|
+
for (const line of output.split(/\r?\n/)) {
|
|
174
|
+
const m = DIAG_RE.exec(line);
|
|
175
|
+
if (!m)
|
|
176
|
+
continue;
|
|
177
|
+
const [, file, lineNo, colNo, code, message] = m;
|
|
178
|
+
// Only diagnostics in the candidate file reflect the model's code.
|
|
179
|
+
if (path.basename(file) !== (spec.candidateFile ?? "candidate.ts"))
|
|
180
|
+
continue;
|
|
181
|
+
errors.push({
|
|
182
|
+
code,
|
|
183
|
+
message,
|
|
184
|
+
line: Number(lineNo),
|
|
185
|
+
column: Number(colNo),
|
|
186
|
+
libraryRelated: API_SHAPE_CODES.has(code) || message.includes(spec.packageName),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return errors;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/core/verify.ts"],"names":[],"mappings":"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"}
|
package/dist/drift.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type Packument } from "./registry.ts";
|
|
2
|
+
import { type Surface } from "./surface.ts";
|
|
3
|
+
/**
|
|
4
|
+
* What changed between two published versions of a package, computed from the
|
|
5
|
+
* .d.ts files alone — no model, no API key, no install.
|
|
6
|
+
*
|
|
7
|
+
* This answers the question that decides whether a scored run is worth paying
|
|
8
|
+
* for: has this package removed anything a model is likely to still be writing?
|
|
9
|
+
*/
|
|
10
|
+
export interface DriftReport {
|
|
11
|
+
package: string;
|
|
12
|
+
from: {
|
|
13
|
+
version: string;
|
|
14
|
+
major: number;
|
|
15
|
+
published: string;
|
|
16
|
+
};
|
|
17
|
+
to: {
|
|
18
|
+
version: string;
|
|
19
|
+
major: number;
|
|
20
|
+
published: string;
|
|
21
|
+
};
|
|
22
|
+
/** months since the FIRST release in the `to` version's major line */
|
|
23
|
+
majorAgeMonths: number;
|
|
24
|
+
/** which extraction mode was used for BOTH versions — never mixed */
|
|
25
|
+
mode: "entry-only" | "all-dts";
|
|
26
|
+
fromCount: number;
|
|
27
|
+
toCount: number;
|
|
28
|
+
/** exported symbols present in `from` and gone in `to`, under `mode` */
|
|
29
|
+
removed: string[];
|
|
30
|
+
/**
|
|
31
|
+
* The subset of `removed` that carried no `@deprecated` jsdoc in the old
|
|
32
|
+
* version. Deprecate-then-remove gives a model's training data a signal to
|
|
33
|
+
* pick up; a silent removal does not, which is where the drift lives.
|
|
34
|
+
*/
|
|
35
|
+
withoutRunway: string[];
|
|
36
|
+
/**
|
|
37
|
+
* The same thing computed from the package's declared type ENTRYPOINT only —
|
|
38
|
+
* what `import { x } from "pkg"` can actually reach. This is the sharp list.
|
|
39
|
+
* `removed` widens to every .d.ts in the package when either version's entry
|
|
40
|
+
* re-exports with `export *`, which drags in internals nobody imports.
|
|
41
|
+
*/
|
|
42
|
+
removedFromEntry: string[];
|
|
43
|
+
/**
|
|
44
|
+
* The subset of `removedFromEntry` that the OLD version's README actually
|
|
45
|
+
* documents. A removed export nobody wrote produces no drift; a removed
|
|
46
|
+
* export the library taught people to write produces all of it. This is the
|
|
47
|
+
* list to lead with, and the reason `zod` looks alarming on raw counts —
|
|
48
|
+
* 155 exports went, but most were internal type aliases nobody imported.
|
|
49
|
+
*/
|
|
50
|
+
documentedRemovals: string[];
|
|
51
|
+
/**
|
|
52
|
+
* The subset of `removedFromEntry` that was a value — a function, hook,
|
|
53
|
+
* class, const or enum — rather than a type-only declaration. A model writes
|
|
54
|
+
* values far more often than type names, so this is the sharper list when the
|
|
55
|
+
* package ships a README too thin to rank against.
|
|
56
|
+
*/
|
|
57
|
+
valueRemovals: string[];
|
|
58
|
+
}
|
|
59
|
+
export interface DriftOptions {
|
|
60
|
+
/** explicit lower version; defaults to the top of the previous major line */
|
|
61
|
+
from?: string;
|
|
62
|
+
/** explicit upper version; defaults to the top of the newest major line */
|
|
63
|
+
to?: string;
|
|
64
|
+
}
|
|
65
|
+
export declare function computeDrift(p: Packument, opts?: DriftOptions): Promise<DriftReport>;
|
|
66
|
+
/** What one surface lost relative to another. Split out so it can be tested without the network. */
|
|
67
|
+
export declare function diffSurfaces(a: Surface, b: Surface, oldReadme: string): Pick<DriftReport, "mode" | "fromCount" | "toCount" | "removed" | "withoutRunway" | "removedFromEntry" | "documentedRemovals" | "valueRemovals">;
|
|
68
|
+
/**
|
|
69
|
+
* The list worth showing a human, sharpest first: exports the old README
|
|
70
|
+
* documented, else everything that left the entrypoint, else the wide diff.
|
|
71
|
+
*/
|
|
72
|
+
export declare function headlineRemovals(d: DriftReport): string[];
|
|
73
|
+
/** How the headline list was arrived at, for a caption the reader can trust. */
|
|
74
|
+
export declare function headlineSource(d: DriftReport): string;
|
|
75
|
+
/**
|
|
76
|
+
* Whether a scored run is likely to find anything, and why. Two facts drive
|
|
77
|
+
* this, both measured across 35 libraries on this project's bench:
|
|
78
|
+
*
|
|
79
|
+
* - the drift window closes. Age of the major predicts drift better than the
|
|
80
|
+
* size of the change does: Apollo v4 scored 0/12 once it had been out long
|
|
81
|
+
* enough, and zustand v5 was fully absorbed by ~19 months.
|
|
82
|
+
* - a removal with a deprecation runway produces almost nothing.
|
|
83
|
+
*/
|
|
84
|
+
export declare function driftVerdict(d: DriftReport): {
|
|
85
|
+
worth: boolean;
|
|
86
|
+
reason: string;
|
|
87
|
+
};
|
package/dist/drift.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { compareVersions, majorLines, monthsSince, readmeFor } from "./registry.js";
|
|
2
|
+
import { isDeprecated, isPublicName, isValueExport, surfaceOf } from "./surface.js";
|
|
3
|
+
export async function computeDrift(p, opts = {}) {
|
|
4
|
+
const lines = majorLines(p);
|
|
5
|
+
if ((!opts.from || !opts.to) && lines.length < 2) {
|
|
6
|
+
throw new Error(`${p.name} has only one major line — there is nothing to diff. Pass --from and --to to compare two specific versions.`);
|
|
7
|
+
}
|
|
8
|
+
const fromVersion = opts.from ?? lines[lines.length - 2].latest;
|
|
9
|
+
const toVersion = opts.to ?? lines[lines.length - 1].latest;
|
|
10
|
+
if (compareVersions(fromVersion, toVersion) >= 0) {
|
|
11
|
+
throw new Error(`--from (${fromVersion}) must be older than --to (${toVersion})`);
|
|
12
|
+
}
|
|
13
|
+
const [a, b] = await Promise.all([surfaceOf(p, fromVersion), surfaceOf(p, toVersion)]);
|
|
14
|
+
const diff = diffSurfaces(a, b, a.readme || readmeFor(p, fromVersion));
|
|
15
|
+
const toMajor = Number(toVersion.split(".")[0]);
|
|
16
|
+
const toLine = lines.find((l) => l.major === toMajor);
|
|
17
|
+
return {
|
|
18
|
+
package: p.name,
|
|
19
|
+
from: { version: fromVersion, major: Number(fromVersion.split(".")[0]), published: p.time?.[fromVersion] ?? "" },
|
|
20
|
+
to: { version: toVersion, major: toMajor, published: p.time?.[toVersion] ?? "" },
|
|
21
|
+
majorAgeMonths: Number(monthsSince(toLine?.first ?? p.time?.[toVersion] ?? "").toFixed(1)),
|
|
22
|
+
...diff,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** What one surface lost relative to another. Split out so it can be tested without the network. */
|
|
26
|
+
export function diffSurfaces(a, b, oldReadme) {
|
|
27
|
+
// ONE mode for the pair. Deciding per version is what made Apollo read as a
|
|
28
|
+
// 674 -> 133 collapse when the real removal count was far smaller.
|
|
29
|
+
const widen = a.needsWiden || b.needsWiden;
|
|
30
|
+
const fromSyms = widen ? a.widened : a.entryOnly;
|
|
31
|
+
const toSyms = widen ? b.widened : b.entryOnly;
|
|
32
|
+
const removed = [...fromSyms].filter((s) => !toSyms.has(s) && isPublicName(s)).sort();
|
|
33
|
+
const withoutRunway = removed.filter((s) => !isDeprecated(a.sources, s));
|
|
34
|
+
const removedFromEntry = [...a.entryOnly]
|
|
35
|
+
.filter((s) => !b.entryOnly.has(s) && isPublicName(s) && !isDeprecated(a.sources, s))
|
|
36
|
+
.sort();
|
|
37
|
+
// Word-boundary hits in the old README, so `parse` does not match `safeParse`.
|
|
38
|
+
const documentedRemovals = removedFromEntry.filter((sym) => new RegExp(`\\b${sym.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`).test(oldReadme));
|
|
39
|
+
const valueRemovals = removedFromEntry.filter((sym) => isValueExport(a.sources, sym));
|
|
40
|
+
return {
|
|
41
|
+
mode: widen ? "all-dts" : "entry-only",
|
|
42
|
+
fromCount: fromSyms.size,
|
|
43
|
+
toCount: toSyms.size,
|
|
44
|
+
removed,
|
|
45
|
+
withoutRunway,
|
|
46
|
+
removedFromEntry,
|
|
47
|
+
documentedRemovals,
|
|
48
|
+
valueRemovals,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The list worth showing a human, sharpest first: exports the old README
|
|
53
|
+
* documented, else everything that left the entrypoint, else the wide diff.
|
|
54
|
+
*/
|
|
55
|
+
export function headlineRemovals(d) {
|
|
56
|
+
if (d.documentedRemovals.length)
|
|
57
|
+
return d.documentedRemovals;
|
|
58
|
+
if (d.valueRemovals.length)
|
|
59
|
+
return d.valueRemovals;
|
|
60
|
+
return d.removedFromEntry.length ? d.removedFromEntry : d.withoutRunway;
|
|
61
|
+
}
|
|
62
|
+
/** How the headline list was arrived at, for a caption the reader can trust. */
|
|
63
|
+
export function headlineSource(d) {
|
|
64
|
+
if (d.documentedRemovals.length) {
|
|
65
|
+
return "exports the old README documented, gone from the entrypoint with no deprecation first";
|
|
66
|
+
}
|
|
67
|
+
if (d.valueRemovals.length) {
|
|
68
|
+
return "functions, hooks and classes gone from the entrypoint with no deprecation first";
|
|
69
|
+
}
|
|
70
|
+
if (d.removedFromEntry.length)
|
|
71
|
+
return "exports gone from the entrypoint with no deprecation first";
|
|
72
|
+
return "symbols gone from a .d.ts in the package with no deprecation first";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Whether a scored run is likely to find anything, and why. Two facts drive
|
|
76
|
+
* this, both measured across 35 libraries on this project's bench:
|
|
77
|
+
*
|
|
78
|
+
* - the drift window closes. Age of the major predicts drift better than the
|
|
79
|
+
* size of the change does: Apollo v4 scored 0/12 once it had been out long
|
|
80
|
+
* enough, and zustand v5 was fully absorbed by ~19 months.
|
|
81
|
+
* - a removal with a deprecation runway produces almost nothing.
|
|
82
|
+
*/
|
|
83
|
+
export function driftVerdict(d) {
|
|
84
|
+
const headline = headlineRemovals(d);
|
|
85
|
+
if (!headline.length) {
|
|
86
|
+
return {
|
|
87
|
+
worth: false,
|
|
88
|
+
reason: d.removed.length
|
|
89
|
+
? `${d.removed.length} symbol(s) went, but every one was deprecated first — that runway is what stops the drift`
|
|
90
|
+
: `nothing was removed from the package entrypoint between v${d.from.major} and v${d.to.major}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (d.majorAgeMonths > 18) {
|
|
94
|
+
return {
|
|
95
|
+
worth: false,
|
|
96
|
+
reason: `v${d.to.major} is ${d.majorAgeMonths.toFixed(0)} months old — old enough that models have absorbed it`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
worth: true,
|
|
101
|
+
reason: `${headline.length} ${headlineSource(d)}, ` +
|
|
102
|
+
`in a major that is ${d.majorAgeMonths.toFixed(0)} months old`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../src/drift.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic entrypoint. Everything the CLI does is available here, so a
|
|
3
|
+
* project can score its own package in CI without shelling out.
|
|
4
|
+
*/
|
|
5
|
+
export { run, parseSpec, type RunOptions, type RunOutcome } from "./run.ts";
|
|
6
|
+
export { computeDrift, driftVerdict, type DriftReport, type DriftOptions } from "./drift.ts";
|
|
7
|
+
export { surfaceOf, symbolsFromSource, isDeprecated, type Surface } from "./surface.ts";
|
|
8
|
+
export { fetchPackument, resolveVersion, majorLines, readmeFor, requiredPeers, type Packument, type VersionMeta, type MajorLine, } from "./registry.ts";
|
|
9
|
+
export { prepareWorkspace, resolveTsc, cacheRoot, type Workspace } from "./workspace.ts";
|
|
10
|
+
export { synthesizeTasks, loadTaskFile, validateTasks, type TaskSet } from "./tasks.ts";
|
|
11
|
+
export { renderTerminal, renderMarkdown, renderDrift, type RunContext } from "./report.ts";
|
|
12
|
+
export { anthropicAdapter, openaiAdapter, adapterFor, defaultAdapters, parseModelRef, type ModelRef, } from "./models.ts";
|
|
13
|
+
export { verify, parseDiagnostics, augmentsLibrary, API_SHAPE_CODES } from "./core/verify.ts";
|
|
14
|
+
export { score } from "./core/score.ts";
|
|
15
|
+
export { classify, categorize } from "./core/classify.ts";
|
|
16
|
+
export { buildUserPrompt, extractCode, GENERATION_SYSTEM } from "./core/prompt.ts";
|
|
17
|
+
export { wilson, rates, fmtInterval } from "./core/stats.ts";
|
|
18
|
+
export type * from "./core/types.ts";
|
|
19
|
+
export { RefusalError, FatalApiError, type ModelAdapter, type GenerateRequest } from "./core/model.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic entrypoint. Everything the CLI does is available here, so a
|
|
3
|
+
* project can score its own package in CI without shelling out.
|
|
4
|
+
*/
|
|
5
|
+
export { run, parseSpec } from "./run.js";
|
|
6
|
+
export { computeDrift, driftVerdict } from "./drift.js";
|
|
7
|
+
export { surfaceOf, symbolsFromSource, isDeprecated } from "./surface.js";
|
|
8
|
+
export { fetchPackument, resolveVersion, majorLines, readmeFor, requiredPeers, } from "./registry.js";
|
|
9
|
+
export { prepareWorkspace, resolveTsc, cacheRoot } from "./workspace.js";
|
|
10
|
+
export { synthesizeTasks, loadTaskFile, validateTasks } from "./tasks.js";
|
|
11
|
+
export { renderTerminal, renderMarkdown, renderDrift } from "./report.js";
|
|
12
|
+
export { anthropicAdapter, openaiAdapter, adapterFor, defaultAdapters, parseModelRef, } from "./models.js";
|
|
13
|
+
export { verify, parseDiagnostics, augmentsLibrary, API_SHAPE_CODES } from "./core/verify.js";
|
|
14
|
+
export { score } from "./core/score.js";
|
|
15
|
+
export { classify, categorize } from "./core/classify.js";
|
|
16
|
+
export { buildUserPrompt, extractCode, GENERATION_SYSTEM } from "./core/prompt.js";
|
|
17
|
+
export { wilson, rates, fmtInterval } from "./core/stats.js";
|
|
18
|
+
export { RefusalError, FatalApiError } from "./core/model.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,GAAG,EAAE,SAAS,EAAoC,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAuC,MAAM,YAAY,CAAC;AAC7F,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAgB,MAAM,cAAc,CAAC;AACxF,OAAO,EACL,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,GAErE,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAkB,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAC;AAC3F,OAAO,EACL,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,GAE5E,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,aAAa,EAA2C,MAAM,iBAAiB,CAAC"}
|
package/dist/models.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ModelAdapter } from "./core/model.ts";
|
|
2
|
+
/** Reset between runs; only the test suite and long-lived embeddings need this. */
|
|
3
|
+
export declare function clearFatal(): void;
|
|
4
|
+
export declare class ApiError extends Error {
|
|
5
|
+
readonly status: number;
|
|
6
|
+
constructor(status: number, message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Claude adapter over the raw Messages API — no SDK, so `npx sdkproof` installs
|
|
10
|
+
* one dependency (typescript) instead of a tree.
|
|
11
|
+
*
|
|
12
|
+
* ANTHROPIC_AUTH_TOKEN is accepted alongside ANTHROPIC_API_KEY because an OAuth
|
|
13
|
+
* token from a Claude subscription is the key most people already have.
|
|
14
|
+
*/
|
|
15
|
+
export declare function anthropicAdapter(model: string): ModelAdapter;
|
|
16
|
+
/** GPT adapter over the raw Chat Completions API. */
|
|
17
|
+
export declare function openaiAdapter(model: string): ModelAdapter;
|
|
18
|
+
export interface ModelRef {
|
|
19
|
+
provider: "anthropic" | "openai";
|
|
20
|
+
model: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const DEFAULT_ANTHROPIC_MODEL: string;
|
|
23
|
+
export declare const DEFAULT_OPENAI_MODEL: string;
|
|
24
|
+
/**
|
|
25
|
+
* Turn a `--model` value into a provider + model id. Accepts an explicit
|
|
26
|
+
* `anthropic:<id>` / `openai:<id>`, or a bare id whose provider is inferred
|
|
27
|
+
* from its prefix — so `--model claude-sonnet-5` and `--model gpt-5` both work.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseModelRef(value: string): ModelRef;
|
|
30
|
+
export declare function adapterFor(ref: ModelRef): ModelAdapter;
|
|
31
|
+
export declare function hasKeyFor(provider: ModelRef["provider"]): boolean;
|
|
32
|
+
/** Every model the environment holds a key for, when --model was not given. */
|
|
33
|
+
export declare function defaultAdapters(): ModelAdapter[];
|