@tiangong-lca/cli 0.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 (96) hide show
  1. package/README.md +368 -0
  2. package/bin/tiangong.d.ts +1 -0
  3. package/bin/tiangong.js +32 -0
  4. package/dist/scripts/assert-full-coverage.js +77 -0
  5. package/dist/scripts/assert-full-coverage.js.map +1 -0
  6. package/dist/src/cli.js +2740 -0
  7. package/dist/src/cli.js.map +1 -0
  8. package/dist/src/lib/artifacts.js +86 -0
  9. package/dist/src/lib/artifacts.js.map +1 -0
  10. package/dist/src/lib/dotenv.js +36 -0
  11. package/dist/src/lib/dotenv.js.map +1 -0
  12. package/dist/src/lib/env.js +139 -0
  13. package/dist/src/lib/env.js.map +1 -0
  14. package/dist/src/lib/errors.js +38 -0
  15. package/dist/src/lib/errors.js.map +1 -0
  16. package/dist/src/lib/flow-build-alias-map.js +299 -0
  17. package/dist/src/lib/flow-build-alias-map.js.map +1 -0
  18. package/dist/src/lib/flow-get.js +81 -0
  19. package/dist/src/lib/flow-get.js.map +1 -0
  20. package/dist/src/lib/flow-governance.js +164 -0
  21. package/dist/src/lib/flow-governance.js.map +1 -0
  22. package/dist/src/lib/flow-list.js +187 -0
  23. package/dist/src/lib/flow-list.js.map +1 -0
  24. package/dist/src/lib/flow-publish-reviewed-data.js +808 -0
  25. package/dist/src/lib/flow-publish-reviewed-data.js.map +1 -0
  26. package/dist/src/lib/flow-publish-version.js +541 -0
  27. package/dist/src/lib/flow-publish-version.js.map +1 -0
  28. package/dist/src/lib/flow-read.js +310 -0
  29. package/dist/src/lib/flow-read.js.map +1 -0
  30. package/dist/src/lib/flow-regen-product.js +1396 -0
  31. package/dist/src/lib/flow-regen-product.js.map +1 -0
  32. package/dist/src/lib/flow-remediate.js +821 -0
  33. package/dist/src/lib/flow-remediate.js.map +1 -0
  34. package/dist/src/lib/http.js +45 -0
  35. package/dist/src/lib/http.js.map +1 -0
  36. package/dist/src/lib/io.js +30 -0
  37. package/dist/src/lib/io.js.map +1 -0
  38. package/dist/src/lib/kb-search.js +83 -0
  39. package/dist/src/lib/kb-search.js.map +1 -0
  40. package/dist/src/lib/lifecyclemodel-auto-build.js +1328 -0
  41. package/dist/src/lib/lifecyclemodel-auto-build.js.map +1 -0
  42. package/dist/src/lib/lifecyclemodel-orchestrate.js +1556 -0
  43. package/dist/src/lib/lifecyclemodel-orchestrate.js.map +1 -0
  44. package/dist/src/lib/lifecyclemodel-publish-build.js +296 -0
  45. package/dist/src/lib/lifecyclemodel-publish-build.js.map +1 -0
  46. package/dist/src/lib/lifecyclemodel-publish-resulting-process.js +101 -0
  47. package/dist/src/lib/lifecyclemodel-publish-resulting-process.js.map +1 -0
  48. package/dist/src/lib/lifecyclemodel-resulting-process.js +1152 -0
  49. package/dist/src/lib/lifecyclemodel-resulting-process.js.map +1 -0
  50. package/dist/src/lib/lifecyclemodel-validate-build.js +238 -0
  51. package/dist/src/lib/lifecyclemodel-validate-build.js.map +1 -0
  52. package/dist/src/lib/llm.js +383 -0
  53. package/dist/src/lib/llm.js.map +1 -0
  54. package/dist/src/lib/process-auto-build.js +717 -0
  55. package/dist/src/lib/process-auto-build.js.map +1 -0
  56. package/dist/src/lib/process-batch-build.js +409 -0
  57. package/dist/src/lib/process-batch-build.js.map +1 -0
  58. package/dist/src/lib/process-get.js +66 -0
  59. package/dist/src/lib/process-get.js.map +1 -0
  60. package/dist/src/lib/process-publish-build.js +451 -0
  61. package/dist/src/lib/process-publish-build.js.map +1 -0
  62. package/dist/src/lib/process-resume-build.js +364 -0
  63. package/dist/src/lib/process-resume-build.js.map +1 -0
  64. package/dist/src/lib/publish.js +562 -0
  65. package/dist/src/lib/publish.js.map +1 -0
  66. package/dist/src/lib/remote.js +88 -0
  67. package/dist/src/lib/remote.js.map +1 -0
  68. package/dist/src/lib/review-flow.js +1110 -0
  69. package/dist/src/lib/review-flow.js.map +1 -0
  70. package/dist/src/lib/review-lifecyclemodel.js +727 -0
  71. package/dist/src/lib/review-lifecyclemodel.js.map +1 -0
  72. package/dist/src/lib/review-process.js +702 -0
  73. package/dist/src/lib/review-process.js.map +1 -0
  74. package/dist/src/lib/run.js +106 -0
  75. package/dist/src/lib/run.js.map +1 -0
  76. package/dist/src/lib/state-lock.js +150 -0
  77. package/dist/src/lib/state-lock.js.map +1 -0
  78. package/dist/src/lib/supabase-client.js +269 -0
  79. package/dist/src/lib/supabase-client.js.map +1 -0
  80. package/dist/src/lib/supabase-json-ordered-write.js +186 -0
  81. package/dist/src/lib/supabase-json-ordered-write.js.map +1 -0
  82. package/dist/src/lib/supabase-rest.js +138 -0
  83. package/dist/src/lib/supabase-rest.js.map +1 -0
  84. package/dist/src/lib/supabase-session.js +424 -0
  85. package/dist/src/lib/supabase-session.js.map +1 -0
  86. package/dist/src/lib/tidas-sdk-package-validator.js +493 -0
  87. package/dist/src/lib/tidas-sdk-package-validator.js.map +1 -0
  88. package/dist/src/lib/unstructured.js +203 -0
  89. package/dist/src/lib/unstructured.js.map +1 -0
  90. package/dist/src/lib/user-api-key.js +75 -0
  91. package/dist/src/lib/user-api-key.js.map +1 -0
  92. package/dist/src/lib/validation.js +191 -0
  93. package/dist/src/lib/validation.js.map +1 -0
  94. package/dist/src/main.js +38 -0
  95. package/dist/src/main.js.map +1 -0
  96. package/package.json +81 -0
@@ -0,0 +1,36 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ function stripQuotes(value) {
4
+ if ((value.startsWith('"') && value.endsWith('"')) ||
5
+ (value.startsWith("'") && value.endsWith("'"))) {
6
+ return value.slice(1, -1);
7
+ }
8
+ return value;
9
+ }
10
+ export function loadDotEnv(cwd, env) {
11
+ const envPath = path.join(cwd, '.env');
12
+ if (!existsSync(envPath)) {
13
+ return { loaded: false, path: envPath, count: 0 };
14
+ }
15
+ const lines = readFileSync(envPath, 'utf8').split(/\r?\n/u);
16
+ let count = 0;
17
+ for (const line of lines) {
18
+ const trimmed = line.trim();
19
+ if (!trimmed || trimmed.startsWith('#')) {
20
+ continue;
21
+ }
22
+ const separatorIndex = trimmed.indexOf('=');
23
+ if (separatorIndex <= 0) {
24
+ continue;
25
+ }
26
+ const key = trimmed.slice(0, separatorIndex).trim();
27
+ const rawValue = trimmed.slice(separatorIndex + 1).trim();
28
+ if (!key || env[key] !== undefined) {
29
+ continue;
30
+ }
31
+ env[key] = stripQuotes(rawValue);
32
+ count += 1;
33
+ }
34
+ return { loaded: true, path: envPath, count };
35
+ }
36
+ //# sourceMappingURL=dotenv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotenv.js","sourceRoot":"","sources":["../../../src/lib/dotenv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B,SAAS,WAAW,CAAC,KAAa;IAChC,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAsB;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACpD,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5D,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,SAAS;QACX,CAAC;QAED,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;YACxB,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACnC,SAAS;QACX,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAChD,CAAC","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\n\nexport type DotEnvLoadResult = {\n loaded: boolean;\n path: string;\n count: number;\n};\n\nfunction stripQuotes(value: string): string {\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n return value;\n}\n\nexport function loadDotEnv(cwd: string, env: NodeJS.ProcessEnv): DotEnvLoadResult {\n const envPath = path.join(cwd, '.env');\n if (!existsSync(envPath)) {\n return { loaded: false, path: envPath, count: 0 };\n }\n\n const lines = readFileSync(envPath, 'utf8').split(/\\r?\\n/u);\n let count = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) {\n continue;\n }\n\n const separatorIndex = trimmed.indexOf('=');\n if (separatorIndex <= 0) {\n continue;\n }\n\n const key = trimmed.slice(0, separatorIndex).trim();\n const rawValue = trimmed.slice(separatorIndex + 1).trim();\n if (!key || env[key] !== undefined) {\n continue;\n }\n\n env[key] = stripQuotes(rawValue);\n count += 1;\n }\n\n return { loaded: true, path: envPath, count };\n}\n"]}
@@ -0,0 +1,139 @@
1
+ export const ENV_KEYS = {
2
+ apiBaseUrl: 'TIANGONG_LCA_API_BASE_URL',
3
+ apiKey: 'TIANGONG_LCA_API_KEY',
4
+ region: 'TIANGONG_LCA_REGION',
5
+ supabasePublishableKey: 'TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY',
6
+ sessionFile: 'TIANGONG_LCA_SESSION_FILE',
7
+ disableSessionCache: 'TIANGONG_LCA_DISABLE_SESSION_CACHE',
8
+ forceReauth: 'TIANGONG_LCA_FORCE_REAUTH',
9
+ };
10
+ export const ENV_SPECS = [
11
+ {
12
+ key: ENV_KEYS.apiBaseUrl,
13
+ required: true,
14
+ description: 'Main TianGong LCA API / Edge Functions base URL',
15
+ },
16
+ {
17
+ key: ENV_KEYS.apiKey,
18
+ required: true,
19
+ description: 'Main TianGong LCA API key',
20
+ },
21
+ {
22
+ key: ENV_KEYS.region,
23
+ required: false,
24
+ description: 'Target TianGong LCA API region',
25
+ defaultValue: 'us-east-1',
26
+ },
27
+ {
28
+ key: ENV_KEYS.supabasePublishableKey,
29
+ required: true,
30
+ description: 'Supabase publishable key used to bootstrap and refresh user sessions',
31
+ },
32
+ {
33
+ key: ENV_KEYS.sessionFile,
34
+ required: false,
35
+ description: 'Optional local path for the CLI session cache file',
36
+ },
37
+ {
38
+ key: ENV_KEYS.disableSessionCache,
39
+ required: false,
40
+ description: 'Disable the persistent CLI session cache when set to true',
41
+ defaultValue: 'false',
42
+ },
43
+ {
44
+ key: ENV_KEYS.forceReauth,
45
+ required: false,
46
+ description: 'Ignore cached sessions and force a fresh login when set to true',
47
+ defaultValue: 'false',
48
+ },
49
+ ];
50
+ function parseBooleanEnv(value) {
51
+ if (typeof value !== 'string') {
52
+ return false;
53
+ }
54
+ switch (value.trim().toLowerCase()) {
55
+ case '1':
56
+ case 'true':
57
+ case 'yes':
58
+ case 'on':
59
+ return true;
60
+ default:
61
+ return false;
62
+ }
63
+ }
64
+ export function resolveEnv(spec, env) {
65
+ const envValue = env[spec.key];
66
+ if (envValue) {
67
+ return {
68
+ key: spec.key,
69
+ source: 'env',
70
+ value: envValue,
71
+ present: true,
72
+ };
73
+ }
74
+ if (spec.defaultValue !== undefined) {
75
+ return {
76
+ key: spec.key,
77
+ source: 'default',
78
+ value: spec.defaultValue,
79
+ present: true,
80
+ };
81
+ }
82
+ return {
83
+ key: spec.key,
84
+ source: 'missing',
85
+ value: null,
86
+ present: false,
87
+ };
88
+ }
89
+ export function readRuntimeEnv(env) {
90
+ const apiBaseUrl = resolveEnv(ENV_SPECS[0], env).value;
91
+ const apiKey = resolveEnv(ENV_SPECS[1], env).value;
92
+ const region = resolveEnv(ENV_SPECS[2], env).value;
93
+ const supabasePublishableKey = resolveEnv(ENV_SPECS[3], env).value;
94
+ const sessionFile = resolveEnv(ENV_SPECS[4], env).value;
95
+ const disableSessionCache = parseBooleanEnv(resolveEnv(ENV_SPECS[5], env).value);
96
+ const forceReauth = parseBooleanEnv(resolveEnv(ENV_SPECS[6], env).value);
97
+ return {
98
+ apiBaseUrl,
99
+ apiKey,
100
+ region,
101
+ supabasePublishableKey,
102
+ sessionFile,
103
+ disableSessionCache,
104
+ forceReauth,
105
+ };
106
+ }
107
+ export function maskSecret(value) {
108
+ if (!value) {
109
+ return value;
110
+ }
111
+ if (value.length <= 8) {
112
+ return value;
113
+ }
114
+ return `${value.slice(0, 4)}...${value.slice(-4)}`;
115
+ }
116
+ export function buildDoctorReport(env, dotEnvStatus) {
117
+ const checks = ENV_SPECS.map((spec) => {
118
+ const resolved = resolveEnv(spec, env);
119
+ return {
120
+ key: spec.key,
121
+ description: spec.description,
122
+ required: spec.required,
123
+ source: resolved.source,
124
+ present: resolved.present,
125
+ valuePreview: maskSecret(resolved.value),
126
+ };
127
+ });
128
+ return {
129
+ ok: checks.every((check) => !check.required || check.present),
130
+ loadedDotEnv: dotEnvStatus.loaded,
131
+ dotEnvPath: dotEnvStatus.path,
132
+ dotEnvKeysLoaded: dotEnvStatus.count,
133
+ checks,
134
+ };
135
+ }
136
+ export const __testInternals = {
137
+ parseBooleanEnv,
138
+ };
139
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/lib/env.ts"],"names":[],"mappings":"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","sourcesContent":["export type EnvSpec = {\n key: string;\n required: boolean;\n description: string;\n defaultValue?: string;\n};\n\nexport type ResolvedEnv = {\n key: string;\n source: 'env' | 'default' | 'missing';\n value: string | null;\n present: boolean;\n};\n\nexport const ENV_KEYS = {\n apiBaseUrl: 'TIANGONG_LCA_API_BASE_URL',\n apiKey: 'TIANGONG_LCA_API_KEY',\n region: 'TIANGONG_LCA_REGION',\n supabasePublishableKey: 'TIANGONG_LCA_SUPABASE_PUBLISHABLE_KEY',\n sessionFile: 'TIANGONG_LCA_SESSION_FILE',\n disableSessionCache: 'TIANGONG_LCA_DISABLE_SESSION_CACHE',\n forceReauth: 'TIANGONG_LCA_FORCE_REAUTH',\n} as const;\n\nexport const ENV_SPECS: EnvSpec[] = [\n {\n key: ENV_KEYS.apiBaseUrl,\n required: true,\n description: 'Main TianGong LCA API / Edge Functions base URL',\n },\n {\n key: ENV_KEYS.apiKey,\n required: true,\n description: 'Main TianGong LCA API key',\n },\n {\n key: ENV_KEYS.region,\n required: false,\n description: 'Target TianGong LCA API region',\n defaultValue: 'us-east-1',\n },\n {\n key: ENV_KEYS.supabasePublishableKey,\n required: true,\n description: 'Supabase publishable key used to bootstrap and refresh user sessions',\n },\n {\n key: ENV_KEYS.sessionFile,\n required: false,\n description: 'Optional local path for the CLI session cache file',\n },\n {\n key: ENV_KEYS.disableSessionCache,\n required: false,\n description: 'Disable the persistent CLI session cache when set to true',\n defaultValue: 'false',\n },\n {\n key: ENV_KEYS.forceReauth,\n required: false,\n description: 'Ignore cached sessions and force a fresh login when set to true',\n defaultValue: 'false',\n },\n];\n\nexport type DoctorCheck = {\n key: string;\n description: string;\n required: boolean;\n source: ResolvedEnv['source'];\n present: boolean;\n valuePreview: string | null;\n};\n\nexport type DoctorReport = {\n ok: boolean;\n loadedDotEnv: boolean;\n dotEnvPath: string;\n dotEnvKeysLoaded: number;\n checks: DoctorCheck[];\n};\n\nexport type RuntimeEnv = {\n apiBaseUrl: string | null;\n apiKey: string | null;\n region: string;\n supabasePublishableKey: string | null;\n sessionFile: string | null;\n disableSessionCache: boolean;\n forceReauth: boolean;\n};\n\nfunction parseBooleanEnv(value: string | null): boolean {\n if (typeof value !== 'string') {\n return false;\n }\n\n switch (value.trim().toLowerCase()) {\n case '1':\n case 'true':\n case 'yes':\n case 'on':\n return true;\n default:\n return false;\n }\n}\n\nexport function resolveEnv(spec: EnvSpec, env: NodeJS.ProcessEnv): ResolvedEnv {\n const envValue = env[spec.key];\n if (envValue) {\n return {\n key: spec.key,\n source: 'env',\n value: envValue,\n present: true,\n };\n }\n\n if (spec.defaultValue !== undefined) {\n return {\n key: spec.key,\n source: 'default',\n value: spec.defaultValue,\n present: true,\n };\n }\n\n return {\n key: spec.key,\n source: 'missing',\n value: null,\n present: false,\n };\n}\n\nexport function readRuntimeEnv(env: NodeJS.ProcessEnv): RuntimeEnv {\n const apiBaseUrl = resolveEnv(ENV_SPECS[0], env).value;\n const apiKey = resolveEnv(ENV_SPECS[1], env).value;\n const region = resolveEnv(ENV_SPECS[2], env).value as string;\n const supabasePublishableKey = resolveEnv(ENV_SPECS[3], env).value;\n const sessionFile = resolveEnv(ENV_SPECS[4], env).value;\n const disableSessionCache = parseBooleanEnv(resolveEnv(ENV_SPECS[5], env).value);\n const forceReauth = parseBooleanEnv(resolveEnv(ENV_SPECS[6], env).value);\n\n return {\n apiBaseUrl,\n apiKey,\n region,\n supabasePublishableKey,\n sessionFile,\n disableSessionCache,\n forceReauth,\n };\n}\n\nexport function maskSecret(value: string | null): string | null {\n if (!value) {\n return value;\n }\n if (value.length <= 8) {\n return value;\n }\n return `${value.slice(0, 4)}...${value.slice(-4)}`;\n}\n\nexport function buildDoctorReport(\n env: NodeJS.ProcessEnv,\n dotEnvStatus: { loaded: boolean; path: string; count: number },\n): DoctorReport {\n const checks = ENV_SPECS.map((spec) => {\n const resolved = resolveEnv(spec, env);\n return {\n key: spec.key,\n description: spec.description,\n required: spec.required,\n source: resolved.source,\n present: resolved.present,\n valuePreview: maskSecret(resolved.value),\n };\n });\n\n return {\n ok: checks.every((check) => !check.required || check.present),\n loadedDotEnv: dotEnvStatus.loaded,\n dotEnvPath: dotEnvStatus.path,\n dotEnvKeysLoaded: dotEnvStatus.count,\n checks,\n };\n}\n\nexport const __testInternals = {\n parseBooleanEnv,\n};\n"]}
@@ -0,0 +1,38 @@
1
+ export class CliError extends Error {
2
+ code;
3
+ exitCode;
4
+ details;
5
+ constructor(message, options) {
6
+ super(message);
7
+ this.name = 'CliError';
8
+ this.code = options?.code ?? 'CLI_ERROR';
9
+ this.exitCode = options?.exitCode ?? 1;
10
+ this.details = options?.details;
11
+ }
12
+ }
13
+ export function toErrorPayload(error) {
14
+ if (error instanceof CliError) {
15
+ return {
16
+ error: {
17
+ code: error.code,
18
+ message: error.message,
19
+ ...(error.details === undefined ? {} : { details: error.details }),
20
+ },
21
+ };
22
+ }
23
+ if (error instanceof Error) {
24
+ return {
25
+ error: {
26
+ code: 'UNEXPECTED_ERROR',
27
+ message: error.message,
28
+ },
29
+ };
30
+ }
31
+ return {
32
+ error: {
33
+ code: 'UNKNOWN_THROWN_VALUE',
34
+ message: String(error),
35
+ },
36
+ };
37
+ }
38
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAS;IACb,QAAQ,CAAS;IACjB,OAAO,CAAW;IAE3B,YAAY,OAAe,EAAE,OAAiE;QAC5F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,WAAW,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAClC,CAAC;CACF;AAUD,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;aACnE;SACF,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE;YACL,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;SACvB;KACF,CAAC;AACJ,CAAC","sourcesContent":["export class CliError extends Error {\n readonly code: string;\n readonly exitCode: number;\n readonly details?: unknown;\n\n constructor(message: string, options?: { code?: string; exitCode?: number; details?: unknown }) {\n super(message);\n this.name = 'CliError';\n this.code = options?.code ?? 'CLI_ERROR';\n this.exitCode = options?.exitCode ?? 1;\n this.details = options?.details;\n }\n}\n\nexport type ErrorPayload = {\n error: {\n code: string;\n message: string;\n details?: unknown;\n };\n};\n\nexport function toErrorPayload(error: unknown): ErrorPayload {\n if (error instanceof CliError) {\n return {\n error: {\n code: error.code,\n message: error.message,\n ...(error.details === undefined ? {} : { details: error.details }),\n },\n };\n }\n\n if (error instanceof Error) {\n return {\n error: {\n code: 'UNEXPECTED_ERROR',\n message: error.message,\n },\n };\n }\n\n return {\n error: {\n code: 'UNKNOWN_THROWN_VALUE',\n message: String(error),\n },\n };\n}\n"]}
@@ -0,0 +1,299 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';
4
+ import { CliError } from './errors.js';
5
+ import { extractFlowRecord, isRecord, loadRowsFromFile, normalizeText, } from './flow-governance.js';
6
+ function assertInputFile(inputFile, requiredCode, missingCode) {
7
+ if (!inputFile) {
8
+ throw new CliError('Missing required input file value.', {
9
+ code: requiredCode,
10
+ exitCode: 2,
11
+ });
12
+ }
13
+ const resolved = path.resolve(inputFile);
14
+ if (!existsSync(resolved)) {
15
+ throw new CliError(`Input file not found: ${resolved}`, {
16
+ code: missingCode,
17
+ exitCode: 2,
18
+ });
19
+ }
20
+ return resolved;
21
+ }
22
+ function assertInputFiles(inputFiles, requiredCode, missingCode) {
23
+ if (!inputFiles.length) {
24
+ throw new CliError('At least one input file is required.', {
25
+ code: requiredCode,
26
+ exitCode: 2,
27
+ });
28
+ }
29
+ return inputFiles.map((inputFile) => assertInputFile(inputFile, requiredCode, missingCode));
30
+ }
31
+ function assertOutDir(outDir) {
32
+ if (!outDir) {
33
+ throw new CliError('Missing required --out-dir value.', {
34
+ code: 'FLOW_BUILD_ALIAS_MAP_OUT_DIR_REQUIRED',
35
+ exitCode: 2,
36
+ });
37
+ }
38
+ return path.resolve(outDir);
39
+ }
40
+ function readJsonObjectFile(filePath, requiredCode, missingCode, invalidCode) {
41
+ const resolved = assertInputFile(filePath, requiredCode, missingCode);
42
+ let parsed;
43
+ try {
44
+ parsed = JSON.parse(readFileSync(resolved, 'utf8'));
45
+ }
46
+ catch (error) {
47
+ throw new CliError(`Expected JSON object file: ${resolved}`, {
48
+ code: invalidCode,
49
+ exitCode: 2,
50
+ details: String(error),
51
+ });
52
+ }
53
+ if (!isRecord(parsed)) {
54
+ throw new CliError(`Expected JSON object file: ${resolved}`, {
55
+ code: invalidCode,
56
+ exitCode: 2,
57
+ });
58
+ }
59
+ return parsed;
60
+ }
61
+ function buildFlowIndex(rows) {
62
+ const byUuid = {};
63
+ const byUuidVersion = {};
64
+ const byName = {};
65
+ const records = [];
66
+ for (const row of rows) {
67
+ const record = extractFlowRecord(row);
68
+ records.push(record);
69
+ byUuid[record.id] ??= [];
70
+ byUuid[record.id].push(record);
71
+ byUuidVersion[`${record.id}@${record.version}`] = record;
72
+ const normalizedName = normalizeText(record.name);
73
+ byName[normalizedName] ??= [];
74
+ byName[normalizedName].push(record);
75
+ }
76
+ return {
77
+ records,
78
+ byUuid,
79
+ byUuidVersion,
80
+ byName,
81
+ };
82
+ }
83
+ function aliasLookup(aliasMap, flowUuid, flowVersion) {
84
+ const versionedKey = flowVersion ? `${flowUuid}@${flowVersion}` : null;
85
+ for (const key of [versionedKey, flowUuid]) {
86
+ if (!key) {
87
+ continue;
88
+ }
89
+ const candidate = aliasMap[key];
90
+ if (isRecord(candidate)) {
91
+ return candidate;
92
+ }
93
+ }
94
+ return null;
95
+ }
96
+ function candidateRef(record, includeType = false) {
97
+ return {
98
+ id: record.id,
99
+ version: record.version,
100
+ name: record.name,
101
+ ...(includeType ? { flow_type: record.flowType } : {}),
102
+ };
103
+ }
104
+ function planAlias(oldRecord, newIndex, seedAliasMap) {
105
+ const base = {
106
+ old_flow_id: oldRecord.id,
107
+ old_flow_version: oldRecord.version,
108
+ old_flow_name: oldRecord.name,
109
+ old_flow_type: oldRecord.flowType,
110
+ decision: 'manual_review',
111
+ reason: 'no_deterministic_match',
112
+ };
113
+ const existingTarget = newIndex.byUuidVersion[`${oldRecord.id}@${oldRecord.version}`];
114
+ if (existingTarget) {
115
+ return {
116
+ ...base,
117
+ decision: 'no_alias_needed',
118
+ reason: 'already_present_in_target',
119
+ target_flow_id: existingTarget.id,
120
+ target_flow_version: existingTarget.version,
121
+ };
122
+ }
123
+ const seededTarget = aliasLookup(seedAliasMap, oldRecord.id, oldRecord.version || null);
124
+ if (seededTarget) {
125
+ const targetRecord = newIndex.byUuidVersion[`${String(seededTarget.id ?? '')}@${String(seededTarget.version ?? '')}`];
126
+ if (targetRecord) {
127
+ return {
128
+ ...base,
129
+ decision: 'alias_map_entry',
130
+ reason: 'seed_alias_map',
131
+ target_flow_id: targetRecord.id,
132
+ target_flow_version: targetRecord.version,
133
+ target_flow_name: targetRecord.name,
134
+ target_flow_type: targetRecord.flowType,
135
+ };
136
+ }
137
+ }
138
+ const sameUuidCandidates = newIndex.byUuid[oldRecord.id] ?? [];
139
+ if (sameUuidCandidates.length === 1) {
140
+ const candidate = sameUuidCandidates[0];
141
+ return {
142
+ ...base,
143
+ decision: 'alias_map_entry',
144
+ reason: 'same_uuid_single_target_version',
145
+ target_flow_id: candidate.id,
146
+ target_flow_version: candidate.version,
147
+ target_flow_name: candidate.name,
148
+ target_flow_type: candidate.flowType,
149
+ };
150
+ }
151
+ if (sameUuidCandidates.length > 1) {
152
+ return {
153
+ ...base,
154
+ decision: 'manual_review',
155
+ reason: 'same_uuid_multiple_target_versions',
156
+ candidate_refs: sameUuidCandidates.map((candidate) => candidateRef(candidate)),
157
+ };
158
+ }
159
+ const byName = newIndex.byName[normalizeText(oldRecord.name)] ?? [];
160
+ const nameAndTypeCandidates = byName.filter((candidate) => candidate.flowType === oldRecord.flowType);
161
+ if (nameAndTypeCandidates.length === 1) {
162
+ const candidate = nameAndTypeCandidates[0];
163
+ return {
164
+ ...base,
165
+ decision: 'alias_map_entry',
166
+ reason: 'unique_exact_name_and_type_match',
167
+ target_flow_id: candidate.id,
168
+ target_flow_version: candidate.version,
169
+ target_flow_name: candidate.name,
170
+ target_flow_type: candidate.flowType,
171
+ };
172
+ }
173
+ if (nameAndTypeCandidates.length > 1) {
174
+ return {
175
+ ...base,
176
+ decision: 'manual_review',
177
+ reason: 'ambiguous_name_and_type_match',
178
+ candidate_refs: nameAndTypeCandidates.map((candidate) => candidateRef(candidate)),
179
+ };
180
+ }
181
+ if (byName.length > 0) {
182
+ return {
183
+ ...base,
184
+ decision: 'manual_review',
185
+ reason: 'name_match_flow_type_mismatch',
186
+ candidate_refs: byName.map((candidate) => candidateRef(candidate, true)),
187
+ };
188
+ }
189
+ return base;
190
+ }
191
+ function buildDecisionCounts(actions) {
192
+ const counts = {};
193
+ actions.forEach((action) => {
194
+ counts[action.decision] = (counts[action.decision] ?? 0) + 1;
195
+ });
196
+ return counts;
197
+ }
198
+ function buildOutputFiles(outDir) {
199
+ return {
200
+ out_dir: outDir,
201
+ alias_plan: path.join(outDir, 'alias-plan.json'),
202
+ alias_plan_jsonl: path.join(outDir, 'alias-plan.jsonl'),
203
+ flow_alias_map: path.join(outDir, 'flow-alias-map.json'),
204
+ manual_review_queue: path.join(outDir, 'manual-review-queue.jsonl'),
205
+ summary: path.join(outDir, 'alias-summary.json'),
206
+ };
207
+ }
208
+ export async function runFlowBuildAliasMap(options, deps = {}) {
209
+ const oldFlowFiles = assertInputFiles(options.oldFlowFiles ?? [], 'FLOW_BUILD_ALIAS_MAP_OLD_FLOW_FILES_REQUIRED', 'FLOW_BUILD_ALIAS_MAP_OLD_FLOW_FILE_NOT_FOUND');
210
+ const newFlowFiles = assertInputFiles(options.newFlowFiles ?? [], 'FLOW_BUILD_ALIAS_MAP_NEW_FLOW_FILES_REQUIRED', 'FLOW_BUILD_ALIAS_MAP_NEW_FLOW_FILE_NOT_FOUND');
211
+ const seedAliasMapFile = options.seedAliasMapFile
212
+ ? assertInputFile(options.seedAliasMapFile, 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_REQUIRED', 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_NOT_FOUND')
213
+ : null;
214
+ const outDir = assertOutDir(options.outDir);
215
+ const now = deps.now ?? (() => new Date());
216
+ const files = buildOutputFiles(outDir);
217
+ const oldRows = oldFlowFiles.flatMap((filePath) => loadRowsFromFile(filePath));
218
+ const newRows = newFlowFiles.flatMap((filePath) => loadRowsFromFile(filePath));
219
+ const oldIndex = buildFlowIndex(oldRows);
220
+ const newIndex = buildFlowIndex(newRows);
221
+ const seedAliasMap = seedAliasMapFile
222
+ ? readJsonObjectFile(seedAliasMapFile, 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_REQUIRED', 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_NOT_FOUND', 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_INVALID')
223
+ : {};
224
+ const aliasPlan = [];
225
+ const manualQueue = [];
226
+ const versionAliasMap = {};
227
+ const uuidTargets = {};
228
+ oldIndex.records.forEach((oldRecord) => {
229
+ const action = planAlias(oldRecord, newIndex, seedAliasMap);
230
+ aliasPlan.push(action);
231
+ if (action.decision === 'alias_map_entry' &&
232
+ action.target_flow_id &&
233
+ action.target_flow_version) {
234
+ const target = {
235
+ id: action.target_flow_id,
236
+ version: action.target_flow_version,
237
+ reason: action.reason,
238
+ };
239
+ versionAliasMap[`${oldRecord.id}@${oldRecord.version}`] = target;
240
+ uuidTargets[oldRecord.id] ??= new Set();
241
+ uuidTargets[oldRecord.id].add(`${action.target_flow_id}@${action.target_flow_version}`);
242
+ return;
243
+ }
244
+ if (action.decision === 'manual_review') {
245
+ manualQueue.push(action);
246
+ }
247
+ });
248
+ const flowAliasMap = {
249
+ ...versionAliasMap,
250
+ };
251
+ Object.entries(uuidTargets).forEach(([oldUuid, targets]) => {
252
+ if (targets.size !== 1) {
253
+ return;
254
+ }
255
+ const [targetId, targetVersion] = [...targets][0].split('@', 2);
256
+ flowAliasMap[oldUuid] = {
257
+ id: targetId,
258
+ version: targetVersion,
259
+ reason: 'all_versions_share_same_target',
260
+ };
261
+ });
262
+ const summary = {
263
+ old_flow_count: oldIndex.records.length,
264
+ new_flow_count: newIndex.records.length,
265
+ alias_entries_versioned: Object.keys(versionAliasMap).length,
266
+ alias_entries_uuid_only: Object.keys(flowAliasMap).length - Object.keys(versionAliasMap).length,
267
+ manual_review_count: manualQueue.length,
268
+ decision_counts: buildDecisionCounts(aliasPlan),
269
+ };
270
+ writeJsonArtifact(files.alias_plan, aliasPlan);
271
+ writeJsonLinesArtifact(files.alias_plan_jsonl, aliasPlan);
272
+ writeJsonArtifact(files.flow_alias_map, flowAliasMap);
273
+ writeJsonLinesArtifact(files.manual_review_queue, manualQueue);
274
+ writeJsonArtifact(files.summary, summary);
275
+ return {
276
+ schema_version: 1,
277
+ generated_at_utc: now().toISOString(),
278
+ status: 'completed_local_flow_build_alias_map',
279
+ old_flow_files: oldFlowFiles,
280
+ new_flow_files: newFlowFiles,
281
+ seed_alias_map_file: seedAliasMapFile,
282
+ out_dir: outDir,
283
+ summary,
284
+ files,
285
+ };
286
+ }
287
+ export const __testInternals = {
288
+ assertInputFile,
289
+ assertInputFiles,
290
+ assertOutDir,
291
+ readJsonObjectFile,
292
+ buildFlowIndex,
293
+ aliasLookup,
294
+ candidateRef,
295
+ planAlias,
296
+ buildDecisionCounts,
297
+ buildOutputFiles,
298
+ };
299
+ //# sourceMappingURL=flow-build-alias-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-build-alias-map.js","sourceRoot":"","sources":["../../../src/lib/flow-build-alias-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport {\n extractFlowRecord,\n isRecord,\n loadRowsFromFile,\n normalizeText,\n type FlowRecord,\n type JsonRecord,\n} from './flow-governance.js';\n\ntype FlowIndex = {\n records: FlowRecord[];\n byUuid: Record<string, FlowRecord[]>;\n byUuidVersion: Record<string, FlowRecord>;\n byName: Record<string, FlowRecord[]>;\n};\n\nexport type FlowBuildAliasMapFiles = {\n out_dir: string;\n alias_plan: string;\n alias_plan_jsonl: string;\n flow_alias_map: string;\n manual_review_queue: string;\n summary: string;\n};\n\nexport type FlowBuildAliasMapSummary = {\n old_flow_count: number;\n new_flow_count: number;\n alias_entries_versioned: number;\n alias_entries_uuid_only: number;\n manual_review_count: number;\n decision_counts: Record<string, number>;\n};\n\nexport type FlowAliasPlanAction = {\n old_flow_id: string;\n old_flow_version: string;\n old_flow_name: string;\n old_flow_type: string;\n decision: 'no_alias_needed' | 'alias_map_entry' | 'manual_review';\n reason: string;\n target_flow_id?: string;\n target_flow_version?: string;\n target_flow_name?: string;\n target_flow_type?: string;\n candidate_refs?: Array<Record<string, string>>;\n};\n\nexport type FlowBuildAliasMapReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: 'completed_local_flow_build_alias_map';\n old_flow_files: string[];\n new_flow_files: string[];\n seed_alias_map_file: string | null;\n out_dir: string;\n summary: FlowBuildAliasMapSummary;\n files: FlowBuildAliasMapFiles;\n};\n\nexport type RunFlowBuildAliasMapOptions = {\n oldFlowFiles: string[];\n newFlowFiles: string[];\n seedAliasMapFile?: string | null;\n outDir: string;\n};\n\ntype FlowBuildAliasMapDeps = {\n now?: () => Date;\n};\n\nfunction assertInputFile(inputFile: string, requiredCode: string, missingCode: string): string {\n if (!inputFile) {\n throw new CliError('Missing required input file value.', {\n code: requiredCode,\n exitCode: 2,\n });\n }\n\n const resolved = path.resolve(inputFile);\n if (!existsSync(resolved)) {\n throw new CliError(`Input file not found: ${resolved}`, {\n code: missingCode,\n exitCode: 2,\n });\n }\n\n return resolved;\n}\n\nfunction assertInputFiles(\n inputFiles: string[],\n requiredCode: string,\n missingCode: string,\n): string[] {\n if (!inputFiles.length) {\n throw new CliError('At least one input file is required.', {\n code: requiredCode,\n exitCode: 2,\n });\n }\n\n return inputFiles.map((inputFile) => assertInputFile(inputFile, requiredCode, missingCode));\n}\n\nfunction assertOutDir(outDir: string): string {\n if (!outDir) {\n throw new CliError('Missing required --out-dir value.', {\n code: 'FLOW_BUILD_ALIAS_MAP_OUT_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n\n return path.resolve(outDir);\n}\n\nfunction readJsonObjectFile(\n filePath: string,\n requiredCode: string,\n missingCode: string,\n invalidCode: string,\n): JsonRecord {\n const resolved = assertInputFile(filePath, requiredCode, missingCode);\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(resolved, 'utf8'));\n } catch (error) {\n throw new CliError(`Expected JSON object file: ${resolved}`, {\n code: invalidCode,\n exitCode: 2,\n details: String(error),\n });\n }\n\n if (!isRecord(parsed)) {\n throw new CliError(`Expected JSON object file: ${resolved}`, {\n code: invalidCode,\n exitCode: 2,\n });\n }\n\n return parsed;\n}\n\nfunction buildFlowIndex(rows: JsonRecord[]): FlowIndex {\n const byUuid: Record<string, FlowRecord[]> = {};\n const byUuidVersion: Record<string, FlowRecord> = {};\n const byName: Record<string, FlowRecord[]> = {};\n const records: FlowRecord[] = [];\n\n for (const row of rows) {\n const record = extractFlowRecord(row);\n records.push(record);\n byUuid[record.id] ??= [];\n byUuid[record.id].push(record);\n byUuidVersion[`${record.id}@${record.version}`] = record;\n const normalizedName = normalizeText(record.name);\n byName[normalizedName] ??= [];\n byName[normalizedName].push(record);\n }\n\n return {\n records,\n byUuid,\n byUuidVersion,\n byName,\n };\n}\n\nfunction aliasLookup(\n aliasMap: JsonRecord,\n flowUuid: string,\n flowVersion: string | null,\n): JsonRecord | null {\n const versionedKey = flowVersion ? `${flowUuid}@${flowVersion}` : null;\n for (const key of [versionedKey, flowUuid]) {\n if (!key) {\n continue;\n }\n const candidate = aliasMap[key];\n if (isRecord(candidate)) {\n return candidate;\n }\n }\n return null;\n}\n\nfunction candidateRef(record: FlowRecord, includeType = false): Record<string, string> {\n return {\n id: record.id,\n version: record.version,\n name: record.name,\n ...(includeType ? { flow_type: record.flowType } : {}),\n };\n}\n\nfunction planAlias(\n oldRecord: FlowRecord,\n newIndex: FlowIndex,\n seedAliasMap: JsonRecord,\n): FlowAliasPlanAction {\n const base: FlowAliasPlanAction = {\n old_flow_id: oldRecord.id,\n old_flow_version: oldRecord.version,\n old_flow_name: oldRecord.name,\n old_flow_type: oldRecord.flowType,\n decision: 'manual_review',\n reason: 'no_deterministic_match',\n };\n\n const existingTarget = newIndex.byUuidVersion[`${oldRecord.id}@${oldRecord.version}`];\n if (existingTarget) {\n return {\n ...base,\n decision: 'no_alias_needed',\n reason: 'already_present_in_target',\n target_flow_id: existingTarget.id,\n target_flow_version: existingTarget.version,\n };\n }\n\n const seededTarget = aliasLookup(seedAliasMap, oldRecord.id, oldRecord.version || null);\n if (seededTarget) {\n const targetRecord =\n newIndex.byUuidVersion[\n `${String(seededTarget.id ?? '')}@${String(seededTarget.version ?? '')}`\n ];\n if (targetRecord) {\n return {\n ...base,\n decision: 'alias_map_entry',\n reason: 'seed_alias_map',\n target_flow_id: targetRecord.id,\n target_flow_version: targetRecord.version,\n target_flow_name: targetRecord.name,\n target_flow_type: targetRecord.flowType,\n };\n }\n }\n\n const sameUuidCandidates = newIndex.byUuid[oldRecord.id] ?? [];\n if (sameUuidCandidates.length === 1) {\n const candidate = sameUuidCandidates[0];\n return {\n ...base,\n decision: 'alias_map_entry',\n reason: 'same_uuid_single_target_version',\n target_flow_id: candidate.id,\n target_flow_version: candidate.version,\n target_flow_name: candidate.name,\n target_flow_type: candidate.flowType,\n };\n }\n\n if (sameUuidCandidates.length > 1) {\n return {\n ...base,\n decision: 'manual_review',\n reason: 'same_uuid_multiple_target_versions',\n candidate_refs: sameUuidCandidates.map((candidate) => candidateRef(candidate)),\n };\n }\n\n const byName = newIndex.byName[normalizeText(oldRecord.name)] ?? [];\n const nameAndTypeCandidates = byName.filter(\n (candidate) => candidate.flowType === oldRecord.flowType,\n );\n if (nameAndTypeCandidates.length === 1) {\n const candidate = nameAndTypeCandidates[0];\n return {\n ...base,\n decision: 'alias_map_entry',\n reason: 'unique_exact_name_and_type_match',\n target_flow_id: candidate.id,\n target_flow_version: candidate.version,\n target_flow_name: candidate.name,\n target_flow_type: candidate.flowType,\n };\n }\n\n if (nameAndTypeCandidates.length > 1) {\n return {\n ...base,\n decision: 'manual_review',\n reason: 'ambiguous_name_and_type_match',\n candidate_refs: nameAndTypeCandidates.map((candidate) => candidateRef(candidate)),\n };\n }\n\n if (byName.length > 0) {\n return {\n ...base,\n decision: 'manual_review',\n reason: 'name_match_flow_type_mismatch',\n candidate_refs: byName.map((candidate) => candidateRef(candidate, true)),\n };\n }\n\n return base;\n}\n\nfunction buildDecisionCounts(actions: FlowAliasPlanAction[]): Record<string, number> {\n const counts: Record<string, number> = {};\n actions.forEach((action) => {\n counts[action.decision] = (counts[action.decision] ?? 0) + 1;\n });\n return counts;\n}\n\nfunction buildOutputFiles(outDir: string): FlowBuildAliasMapFiles {\n return {\n out_dir: outDir,\n alias_plan: path.join(outDir, 'alias-plan.json'),\n alias_plan_jsonl: path.join(outDir, 'alias-plan.jsonl'),\n flow_alias_map: path.join(outDir, 'flow-alias-map.json'),\n manual_review_queue: path.join(outDir, 'manual-review-queue.jsonl'),\n summary: path.join(outDir, 'alias-summary.json'),\n };\n}\n\nexport async function runFlowBuildAliasMap(\n options: RunFlowBuildAliasMapOptions,\n deps: FlowBuildAliasMapDeps = {},\n): Promise<FlowBuildAliasMapReport> {\n const oldFlowFiles = assertInputFiles(\n options.oldFlowFiles ?? [],\n 'FLOW_BUILD_ALIAS_MAP_OLD_FLOW_FILES_REQUIRED',\n 'FLOW_BUILD_ALIAS_MAP_OLD_FLOW_FILE_NOT_FOUND',\n );\n const newFlowFiles = assertInputFiles(\n options.newFlowFiles ?? [],\n 'FLOW_BUILD_ALIAS_MAP_NEW_FLOW_FILES_REQUIRED',\n 'FLOW_BUILD_ALIAS_MAP_NEW_FLOW_FILE_NOT_FOUND',\n );\n const seedAliasMapFile = options.seedAliasMapFile\n ? assertInputFile(\n options.seedAliasMapFile,\n 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_REQUIRED',\n 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_NOT_FOUND',\n )\n : null;\n const outDir = assertOutDir(options.outDir);\n const now = deps.now ?? (() => new Date());\n const files = buildOutputFiles(outDir);\n\n const oldRows = oldFlowFiles.flatMap((filePath) => loadRowsFromFile(filePath));\n const newRows = newFlowFiles.flatMap((filePath) => loadRowsFromFile(filePath));\n const oldIndex = buildFlowIndex(oldRows);\n const newIndex = buildFlowIndex(newRows);\n const seedAliasMap = seedAliasMapFile\n ? readJsonObjectFile(\n seedAliasMapFile,\n 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_REQUIRED',\n 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_NOT_FOUND',\n 'FLOW_BUILD_ALIAS_MAP_SEED_ALIAS_MAP_INVALID',\n )\n : {};\n\n const aliasPlan: FlowAliasPlanAction[] = [];\n const manualQueue: FlowAliasPlanAction[] = [];\n const versionAliasMap: Record<string, JsonRecord> = {};\n const uuidTargets: Record<string, Set<string>> = {};\n\n oldIndex.records.forEach((oldRecord) => {\n const action = planAlias(oldRecord, newIndex, seedAliasMap);\n aliasPlan.push(action);\n\n if (\n action.decision === 'alias_map_entry' &&\n action.target_flow_id &&\n action.target_flow_version\n ) {\n const target = {\n id: action.target_flow_id,\n version: action.target_flow_version,\n reason: action.reason,\n } satisfies JsonRecord;\n versionAliasMap[`${oldRecord.id}@${oldRecord.version}`] = target;\n uuidTargets[oldRecord.id] ??= new Set<string>();\n uuidTargets[oldRecord.id].add(`${action.target_flow_id}@${action.target_flow_version}`);\n return;\n }\n\n if (action.decision === 'manual_review') {\n manualQueue.push(action);\n }\n });\n\n const flowAliasMap: Record<string, JsonRecord> = {\n ...versionAliasMap,\n };\n Object.entries(uuidTargets).forEach(([oldUuid, targets]) => {\n if (targets.size !== 1) {\n return;\n }\n const [targetId, targetVersion] = [...targets][0].split('@', 2);\n flowAliasMap[oldUuid] = {\n id: targetId,\n version: targetVersion,\n reason: 'all_versions_share_same_target',\n };\n });\n\n const summary: FlowBuildAliasMapSummary = {\n old_flow_count: oldIndex.records.length,\n new_flow_count: newIndex.records.length,\n alias_entries_versioned: Object.keys(versionAliasMap).length,\n alias_entries_uuid_only: Object.keys(flowAliasMap).length - Object.keys(versionAliasMap).length,\n manual_review_count: manualQueue.length,\n decision_counts: buildDecisionCounts(aliasPlan),\n };\n\n writeJsonArtifact(files.alias_plan, aliasPlan);\n writeJsonLinesArtifact(files.alias_plan_jsonl, aliasPlan);\n writeJsonArtifact(files.flow_alias_map, flowAliasMap);\n writeJsonLinesArtifact(files.manual_review_queue, manualQueue);\n writeJsonArtifact(files.summary, summary);\n\n return {\n schema_version: 1,\n generated_at_utc: now().toISOString(),\n status: 'completed_local_flow_build_alias_map',\n old_flow_files: oldFlowFiles,\n new_flow_files: newFlowFiles,\n seed_alias_map_file: seedAliasMapFile,\n out_dir: outDir,\n summary,\n files,\n };\n}\n\nexport const __testInternals = {\n assertInputFile,\n assertInputFiles,\n assertOutDir,\n readJsonObjectFile,\n buildFlowIndex,\n aliasLookup,\n candidateRef,\n planAlias,\n buildDecisionCounts,\n buildOutputFiles,\n};\n"]}