@logixjs/cli 1.0.1

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 (46) hide show
  1. package/LICENSE +201 -0
  2. package/dist/Commands.d.ts +61 -0
  3. package/dist/Commands.js +16 -0
  4. package/dist/Commands.js.map +1 -0
  5. package/dist/anchorAutofill-V6CAXQHT.js +128 -0
  6. package/dist/anchorAutofill-V6CAXQHT.js.map +1 -0
  7. package/dist/anchorIndex-IEFARUZM.js +15 -0
  8. package/dist/anchorIndex-IEFARUZM.js.map +1 -0
  9. package/dist/bin/logix-devserver.d.ts +1 -0
  10. package/dist/bin/logix-devserver.js +32 -0
  11. package/dist/bin/logix-devserver.js.map +1 -0
  12. package/dist/bin/logix.d.ts +1 -0
  13. package/dist/bin/logix.js +37 -0
  14. package/dist/bin/logix.js.map +1 -0
  15. package/dist/chunk-6DZEO5HP.js +102 -0
  16. package/dist/chunk-6DZEO5HP.js.map +1 -0
  17. package/dist/chunk-HGHTOYNL.js +27 -0
  18. package/dist/chunk-HGHTOYNL.js.map +1 -0
  19. package/dist/chunk-PZ5AY32C.js +10 -0
  20. package/dist/chunk-PZ5AY32C.js.map +1 -0
  21. package/dist/chunk-RF7XSP3P.js +22 -0
  22. package/dist/chunk-RF7XSP3P.js.map +1 -0
  23. package/dist/chunk-TDQVD2IA.js +1193 -0
  24. package/dist/chunk-TDQVD2IA.js.map +1 -0
  25. package/dist/chunk-VRPSB3SV.js +143 -0
  26. package/dist/chunk-VRPSB3SV.js.map +1 -0
  27. package/dist/contractSuiteRun-5Y7LVI72.js +15 -0
  28. package/dist/contractSuiteRun-5Y7LVI72.js.map +1 -0
  29. package/dist/describe-5MFSLD7R.js +218 -0
  30. package/dist/describe-5MFSLD7R.js.map +1 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +10 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/irDiff-WYXZEVA7.js +351 -0
  35. package/dist/irDiff-WYXZEVA7.js.map +1 -0
  36. package/dist/irExport-EI2VYIMT.js +87 -0
  37. package/dist/irExport-EI2VYIMT.js.map +1 -0
  38. package/dist/irValidate-JEQGVRL5.js +229 -0
  39. package/dist/irValidate-JEQGVRL5.js.map +1 -0
  40. package/dist/spyEvidence-JTJDS2WN.js +15 -0
  41. package/dist/spyEvidence-JTJDS2WN.js.map +1 -0
  42. package/dist/transformModule-D6YE3U5W.js +15 -0
  43. package/dist/transformModule-D6YE3U5W.js.map +1 -0
  44. package/dist/trialRun-SWVYG67P.js +15 -0
  45. package/dist/trialRun-SWVYG67P.js.map +1 -0
  46. package/package.json +69 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/commands/describe.ts"],"sourcesContent":["import { Effect } from 'effect'\n\nimport { makeArtifactOutput } from '../artifacts.js'\nimport type { CliInvocation } from '../args.js'\nimport type { CliConfigArgvPrefixResolution } from '../cliConfig.js'\nimport { asSerializableErrorSummary } from '../errors.js'\nimport type { ArtifactOutput, CommandResult } from '../result.js'\nimport { makeCommandResult } from '../result.js'\n\ntype DescribeInvocation = Extract<CliInvocation, { readonly command: 'describe' }>\n\nexport type DescribeRuntimeContext = {\n readonly argv: ReadonlyArray<string>\n readonly argvWithConfigPrefix: ReadonlyArray<string>\n readonly cliConfig: CliConfigArgvPrefixResolution\n}\n\ntype OptionContractV1 = {\n readonly name: `--${string}`\n readonly type: 'string' | 'integer' | 'boolean' | 'enum' | 'kv'\n readonly required: boolean\n readonly repeatable?: boolean\n readonly default?: string | number | boolean\n readonly enumValues?: ReadonlyArray<string>\n}\n\ntype CommandContractV1 = {\n readonly name: string\n readonly category: 'meta' | 'oracle' | 'gate' | 'write'\n readonly summary: string\n readonly availability: 'available' | 'unavailable'\n readonly unavailableReasonCode?: 'CLI_NOT_IMPLEMENTED'\n readonly options: ReadonlyArray<OptionContractV1>\n readonly outputs: ReadonlyArray<{\n readonly outputKey: string\n readonly kind: string\n readonly schemaRef?: string\n }>\n readonly exitCodes: ReadonlyArray<0 | 1 | 2>\n}\n\ntype DescribeReportV1 = {\n readonly schemaVersion: 1\n readonly kind: 'CliDescribeReport'\n readonly nonGoals: ReadonlyArray<string>\n readonly protocol: {\n readonly commandResultSchemaRef: string\n readonly reasonCodeCatalogRef: string\n readonly exitCodes: ReadonlyArray<{\n readonly code: 0 | 1 | 2\n readonly meaning: string\n }>\n }\n readonly commands: ReadonlyArray<CommandContractV1>\n readonly configVisibility: {\n readonly precedence: readonly ['defaults', 'profile', 'argv']\n readonly argv: ReadonlyArray<string>\n readonly argvWithConfigPrefix: ReadonlyArray<string>\n readonly cliConfigPathArg?: string\n readonly profile?: string\n readonly discoveredPath?: string\n readonly layers: ReadonlyArray<{\n readonly source: 'defaults' | 'profile'\n readonly profile?: string\n readonly tokens: ReadonlyArray<string>\n }>\n readonly discovery: CliConfigArgvPrefixResolution['discovery']\n }\n}\n\nconst GLOBAL_OPTIONS: ReadonlyArray<OptionContractV1> = [\n { name: '--runId', type: 'string', required: true },\n { name: '--out', type: 'string', required: false },\n { name: '--outRoot', type: 'string', required: false },\n { name: '--budgetBytes', type: 'integer', required: false },\n { name: '--mode', type: 'enum', required: false, enumValues: ['report', 'write'] },\n { name: '--tsconfig', type: 'string', required: false },\n { name: '--host', type: 'enum', required: false, default: 'node', enumValues: ['node', 'browser-mock'] },\n { name: '--cliConfig', type: 'string', required: false },\n { name: '--profile', type: 'string', required: false },\n]\n\nconst makeCommand = (\n input: Omit<CommandContractV1, 'options' | 'exitCodes'> & {\n readonly options?: ReadonlyArray<OptionContractV1>\n },\n): CommandContractV1 => ({\n ...input,\n options: [...GLOBAL_OPTIONS, ...(input.options ?? [])],\n exitCodes: [0, 1, 2],\n})\n\nconst makeUnsupportedCommand = (\n input: Omit<CommandContractV1, 'options' | 'exitCodes' | 'outputs' | 'availability' | 'unavailableReasonCode'> & {\n readonly options?: ReadonlyArray<OptionContractV1>\n },\n): CommandContractV1 =>\n makeCommand({\n ...input,\n availability: 'unavailable',\n unavailableReasonCode: 'CLI_NOT_IMPLEMENTED',\n outputs: [],\n })\n\nconst COMMAND_CONTRACTS: ReadonlyArray<CommandContractV1> = [\n makeCommand({\n name: 'describe',\n category: 'meta',\n summary: '机器可读命令契约与配置可见性(仅支持 --json)',\n availability: 'available',\n options: [{ name: '--json', type: 'boolean', required: true, default: true }],\n outputs: [{ outputKey: 'describeReport', kind: 'CliDescribeReport' }],\n }),\n makeCommand({\n name: 'ir.export',\n category: 'oracle',\n summary: '导出控制面 IR(manifest/workflow surface)',\n availability: 'available',\n options: [{ name: '--entry', type: 'string', required: true }],\n outputs: [\n { outputKey: 'controlSurfaceManifest', kind: 'ControlSurfaceManifest' },\n { outputKey: 'workflowSurface', kind: 'WorkflowSurfaceBundle' },\n ],\n }),\n makeCommand({\n name: 'ir.validate',\n category: 'gate',\n summary: '对导出工件做结构化门禁校验',\n availability: 'available',\n options: [\n { name: '--in', type: 'string', required: false },\n { name: '--artifact', type: 'string', required: false },\n ],\n outputs: [{ outputKey: 'irValidateReport', kind: 'IrValidateReport' }],\n }),\n makeCommand({\n name: 'ir.diff',\n category: 'gate',\n summary: '比较 before/after 工件差异并门禁化',\n availability: 'available',\n options: [\n { name: '--before', type: 'string', required: true },\n { name: '--after', type: 'string', required: true },\n ],\n outputs: [{ outputKey: 'irDiffReport', kind: 'IrDiffReport' }],\n }),\n makeUnsupportedCommand({\n name: 'trialrun',\n category: 'oracle',\n summary: '受控试跑并输出 TrialRunReport',\n options: [\n { name: '--entry', type: 'string', required: true },\n { name: '--diagnosticsLevel', type: 'enum', required: false, default: 'light', enumValues: ['off', 'light', 'full'] },\n { name: '--maxEvents', type: 'integer', required: false },\n { name: '--timeout', type: 'integer', required: false },\n { name: '--includeTrace', type: 'boolean', required: false, default: false },\n { name: '--config', type: 'kv', required: false, repeatable: true },\n ],\n }),\n makeUnsupportedCommand({\n name: 'contract-suite.run',\n category: 'gate',\n summary: '一键验收(trialrun + verdict/context-pack)',\n options: [\n { name: '--entry', type: 'string', required: true },\n { name: '--allowWarn', type: 'boolean', required: false, default: false },\n { name: '--baseline', type: 'string', required: false },\n { name: '--includeContextPack', type: 'boolean', required: false, default: false },\n { name: '--inputs', type: 'string', required: false },\n { name: '--includeUiKitRegistry', type: 'boolean', required: false, default: false },\n { name: '--packMaxBytes', type: 'integer', required: false },\n { name: '--requireRulesManifest', type: 'boolean', required: false, default: false },\n { name: '--includeAnchorAutofill', type: 'boolean', required: false, default: false },\n { name: '--repoRoot', type: 'string', required: false, default: '.' },\n { name: '--diagnosticsLevel', type: 'enum', required: false, default: 'light', enumValues: ['off', 'light', 'full'] },\n { name: '--maxEvents', type: 'integer', required: false },\n { name: '--timeout', type: 'integer', required: false },\n { name: '--includeTrace', type: 'boolean', required: false, default: false },\n { name: '--config', type: 'kv', required: false, repeatable: true },\n ],\n }),\n makeUnsupportedCommand({\n name: 'spy.evidence',\n category: 'oracle',\n summary: '采集 $.use(Tag) 证据(不写回源码)',\n options: [\n { name: '--entry', type: 'string', required: true },\n { name: '--maxUsedServices', type: 'integer', required: false },\n { name: '--maxRawMode', type: 'integer', required: false },\n { name: '--timeout', type: 'integer', required: false },\n ],\n }),\n makeUnsupportedCommand({\n name: 'anchor.index',\n category: 'oracle',\n summary: '扫描仓库并构建 AnchorIndex',\n options: [{ name: '--repoRoot', type: 'string', required: false, default: '.' }],\n }),\n makeCommand({\n name: 'anchor.autofill',\n category: 'write',\n summary: '补齐锚点(默认 report-only)',\n availability: 'available',\n options: [{ name: '--repoRoot', type: 'string', required: false, default: '.' }],\n outputs: [\n { outputKey: 'patchPlan', kind: 'PatchPlan' },\n { outputKey: 'autofillReport', kind: 'AutofillReport' },\n { outputKey: 'writeBackResult', kind: 'WriteBackResult' },\n ],\n }),\n makeUnsupportedCommand({\n name: 'transform.module',\n category: 'write',\n summary: '按 delta 批量变更 module(默认 report-only)',\n options: [\n { name: '--repoRoot', type: 'string', required: false, default: '.' },\n { name: '--ops', type: 'string', required: true },\n ],\n }),\n]\n\nconst toConfigLayers = (\n layers: ReadonlyArray<CliConfigArgvPrefixResolution['layers'][number]>,\n): DescribeReportV1['configVisibility']['layers'] =>\n layers.map((layer) =>\n layer.source === 'profile'\n ? { source: 'profile' as const, profile: layer.profile, tokens: layer.tokens }\n : { source: 'defaults' as const, tokens: layer.tokens },\n )\n\nconst makeDescribeReport = (ctx: DescribeRuntimeContext): DescribeReportV1 => ({\n schemaVersion: 1,\n kind: 'CliDescribeReport',\n nonGoals: [\n 'CLI_IS_NOT_AGENT_RUNTIME',\n 'CLI_MUST_NOT_EMBED_LOOP_MEMORY_POLICY',\n 'CLI_AGENT_DECISIONS_MUST_STAY_EXTERNAL',\n ],\n protocol: {\n commandResultSchemaRef: 'specs/085-logix-cli-node-only/contracts/schemas/cli-command-result.schema.json',\n reasonCodeCatalogRef: 'specs/085-logix-cli-node-only/contracts/reason-codes.md',\n exitCodes: [\n { code: 0, meaning: 'PASS' },\n { code: 1, meaning: 'ERROR' },\n { code: 2, meaning: 'VIOLATION_OR_INVALID_INPUT' },\n ],\n },\n commands: COMMAND_CONTRACTS,\n configVisibility: {\n precedence: ['defaults', 'profile', 'argv'],\n argv: ctx.argv,\n argvWithConfigPrefix: ctx.argvWithConfigPrefix,\n ...(ctx.cliConfig.cliConfigPathArg ? { cliConfigPathArg: ctx.cliConfig.cliConfigPathArg } : null),\n ...(ctx.cliConfig.profile ? { profile: ctx.cliConfig.profile } : null),\n ...(ctx.cliConfig.discoveredPath ? { discoveredPath: ctx.cliConfig.discoveredPath } : null),\n layers: toConfigLayers(ctx.cliConfig.layers),\n discovery: ctx.cliConfig.discovery,\n },\n})\n\nexport const runDescribe = (\n inv: DescribeInvocation,\n ctx: DescribeRuntimeContext,\n): Effect.Effect<CommandResult, never> => {\n const runId = inv.global.runId\n\n return Effect.gen(function* () {\n const report = makeDescribeReport(ctx)\n const artifacts: ArtifactOutput[] = [\n yield* makeArtifactOutput({\n outDir: inv.global.outDir,\n budgetBytes: inv.global.budgetBytes,\n fileName: 'describe.report.json',\n outputKey: 'describeReport',\n kind: 'CliDescribeReport',\n value: report,\n }),\n ]\n\n return makeCommandResult({\n runId,\n command: 'describe',\n ok: true,\n artifacts,\n })\n }).pipe(\n Effect.catch((cause) =>\n Effect.succeed(\n makeCommandResult({\n runId,\n command: 'describe',\n ok: false,\n artifacts: [],\n error: asSerializableErrorSummary(cause),\n }),\n )),\n )\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+ export { C as Commands } from './Commands.js';
2
+ import 'effect';
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import {
2
+ Commands_exports
3
+ } from "./chunk-TDQVD2IA.js";
4
+ import "./chunk-RF7XSP3P.js";
5
+ import "./chunk-6DZEO5HP.js";
6
+ import "./chunk-PZ5AY32C.js";
7
+ export {
8
+ Commands_exports as Commands
9
+ };
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,351 @@
1
+ import {
2
+ makeArtifactOutput,
3
+ readJsonFile
4
+ } from "./chunk-VRPSB3SV.js";
5
+ import {
6
+ sha256DigestOfJson
7
+ } from "./chunk-RF7XSP3P.js";
8
+ import {
9
+ asSerializableErrorSummary,
10
+ makeCliError,
11
+ makeCommandResult
12
+ } from "./chunk-6DZEO5HP.js";
13
+ import "./chunk-PZ5AY32C.js";
14
+
15
+ // src/internal/commands/irDiff.ts
16
+ import { Effect } from "effect";
17
+ import fs from "fs/promises";
18
+ import path from "path";
19
+ var escapeJsonPointer = (seg) => seg.replace(/~/g, "~0").replace(/\//g, "~1");
20
+ var diffJsonPaths = (a, b, args) => {
21
+ if (args.out.length >= args.limit) return true;
22
+ if (a === b) return false;
23
+ if (a === null || b === null) {
24
+ if (a !== b) args.out.push(args.path);
25
+ return args.out.length >= args.limit;
26
+ }
27
+ const ta = typeof a;
28
+ const tb = typeof b;
29
+ if (ta !== tb) {
30
+ args.out.push(args.path);
31
+ return args.out.length >= args.limit;
32
+ }
33
+ if (ta !== "object") {
34
+ if (!Object.is(a, b)) args.out.push(args.path);
35
+ return args.out.length >= args.limit;
36
+ }
37
+ const aa = a;
38
+ const bb = b;
39
+ const isArrA = Array.isArray(aa);
40
+ const isArrB = Array.isArray(bb);
41
+ if (isArrA || isArrB) {
42
+ if (!(isArrA && isArrB)) {
43
+ args.out.push(args.path);
44
+ return args.out.length >= args.limit;
45
+ }
46
+ const min = Math.min(aa.length, bb.length);
47
+ if (aa.length !== bb.length) args.out.push(`${args.path}/length`);
48
+ for (let i = 0; i < min; i++) {
49
+ if (diffJsonPaths(aa[i], bb[i], { ...args, path: `${args.path}/${i}` })) return true;
50
+ if (args.out.length >= args.limit) return true;
51
+ }
52
+ return args.out.length >= args.limit;
53
+ }
54
+ const keys = Array.from(/* @__PURE__ */ new Set([...Object.keys(aa), ...Object.keys(bb)])).sort((x, y) => x < y ? -1 : x > y ? 1 : 0);
55
+ for (const key of keys) {
56
+ const nextPath = `${args.path}/${escapeJsonPointer(key)}`;
57
+ if (!(key in aa)) {
58
+ args.out.push(nextPath);
59
+ if (args.out.length >= args.limit) return true;
60
+ continue;
61
+ }
62
+ if (!(key in bb)) {
63
+ args.out.push(nextPath);
64
+ if (args.out.length >= args.limit) return true;
65
+ continue;
66
+ }
67
+ if (diffJsonPaths(aa[key], bb[key], { ...args, path: nextPath })) return true;
68
+ if (args.out.length >= args.limit) return true;
69
+ }
70
+ return args.out.length >= args.limit;
71
+ };
72
+ var listJsonFiles = (dirAbs) => Effect.tryPromise({
73
+ try: () => fs.readdir(dirAbs, { withFileTypes: true }),
74
+ catch: (cause) => makeCliError({
75
+ code: "CLI_IO_ERROR",
76
+ message: `[Logix][CLI] \u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF1A${dirAbs}`,
77
+ cause
78
+ })
79
+ }).pipe(
80
+ Effect.map(
81
+ (entries) => entries.filter((e) => e.isFile() && e.name.endsWith(".json")).map((e) => e.name).sort((a, b) => a < b ? -1 : a > b ? 1 : 0)
82
+ )
83
+ );
84
+ var readJsonForSide = (fileAbs) => readJsonFile(fileAbs).pipe(
85
+ Effect.map((value) => ({ ok: true, value })),
86
+ Effect.catch((cause) => Effect.succeed({ ok: false, error: asSerializableErrorSummary(cause) }))
87
+ );
88
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
89
+ var isNonGatingFile = (fileName) => fileName === "trace.slim.json" || fileName === "trialrun.report.json";
90
+ var extractSemanticDigest = (fileName, value) => {
91
+ if (isNonGatingFile(fileName)) {
92
+ return { kind: "nonGating", reason: "non_gating_by_policy" };
93
+ }
94
+ if (fileName === "control-surface.manifest.json") {
95
+ const digest = isRecord(value) && typeof value.digest === "string" ? value.digest : void 0;
96
+ return { kind: "semantic", digest: digest ?? sha256DigestOfJson(value) };
97
+ }
98
+ if (fileName === "workflow.surface.json") {
99
+ const digestPairs = Array.isArray(value) ? value.map((x) => {
100
+ const moduleId = isRecord(x) && typeof x.moduleId === "string" ? x.moduleId : void 0;
101
+ const surface = isRecord(x) ? x.surface : void 0;
102
+ const digest = isRecord(surface) && typeof surface.digest === "string" ? surface.digest : void 0;
103
+ return moduleId && digest ? { moduleId, digest } : void 0;
104
+ }).filter((x) => Boolean(x)).sort((a, b) => a.moduleId < b.moduleId ? -1 : a.moduleId > b.moduleId ? 1 : 0) : [];
105
+ return { kind: "semantic", digest: sha256DigestOfJson(digestPairs) };
106
+ }
107
+ return { kind: "semantic", digest: sha256DigestOfJson(value) };
108
+ };
109
+ var runIrDiff = (inv) => {
110
+ const runId = inv.global.runId;
111
+ return Effect.gen(function* () {
112
+ const { before, after } = inv;
113
+ const beforeAbs = path.resolve(process.cwd(), before);
114
+ const afterAbs = path.resolve(process.cwd(), after);
115
+ const beforeStat = yield* Effect.tryPromise({
116
+ try: () => fs.stat(beforeAbs),
117
+ catch: (cause) => makeCliError({
118
+ code: "CLI_IO_ERROR",
119
+ message: `[Logix][CLI] \u65E0\u6CD5\u8BFB\u53D6\u8F93\u5165\uFF1A${before}`,
120
+ cause
121
+ })
122
+ });
123
+ const afterStat = yield* Effect.tryPromise({
124
+ try: () => fs.stat(afterAbs),
125
+ catch: (cause) => makeCliError({
126
+ code: "CLI_IO_ERROR",
127
+ message: `[Logix][CLI] \u65E0\u6CD5\u8BFB\u53D6\u8F93\u5165\uFF1A${after}`,
128
+ cause
129
+ })
130
+ });
131
+ const beforeIsDir = beforeStat.isDirectory();
132
+ const afterIsDir = afterStat.isDirectory();
133
+ if (beforeIsDir !== afterIsDir) {
134
+ const error = asSerializableErrorSummary(
135
+ makeCliError({
136
+ code: "CLI_INVALID_INPUT",
137
+ message: "--before/--after \u7C7B\u578B\u4E0D\u5339\u914D\uFF1A\u5FC5\u987B\u540C\u4E3A\u76EE\u5F55\u6216\u540C\u4E3A\u6587\u4EF6"
138
+ })
139
+ );
140
+ return makeCommandResult({ runId, command: "ir.diff", ok: false, artifacts: [], error });
141
+ }
142
+ const parseErrors = [];
143
+ const addedFiles = [];
144
+ const removedFiles = [];
145
+ const changedFiles = [];
146
+ const nonGatingChangedFiles = [];
147
+ let unchanged = 0;
148
+ if (!beforeIsDir) {
149
+ const fileName = `${path.basename(beforeAbs)}\u2192${path.basename(afterAbs)}`;
150
+ const beforeRes = yield* readJsonForSide(beforeAbs);
151
+ const afterRes = yield* readJsonForSide(afterAbs);
152
+ if (!beforeRes.ok) parseErrors.push({ fileName, side: "before", error: beforeRes.error });
153
+ if (!afterRes.ok) parseErrors.push({ fileName, side: "after", error: afterRes.error });
154
+ if (beforeRes.ok && afterRes.ok) {
155
+ const beforeDigest = sha256DigestOfJson(beforeRes.value);
156
+ const afterDigest = sha256DigestOfJson(afterRes.value);
157
+ if (beforeDigest === afterDigest) {
158
+ unchanged = 1;
159
+ } else {
160
+ const changedPaths = [];
161
+ const truncated = diffJsonPaths(beforeRes.value, afterRes.value, { path: "$", out: changedPaths, limit: 200 });
162
+ changedFiles.push({
163
+ fileName,
164
+ beforeDigest,
165
+ afterDigest,
166
+ digestKind: "semantic",
167
+ changedPathsSample: changedPaths,
168
+ truncated
169
+ });
170
+ }
171
+ }
172
+ } else {
173
+ const beforeFiles = yield* listJsonFiles(beforeAbs);
174
+ const afterFiles = yield* listJsonFiles(afterAbs);
175
+ const allFiles = Array.from(/* @__PURE__ */ new Set([...beforeFiles, ...afterFiles])).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
176
+ for (const fileName of allFiles) {
177
+ const beforeHas = beforeFiles.includes(fileName);
178
+ const afterHas = afterFiles.includes(fileName);
179
+ if (!beforeHas && afterHas) {
180
+ const v = yield* readJsonForSide(path.join(afterAbs, fileName));
181
+ if (v.ok) {
182
+ const digestInfo = extractSemanticDigest(fileName, v.value);
183
+ if (digestInfo.kind === "semantic") {
184
+ addedFiles.push({ fileName, digest: digestInfo.digest });
185
+ } else {
186
+ nonGatingChangedFiles.push({
187
+ fileName,
188
+ beforeDigest: void 0,
189
+ afterDigest: void 0,
190
+ digestKind: "nonGating",
191
+ changedPathsSample: ["$"],
192
+ truncated: false
193
+ });
194
+ }
195
+ } else parseErrors.push({ fileName, side: "after", error: v.error });
196
+ continue;
197
+ }
198
+ if (beforeHas && !afterHas) {
199
+ const v = yield* readJsonForSide(path.join(beforeAbs, fileName));
200
+ if (v.ok) {
201
+ const digestInfo = extractSemanticDigest(fileName, v.value);
202
+ if (digestInfo.kind === "semantic") {
203
+ removedFiles.push({ fileName, digest: digestInfo.digest });
204
+ } else {
205
+ nonGatingChangedFiles.push({
206
+ fileName,
207
+ beforeDigest: void 0,
208
+ afterDigest: void 0,
209
+ digestKind: "nonGating",
210
+ changedPathsSample: ["$"],
211
+ truncated: false
212
+ });
213
+ }
214
+ } else parseErrors.push({ fileName, side: "before", error: v.error });
215
+ continue;
216
+ }
217
+ const vBefore = yield* readJsonForSide(path.join(beforeAbs, fileName));
218
+ const vAfter = yield* readJsonForSide(path.join(afterAbs, fileName));
219
+ if (!vBefore.ok) parseErrors.push({ fileName, side: "before", error: vBefore.error });
220
+ if (!vAfter.ok) parseErrors.push({ fileName, side: "after", error: vAfter.error });
221
+ if (!(vBefore.ok && vAfter.ok)) continue;
222
+ const beforeSem = extractSemanticDigest(fileName, vBefore.value);
223
+ const afterSem = extractSemanticDigest(fileName, vAfter.value);
224
+ if (beforeSem.kind === "nonGating" || afterSem.kind === "nonGating") {
225
+ const beforeContent = sha256DigestOfJson(vBefore.value);
226
+ const afterContent = sha256DigestOfJson(vAfter.value);
227
+ if (beforeContent === afterContent) {
228
+ unchanged += 1;
229
+ continue;
230
+ }
231
+ const changedPaths2 = [];
232
+ const truncated2 = diffJsonPaths(vBefore.value, vAfter.value, { path: "$", out: changedPaths2, limit: 200 });
233
+ nonGatingChangedFiles.push({
234
+ fileName,
235
+ beforeDigest: void 0,
236
+ afterDigest: void 0,
237
+ digestKind: "nonGating",
238
+ changedPathsSample: changedPaths2,
239
+ truncated: truncated2
240
+ });
241
+ continue;
242
+ }
243
+ if (beforeSem.digest === afterSem.digest) {
244
+ const beforeContent = sha256DigestOfJson(vBefore.value);
245
+ const afterContent = sha256DigestOfJson(vAfter.value);
246
+ if (beforeContent !== afterContent) {
247
+ const changedPaths2 = [];
248
+ const truncated2 = diffJsonPaths(vBefore.value, vAfter.value, { path: "$", out: changedPaths2, limit: 200 });
249
+ nonGatingChangedFiles.push({
250
+ fileName,
251
+ beforeDigest: beforeSem.digest,
252
+ afterDigest: afterSem.digest,
253
+ digestKind: "semantic",
254
+ changedPathsSample: changedPaths2,
255
+ truncated: truncated2
256
+ });
257
+ continue;
258
+ }
259
+ unchanged += 1;
260
+ continue;
261
+ }
262
+ const changedPaths = [];
263
+ const truncated = diffJsonPaths(vBefore.value, vAfter.value, { path: "$", out: changedPaths, limit: 200 });
264
+ changedFiles.push({
265
+ fileName,
266
+ beforeDigest: beforeSem.digest,
267
+ afterDigest: afterSem.digest,
268
+ digestKind: "semantic",
269
+ changedPathsSample: changedPaths,
270
+ truncated
271
+ });
272
+ }
273
+ }
274
+ const hasGatingDiffs = addedFiles.length > 0 || removedFiles.length > 0 || changedFiles.length > 0;
275
+ const status = parseErrors.length > 0 ? "error" : hasGatingDiffs ? "violation" : "pass";
276
+ const report = {
277
+ schemaVersion: 1,
278
+ kind: "IrDiffReport",
279
+ before,
280
+ after,
281
+ status,
282
+ parseErrors,
283
+ addedFiles,
284
+ removedFiles,
285
+ changedFiles,
286
+ nonGatingChangedFiles,
287
+ summary: {
288
+ added: addedFiles.length,
289
+ removed: removedFiles.length,
290
+ changed: changedFiles.length,
291
+ nonGatingChanged: nonGatingChangedFiles.length,
292
+ unchanged
293
+ }
294
+ };
295
+ const artifactReasonCodes = Array.from(
296
+ /* @__PURE__ */ new Set([
297
+ ...addedFiles.length > 0 ? ["DIFF_ADDED_FILES"] : [],
298
+ ...removedFiles.length > 0 ? ["DIFF_REMOVED_FILES"] : [],
299
+ ...changedFiles.length > 0 ? ["DIFF_CHANGED_FILES"] : [],
300
+ ...nonGatingChangedFiles.length > 0 ? ["DIFF_NON_GATING_CHANGES"] : [],
301
+ ...parseErrors.length > 0 ? parseErrors.map((entry) => `DIFF_PARSE_ERROR:${entry.side.toUpperCase()}:${entry.fileName}:${entry.error.code ?? "UNKNOWN"}`) : []
302
+ ])
303
+ ).sort();
304
+ const artifacts = [
305
+ yield* makeArtifactOutput({
306
+ outDir: inv.global.outDir,
307
+ budgetBytes: inv.global.budgetBytes,
308
+ fileName: "ir.diff.report.json",
309
+ outputKey: "irDiffReport",
310
+ kind: "IrDiffReport",
311
+ value: report,
312
+ ...artifactReasonCodes.length > 0 ? { reasonCodes: artifactReasonCodes } : null
313
+ })
314
+ ];
315
+ if (status === "pass") {
316
+ return makeCommandResult({ runId, command: "ir.diff", ok: true, artifacts });
317
+ }
318
+ const topError = status === "violation" ? asSerializableErrorSummary(
319
+ makeCliError({
320
+ code: "CLI_VIOLATION_IR_DIFF",
321
+ message: "[Logix][CLI] ir diff: \u5B58\u5728\u5DEE\u5F02"
322
+ })
323
+ ) : asSerializableErrorSummary(
324
+ makeCliError({
325
+ code: "CLI_INVALID_INPUT",
326
+ message: "[Logix][CLI] ir diff: \u8F93\u5165\u4E0D\u53EF\u89E3\u6790"
327
+ })
328
+ );
329
+ return makeCommandResult({
330
+ runId,
331
+ command: "ir.diff",
332
+ ok: false,
333
+ artifacts,
334
+ error: topError
335
+ });
336
+ }).pipe(
337
+ Effect.catch((cause) => Effect.succeed(
338
+ makeCommandResult({
339
+ runId,
340
+ command: "ir.diff",
341
+ ok: false,
342
+ artifacts: [],
343
+ error: asSerializableErrorSummary(cause)
344
+ })
345
+ ))
346
+ );
347
+ };
348
+ export {
349
+ runIrDiff
350
+ };
351
+ //# sourceMappingURL=irDiff-WYXZEVA7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/commands/irDiff.ts"],"sourcesContent":["import { Effect } from 'effect'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { makeArtifactOutput } from '../artifacts.js'\nimport type { CliInvocation } from '../args.js'\nimport { asSerializableErrorSummary, makeCliError } from '../errors.js'\nimport { readJsonFile } from '../output.js'\nimport type { ArtifactOutput, CommandResult } from '../result.js'\nimport { makeCommandResult } from '../result.js'\nimport { sha256DigestOfJson } from '../stableJson.js'\n\ntype DigestInfo =\n | { readonly kind: 'semantic'; readonly digest: string }\n | { readonly kind: 'nonGating'; readonly reason: string }\n\ntype IrDiffChangedFile = {\n readonly fileName: string\n readonly beforeDigest: string | undefined\n readonly afterDigest: string | undefined\n readonly digestKind: DigestInfo['kind']\n readonly changedPathsSample: ReadonlyArray<string>\n readonly truncated: boolean\n}\n\ntype IrDiffReportV1 = {\n readonly schemaVersion: 1\n readonly kind: 'IrDiffReport'\n readonly before: string\n readonly after: string\n readonly status: 'pass' | 'violation' | 'error'\n readonly parseErrors: ReadonlyArray<{\n readonly fileName: string\n readonly side: 'before' | 'after'\n readonly error: ReturnType<typeof asSerializableErrorSummary>\n }>\n readonly addedFiles: ReadonlyArray<{ readonly fileName: string; readonly digest: string | undefined }>\n readonly removedFiles: ReadonlyArray<{ readonly fileName: string; readonly digest: string | undefined }>\n readonly changedFiles: ReadonlyArray<IrDiffChangedFile>\n readonly nonGatingChangedFiles: ReadonlyArray<IrDiffChangedFile>\n readonly summary: {\n readonly added: number\n readonly removed: number\n readonly changed: number\n readonly nonGatingChanged: number\n readonly unchanged: number\n }\n}\n\nconst escapeJsonPointer = (seg: string): string => seg.replace(/~/g, '~0').replace(/\\//g, '~1')\n\nconst diffJsonPaths = (a: unknown, b: unknown, args: { readonly path: string; readonly out: string[]; readonly limit: number }): boolean => {\n if (args.out.length >= args.limit) return true\n\n if (a === b) return false\n if (a === null || b === null) {\n if (a !== b) args.out.push(args.path)\n return args.out.length >= args.limit\n }\n\n const ta = typeof a\n const tb = typeof b\n if (ta !== tb) {\n args.out.push(args.path)\n return args.out.length >= args.limit\n }\n\n if (ta !== 'object') {\n if (!Object.is(a, b)) args.out.push(args.path)\n return args.out.length >= args.limit\n }\n\n const aa = a as any\n const bb = b as any\n\n const isArrA = Array.isArray(aa)\n const isArrB = Array.isArray(bb)\n if (isArrA || isArrB) {\n if (!(isArrA && isArrB)) {\n args.out.push(args.path)\n return args.out.length >= args.limit\n }\n const min = Math.min(aa.length, bb.length)\n if (aa.length !== bb.length) args.out.push(`${args.path}/length`)\n for (let i = 0; i < min; i++) {\n if (diffJsonPaths(aa[i], bb[i], { ...args, path: `${args.path}/${i}` })) return true\n if (args.out.length >= args.limit) return true\n }\n return args.out.length >= args.limit\n }\n\n const keys = Array.from(new Set([...Object.keys(aa), ...Object.keys(bb)])).sort((x, y) => (x < y ? -1 : x > y ? 1 : 0))\n for (const key of keys) {\n const nextPath = `${args.path}/${escapeJsonPointer(key)}`\n if (!(key in aa)) {\n args.out.push(nextPath)\n if (args.out.length >= args.limit) return true\n continue\n }\n if (!(key in bb)) {\n args.out.push(nextPath)\n if (args.out.length >= args.limit) return true\n continue\n }\n if (diffJsonPaths(aa[key], bb[key], { ...args, path: nextPath })) return true\n if (args.out.length >= args.limit) return true\n }\n\n return args.out.length >= args.limit\n}\n\nconst listJsonFiles = (dirAbs: string): Effect.Effect<ReadonlyArray<string>, unknown> =>\n Effect.tryPromise({\n try: () => fs.readdir(dirAbs, { withFileTypes: true }),\n catch: (cause) =>\n makeCliError({\n code: 'CLI_IO_ERROR',\n message: `[Logix][CLI] 无法读取目录:${dirAbs}`,\n cause,\n }),\n }).pipe(\n Effect.map((entries) =>\n entries\n .filter((e) => e.isFile() && e.name.endsWith('.json'))\n .map((e) => e.name)\n .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),\n ),\n )\n\ntype ReadJsonResult = { readonly ok: true; readonly value: unknown } | { readonly ok: false; readonly error: ReturnType<typeof asSerializableErrorSummary> }\n\nconst readJsonForSide = (fileAbs: string): Effect.Effect<ReadJsonResult, never> =>\n readJsonFile(fileAbs).pipe(\n Effect.map((value) => ({ ok: true as const, value })),\n Effect.catch((cause) => Effect.succeed({ ok: false as const, error: asSerializableErrorSummary(cause) })),\n )\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst isNonGatingFile = (fileName: string): boolean => fileName === 'trace.slim.json' || fileName === 'trialrun.report.json'\n\nconst extractSemanticDigest = (fileName: string, value: unknown): DigestInfo => {\n if (isNonGatingFile(fileName)) {\n return { kind: 'nonGating', reason: 'non_gating_by_policy' }\n }\n\n if (fileName === 'control-surface.manifest.json') {\n const digest = isRecord(value) && typeof value.digest === 'string' ? value.digest : undefined\n return { kind: 'semantic', digest: digest ?? sha256DigestOfJson(value) }\n }\n\n if (fileName === 'workflow.surface.json') {\n const digestPairs = Array.isArray(value)\n ? value\n .map((x) => {\n const moduleId = isRecord(x) && typeof x.moduleId === 'string' ? x.moduleId : undefined\n const surface = isRecord(x) ? x.surface : undefined\n const digest = isRecord(surface) && typeof surface.digest === 'string' ? surface.digest : undefined\n return moduleId && digest ? { moduleId, digest } : undefined\n })\n .filter((x): x is { moduleId: string; digest: string } => Boolean(x))\n .sort((a, b) => (a.moduleId < b.moduleId ? -1 : a.moduleId > b.moduleId ? 1 : 0))\n : []\n return { kind: 'semantic', digest: sha256DigestOfJson(digestPairs) }\n }\n\n return { kind: 'semantic', digest: sha256DigestOfJson(value) }\n}\n\ntype IrDiffInvocation = Extract<CliInvocation, { readonly command: 'ir.diff' }>\n\nexport const runIrDiff = (inv: IrDiffInvocation): Effect.Effect<CommandResult, never> => {\n const runId = inv.global.runId\n\n return Effect.gen(function* () {\n const { before, after } = inv\n\n const beforeAbs = path.resolve(process.cwd(), before)\n const afterAbs = path.resolve(process.cwd(), after)\n\n const beforeStat = yield* Effect.tryPromise({\n try: () => fs.stat(beforeAbs),\n catch: (cause) =>\n makeCliError({\n code: 'CLI_IO_ERROR',\n message: `[Logix][CLI] 无法读取输入:${before}`,\n cause,\n }),\n })\n const afterStat = yield* Effect.tryPromise({\n try: () => fs.stat(afterAbs),\n catch: (cause) =>\n makeCliError({\n code: 'CLI_IO_ERROR',\n message: `[Logix][CLI] 无法读取输入:${after}`,\n cause,\n }),\n })\n\n const beforeIsDir = beforeStat.isDirectory()\n const afterIsDir = afterStat.isDirectory()\n if (beforeIsDir !== afterIsDir) {\n const error = asSerializableErrorSummary(\n makeCliError({\n code: 'CLI_INVALID_INPUT',\n message: '--before/--after 类型不匹配:必须同为目录或同为文件',\n }),\n )\n return makeCommandResult({ runId, command: 'ir.diff', ok: false, artifacts: [], error })\n }\n\n const parseErrors: Array<{ fileName: string; side: 'before' | 'after'; error: ReturnType<typeof asSerializableErrorSummary> }> = []\n const addedFiles: Array<{ fileName: string; digest: string | undefined }> = []\n const removedFiles: Array<{ fileName: string; digest: string | undefined }> = []\n const changedFiles: IrDiffChangedFile[] = []\n const nonGatingChangedFiles: IrDiffChangedFile[] = []\n let unchanged = 0\n\n if (!beforeIsDir) {\n const fileName = `${path.basename(beforeAbs)}→${path.basename(afterAbs)}`\n\n const beforeRes = yield* readJsonForSide(beforeAbs)\n const afterRes = yield* readJsonForSide(afterAbs)\n\n if (!beforeRes.ok) parseErrors.push({ fileName, side: 'before', error: beforeRes.error })\n if (!afterRes.ok) parseErrors.push({ fileName, side: 'after', error: afterRes.error })\n\n if (beforeRes.ok && afterRes.ok) {\n const beforeDigest = sha256DigestOfJson(beforeRes.value)\n const afterDigest = sha256DigestOfJson(afterRes.value)\n if (beforeDigest === afterDigest) {\n unchanged = 1\n } else {\n const changedPaths: string[] = []\n const truncated = diffJsonPaths(beforeRes.value, afterRes.value, { path: '$', out: changedPaths, limit: 200 })\n changedFiles.push({\n fileName,\n beforeDigest,\n afterDigest,\n digestKind: 'semantic',\n changedPathsSample: changedPaths,\n truncated,\n })\n }\n }\n } else {\n const beforeFiles = yield* listJsonFiles(beforeAbs)\n const afterFiles = yield* listJsonFiles(afterAbs)\n const allFiles = Array.from(new Set([...beforeFiles, ...afterFiles])).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n\n for (const fileName of allFiles) {\n const beforeHas = beforeFiles.includes(fileName)\n const afterHas = afterFiles.includes(fileName)\n\n if (!beforeHas && afterHas) {\n const v = yield* readJsonForSide(path.join(afterAbs, fileName))\n if (v.ok) {\n const digestInfo = extractSemanticDigest(fileName, v.value)\n if (digestInfo.kind === 'semantic') {\n addedFiles.push({ fileName, digest: digestInfo.digest })\n } else {\n nonGatingChangedFiles.push({\n fileName,\n beforeDigest: undefined,\n afterDigest: undefined,\n digestKind: 'nonGating',\n changedPathsSample: ['$'],\n truncated: false,\n })\n }\n } else parseErrors.push({ fileName, side: 'after', error: v.error })\n continue\n }\n\n if (beforeHas && !afterHas) {\n const v = yield* readJsonForSide(path.join(beforeAbs, fileName))\n if (v.ok) {\n const digestInfo = extractSemanticDigest(fileName, v.value)\n if (digestInfo.kind === 'semantic') {\n removedFiles.push({ fileName, digest: digestInfo.digest })\n } else {\n nonGatingChangedFiles.push({\n fileName,\n beforeDigest: undefined,\n afterDigest: undefined,\n digestKind: 'nonGating',\n changedPathsSample: ['$'],\n truncated: false,\n })\n }\n } else parseErrors.push({ fileName, side: 'before', error: v.error })\n continue\n }\n\n const vBefore = yield* readJsonForSide(path.join(beforeAbs, fileName))\n const vAfter = yield* readJsonForSide(path.join(afterAbs, fileName))\n\n if (!vBefore.ok) parseErrors.push({ fileName, side: 'before', error: vBefore.error })\n if (!vAfter.ok) parseErrors.push({ fileName, side: 'after', error: vAfter.error })\n\n if (!(vBefore.ok && vAfter.ok)) continue\n\n const beforeSem = extractSemanticDigest(fileName, vBefore.value)\n const afterSem = extractSemanticDigest(fileName, vAfter.value)\n\n if (beforeSem.kind === 'nonGating' || afterSem.kind === 'nonGating') {\n const beforeContent = sha256DigestOfJson(vBefore.value)\n const afterContent = sha256DigestOfJson(vAfter.value)\n if (beforeContent === afterContent) {\n unchanged += 1\n continue\n }\n const changedPaths: string[] = []\n const truncated = diffJsonPaths(vBefore.value, vAfter.value, { path: '$', out: changedPaths, limit: 200 })\n nonGatingChangedFiles.push({\n fileName,\n beforeDigest: undefined,\n afterDigest: undefined,\n digestKind: 'nonGating',\n changedPathsSample: changedPaths,\n truncated,\n })\n continue\n }\n\n if (beforeSem.digest === afterSem.digest) {\n const beforeContent = sha256DigestOfJson(vBefore.value)\n const afterContent = sha256DigestOfJson(vAfter.value)\n if (beforeContent !== afterContent) {\n const changedPaths: string[] = []\n const truncated = diffJsonPaths(vBefore.value, vAfter.value, { path: '$', out: changedPaths, limit: 200 })\n nonGatingChangedFiles.push({\n fileName,\n beforeDigest: beforeSem.digest,\n afterDigest: afterSem.digest,\n digestKind: 'semantic',\n changedPathsSample: changedPaths,\n truncated,\n })\n continue\n }\n unchanged += 1\n continue\n }\n\n const changedPaths: string[] = []\n const truncated = diffJsonPaths(vBefore.value, vAfter.value, { path: '$', out: changedPaths, limit: 200 })\n changedFiles.push({\n fileName,\n beforeDigest: beforeSem.digest,\n afterDigest: afterSem.digest,\n digestKind: 'semantic',\n changedPathsSample: changedPaths,\n truncated,\n })\n }\n }\n\n const hasGatingDiffs = addedFiles.length > 0 || removedFiles.length > 0 || changedFiles.length > 0\n const status: IrDiffReportV1['status'] = parseErrors.length > 0 ? 'error' : hasGatingDiffs ? 'violation' : 'pass'\n\n const report: IrDiffReportV1 = {\n schemaVersion: 1,\n kind: 'IrDiffReport',\n before,\n after,\n status,\n parseErrors,\n addedFiles,\n removedFiles,\n changedFiles,\n nonGatingChangedFiles,\n summary: {\n added: addedFiles.length,\n removed: removedFiles.length,\n changed: changedFiles.length,\n nonGatingChanged: nonGatingChangedFiles.length,\n unchanged,\n },\n }\n\n const artifactReasonCodes = Array.from(\n new Set([\n ...(addedFiles.length > 0 ? ['DIFF_ADDED_FILES'] : []),\n ...(removedFiles.length > 0 ? ['DIFF_REMOVED_FILES'] : []),\n ...(changedFiles.length > 0 ? ['DIFF_CHANGED_FILES'] : []),\n ...(nonGatingChangedFiles.length > 0 ? ['DIFF_NON_GATING_CHANGES'] : []),\n ...(parseErrors.length > 0\n ? parseErrors.map((entry) => `DIFF_PARSE_ERROR:${entry.side.toUpperCase()}:${entry.fileName}:${entry.error.code ?? 'UNKNOWN'}`)\n : []),\n ]),\n ).sort()\n\n const artifacts: ArtifactOutput[] = [\n yield* makeArtifactOutput({\n outDir: inv.global.outDir,\n budgetBytes: inv.global.budgetBytes,\n fileName: 'ir.diff.report.json',\n outputKey: 'irDiffReport',\n kind: 'IrDiffReport',\n value: report,\n ...(artifactReasonCodes.length > 0 ? { reasonCodes: artifactReasonCodes } : null),\n }),\n ]\n\n if (status === 'pass') {\n return makeCommandResult({ runId, command: 'ir.diff', ok: true, artifacts })\n }\n\n const topError =\n status === 'violation'\n ? asSerializableErrorSummary(\n makeCliError({\n code: 'CLI_VIOLATION_IR_DIFF',\n message: '[Logix][CLI] ir diff: 存在差异',\n }),\n )\n : asSerializableErrorSummary(\n makeCliError({\n code: 'CLI_INVALID_INPUT',\n message: '[Logix][CLI] ir diff: 输入不可解析',\n }),\n )\n\n return makeCommandResult({\n runId,\n command: 'ir.diff',\n ok: false,\n artifacts,\n error: topError,\n })\n }).pipe(\n Effect.catch((cause) =>\n Effect.succeed(\n makeCommandResult({\n runId,\n command: 'ir.diff',\n ok: false,\n artifacts: [],\n error: asSerializableErrorSummary(cause),\n }),\n )),\n )\n}\n"],"mappings":"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","names":["changedPaths","truncated"]}
@@ -0,0 +1,87 @@
1
+ import {
2
+ makeArtifactOutput
3
+ } from "./chunk-VRPSB3SV.js";
4
+ import {
5
+ sha256DigestOfJson
6
+ } from "./chunk-RF7XSP3P.js";
7
+ import {
8
+ asSerializableErrorSummary,
9
+ makeCommandResult
10
+ } from "./chunk-6DZEO5HP.js";
11
+ import "./chunk-PZ5AY32C.js";
12
+
13
+ // src/internal/commands/irExport.ts
14
+ import { Effect } from "effect";
15
+ import path from "path";
16
+ var toModuleId = (entry) => `${path.basename(entry.modulePath)}#${entry.exportName}`;
17
+ var makeWorkflowSurfaces = (entry) => {
18
+ const moduleId = toModuleId(entry);
19
+ const source = `${entry.modulePath}#${entry.exportName}`;
20
+ const digest = sha256DigestOfJson({ moduleId, source });
21
+ return [
22
+ {
23
+ moduleId,
24
+ surface: { digest, source }
25
+ }
26
+ ];
27
+ };
28
+ var makeManifest = (workflowSurfaces) => {
29
+ const modules = workflowSurfaces.map((item) => ({
30
+ moduleId: item.moduleId,
31
+ workflowSurface: { digest: item.surface.digest }
32
+ }));
33
+ const digest = sha256DigestOfJson({ modules });
34
+ return {
35
+ schemaVersion: 1,
36
+ kind: "ControlSurfaceManifest",
37
+ version: 1,
38
+ digest,
39
+ modules
40
+ };
41
+ };
42
+ var runIrExport = (inv) => {
43
+ const runId = inv.global.runId;
44
+ return Effect.gen(function* () {
45
+ const workflowSurfaces = makeWorkflowSurfaces(inv.entry);
46
+ const manifest = makeManifest(workflowSurfaces);
47
+ const artifacts = [
48
+ yield* makeArtifactOutput({
49
+ outDir: inv.global.outDir,
50
+ budgetBytes: inv.global.budgetBytes,
51
+ fileName: "control-surface.manifest.json",
52
+ outputKey: "controlSurfaceManifest",
53
+ kind: "ControlSurfaceManifest",
54
+ value: manifest,
55
+ digest: manifest.digest
56
+ }),
57
+ yield* makeArtifactOutput({
58
+ outDir: inv.global.outDir,
59
+ budgetBytes: inv.global.budgetBytes,
60
+ fileName: "workflow.surface.json",
61
+ outputKey: "workflowSurface",
62
+ kind: "WorkflowSurfaceBundle",
63
+ value: workflowSurfaces
64
+ })
65
+ ];
66
+ return makeCommandResult({
67
+ runId,
68
+ command: "ir.export",
69
+ ok: true,
70
+ artifacts
71
+ });
72
+ }).pipe(
73
+ Effect.catch((cause) => Effect.succeed(
74
+ makeCommandResult({
75
+ runId,
76
+ command: "ir.export",
77
+ ok: false,
78
+ artifacts: [],
79
+ error: asSerializableErrorSummary(cause)
80
+ })
81
+ ))
82
+ );
83
+ };
84
+ export {
85
+ runIrExport
86
+ };
87
+ //# sourceMappingURL=irExport-EI2VYIMT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/commands/irExport.ts"],"sourcesContent":["import { Effect } from 'effect'\nimport path from 'node:path'\n\nimport { makeArtifactOutput } from '../artifacts.js'\nimport type { CliInvocation } from '../args.js'\nimport { asSerializableErrorSummary } from '../errors.js'\nimport type { ArtifactOutput, CommandResult } from '../result.js'\nimport { makeCommandResult } from '../result.js'\nimport { sha256DigestOfJson } from '../stableJson.js'\n\ntype IrExportInvocation = Extract<CliInvocation, { readonly command: 'ir.export' }>\n\ntype WorkflowSurfaceItem = {\n readonly moduleId: string\n readonly surface: {\n readonly digest: string\n readonly source: string\n }\n}\n\nconst toModuleId = (entry: IrExportInvocation['entry']): string => `${path.basename(entry.modulePath)}#${entry.exportName}`\n\nconst makeWorkflowSurfaces = (entry: IrExportInvocation['entry']): ReadonlyArray<WorkflowSurfaceItem> => {\n const moduleId = toModuleId(entry)\n const source = `${entry.modulePath}#${entry.exportName}`\n const digest = sha256DigestOfJson({ moduleId, source })\n return [\n {\n moduleId,\n surface: { digest, source },\n },\n ]\n}\n\nconst makeManifest = (workflowSurfaces: ReadonlyArray<WorkflowSurfaceItem>) => {\n const modules = workflowSurfaces.map((item) => ({\n moduleId: item.moduleId,\n workflowSurface: { digest: item.surface.digest },\n }))\n const digest = sha256DigestOfJson({ modules })\n return {\n schemaVersion: 1,\n kind: 'ControlSurfaceManifest',\n version: 1,\n digest,\n modules,\n } as const\n}\n\nexport const runIrExport = (inv: IrExportInvocation): Effect.Effect<CommandResult, never> => {\n const runId = inv.global.runId\n\n return Effect.gen(function* () {\n const workflowSurfaces = makeWorkflowSurfaces(inv.entry)\n const manifest = makeManifest(workflowSurfaces)\n\n const artifacts: ArtifactOutput[] = [\n yield* makeArtifactOutput({\n outDir: inv.global.outDir,\n budgetBytes: inv.global.budgetBytes,\n fileName: 'control-surface.manifest.json',\n outputKey: 'controlSurfaceManifest',\n kind: 'ControlSurfaceManifest',\n value: manifest,\n digest: manifest.digest,\n }),\n yield* makeArtifactOutput({\n outDir: inv.global.outDir,\n budgetBytes: inv.global.budgetBytes,\n fileName: 'workflow.surface.json',\n outputKey: 'workflowSurface',\n kind: 'WorkflowSurfaceBundle',\n value: workflowSurfaces,\n }),\n ]\n\n return makeCommandResult({\n runId,\n command: 'ir.export',\n ok: true,\n artifacts,\n })\n }).pipe(\n Effect.catch((cause) =>\n Effect.succeed(\n makeCommandResult({\n runId,\n command: 'ir.export',\n ok: false,\n artifacts: [],\n error: asSerializableErrorSummary(cause),\n }),\n )),\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,cAAc;AACvB,OAAO,UAAU;AAmBjB,IAAM,aAAa,CAAC,UAA+C,GAAG,KAAK,SAAS,MAAM,UAAU,CAAC,IAAI,MAAM,UAAU;AAEzH,IAAM,uBAAuB,CAAC,UAA2E;AACvG,QAAM,WAAW,WAAW,KAAK;AACjC,QAAM,SAAS,GAAG,MAAM,UAAU,IAAI,MAAM,UAAU;AACtD,QAAM,SAAS,mBAAmB,EAAE,UAAU,OAAO,CAAC;AACtD,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,SAAS,EAAE,QAAQ,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,IAAM,eAAe,CAAC,qBAAyD;AAC7E,QAAM,UAAU,iBAAiB,IAAI,CAAC,UAAU;AAAA,IAC9C,UAAU,KAAK;AAAA,IACf,iBAAiB,EAAE,QAAQ,KAAK,QAAQ,OAAO;AAAA,EACjD,EAAE;AACF,QAAM,SAAS,mBAAmB,EAAE,QAAQ,CAAC;AAC7C,SAAO;AAAA,IACL,eAAe;AAAA,IACf,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,cAAc,CAAC,QAAiE;AAC3F,QAAM,QAAQ,IAAI,OAAO;AAEzB,SAAO,OAAO,IAAI,aAAa;AAC7B,UAAM,mBAAmB,qBAAqB,IAAI,KAAK;AACvD,UAAM,WAAW,aAAa,gBAAgB;AAE9C,UAAM,YAA8B;AAAA,MAClC,OAAO,mBAAmB;AAAA,QACxB,QAAQ,IAAI,OAAO;AAAA,QACnB,aAAa,IAAI,OAAO;AAAA,QACxB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ,SAAS;AAAA,MACnB,CAAC;AAAA,MACD,OAAO,mBAAmB;AAAA,QACxB,QAAQ,IAAI,OAAO;AAAA,QACnB,aAAa,IAAI,OAAO;AAAA,QACxB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA,SAAS;AAAA,MACT,IAAI;AAAA,MACJ;AAAA,IACF,CAAC;AAAA,EACH,CAAC,EAAE;AAAA,IACD,OAAO,MAAM,CAAC,UACZ,OAAO;AAAA,MACL,kBAAkB;AAAA,QAChB;AAAA,QACA,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,WAAW,CAAC;AAAA,QACZ,OAAO,2BAA2B,KAAK;AAAA,MACzC,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AACF;","names":[]}