@ontrails/regrade 1.0.0-beta.29

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/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ // Root package surface for `@ontrails/regrade`.
2
+ export {
3
+ literalRegradeTopo,
4
+ literalRegradeTrail,
5
+ } from './literal-transform.js';
6
+ export {
7
+ buildRegradeReport,
8
+ createTermRewriteClass,
9
+ createWardenTermRewriteClass,
10
+ regradeReportOutput,
11
+ runRegrade,
12
+ selectRegradeClasses,
13
+ wardenTermRewriteClasses,
14
+ } from './downstream/report.js';
15
+ export type {
16
+ RegradeApplySummary,
17
+ RegradeClass,
18
+ RegradeClassContext,
19
+ RegradeClassResult,
20
+ RegradeReport,
21
+ RegradeReportEntry,
22
+ RegradeReviewDetail,
23
+ RegradeReviewSpan,
24
+ RegradeScanTargets,
25
+ RegradeSelection,
26
+ } from './downstream/report.js';
27
+ export {
28
+ createAstIdentifierRenameClass,
29
+ createAstRewriteClass,
30
+ } from './downstream/ast-rewrite.js';
31
+ export type {
32
+ AstIdentifierRenameClassOptions,
33
+ AstRewriteClassOptions,
34
+ AstRewriteContext,
35
+ AstRewriteMatch,
36
+ AstRewriteVisitResult,
37
+ } from './downstream/ast-rewrite.js';
@@ -0,0 +1,118 @@
1
+ import { InternalError, Result, topo, trail } from '@ontrails/core';
2
+ import { z } from 'zod';
3
+
4
+ export const regradeTransformInput = z.object({
5
+ source: z.string().describe('Source text to transform'),
6
+ });
7
+
8
+ export const regradeTransformOutput = z.object({
9
+ changed: z.boolean().describe('Whether the transform changed the source'),
10
+ nextSource: z.string().describe('Transformed source text'),
11
+ notes: z.array(z.string()).describe('Tracer notes for the transform run'),
12
+ });
13
+
14
+ const childInput = z.object({
15
+ source: z.string(),
16
+ });
17
+
18
+ /**
19
+ * Parent input schema with its raw-to-blaze transform attached.
20
+ *
21
+ * Naming the transformed schema lets examples and tests reference both its raw
22
+ * pre-transform input (`z.input`) and its post-transform blaze input
23
+ * (`z.infer`) without restating either shape by hand.
24
+ */
25
+ const regradeTransformInputToChild = regradeTransformInput.transform(
26
+ ({ source }) => ({
27
+ child: { source },
28
+ })
29
+ );
30
+
31
+ /**
32
+ * Raw, pre-transform input accepted by {@link regradeTransformInputToChild}.
33
+ *
34
+ * Trail examples and `testExamples()` feed this shape through validation; the
35
+ * Zod transform then projects it into the blaze input.
36
+ */
37
+ type RegradeTransformRawInput = z.input<typeof regradeTransformInputToChild>;
38
+
39
+ /**
40
+ * Post-transform blaze input shape — the trail's inferred input type `I`.
41
+ *
42
+ * TRL-842: With a `.transform()` input schema, the trail's inferred input type
43
+ * `I` is the transform OUTPUT (the blaze input), while examples and
44
+ * `testExamples()` validate the raw pre-transform INPUT. Those two shapes are
45
+ * disjoint, so an authored example must carry raw input typed as the
46
+ * post-transform shape. A framework-level fix would thread a separate
47
+ * `z.input<>` raw-input type parameter through `TrailSpec`, `Trail`, and every
48
+ * `trail()` overload — a core-wide generics change beyond this tracer. Until
49
+ * then the divergence is captured by the two named types here and exercised by
50
+ * the runtime validation test in `__tests__/literal-transform.test.ts`.
51
+ */
52
+ type RegradeTransformBlazeInput = z.infer<typeof regradeTransformInputToChild>;
53
+
54
+ /**
55
+ * Raw example input, statically checked as valid pre-transform input. If the
56
+ * input schema changes so this literal is no longer valid raw input, source
57
+ * typecheck fails here instead of silently relying on the cast below.
58
+ */
59
+ const codeStringExampleInput: RegradeTransformRawInput = {
60
+ source: 'export const answer = 41;',
61
+ };
62
+
63
+ export const normalizeExportConstTrail = trail(
64
+ 'regrade.literal.normalize-export-const',
65
+ {
66
+ blaze: (input) => {
67
+ const nextSource = input.source.replaceAll('export const', 'export let');
68
+ return Result.ok({
69
+ changed: nextSource !== input.source,
70
+ nextSource,
71
+ notes:
72
+ nextSource === input.source
73
+ ? ['No export const declaration found.']
74
+ : ['Rewrote export const declarations to export let.'],
75
+ });
76
+ },
77
+ input: childInput,
78
+ output: regradeTransformOutput,
79
+ visibility: 'internal',
80
+ }
81
+ );
82
+
83
+ export const literalRegradeTrail = trail('regrade.literal.run', {
84
+ blaze: async (input, ctx) => {
85
+ if (!ctx.compose) {
86
+ return Result.err(
87
+ new InternalError(
88
+ 'Literal Regrade tracer requires compose-capable execution.'
89
+ )
90
+ );
91
+ }
92
+ const blazeInput = input as RegradeTransformBlazeInput;
93
+ return await ctx.compose(normalizeExportConstTrail, blazeInput.child);
94
+ },
95
+ composes: [normalizeExportConstTrail],
96
+ examples: [
97
+ {
98
+ expected: {
99
+ changed: true,
100
+ nextSource: 'export let answer = 41;',
101
+ notes: ['Rewrote export const declarations to export let.'],
102
+ },
103
+ // TRL-842: author the raw pre-transform value (validated as
104
+ // RegradeTransformRawInput) and widen through `unknown` to the trail's
105
+ // inferred post-transform input type. The runtime still parses raw input;
106
+ // see RegradeTransformBlazeInput for why the two shapes diverge.
107
+ input: codeStringExampleInput as unknown as RegradeTransformBlazeInput,
108
+ name: 'code-string fixture',
109
+ },
110
+ ],
111
+ input: regradeTransformInputToChild,
112
+ output: regradeTransformOutput,
113
+ });
114
+
115
+ export const literalRegradeTopo = topo('regrade-literal', {
116
+ literalRegradeTrail,
117
+ normalizeExportConstTrail,
118
+ });