@aid-framework/cli 0.0.0-stage → 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +45 -2
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/args.d.ts +37 -0
  5. package/dist/args.d.ts.map +1 -0
  6. package/dist/args.js +74 -0
  7. package/dist/args.js.map +1 -0
  8. package/dist/cli.d.ts +17 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +26 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/eval.d.ts +44 -0
  13. package/dist/commands/eval.d.ts.map +1 -0
  14. package/dist/commands/eval.js +257 -0
  15. package/dist/commands/eval.js.map +1 -0
  16. package/dist/commands/gen.d.ts +42 -0
  17. package/dist/commands/gen.d.ts.map +1 -0
  18. package/dist/commands/gen.js +138 -0
  19. package/dist/commands/gen.js.map +1 -0
  20. package/dist/commands/ingest.d.ts +44 -0
  21. package/dist/commands/ingest.d.ts.map +1 -0
  22. package/dist/commands/ingest.js +238 -0
  23. package/dist/commands/ingest.js.map +1 -0
  24. package/dist/commands/init.d.ts +38 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +203 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/validate.d.ts +22 -0
  29. package/dist/commands/validate.d.ts.map +1 -0
  30. package/dist/commands/validate.js +53 -0
  31. package/dist/commands/validate.js.map +1 -0
  32. package/dist/context.d.ts +37 -0
  33. package/dist/context.d.ts.map +1 -0
  34. package/dist/context.js +36 -0
  35. package/dist/context.js.map +1 -0
  36. package/dist/diagnostics.d.ts +42 -0
  37. package/dist/diagnostics.d.ts.map +1 -0
  38. package/dist/diagnostics.js +47 -0
  39. package/dist/diagnostics.js.map +1 -0
  40. package/dist/exit.d.ts +16 -0
  41. package/dist/exit.d.ts.map +1 -0
  42. package/dist/exit.js +15 -0
  43. package/dist/exit.js.map +1 -0
  44. package/dist/index.d.ts +42 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +29 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/main.d.ts +25 -0
  49. package/dist/main.d.ts.map +1 -0
  50. package/dist/main.js +155 -0
  51. package/dist/main.js.map +1 -0
  52. package/dist/output.d.ts +48 -0
  53. package/dist/output.d.ts.map +1 -0
  54. package/dist/output.js +50 -0
  55. package/dist/output.js.map +1 -0
  56. package/dist/paths.d.ts +21 -0
  57. package/dist/paths.d.ts.map +1 -0
  58. package/dist/paths.js +31 -0
  59. package/dist/paths.js.map +1 -0
  60. package/dist/pipeline.d.ts +74 -0
  61. package/dist/pipeline.d.ts.map +1 -0
  62. package/dist/pipeline.js +113 -0
  63. package/dist/pipeline.js.map +1 -0
  64. package/dist/python.d.ts +30 -0
  65. package/dist/python.d.ts.map +1 -0
  66. package/dist/python.js +57 -0
  67. package/dist/python.js.map +1 -0
  68. package/dist/targets.d.ts +75 -0
  69. package/dist/targets.d.ts.map +1 -0
  70. package/dist/targets.js +136 -0
  71. package/dist/targets.js.map +1 -0
  72. package/dist/usage.d.ts +20 -0
  73. package/dist/usage.d.ts.map +1 -0
  74. package/dist/usage.js +49 -0
  75. package/dist/usage.js.map +1 -0
  76. package/package.json +46 -3
@@ -0,0 +1,203 @@
1
+ /**
2
+ * `aid init` — scaffold a project: a starter spec and a README.
3
+ *
4
+ * It does not generate. `aid gen` generates, and `--gen` is the convenience for the one
5
+ * thing a person types next; keeping the two apart is what makes "scaffold" and "compile"
6
+ * separately testable and separately re-runnable.
7
+ *
8
+ * Two deliberate refusals, because scaffolding is the command most likely to be pointed at
9
+ * a directory that already has something in it:
10
+ *
11
+ * - An existing spec is not overwritten without `--force`. That file is the project's
12
+ * source of truth; replacing it silently is the worst thing this command could do.
13
+ * - An existing README is left exactly as it is, and reported as skipped -- under `--force`
14
+ * too. A README is the file a directory is most likely to already have, its contents are
15
+ * the author's, and `--force` here is usually aimed at the spec.
16
+ *
17
+ * `--from <spec>` imports a spec rather than copying one: the imported text has to lower to
18
+ * an IR and pass the gates before anything is written, so `aid init --from` cannot produce a
19
+ * project that `aid validate` immediately rejects.
20
+ */
21
+ import { mkdirSync, writeFileSync } from 'node:fs';
22
+ import { basename, join, resolve } from 'node:path';
23
+ import { CLI_DIAGNOSTIC_CODES, cliError } from '../diagnostics.js';
24
+ import { EXIT_FAILURE, EXIT_OK, EXIT_USAGE } from '../exit.js';
25
+ import { outcome } from '../output.js';
26
+ import { absolutePath, parentPath } from '../paths.js';
27
+ import { lowerSpec, readSpec } from '../pipeline.js';
28
+ import { resolveTarget, unknownTargetDiagnostic } from '../targets.js';
29
+ import { generate } from './gen.js';
30
+ /**
31
+ * Lower-case a directory name, keep only `[a-z0-9]`, and collapse every run of anything
32
+ * else into a single `-`.
33
+ *
34
+ * A loop rather than a regular expression on purpose: trimming with `/^-+|-+$/g` after
35
+ * collapsing is quadratic on a name that is mostly separators, and the directory name is
36
+ * input this command does not control. Emitting the separator only between two kept
37
+ * characters means the result can never begin or end with one, so no trim pass is needed.
38
+ */
39
+ function slugify(name) {
40
+ let slug = '';
41
+ let separatorPending = false;
42
+ for (const character of name.toLowerCase()) {
43
+ if (!((character >= 'a' && character <= 'z') || (character >= '0' && character <= '9'))) {
44
+ separatorPending = true;
45
+ continue;
46
+ }
47
+ if (separatorPending && slug !== '')
48
+ slug += '-';
49
+ separatorPending = false;
50
+ slug += character;
51
+ }
52
+ return slug;
53
+ }
54
+ /**
55
+ * A `project.name` from a directory name. The spec's pattern is `^[a-z][a-z0-9-]{0,63}$`,
56
+ * and a directory called `My App` or `2024-prototype` is not a reason to fail `aid init`
57
+ * with a schema error about a field the caller never wrote.
58
+ */
59
+ export function projectNameFor(directory) {
60
+ const slug = slugify(basename(directory)).slice(0, 64);
61
+ if (slug === '')
62
+ return 'app';
63
+ const first = slug.charAt(0);
64
+ return first >= 'a' && first <= 'z' ? slug : `app-${slug}`.slice(0, 64);
65
+ }
66
+ export function starterSpec(target, projectName) {
67
+ return [
68
+ 'specVersion: "0.1"',
69
+ '',
70
+ '# This file is the source of truth: `aid gen` compiles it into app/generated/,',
71
+ '# `aid validate` checks it, and `aid eval` gates the behaviour it declares.',
72
+ 'project:',
73
+ ` name: ${projectName}`,
74
+ ' targets:',
75
+ ` - ${target}`,
76
+ '',
77
+ ].join('\n');
78
+ }
79
+ function starterReadme(projectName, target) {
80
+ return [
81
+ `# ${projectName}`,
82
+ '',
83
+ `An AID Framework project targeting \`${target.name}\`. \`${target.specPath}\` is the source`,
84
+ 'of truth: the types, prompts, tools, pipelines and evals the application is made of.',
85
+ '',
86
+ '```bash',
87
+ 'aid validate # parse the spec, reduce it to the IR, run every build-time gate',
88
+ 'aid gen # compile the spec and reconcile the tree with it',
89
+ 'aid gen --dry-run # report what would change, and write nothing',
90
+ 'aid eval # run the eval gate',
91
+ '```',
92
+ '',
93
+ `\`${target.generatedDir}/\` is owned by the generator: \`aid gen\` writes it, and refuses to`,
94
+ 'overwrite it once you have edited it, keeping the rejected bytes beside the file.',
95
+ `\`${target.businessDir}/\` is yours: \`aid gen\` creates a file there once and never touches it`,
96
+ 'again.',
97
+ '',
98
+ ].join('\n');
99
+ }
100
+ /**
101
+ * Create a file, reporting whether this call is the one that created it.
102
+ *
103
+ * The exclusive flag makes the create itself the existence check, so a file that appears
104
+ * between a probe and a write cannot be clobbered -- a check-then-act refusal is not a
105
+ * refusal. Returns `false` when the path already exists, and rethrows anything else.
106
+ */
107
+ function createExclusively(path, data) {
108
+ try {
109
+ writeFileSync(path, data, { encoding: 'utf8', flag: 'wx' });
110
+ return true;
111
+ }
112
+ catch (error) {
113
+ if (isAlreadyExists(error))
114
+ return false;
115
+ throw error;
116
+ }
117
+ }
118
+ function isAlreadyExists(error) {
119
+ return (typeof error === 'object' && error !== null && error.code === 'EEXIST');
120
+ }
121
+ export function init(context, options) {
122
+ const command = 'init';
123
+ const target = resolveTarget(options.target);
124
+ if (target === undefined) {
125
+ return outcome({
126
+ command,
127
+ exitCode: EXIT_USAGE,
128
+ diagnostics: [unknownTargetDiagnostic(options.target ?? '')],
129
+ });
130
+ }
131
+ const root = options.dir === undefined ? context.cwd : resolve(context.cwd, options.dir);
132
+ const specPath = target.specPath;
133
+ const displayed = options.dir ?? '.';
134
+ const fields = { dir: displayed, target: target.name, spec: specPath };
135
+ const source = options.from === undefined
136
+ ? { ok: true, text: starterSpec(target.name, projectNameFor(root)) }
137
+ : readSpec(context, options.from);
138
+ if (!source.ok) {
139
+ return outcome({ command, exitCode: EXIT_FAILURE, fields, diagnostics: source.diagnostics });
140
+ }
141
+ // Checked against the path the spec will actually live at, so the diagnostics carry the
142
+ // file the reader will open rather than the one it was imported from.
143
+ const lowered = lowerSpec(source.text, specPath);
144
+ if (!lowered.ok) {
145
+ return outcome({ command, exitCode: EXIT_FAILURE, fields, diagnostics: lowered.diagnostics });
146
+ }
147
+ const specAbsolute = absolutePath(root, specPath);
148
+ const written = [];
149
+ const skipped = [];
150
+ mkdirSync(absolutePath(root, parentPath(specPath)), { recursive: true });
151
+ // Created exclusively so that "does it already exist" and "write it" are one syscall. The
152
+ // refusal holds even if the file appears between a check and a write, and no separate
153
+ // `existsSync` has to stay true for the guarantee to mean anything. `--force` is the one
154
+ // path meant to replace the file, so it writes normally; nothing else reaches the write.
155
+ if (!createExclusively(specAbsolute, source.text)) {
156
+ if (!options.force) {
157
+ return outcome({
158
+ command,
159
+ exitCode: EXIT_FAILURE,
160
+ fields,
161
+ diagnostics: [
162
+ cliError({
163
+ code: CLI_DIAGNOSTIC_CODES.refusingToOverwrite,
164
+ message: `"${specPath}" already exists.`,
165
+ path: [specPath],
166
+ hint: 'Pass --force to overwrite it, or run `aid gen` to regenerate from the spec that is already there.',
167
+ }),
168
+ ],
169
+ });
170
+ }
171
+ writeFileSync(specAbsolute, source.text, 'utf8');
172
+ }
173
+ written.push(specPath);
174
+ // A README is the one file written here whose contents are the caller's, so it is
175
+ // created once and then never replaced -- not even under `--force`, which is passed
176
+ // routinely just to overwrite a spec. Replacing prose a person wrote as a side effect
177
+ // of resetting a spec is not what `--force` was asked for.
178
+ const readmeAbsolute = join(root, 'README.md');
179
+ if (createExclusively(readmeAbsolute, starterReadme(projectNameFor(root), target))) {
180
+ written.push('README.md');
181
+ }
182
+ else {
183
+ skipped.push('README.md');
184
+ }
185
+ // The generation runs against the scaffolded project root, not the caller's working
186
+ // directory: `aid init sub/project --gen` must generate into `sub/project`.
187
+ const generation = options.gen
188
+ ? generate({ ...context, cwd: root }, { spec: specPath, target: target.name, dryRun: false, force: false })
189
+ : undefined;
190
+ const text = [
191
+ ...written.map((path) => `created ${path}`),
192
+ ...skipped.map((path) => `kept ${path} (already there; it is never replaced)`),
193
+ ...(generation === undefined ? ['next: aid validate, then aid gen'] : [generation.text]),
194
+ ].filter((line) => line !== '');
195
+ return outcome({
196
+ command,
197
+ exitCode: generation?.exitCode ?? EXIT_OK,
198
+ diagnostics: [...lowered.diagnostics, ...(generation?.diagnostics ?? [])],
199
+ text: text.join('\n'),
200
+ fields: { ...fields, written, skipped, generation: generation?.report ?? null },
201
+ });
202
+ }
203
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `aid validate` — parse the spec, reduce it to the IR, and run every build-time gate.
3
+ *
4
+ * This is the "is this spec buildable" question, asked without touching the tree and
5
+ * without asking the target to compile anything. It stops at the first stage that
6
+ * produced an error, because lowering a spec whose own schema did not validate reports a
7
+ * cascade of consequences of the first mistake and buries it. Warnings from the stages
8
+ * that did run are kept and printed: the eval-coverage gate warns by design, and a
9
+ * validation that swallowed warnings would make a deliberate signal invisible.
10
+ *
11
+ * `aid gen` asks the same question and then goes further, into the target's compiler and
12
+ * its plan. So a spec can pass `aid validate` and still fail `aid gen` -- that is the
13
+ * honest split, and it is why the two commands report their own stage rather than
14
+ * pretending to be one command with a flag.
15
+ */
16
+ import type { CliContext } from '../context.js';
17
+ import type { CommandOutcome } from '../output.js';
18
+ export interface ValidateOptions {
19
+ readonly spec: string | undefined;
20
+ }
21
+ export declare function validate(context: CliContext, options: ValidateOptions): CommandOutcome;
22
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,CAmCtF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * `aid validate` — parse the spec, reduce it to the IR, and run every build-time gate.
3
+ *
4
+ * This is the "is this spec buildable" question, asked without touching the tree and
5
+ * without asking the target to compile anything. It stops at the first stage that
6
+ * produced an error, because lowering a spec whose own schema did not validate reports a
7
+ * cascade of consequences of the first mistake and buries it. Warnings from the stages
8
+ * that did run are kept and printed: the eval-coverage gate warns by design, and a
9
+ * validation that swallowed warnings would make a deliberate signal invisible.
10
+ *
11
+ * `aid gen` asks the same question and then goes further, into the target's compiler and
12
+ * its plan. So a spec can pass `aid validate` and still fail `aid gen` -- that is the
13
+ * honest split, and it is why the two commands report their own stage rather than
14
+ * pretending to be one command with a flag.
15
+ */
16
+ import { countBySeverity } from '@aid-framework/spec';
17
+ import { EXIT_FAILURE, EXIT_OK } from '../exit.js';
18
+ import { outcome } from '../output.js';
19
+ import { lowerSpec, readSpec } from '../pipeline.js';
20
+ import { DEFAULT_SPEC_PATH } from '../targets.js';
21
+ export function validate(context, options) {
22
+ const command = 'validate';
23
+ const specPath = options.spec ?? DEFAULT_SPEC_PATH;
24
+ const read = readSpec(context, specPath);
25
+ if (!read.ok) {
26
+ return outcome({
27
+ command,
28
+ exitCode: EXIT_FAILURE,
29
+ fields: { spec: specPath },
30
+ diagnostics: read.diagnostics,
31
+ });
32
+ }
33
+ const lowered = lowerSpec(read.text, specPath);
34
+ const counts = countBySeverity(lowered.diagnostics);
35
+ const fields = { spec: specPath, counts };
36
+ if (!lowered.ok) {
37
+ return outcome({
38
+ command,
39
+ exitCode: EXIT_FAILURE,
40
+ fields,
41
+ diagnostics: lowered.diagnostics,
42
+ text: `${specPath}: ${counts.error} error(s), ${counts.warning} warning(s)`,
43
+ });
44
+ }
45
+ return outcome({
46
+ command,
47
+ exitCode: EXIT_OK,
48
+ fields,
49
+ diagnostics: lowered.diagnostics,
50
+ text: `${specPath}: ok (${counts.error} errors, ${counts.warning} warnings)`,
51
+ });
52
+ }
53
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAMlD,MAAM,UAAU,QAAQ,CAAC,OAAmB,EAAE,OAAwB;IACpE,MAAM,OAAO,GAAG,UAAU,CAAC;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,iBAAiB,CAAC;IAEnD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,OAAO,CAAC;YACb,OAAO;YACP,QAAQ,EAAE,YAAY;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC1B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAE1C,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,OAAO,CAAC;YACb,OAAO;YACP,QAAQ,EAAE,YAAY;YACtB,MAAM;YACN,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,IAAI,EAAE,GAAG,QAAQ,KAAK,MAAM,CAAC,KAAK,cAAc,MAAM,CAAC,OAAO,aAAa;SAC5E,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;QACb,OAAO;QACP,QAAQ,EAAE,OAAO;QACjB,MAAM;QACN,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI,EAAE,GAAG,QAAQ,SAAS,MAAM,CAAC,KAAK,YAAY,MAAM,CAAC,OAAO,YAAY;KAC7E,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Everything the CLI touches outside of itself, behind one injectable object.
3
+ *
4
+ * A CLI is mostly side effects, and side effects are what makes a command hard to test.
5
+ * Naming them in one place keeps every command a pure function of its arguments and
6
+ * this context, so a test can run a whole command against a temporary directory and
7
+ * assert on what it printed, what it wrote, and what it exited with -- without a
8
+ * subprocess, and without a mock for the parts that are not I/O.
9
+ */
10
+ export interface SpawnOptions {
11
+ readonly cwd: string;
12
+ /** `inherit` streams the child's output straight through; `pipe` captures it. */
13
+ readonly stdio: 'inherit' | 'pipe';
14
+ readonly env: Readonly<Record<string, string | undefined>>;
15
+ /** Written to the child's stdin, then closed. Used for the baseline recipe. */
16
+ readonly stdin?: string;
17
+ }
18
+ export interface SpawnResult {
19
+ /** The exit status, or `null` when the child never ran or died by signal. */
20
+ readonly status: number | null;
21
+ readonly stdout: string;
22
+ readonly stderr: string;
23
+ /** Set when the child could not be executed at all, such as a missing binary. */
24
+ readonly error?: Error;
25
+ }
26
+ export type Spawn = (command: string, args: readonly string[], options: SpawnOptions) => SpawnResult;
27
+ export interface CliContext {
28
+ /** The project root: every repository-relative path resolves against this. */
29
+ readonly cwd: string;
30
+ readonly env: Readonly<Record<string, string | undefined>>;
31
+ readonly stdout: (text: string) => void;
32
+ readonly stderr: (text: string) => void;
33
+ readonly spawn: Spawn;
34
+ }
35
+ /** The real world: the process streams, the process environment, and real children. */
36
+ export declare function createContext(overrides?: Partial<CliContext>): CliContext;
37
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,MAAM,KAAK,GAAG,CAClB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,YAAY,KAClB,WAAW,CAAC;AAEjB,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAkBD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,SAAS,GAAE,OAAO,CAAC,UAAU,CAAM,GAAG,UAAU,CAQ7E"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Everything the CLI touches outside of itself, behind one injectable object.
3
+ *
4
+ * A CLI is mostly side effects, and side effects are what makes a command hard to test.
5
+ * Naming them in one place keeps every command a pure function of its arguments and
6
+ * this context, so a test can run a whole command against a temporary directory and
7
+ * assert on what it printed, what it wrote, and what it exited with -- without a
8
+ * subprocess, and without a mock for the parts that are not I/O.
9
+ */
10
+ import { spawnSync } from 'node:child_process';
11
+ function spawnWith(command, args, options) {
12
+ const result = spawnSync(command, [...args], {
13
+ cwd: options.cwd,
14
+ env: { ...options.env },
15
+ stdio: options.stdio === 'pipe' ? ['pipe', 'pipe', 'pipe'] : 'inherit',
16
+ encoding: 'utf8',
17
+ ...(options.stdin === undefined ? {} : { input: options.stdin }),
18
+ });
19
+ return {
20
+ status: result.status,
21
+ stdout: result.stdout ?? '',
22
+ stderr: result.stderr ?? '',
23
+ ...(result.error === undefined ? {} : { error: result.error }),
24
+ };
25
+ }
26
+ /** The real world: the process streams, the process environment, and real children. */
27
+ export function createContext(overrides = {}) {
28
+ return {
29
+ cwd: overrides.cwd ?? process.cwd(),
30
+ env: overrides.env ?? process.env,
31
+ stdout: overrides.stdout ?? ((text) => process.stdout.write(text)),
32
+ stderr: overrides.stderr ?? ((text) => process.stderr.write(text)),
33
+ spawn: overrides.spawn ?? spawnWith,
34
+ };
35
+ }
36
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAmC/C,SAAS,SAAS,CAAC,OAAe,EAAE,IAAuB,EAAE,OAAqB;IAChF,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE;QAC3C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAuB;QAC5C,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QACtE,QAAQ,EAAE,MAAM;QAChB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;KACjE,CAAC,CAAC;IACH,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,SAAS,GAAwB,EAAE;IAC/D,OAAO;QACL,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACnC,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;QACjC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1E,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1E,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,SAAS;KACpC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Diagnostics, the one currency every layer already speaks.
3
+ *
4
+ * `@aid-framework/spec` defines the shape and the renderer, and `@aid-framework/ir` and
5
+ * `@aid-framework/generator-sdk` re-declare the same shape nominally with their own closed code
6
+ * unions. The CLI reads all of them through the widened `Diagnostic<string>` view and
7
+ * renders them with the spec package's renderer: it renames no code, re-ranks no
8
+ * severity, and re-checks nothing a gate already decided.
9
+ *
10
+ * The codes below are the ones *this* layer originates -- a file that could not be
11
+ * read, a target that does not exist, a Python interpreter that is not there. They
12
+ * follow the same `<layer>/<slug>` convention so that a reader cannot tell which layer
13
+ * produced a code from its shape, which is the point.
14
+ */
15
+ import type { Diagnostic } from '@aid-framework/spec';
16
+ /** The shared diagnostic shape, widened over the code union. */
17
+ export type CliDiagnostic = Diagnostic<string>;
18
+ export declare const CLI_DIAGNOSTIC_CODES: {
19
+ readonly specUnreadable: 'cli/spec-unreadable';
20
+ readonly unknownTarget: 'cli/unknown-target';
21
+ readonly refusingToOverwrite: 'cli/refusing-to-overwrite';
22
+ readonly pythonMissing: 'cli/python-missing';
23
+ readonly suiteNotFound: 'cli/suite-not-found';
24
+ readonly evalModulesMissing: 'cli/eval-modules-missing';
25
+ readonly retrieverRequired: 'cli/retriever-required';
26
+ readonly retrieverConflict: 'cli/retriever-conflict';
27
+ readonly retrieverNotFound: 'cli/retriever-not-found';
28
+ readonly ingestModulesMissing: 'cli/ingest-modules-missing';
29
+ readonly runnerUnsupported: 'cli/runner-unsupported';
30
+ readonly runnerFailed: 'cli/runner-failed';
31
+ readonly runnerWarned: 'cli/runner-warned';
32
+ };
33
+ export type CliDiagnosticCode = (typeof CLI_DIAGNOSTIC_CODES)[keyof typeof CLI_DIAGNOSTIC_CODES];
34
+ export interface CliDiagnosticInit {
35
+ readonly code: CliDiagnosticCode;
36
+ readonly message: string;
37
+ readonly path?: readonly string[];
38
+ readonly hint?: string;
39
+ }
40
+ export declare function cliError(init: CliDiagnosticInit): CliDiagnostic;
41
+ export declare function cliWarning(init: CliDiagnosticInit): CliDiagnostic;
42
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAE/C,eAAO,MAAM,oBAAoB;aAC/B,cAAc,EAAE,qBAAqB;aACrC,aAAa,EAAE,oBAAoB;aACnC,mBAAmB,EAAE,2BAA2B;aAChD,aAAa,EAAE,oBAAoB;aACnC,aAAa,EAAE,qBAAqB;aACpC,kBAAkB,EAAE,0BAA0B;aAC9C,iBAAiB,EAAE,wBAAwB;aAC3C,iBAAiB,EAAE,wBAAwB;aAC3C,iBAAiB,EAAE,yBAAyB;aAC5C,oBAAoB,EAAE,4BAA4B;aAClD,iBAAiB,EAAE,wBAAwB;aAC3C,YAAY,EAAE,mBAAmB;aACjC,YAAY,EAAE,mBAAmB;CACzB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,OAAO,oBAAoB,CAAC,CAAC;AAEjG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAO/D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAOjE"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Diagnostics, the one currency every layer already speaks.
3
+ *
4
+ * `@aid-framework/spec` defines the shape and the renderer, and `@aid-framework/ir` and
5
+ * `@aid-framework/generator-sdk` re-declare the same shape nominally with their own closed code
6
+ * unions. The CLI reads all of them through the widened `Diagnostic<string>` view and
7
+ * renders them with the spec package's renderer: it renames no code, re-ranks no
8
+ * severity, and re-checks nothing a gate already decided.
9
+ *
10
+ * The codes below are the ones *this* layer originates -- a file that could not be
11
+ * read, a target that does not exist, a Python interpreter that is not there. They
12
+ * follow the same `<layer>/<slug>` convention so that a reader cannot tell which layer
13
+ * produced a code from its shape, which is the point.
14
+ */
15
+ import { errorDiagnostic, warningDiagnostic } from '@aid-framework/spec';
16
+ export const CLI_DIAGNOSTIC_CODES = {
17
+ specUnreadable: 'cli/spec-unreadable',
18
+ unknownTarget: 'cli/unknown-target',
19
+ refusingToOverwrite: 'cli/refusing-to-overwrite',
20
+ pythonMissing: 'cli/python-missing',
21
+ suiteNotFound: 'cli/suite-not-found',
22
+ evalModulesMissing: 'cli/eval-modules-missing',
23
+ retrieverRequired: 'cli/retriever-required',
24
+ retrieverConflict: 'cli/retriever-conflict',
25
+ retrieverNotFound: 'cli/retriever-not-found',
26
+ ingestModulesMissing: 'cli/ingest-modules-missing',
27
+ runnerUnsupported: 'cli/runner-unsupported',
28
+ runnerFailed: 'cli/runner-failed',
29
+ runnerWarned: 'cli/runner-warned',
30
+ };
31
+ export function cliError(init) {
32
+ return errorDiagnostic({
33
+ code: init.code,
34
+ message: init.message,
35
+ path: init.path ?? [],
36
+ ...(init.hint === undefined ? {} : { hint: init.hint }),
37
+ });
38
+ }
39
+ export function cliWarning(init) {
40
+ return warningDiagnostic({
41
+ code: init.code,
42
+ message: init.message,
43
+ path: init.path ?? [],
44
+ ...(init.hint === undefined ? {} : { hint: init.hint }),
45
+ });
46
+ }
47
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAKzE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,cAAc,EAAE,qBAAqB;IACrC,aAAa,EAAE,oBAAoB;IACnC,mBAAmB,EAAE,2BAA2B;IAChD,aAAa,EAAE,oBAAoB;IACnC,aAAa,EAAE,qBAAqB;IACpC,kBAAkB,EAAE,0BAA0B;IAC9C,iBAAiB,EAAE,wBAAwB;IAC3C,iBAAiB,EAAE,wBAAwB;IAC3C,iBAAiB,EAAE,yBAAyB;IAC5C,oBAAoB,EAAE,4BAA4B;IAClD,iBAAiB,EAAE,wBAAwB;IAC3C,YAAY,EAAE,mBAAmB;IACjC,YAAY,EAAE,mBAAmB;CACzB,CAAC;AAWX,MAAM,UAAU,QAAQ,CAAC,IAAuB;IAC9C,OAAO,eAAe,CAAC;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;QACrB,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;KACxD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,OAAO,iBAAiB,CAAC;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;QACrB,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;KACxD,CAAC,CAAC;AACL,CAAC"}
package/dist/exit.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The CLI's exit-code taxonomy, which is a contract with CI rather than a convention.
3
+ *
4
+ * `0` means the command finished *and* the project is in the shape the command asked
5
+ * for; `1` means the command ran but the spec, a gate, the target's compiler or the
6
+ * working tree rejected it; `2` means the command line itself was wrong, or the CLI
7
+ * could not get far enough to judge the project at all. Nothing else is ever returned,
8
+ * and no command maps two different outcomes onto the same code.
9
+ */
10
+ export declare const EXIT_OK = 0;
11
+ /** The spec, the gates, the target's plan, or the working tree said no. */
12
+ export declare const EXIT_FAILURE = 1;
13
+ /** The invocation was wrong, or the CLI hit an internal failure. */
14
+ export declare const EXIT_USAGE = 2;
15
+ export type ExitCode = typeof EXIT_OK | typeof EXIT_FAILURE | typeof EXIT_USAGE;
16
+ //# sourceMappingURL=exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit.d.ts","sourceRoot":"","sources":["../src/exit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,OAAO,IAAI,CAAC;AAEzB,2EAA2E;AAC3E,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,oEAAoE;AACpE,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,MAAM,MAAM,QAAQ,GAAG,OAAO,OAAO,GAAG,OAAO,YAAY,GAAG,OAAO,UAAU,CAAC"}
package/dist/exit.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The CLI's exit-code taxonomy, which is a contract with CI rather than a convention.
3
+ *
4
+ * `0` means the command finished *and* the project is in the shape the command asked
5
+ * for; `1` means the command ran but the spec, a gate, the target's compiler or the
6
+ * working tree rejected it; `2` means the command line itself was wrong, or the CLI
7
+ * could not get far enough to judge the project at all. Nothing else is ever returned,
8
+ * and no command maps two different outcomes onto the same code.
9
+ */
10
+ export const EXIT_OK = 0;
11
+ /** The spec, the gates, the target's plan, or the working tree said no. */
12
+ export const EXIT_FAILURE = 1;
13
+ /** The invocation was wrong, or the CLI hit an internal failure. */
14
+ export const EXIT_USAGE = 2;
15
+ //# sourceMappingURL=exit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit.js","sourceRoot":"","sources":["../src/exit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AAEzB,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,oEAAoE;AACpE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `@aid-framework/cli` - the `aid` command: init, validate, gen, ingest and eval.
3
+ *
4
+ * The CLI is glue. Every judgement it reports -- whether a spec parses, what the IR is,
5
+ * what a target can emit, which generated file was hand-edited, whether an eval regressed
6
+ * -- is made by a package below it, and this layer's job is to route arguments into those
7
+ * packages and their answers back out as text, JSON and an exit code. It reimplements no
8
+ * gate, no hash and no drift rule, because a second implementation of a rule is a defect:
9
+ * the two will disagree, and only one of them will be right.
10
+ *
11
+ * The layering is `spec <- ir <- generator-sdk <- generators <- cli`.
12
+ */
13
+ export type { FlagSpec, ParsedArguments, ParseOutcome } from './args.js';
14
+ export { booleanFlag, JSON_FLAG, parseArguments, valueFlag } from './args.js';
15
+ export type { EvalOptions } from './commands/eval.js';
16
+ export { evaluate } from './commands/eval.js';
17
+ export type { GenerateOptions, GenerateSuccess } from './commands/gen.js';
18
+ export { generate } from './commands/gen.js';
19
+ export type { IngestOptions } from './commands/ingest.js';
20
+ export { ingest } from './commands/ingest.js';
21
+ export type { InitOptions } from './commands/init.js';
22
+ export { init, projectNameFor, starterSpec } from './commands/init.js';
23
+ export type { ValidateOptions } from './commands/validate.js';
24
+ export { validate } from './commands/validate.js';
25
+ export type { CliContext, Spawn, SpawnOptions, SpawnResult } from './context.js';
26
+ export { createContext } from './context.js';
27
+ export type { CliDiagnostic, CliDiagnosticCode, CliDiagnosticInit } from './diagnostics.js';
28
+ export { CLI_DIAGNOSTIC_CODES, cliError, cliWarning } from './diagnostics.js';
29
+ export type { ExitCode } from './exit.js';
30
+ export { EXIT_FAILURE, EXIT_OK, EXIT_USAGE } from './exit.js';
31
+ export { COMMANDS, run } from './main.js';
32
+ export type { CommandOutcome, OutcomeInit } from './output.js';
33
+ export { emit, outcome } from './output.js';
34
+ export { absolutePath, parentPath } from './paths.js';
35
+ export type { Compiled, CompileOutcome, Failed, Lowered, LowerOutcome, ManifestOutcome, ReadManifest, ReadSpec, } from './pipeline.js';
36
+ export { compile, lowerSpec, provenanceFor, readManifest, readSpec } from './pipeline.js';
37
+ export { discoverInterpreter, INTERPRETERS, interpreterCommand, invoke } from './python.js';
38
+ export type { Target } from './targets.js';
39
+ export { DEFAULT_SPEC_PATH, DEFAULT_TARGET, resolveTarget, TARGETS, targetCapabilities, targetNames, unknownTargetDiagnostic, } from './targets.js';
40
+ export type { CommandSpec } from './usage.js';
41
+ export { commandUsage, globalUsage } from './usage.js';
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9E,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EACV,QAAQ,EACR,cAAc,EACd,MAAM,EACN,OAAO,EACP,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC5F,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `@aid-framework/cli` - the `aid` command: init, validate, gen, ingest and eval.
3
+ *
4
+ * The CLI is glue. Every judgement it reports -- whether a spec parses, what the IR is,
5
+ * what a target can emit, which generated file was hand-edited, whether an eval regressed
6
+ * -- is made by a package below it, and this layer's job is to route arguments into those
7
+ * packages and their answers back out as text, JSON and an exit code. It reimplements no
8
+ * gate, no hash and no drift rule, because a second implementation of a rule is a defect:
9
+ * the two will disagree, and only one of them will be right.
10
+ *
11
+ * The layering is `spec <- ir <- generator-sdk <- generators <- cli`.
12
+ */
13
+ export { booleanFlag, JSON_FLAG, parseArguments, valueFlag } from './args.js';
14
+ export { evaluate } from './commands/eval.js';
15
+ export { generate } from './commands/gen.js';
16
+ export { ingest } from './commands/ingest.js';
17
+ export { init, projectNameFor, starterSpec } from './commands/init.js';
18
+ export { validate } from './commands/validate.js';
19
+ export { createContext } from './context.js';
20
+ export { CLI_DIAGNOSTIC_CODES, cliError, cliWarning } from './diagnostics.js';
21
+ export { EXIT_FAILURE, EXIT_OK, EXIT_USAGE } from './exit.js';
22
+ export { COMMANDS, run } from './main.js';
23
+ export { emit, outcome } from './output.js';
24
+ export { absolutePath, parentPath } from './paths.js';
25
+ export { compile, lowerSpec, provenanceFor, readManifest, readSpec } from './pipeline.js';
26
+ export { discoverInterpreter, INTERPRETERS, interpreterCommand, invoke } from './python.js';
27
+ export { DEFAULT_SPEC_PATH, DEFAULT_TARGET, resolveTarget, TARGETS, targetCapabilities, targetNames, unknownTargetDiagnostic, } from './targets.js';
28
+ export { commandUsage, globalUsage } from './usage.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE9E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9E,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAWtD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE5F,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}