@tiangong-lca/cli 0.0.6 → 0.0.8

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 (90) hide show
  1. package/README.md +154 -30
  2. package/dist/src/cli.js +2235 -149
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/lib/dataset-author.js +100 -0
  5. package/dist/src/lib/dataset-author.js.map +1 -0
  6. package/dist/src/lib/dataset-bilingual.js +545 -0
  7. package/dist/src/lib/dataset-bilingual.js.map +1 -0
  8. package/dist/src/lib/dataset-contract.js +350 -0
  9. package/dist/src/lib/dataset-contract.js.map +1 -0
  10. package/dist/src/lib/dataset-evidence-search.js +636 -0
  11. package/dist/src/lib/dataset-evidence-search.js.map +1 -0
  12. package/dist/src/lib/dataset-import-lca.js +171 -0
  13. package/dist/src/lib/dataset-import-lca.js.map +1 -0
  14. package/dist/src/lib/dataset-local.js +231 -0
  15. package/dist/src/lib/dataset-local.js.map +1 -0
  16. package/dist/src/lib/dataset-references-rewrite.js +214 -0
  17. package/dist/src/lib/dataset-references-rewrite.js.map +1 -0
  18. package/dist/src/lib/dataset-remote-refresh.js +166 -0
  19. package/dist/src/lib/dataset-remote-refresh.js.map +1 -0
  20. package/dist/src/lib/dataset-remote-verify.js +543 -0
  21. package/dist/src/lib/dataset-remote-verify.js.map +1 -0
  22. package/dist/src/lib/dataset-validate.js +247 -0
  23. package/dist/src/lib/dataset-validate.js.map +1 -0
  24. package/dist/src/lib/flow-payload-validation.js +51 -0
  25. package/dist/src/lib/flow-payload-validation.js.map +1 -0
  26. package/dist/src/lib/flow-publish-reviewed-data.js +16 -0
  27. package/dist/src/lib/flow-publish-reviewed-data.js.map +1 -1
  28. package/dist/src/lib/flow-publish-version.js +182 -12
  29. package/dist/src/lib/flow-publish-version.js.map +1 -1
  30. package/dist/src/lib/flow-regen-product.js +2 -10
  31. package/dist/src/lib/flow-regen-product.js.map +1 -1
  32. package/dist/src/lib/flow-remediate.js +4 -8
  33. package/dist/src/lib/flow-remediate.js.map +1 -1
  34. package/dist/src/lib/identity-preflight.js +1021 -0
  35. package/dist/src/lib/identity-preflight.js.map +1 -0
  36. package/dist/src/lib/lifecyclemodel-auto-build.js +11 -8
  37. package/dist/src/lib/lifecyclemodel-auto-build.js.map +1 -1
  38. package/dist/src/lib/lifecyclemodel-graph.js +248 -0
  39. package/dist/src/lib/lifecyclemodel-graph.js.map +1 -0
  40. package/dist/src/lib/lifecyclemodel-publish-build.js +1 -1
  41. package/dist/src/lib/lifecyclemodel-publish-build.js.map +1 -1
  42. package/dist/src/lib/lifecyclemodel-save-draft-run.js +245 -0
  43. package/dist/src/lib/lifecyclemodel-save-draft-run.js.map +1 -0
  44. package/dist/src/lib/lifecyclemodel-validate-build.js +1 -1
  45. package/dist/src/lib/lifecyclemodel-validate-build.js.map +1 -1
  46. package/dist/src/lib/process-auto-build.js +158 -8
  47. package/dist/src/lib/process-auto-build.js.map +1 -1
  48. package/dist/src/lib/process-batch-build.js +6 -3
  49. package/dist/src/lib/process-batch-build.js.map +1 -1
  50. package/dist/src/lib/process-dedup-review.js +921 -0
  51. package/dist/src/lib/process-dedup-review.js.map +1 -0
  52. package/dist/src/lib/process-flow-build-plan.js +1071 -0
  53. package/dist/src/lib/process-flow-build-plan.js.map +1 -0
  54. package/dist/src/lib/process-payload-validation.js +57 -0
  55. package/dist/src/lib/process-payload-validation.js.map +1 -0
  56. package/dist/src/lib/process-publish-build.js +126 -10
  57. package/dist/src/lib/process-publish-build.js.map +1 -1
  58. package/dist/src/lib/process-refresh-references.js +1037 -0
  59. package/dist/src/lib/process-refresh-references.js.map +1 -0
  60. package/dist/src/lib/process-required-fields.js +810 -0
  61. package/dist/src/lib/process-required-fields.js.map +1 -0
  62. package/dist/src/lib/process-resume-build.js +4 -6
  63. package/dist/src/lib/process-resume-build.js.map +1 -1
  64. package/dist/src/lib/process-save-draft-run.js +35 -13
  65. package/dist/src/lib/process-save-draft-run.js.map +1 -1
  66. package/dist/src/lib/process-scope-statistics.js +859 -0
  67. package/dist/src/lib/process-scope-statistics.js.map +1 -0
  68. package/dist/src/lib/process-verify-rows.js +250 -0
  69. package/dist/src/lib/process-verify-rows.js.map +1 -0
  70. package/dist/src/lib/publish.js +101 -1
  71. package/dist/src/lib/publish.js.map +1 -1
  72. package/dist/src/lib/remote.js +4 -4
  73. package/dist/src/lib/remote.js.map +1 -1
  74. package/dist/src/lib/review-flow.js +58 -0
  75. package/dist/src/lib/review-flow.js.map +1 -1
  76. package/dist/src/lib/review-lifecyclemodel.js +2 -2
  77. package/dist/src/lib/review-lifecyclemodel.js.map +1 -1
  78. package/dist/src/lib/review-process.js +150 -2
  79. package/dist/src/lib/review-process.js.map +1 -1
  80. package/dist/src/lib/runtime-rulesets.js +283 -0
  81. package/dist/src/lib/runtime-rulesets.js.map +1 -0
  82. package/dist/src/lib/tidas-sdk-package-validator.js +28 -9
  83. package/dist/src/lib/tidas-sdk-package-validator.js.map +1 -1
  84. package/dist/src/lib/tidas-sdk-validation.js +96 -0
  85. package/dist/src/lib/tidas-sdk-validation.js.map +1 -0
  86. package/dist/src/lib/user-api-key.js +1 -1
  87. package/dist/src/lib/user-api-key.js.map +1 -1
  88. package/package.json +5 -5
  89. /package/bin/{tiangong.d.ts → tiangong-lca.d.ts} +0 -0
  90. /package/bin/{tiangong.js → tiangong-lca.js} +0 -0
@@ -0,0 +1,245 @@
1
+ import path from 'node:path';
2
+ import * as tidasSdk from '@tiangong-lca/tidas-sdk';
3
+ import { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';
4
+ import { CliError } from './errors.js';
5
+ import { firstNonEmpty, isRecord, materializeDatasetRows, } from './dataset-local.js';
6
+ import { syncLifecyclemodelBundleRecord, } from './lifecyclemodel-bundle-save.js';
7
+ import { buildRunId, resolveRunLayout } from './run.js';
8
+ import { normalizeIssuePath, validateSchemaWithDeepFallback, } from './tidas-sdk-validation.js';
9
+ const VALIDATOR_NAME = '@tiangong-lca/tidas-sdk/LifeCycleModelSchema';
10
+ function getLifecyclemodelSchema(sdk = tidasSdk) {
11
+ const schema = sdk.LifeCycleModelSchema;
12
+ if (!schema?.safeParse) {
13
+ throw new Error(`${VALIDATOR_NAME} is unavailable in the published CLI runtime.`);
14
+ }
15
+ return schema;
16
+ }
17
+ function getLifecyclemodelFactory(sdk = tidasSdk) {
18
+ const createLifeCycleModel = sdk.createLifeCycleModel;
19
+ return typeof createLifeCycleModel === 'function'
20
+ ? createLifeCycleModel
21
+ : null;
22
+ }
23
+ export function validateLifecyclemodelPayload(payload, schema, createEntity) {
24
+ const activeSchema = schema ?? getLifecyclemodelSchema();
25
+ const activeCreateEntity = createEntity === undefined && schema === undefined ? getLifecyclemodelFactory() : createEntity;
26
+ const outcome = validateSchemaWithDeepFallback(activeSchema, payload, activeCreateEntity);
27
+ if (outcome.success) {
28
+ return {
29
+ ok: true,
30
+ validator: VALIDATOR_NAME,
31
+ issue_count: 0,
32
+ issues: [],
33
+ };
34
+ }
35
+ const issues = outcome.issues.map((issue) => ({
36
+ path: normalizeIssuePath(issue.path),
37
+ message: issue.message ?? 'Validation failed',
38
+ code: issue.code ?? 'custom',
39
+ }));
40
+ return {
41
+ ok: false,
42
+ validator: VALIDATOR_NAME,
43
+ issue_count: issues.length,
44
+ issues,
45
+ };
46
+ }
47
+ function summarizeValidation(result) {
48
+ if (result.ok) {
49
+ return 'local LifeCycleModelSchema validation passed';
50
+ }
51
+ const preview = result.issues
52
+ .slice(0, 3)
53
+ .map((issue) => `${issue.path}: ${issue.message}`)
54
+ .join('; ');
55
+ return `local LifeCycleModelSchema validation failed with ${result.issue_count} issue(s)${preview ? ` (${preview})` : ''}`;
56
+ }
57
+ function extractMetadata(row) {
58
+ const metadata = {};
59
+ const jsonTg = isRecord(row.json_tg) ? row.json_tg : isRecord(row.jsonTg) ? row.jsonTg : null;
60
+ if (jsonTg) {
61
+ metadata.json_tg = jsonTg;
62
+ }
63
+ if (Array.isArray(row.processMutations)) {
64
+ metadata.processMutations = row.processMutations.filter(isRecord);
65
+ }
66
+ else if (Array.isArray(row.process_mutations)) {
67
+ metadata.processMutations = row.process_mutations.filter(isRecord);
68
+ }
69
+ if (typeof row.ruleVerification === 'boolean') {
70
+ metadata.ruleVerification = row.ruleVerification;
71
+ }
72
+ else if (typeof row.rule_verification === 'boolean') {
73
+ metadata.ruleVerification = row.rule_verification;
74
+ }
75
+ return Object.keys(metadata).length > 0 ? metadata : null;
76
+ }
77
+ function candidateError(message) {
78
+ return { message };
79
+ }
80
+ function buildCandidate(row, payload, validate) {
81
+ const root = isRecord(payload.lifeCycleModelDataSet) ? payload.lifeCycleModelDataSet : payload;
82
+ const information = isRecord(root.lifeCycleModelInformation)
83
+ ? root.lifeCycleModelInformation
84
+ : {};
85
+ const dataSetInformation = isRecord(information.dataSetInformation)
86
+ ? information.dataSetInformation
87
+ : {};
88
+ const administrativeInformation = isRecord(root.administrativeInformation)
89
+ ? root.administrativeInformation
90
+ : {};
91
+ const publicationAndOwnership = isRecord(administrativeInformation.publicationAndOwnership)
92
+ ? administrativeInformation.publicationAndOwnership
93
+ : {};
94
+ const id = firstNonEmpty(row.id, dataSetInformation['common:UUID']);
95
+ const version = firstNonEmpty(row.version, publicationAndOwnership['common:dataSetVersion'], '01.01.000');
96
+ if (!id) {
97
+ return {
98
+ id: null,
99
+ version,
100
+ payload,
101
+ metadata: extractMetadata(row),
102
+ error: candidateError('Lifecyclemodel payload missing lifeCycleModelInformation.dataSetInformation.common:UUID.'),
103
+ };
104
+ }
105
+ const validation = validate(payload);
106
+ if (!validation.ok) {
107
+ return {
108
+ id,
109
+ version,
110
+ payload,
111
+ metadata: extractMetadata(row),
112
+ validation,
113
+ error: candidateError(summarizeValidation(validation)),
114
+ };
115
+ }
116
+ return {
117
+ id,
118
+ version,
119
+ payload,
120
+ metadata: extractMetadata(row),
121
+ validation,
122
+ };
123
+ }
124
+ function defaultOutDir(inputPath, commit, now) {
125
+ const runId = buildRunId({
126
+ namespace: 'lifecyclemodel_save_draft',
127
+ operation: commit ? 'commit' : 'dry_run',
128
+ now,
129
+ });
130
+ return resolveRunLayout(path.join(path.dirname(inputPath), 'artifacts'), 'lifecyclemodel_save_draft', runId).runRoot;
131
+ }
132
+ function buildFiles(outDir) {
133
+ const outputDir = path.join(outDir, 'outputs', 'save-draft-bundle');
134
+ return {
135
+ normalized_input: path.join(outDir, 'inputs', 'normalized-input.json'),
136
+ selected_lifecyclemodels: path.join(outputDir, 'selected-lifecyclemodels.jsonl'),
137
+ progress_jsonl: path.join(outputDir, 'progress.jsonl'),
138
+ failures_jsonl: path.join(outputDir, 'failures.jsonl'),
139
+ summary_json: path.join(outputDir, 'summary.json'),
140
+ };
141
+ }
142
+ function compactCandidate(candidate) {
143
+ return {
144
+ id: candidate.id,
145
+ version: candidate.version,
146
+ payload: candidate.payload,
147
+ metadata: candidate.metadata,
148
+ ...(candidate.validation ? { validation: candidate.validation } : {}),
149
+ ...(candidate.error ? { error: candidate.error } : {}),
150
+ };
151
+ }
152
+ function serializeError(error) {
153
+ return {
154
+ message: error instanceof Error ? error.message : String(error),
155
+ };
156
+ }
157
+ export async function runLifecyclemodelSaveDraft(options) {
158
+ const now = options.now ?? new Date();
159
+ const inputPath = path.resolve(options.inputPath);
160
+ const commit = options.commit === true;
161
+ const outDir = path.resolve(options.outDir ?? defaultOutDir(inputPath, commit, now));
162
+ const validate = options.validateLifecyclemodelPayloadImpl ?? validateLifecyclemodelPayload;
163
+ const datasetRows = materializeDatasetRows(inputPath, options.rawInput);
164
+ const candidates = datasetRows.map((row) => buildCandidate(row.row, row.payload, validate));
165
+ const files = buildFiles(outDir);
166
+ if (commit && (!options.env || !options.fetchImpl)) {
167
+ throw new CliError('Lifecyclemodel save-draft commit requires env and fetch runtime bindings.', {
168
+ code: 'LIFECYCLEMODEL_SAVE_DRAFT_RUNTIME_REQUIRED',
169
+ exitCode: 2,
170
+ });
171
+ }
172
+ writeJsonArtifact(files.normalized_input, {
173
+ input_kind: 'rows_file',
174
+ input_path: inputPath,
175
+ row_count: candidates.length,
176
+ });
177
+ writeJsonLinesArtifact(files.selected_lifecyclemodels, candidates.map(compactCandidate));
178
+ const reports = [];
179
+ for (const candidate of candidates) {
180
+ const report = {
181
+ id: candidate.id,
182
+ version: candidate.version,
183
+ status: 'prepared',
184
+ ...(candidate.validation ? { validation: candidate.validation } : {}),
185
+ };
186
+ if (candidate.error) {
187
+ report.status = 'failed';
188
+ report.error = candidate.error;
189
+ reports.push(report);
190
+ continue;
191
+ }
192
+ if (!commit) {
193
+ reports.push(report);
194
+ continue;
195
+ }
196
+ try {
197
+ report.execution = await syncLifecyclemodelBundleRecord({
198
+ id: candidate.id,
199
+ version: candidate.version,
200
+ payload: candidate.payload,
201
+ metadata: candidate.metadata,
202
+ env: options.env,
203
+ fetchImpl: options.fetchImpl,
204
+ timeoutMs: options.timeoutMs,
205
+ });
206
+ report.status = 'executed';
207
+ }
208
+ catch (error) {
209
+ report.status = 'failed';
210
+ report.error = serializeError(error);
211
+ }
212
+ reports.push(report);
213
+ }
214
+ const failures = reports.filter((report) => report.status === 'failed');
215
+ writeJsonLinesArtifact(files.progress_jsonl, reports);
216
+ writeJsonLinesArtifact(files.failures_jsonl, failures);
217
+ const report = {
218
+ generated_at_utc: now.toISOString(),
219
+ input_path: inputPath,
220
+ out_dir: outDir,
221
+ commit,
222
+ mode: commit ? 'commit' : 'dry_run',
223
+ status: failures.length > 0 ? 'completed_with_failures' : 'completed',
224
+ counts: {
225
+ selected: candidates.length,
226
+ prepared: reports.filter((entry) => entry.status === 'prepared').length,
227
+ executed: reports.filter((entry) => entry.status === 'executed').length,
228
+ failed: failures.length,
229
+ },
230
+ files,
231
+ lifecyclemodels: reports,
232
+ };
233
+ writeJsonArtifact(files.summary_json, report);
234
+ return report;
235
+ }
236
+ export const __testInternals = {
237
+ buildCandidate,
238
+ getLifecyclemodelFactory,
239
+ getLifecyclemodelSchema,
240
+ normalizeIssuePath,
241
+ serializeError,
242
+ summarizeValidation,
243
+ validateLifecyclemodelPayload,
244
+ };
245
+ //# sourceMappingURL=lifecyclemodel-save-draft-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecyclemodel-save-draft-run.js","sourceRoot":"","sources":["../../../src/lib/lifecyclemodel-save-draft-run.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport * as tidasSdk from '@tiangong-lca/tidas-sdk';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport {\n firstNonEmpty,\n isRecord,\n materializeDatasetRows,\n type JsonObject,\n} from './dataset-local.js';\nimport {\n syncLifecyclemodelBundleRecord,\n type LifecyclemodelBundleWriteResult,\n type LifecyclemodelPublishMetadata,\n} from './lifecyclemodel-bundle-save.js';\nimport { buildRunId, resolveRunLayout } from './run.js';\nimport {\n normalizeIssuePath,\n type SafeParseSchema,\n type SdkValidationFactory,\n validateSchemaWithDeepFallback,\n} from './tidas-sdk-validation.js';\n\nexport type LifecyclemodelPayloadValidationIssue = {\n path: string;\n message: string;\n code: string;\n};\n\nexport type LifecyclemodelPayloadValidationResult =\n | {\n ok: true;\n validator: string;\n issue_count: 0;\n issues: [];\n }\n | {\n ok: false;\n validator: string;\n issue_count: number;\n issues: LifecyclemodelPayloadValidationIssue[];\n };\n\ntype LifecyclemodelSaveDraftCandidate = {\n id: string | null;\n version: string | null;\n payload: JsonObject;\n metadata: LifecyclemodelPublishMetadata | null;\n validation?: LifecyclemodelPayloadValidationResult;\n error?: { message: string };\n};\n\nexport type LifecyclemodelSaveDraftModelReport = {\n id: string | null;\n version: string | null;\n status: 'prepared' | 'executed' | 'failed';\n validation?: LifecyclemodelPayloadValidationResult;\n execution?: LifecyclemodelBundleWriteResult;\n error?: { message: string };\n};\n\nexport type LifecyclemodelSaveDraftReport = {\n generated_at_utc: string;\n input_path: string;\n out_dir: string;\n commit: boolean;\n mode: 'dry_run' | 'commit';\n status: 'completed' | 'completed_with_failures';\n counts: {\n selected: number;\n prepared: number;\n executed: number;\n failed: number;\n };\n files: {\n normalized_input: string;\n selected_lifecyclemodels: string;\n progress_jsonl: string;\n failures_jsonl: string;\n summary_json: string;\n };\n lifecyclemodels: LifecyclemodelSaveDraftModelReport[];\n};\n\nexport type RunLifecyclemodelSaveDraftOptions = {\n inputPath: string;\n outDir?: string | null;\n commit?: boolean | null;\n rawInput?: unknown;\n env?: NodeJS.ProcessEnv;\n fetchImpl?: FetchLike;\n timeoutMs?: number;\n now?: Date;\n validateLifecyclemodelPayloadImpl?: (\n payload: JsonObject,\n ) => LifecyclemodelPayloadValidationResult;\n};\n\nconst VALIDATOR_NAME = '@tiangong-lca/tidas-sdk/LifeCycleModelSchema';\n\nfunction getLifecyclemodelSchema(\n sdk: { LifeCycleModelSchema?: unknown } = tidasSdk,\n): SafeParseSchema {\n const schema = sdk.LifeCycleModelSchema as SafeParseSchema | undefined;\n if (!schema?.safeParse) {\n throw new Error(`${VALIDATOR_NAME} is unavailable in the published CLI runtime.`);\n }\n return schema;\n}\n\nfunction getLifecyclemodelFactory(\n sdk: { createLifeCycleModel?: unknown } = tidasSdk,\n): SdkValidationFactory | null {\n const createLifeCycleModel = sdk.createLifeCycleModel;\n return typeof createLifeCycleModel === 'function'\n ? (createLifeCycleModel as SdkValidationFactory)\n : null;\n}\n\nexport function validateLifecyclemodelPayload(\n payload: JsonObject,\n schema?: SafeParseSchema,\n createEntity?: SdkValidationFactory | null,\n): LifecyclemodelPayloadValidationResult {\n const activeSchema = schema ?? getLifecyclemodelSchema();\n const activeCreateEntity =\n createEntity === undefined && schema === undefined ? getLifecyclemodelFactory() : createEntity;\n const outcome = validateSchemaWithDeepFallback(activeSchema, payload, activeCreateEntity);\n if (outcome.success) {\n return {\n ok: true,\n validator: VALIDATOR_NAME,\n issue_count: 0,\n issues: [],\n };\n }\n\n const issues = outcome.issues.map((issue) => ({\n path: normalizeIssuePath(issue.path),\n message: issue.message ?? 'Validation failed',\n code: issue.code ?? 'custom',\n }));\n\n return {\n ok: false,\n validator: VALIDATOR_NAME,\n issue_count: issues.length,\n issues,\n };\n}\n\nfunction summarizeValidation(result: LifecyclemodelPayloadValidationResult): string {\n if (result.ok) {\n return 'local LifeCycleModelSchema validation passed';\n }\n const preview = result.issues\n .slice(0, 3)\n .map((issue) => `${issue.path}: ${issue.message}`)\n .join('; ');\n return `local LifeCycleModelSchema validation failed with ${result.issue_count} issue(s)${\n preview ? ` (${preview})` : ''\n }`;\n}\n\nfunction extractMetadata(row: JsonObject): LifecyclemodelPublishMetadata | null {\n const metadata: LifecyclemodelPublishMetadata = {};\n const jsonTg = isRecord(row.json_tg) ? row.json_tg : isRecord(row.jsonTg) ? row.jsonTg : null;\n if (jsonTg) {\n metadata.json_tg = jsonTg;\n }\n if (Array.isArray(row.processMutations)) {\n metadata.processMutations = row.processMutations.filter(isRecord);\n } else if (Array.isArray(row.process_mutations)) {\n metadata.processMutations = row.process_mutations.filter(isRecord);\n }\n if (typeof row.ruleVerification === 'boolean') {\n metadata.ruleVerification = row.ruleVerification;\n } else if (typeof row.rule_verification === 'boolean') {\n metadata.ruleVerification = row.rule_verification;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : null;\n}\n\nfunction candidateError(message: string): { message: string } {\n return { message };\n}\n\nfunction buildCandidate(\n row: JsonObject,\n payload: JsonObject,\n validate: (payload: JsonObject) => LifecyclemodelPayloadValidationResult,\n): LifecyclemodelSaveDraftCandidate {\n const root = isRecord(payload.lifeCycleModelDataSet) ? payload.lifeCycleModelDataSet : payload;\n const information = isRecord(root.lifeCycleModelInformation)\n ? root.lifeCycleModelInformation\n : {};\n const dataSetInformation = isRecord(information.dataSetInformation)\n ? information.dataSetInformation\n : {};\n const administrativeInformation = isRecord(root.administrativeInformation)\n ? root.administrativeInformation\n : {};\n const publicationAndOwnership = isRecord(administrativeInformation.publicationAndOwnership)\n ? administrativeInformation.publicationAndOwnership\n : {};\n const id = firstNonEmpty(row.id, dataSetInformation['common:UUID']);\n const version = firstNonEmpty(\n row.version,\n publicationAndOwnership['common:dataSetVersion'],\n '01.01.000',\n );\n\n if (!id) {\n return {\n id: null,\n version,\n payload,\n metadata: extractMetadata(row),\n error: candidateError(\n 'Lifecyclemodel payload missing lifeCycleModelInformation.dataSetInformation.common:UUID.',\n ),\n };\n }\n\n const validation = validate(payload);\n if (!validation.ok) {\n return {\n id,\n version,\n payload,\n metadata: extractMetadata(row),\n validation,\n error: candidateError(summarizeValidation(validation)),\n };\n }\n\n return {\n id,\n version,\n payload,\n metadata: extractMetadata(row),\n validation,\n };\n}\n\nfunction defaultOutDir(inputPath: string, commit: boolean, now: Date): string {\n const runId = buildRunId({\n namespace: 'lifecyclemodel_save_draft',\n operation: commit ? 'commit' : 'dry_run',\n now,\n });\n return resolveRunLayout(\n path.join(path.dirname(inputPath), 'artifacts'),\n 'lifecyclemodel_save_draft',\n runId,\n ).runRoot;\n}\n\nfunction buildFiles(outDir: string): LifecyclemodelSaveDraftReport['files'] {\n const outputDir = path.join(outDir, 'outputs', 'save-draft-bundle');\n return {\n normalized_input: path.join(outDir, 'inputs', 'normalized-input.json'),\n selected_lifecyclemodels: path.join(outputDir, 'selected-lifecyclemodels.jsonl'),\n progress_jsonl: path.join(outputDir, 'progress.jsonl'),\n failures_jsonl: path.join(outputDir, 'failures.jsonl'),\n summary_json: path.join(outputDir, 'summary.json'),\n };\n}\n\nfunction compactCandidate(candidate: LifecyclemodelSaveDraftCandidate): JsonObject {\n return {\n id: candidate.id,\n version: candidate.version,\n payload: candidate.payload,\n metadata: candidate.metadata,\n ...(candidate.validation ? { validation: candidate.validation } : {}),\n ...(candidate.error ? { error: candidate.error } : {}),\n };\n}\n\nfunction serializeError(error: unknown): { message: string } {\n return {\n message: error instanceof Error ? error.message : String(error),\n };\n}\n\nexport async function runLifecyclemodelSaveDraft(\n options: RunLifecyclemodelSaveDraftOptions,\n): Promise<LifecyclemodelSaveDraftReport> {\n const now = options.now ?? new Date();\n const inputPath = path.resolve(options.inputPath);\n const commit = options.commit === true;\n const outDir = path.resolve(options.outDir ?? defaultOutDir(inputPath, commit, now));\n const validate = options.validateLifecyclemodelPayloadImpl ?? validateLifecyclemodelPayload;\n const datasetRows = materializeDatasetRows(inputPath, options.rawInput);\n const candidates = datasetRows.map((row) => buildCandidate(row.row, row.payload, validate));\n const files = buildFiles(outDir);\n\n if (commit && (!options.env || !options.fetchImpl)) {\n throw new CliError(\n 'Lifecyclemodel save-draft commit requires env and fetch runtime bindings.',\n {\n code: 'LIFECYCLEMODEL_SAVE_DRAFT_RUNTIME_REQUIRED',\n exitCode: 2,\n },\n );\n }\n\n writeJsonArtifact(files.normalized_input, {\n input_kind: 'rows_file',\n input_path: inputPath,\n row_count: candidates.length,\n });\n writeJsonLinesArtifact(files.selected_lifecyclemodels, candidates.map(compactCandidate));\n\n const reports: LifecyclemodelSaveDraftModelReport[] = [];\n for (const candidate of candidates) {\n const report: LifecyclemodelSaveDraftModelReport = {\n id: candidate.id,\n version: candidate.version,\n status: 'prepared',\n ...(candidate.validation ? { validation: candidate.validation } : {}),\n };\n\n if (candidate.error) {\n report.status = 'failed';\n report.error = candidate.error;\n reports.push(report);\n continue;\n }\n\n if (!commit) {\n reports.push(report);\n continue;\n }\n\n try {\n report.execution = await syncLifecyclemodelBundleRecord({\n id: candidate.id!,\n version: candidate.version!,\n payload: candidate.payload,\n metadata: candidate.metadata,\n env: options.env!,\n fetchImpl: options.fetchImpl!,\n timeoutMs: options.timeoutMs,\n });\n report.status = 'executed';\n } catch (error) {\n report.status = 'failed';\n report.error = serializeError(error);\n }\n reports.push(report);\n }\n\n const failures = reports.filter((report) => report.status === 'failed');\n writeJsonLinesArtifact(files.progress_jsonl, reports);\n writeJsonLinesArtifact(files.failures_jsonl, failures);\n\n const report: LifecyclemodelSaveDraftReport = {\n generated_at_utc: now.toISOString(),\n input_path: inputPath,\n out_dir: outDir,\n commit,\n mode: commit ? 'commit' : 'dry_run',\n status: failures.length > 0 ? 'completed_with_failures' : 'completed',\n counts: {\n selected: candidates.length,\n prepared: reports.filter((entry) => entry.status === 'prepared').length,\n executed: reports.filter((entry) => entry.status === 'executed').length,\n failed: failures.length,\n },\n files,\n lifecyclemodels: reports,\n };\n writeJsonArtifact(files.summary_json, report);\n return report;\n}\n\nexport const __testInternals = {\n buildCandidate,\n getLifecyclemodelFactory,\n getLifecyclemodelSchema,\n normalizeIssuePath,\n serializeError,\n summarizeValidation,\n validateLifecyclemodelPayload,\n};\n"]}
@@ -164,7 +164,7 @@ function buildNextActions(layout) {
164
164
  return [
165
165
  `inspect: ${layout.reportPath}`,
166
166
  `inspect: ${layout.modelReportsDir}`,
167
- `run: tiangong lifecyclemodel publish-build --run-dir ${layout.runRoot}`,
167
+ `run: tiangong-lca lifecyclemodel publish-build --run-dir ${layout.runRoot}`,
168
168
  ];
169
169
  }
170
170
  function resolveValidationImpl(deps) {
@@ -1 +1 @@
1
- {"version":3,"file":"lifecyclemodel-validate-build.js","sourceRoot":"","sources":["../../../src/lib/lifecyclemodel-validate-build.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync } from 'node:fs';\nimport path from 'node:path';\nimport { readJsonArtifact, writeJsonArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport {\n runValidation,\n type RunValidationOptions,\n type ValidationRunReport,\n} from './validation.js';\n\ntype JsonObject = Record<string, unknown>;\n\ntype ModelBundleEntry = {\n runName: string;\n inputDir: string;\n modelFiles: string[];\n};\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction nonEmptyString(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const normalized = value.trim();\n return normalized || null;\n}\n\nfunction readRequiredJsonObject(\n filePath: string,\n missingCode: string,\n invalidCode: string,\n label: string,\n): JsonObject {\n if (!existsSync(filePath)) {\n throw new CliError(`Required lifecyclemodel ${label} artifact not found: ${filePath}`, {\n code: missingCode,\n exitCode: 2,\n details: { filePath, label },\n });\n }\n\n const value = readJsonArtifact(filePath);\n if (!isRecord(value)) {\n throw new CliError(`Expected lifecyclemodel ${label} artifact JSON object: ${filePath}`, {\n code: invalidCode,\n exitCode: 2,\n details: { filePath, label },\n });\n }\n\n return value;\n}\n\nexport type LifecyclemodelValidateBuildLayout = {\n runId: string;\n runRoot: string;\n modelsDir: string;\n reportsDir: string;\n modelReportsDir: string;\n manifestsDir: string;\n runManifestPath: string;\n invocationIndexPath: string;\n autoBuildReportPath: string;\n reportPath: string;\n};\n\nexport type LifecyclemodelValidateBuildModelReport = {\n run_name: string;\n input_dir: string;\n model_files: string[];\n report_file: string;\n validation: ValidationRunReport;\n};\n\nexport type LifecyclemodelValidateBuildReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: 'completed_lifecyclemodel_validate_build';\n run_id: string;\n run_root: string;\n ok: boolean;\n engine: string;\n counts: {\n models: number;\n ok: number;\n failed: number;\n };\n files: {\n run_manifest: string;\n invocation_index: string;\n auto_build_report: string | null;\n report: string;\n model_reports_dir: string;\n };\n model_reports: LifecyclemodelValidateBuildModelReport[];\n next_actions: string[];\n};\n\nexport type RunLifecyclemodelValidateBuildOptions = {\n runDir: string;\n engine?: string;\n now?: Date;\n cwd?: string;\n};\n\nexport type LifecyclemodelValidateBuildDeps = {\n runValidationImpl?: (options: RunValidationOptions) => Promise<ValidationRunReport>;\n};\n\nfunction buildLayout(runRoot: string): LifecyclemodelValidateBuildLayout {\n const runId = path.basename(runRoot);\n return {\n runId,\n runRoot,\n modelsDir: path.join(runRoot, 'models'),\n reportsDir: path.join(runRoot, 'reports'),\n modelReportsDir: path.join(runRoot, 'reports', 'model-validations'),\n manifestsDir: path.join(runRoot, 'manifests'),\n runManifestPath: path.join(runRoot, 'manifests', 'run-manifest.json'),\n invocationIndexPath: path.join(runRoot, 'manifests', 'invocation-index.json'),\n autoBuildReportPath: path.join(runRoot, 'reports', 'lifecyclemodel-auto-build-report.json'),\n reportPath: path.join(runRoot, 'reports', 'lifecyclemodel-validate-build-report.json'),\n };\n}\n\nfunction resolveLayout(\n options: RunLifecyclemodelValidateBuildOptions,\n): LifecyclemodelValidateBuildLayout {\n const runDir = nonEmptyString(options.runDir);\n if (!runDir) {\n throw new CliError('Missing required --run-dir for lifecyclemodel validate-build.', {\n code: 'LIFECYCLEMODEL_VALIDATE_RUN_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n\n return buildLayout(path.resolve(runDir));\n}\n\nfunction ensureRunRootExists(layout: LifecyclemodelValidateBuildLayout): void {\n if (!existsSync(layout.runRoot)) {\n throw new CliError(`lifecyclemodel validate-build run root not found: ${layout.runRoot}`, {\n code: 'LIFECYCLEMODEL_VALIDATE_RUN_NOT_FOUND',\n exitCode: 2,\n });\n }\n}\n\nfunction readRequiredRunManifest(layout: LifecyclemodelValidateBuildLayout): JsonObject {\n const manifest = readRequiredJsonObject(\n layout.runManifestPath,\n 'LIFECYCLEMODEL_VALIDATE_RUN_MANIFEST_MISSING',\n 'LIFECYCLEMODEL_VALIDATE_RUN_MANIFEST_INVALID',\n 'run-manifest',\n );\n\n const manifestRunId = nonEmptyString(manifest.runId);\n if (manifestRunId && manifestRunId !== layout.runId) {\n throw new CliError(\n `lifecyclemodel validate-build run manifest runId mismatch: ${layout.runManifestPath}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_RUN_MANIFEST_MISMATCH',\n exitCode: 2,\n details: {\n expected: layout.runId,\n actual: manifestRunId,\n },\n },\n );\n }\n\n return manifest;\n}\n\nfunction readInvocationIndex(layout: LifecyclemodelValidateBuildLayout): JsonObject {\n if (!existsSync(layout.invocationIndexPath)) {\n return {\n schema_version: 1,\n invocations: [],\n };\n }\n\n const value = readJsonArtifact(layout.invocationIndexPath);\n if (!isRecord(value)) {\n throw new CliError(\n `Expected lifecyclemodel validate invocation index JSON object: ${layout.invocationIndexPath}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_INVOCATION_INDEX_INVALID',\n exitCode: 2,\n },\n );\n }\n\n if (value.invocations === undefined) {\n return {\n schema_version: 1,\n invocations: [],\n };\n }\n\n if (!Array.isArray(value.invocations)) {\n throw new CliError(\n `Expected lifecyclemodel validate invocation index to contain an invocations array: ${layout.invocationIndexPath}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_INVOCATION_INDEX_INVALID',\n exitCode: 2,\n },\n );\n }\n\n return value;\n}\n\nfunction discoverModelEntries(layout: LifecyclemodelValidateBuildLayout): ModelBundleEntry[] {\n const runNames = existsSync(layout.modelsDir) ? readdirSync(layout.modelsDir).sort() : [];\n const entries = runNames.flatMap((runName) => {\n const inputDir = path.join(layout.modelsDir, runName, 'tidas_bundle');\n const lifecyclemodelsDir = path.join(inputDir, 'lifecyclemodels');\n if (!existsSync(lifecyclemodelsDir)) {\n return [];\n }\n\n const modelFiles = readdirSync(lifecyclemodelsDir)\n .filter((entry) => entry.endsWith('.json'))\n .sort()\n .map((entry) => path.join(lifecyclemodelsDir, entry));\n\n if (modelFiles.length === 0) {\n throw new CliError(\n `lifecyclemodel validate-build found a bundle without lifecyclemodel JSON files: ${lifecyclemodelsDir}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_MODELS_EMPTY',\n exitCode: 2,\n },\n );\n }\n\n return [{ runName, inputDir, modelFiles }];\n });\n\n if (entries.length === 0) {\n throw new CliError(\n `lifecyclemodel validate-build run does not contain any model bundles: ${layout.modelsDir}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_MODELS_NOT_FOUND',\n exitCode: 2,\n },\n );\n }\n\n return entries;\n}\n\nfunction buildInvocationIndex(\n layout: LifecyclemodelValidateBuildLayout,\n invocationIndex: JsonObject,\n options: RunLifecyclemodelValidateBuildOptions,\n now: Date,\n): JsonObject {\n const priorInvocations = Array.isArray(invocationIndex.invocations)\n ? [...invocationIndex.invocations]\n : [];\n const command = ['lifecyclemodel', 'validate-build', '--run-dir', options.runDir];\n if (options.engine) {\n command.push('--engine', options.engine);\n }\n\n return {\n ...invocationIndex,\n schema_version:\n typeof invocationIndex.schema_version === 'number' ? invocationIndex.schema_version : 1,\n invocations: [\n ...priorInvocations,\n {\n command,\n cwd: options.cwd ?? process.cwd(),\n created_at: now.toISOString(),\n run_id: layout.runId,\n run_root: layout.runRoot,\n report_path: layout.reportPath,\n model_reports_dir: layout.modelReportsDir,\n },\n ],\n };\n}\n\nfunction buildNextActions(layout: LifecyclemodelValidateBuildLayout): string[] {\n return [\n `inspect: ${layout.reportPath}`,\n `inspect: ${layout.modelReportsDir}`,\n `run: tiangong lifecyclemodel publish-build --run-dir ${layout.runRoot}`,\n ];\n}\n\nfunction resolveValidationImpl(\n deps: LifecyclemodelValidateBuildDeps,\n): (options: RunValidationOptions) => Promise<ValidationRunReport> {\n return deps.runValidationImpl ?? runValidation;\n}\n\nfunction resolveReportEngine(\n modelReports: LifecyclemodelValidateBuildModelReport[],\n requestedEngine?: string,\n): string {\n return modelReports[0]?.validation.mode ?? requestedEngine ?? 'auto';\n}\n\nexport async function runLifecyclemodelValidateBuild(\n options: RunLifecyclemodelValidateBuildOptions,\n deps: LifecyclemodelValidateBuildDeps = {},\n): Promise<LifecyclemodelValidateBuildReport> {\n const now = options.now ?? new Date();\n const layout = resolveLayout(options);\n ensureRunRootExists(layout);\n readRequiredRunManifest(layout);\n const invocationIndex = readInvocationIndex(layout);\n const validationImpl = resolveValidationImpl(deps);\n const modelEntries = discoverModelEntries(layout);\n\n const modelReports: LifecyclemodelValidateBuildModelReport[] = [];\n for (const entry of modelEntries) {\n const reportFile = path.join(layout.modelReportsDir, `${entry.runName}.json`);\n const validation = await validationImpl({\n inputDir: entry.inputDir,\n engine: options.engine,\n reportFile,\n });\n modelReports.push({\n run_name: entry.runName,\n input_dir: entry.inputDir,\n model_files: entry.modelFiles,\n report_file: reportFile,\n validation,\n });\n }\n\n const okCount = modelReports.filter((entry) => entry.validation.ok).length;\n const report: LifecyclemodelValidateBuildReport = {\n schema_version: 1,\n generated_at_utc: now.toISOString(),\n status: 'completed_lifecyclemodel_validate_build',\n run_id: layout.runId,\n run_root: layout.runRoot,\n ok: okCount === modelReports.length,\n engine: resolveReportEngine(modelReports, options.engine),\n counts: {\n models: modelReports.length,\n ok: okCount,\n failed: modelReports.length - okCount,\n },\n files: {\n run_manifest: layout.runManifestPath,\n invocation_index: layout.invocationIndexPath,\n auto_build_report: existsSync(layout.autoBuildReportPath) ? layout.autoBuildReportPath : null,\n report: layout.reportPath,\n model_reports_dir: layout.modelReportsDir,\n },\n model_reports: modelReports,\n next_actions: buildNextActions(layout),\n };\n\n writeJsonArtifact(\n layout.invocationIndexPath,\n buildInvocationIndex(layout, invocationIndex, options, now),\n );\n writeJsonArtifact(layout.reportPath, report);\n return report;\n}\n\nexport const __testInternals = {\n buildLayout,\n resolveLayout,\n readInvocationIndex,\n discoverModelEntries,\n buildInvocationIndex,\n buildNextActions,\n resolveValidationImpl,\n resolveReportEngine,\n};\n"]}
1
+ {"version":3,"file":"lifecyclemodel-validate-build.js","sourceRoot":"","sources":["../../../src/lib/lifecyclemodel-validate-build.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync } from 'node:fs';\nimport path from 'node:path';\nimport { readJsonArtifact, writeJsonArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport {\n runValidation,\n type RunValidationOptions,\n type ValidationRunReport,\n} from './validation.js';\n\ntype JsonObject = Record<string, unknown>;\n\ntype ModelBundleEntry = {\n runName: string;\n inputDir: string;\n modelFiles: string[];\n};\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction nonEmptyString(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const normalized = value.trim();\n return normalized || null;\n}\n\nfunction readRequiredJsonObject(\n filePath: string,\n missingCode: string,\n invalidCode: string,\n label: string,\n): JsonObject {\n if (!existsSync(filePath)) {\n throw new CliError(`Required lifecyclemodel ${label} artifact not found: ${filePath}`, {\n code: missingCode,\n exitCode: 2,\n details: { filePath, label },\n });\n }\n\n const value = readJsonArtifact(filePath);\n if (!isRecord(value)) {\n throw new CliError(`Expected lifecyclemodel ${label} artifact JSON object: ${filePath}`, {\n code: invalidCode,\n exitCode: 2,\n details: { filePath, label },\n });\n }\n\n return value;\n}\n\nexport type LifecyclemodelValidateBuildLayout = {\n runId: string;\n runRoot: string;\n modelsDir: string;\n reportsDir: string;\n modelReportsDir: string;\n manifestsDir: string;\n runManifestPath: string;\n invocationIndexPath: string;\n autoBuildReportPath: string;\n reportPath: string;\n};\n\nexport type LifecyclemodelValidateBuildModelReport = {\n run_name: string;\n input_dir: string;\n model_files: string[];\n report_file: string;\n validation: ValidationRunReport;\n};\n\nexport type LifecyclemodelValidateBuildReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: 'completed_lifecyclemodel_validate_build';\n run_id: string;\n run_root: string;\n ok: boolean;\n engine: string;\n counts: {\n models: number;\n ok: number;\n failed: number;\n };\n files: {\n run_manifest: string;\n invocation_index: string;\n auto_build_report: string | null;\n report: string;\n model_reports_dir: string;\n };\n model_reports: LifecyclemodelValidateBuildModelReport[];\n next_actions: string[];\n};\n\nexport type RunLifecyclemodelValidateBuildOptions = {\n runDir: string;\n engine?: string;\n now?: Date;\n cwd?: string;\n};\n\nexport type LifecyclemodelValidateBuildDeps = {\n runValidationImpl?: (options: RunValidationOptions) => Promise<ValidationRunReport>;\n};\n\nfunction buildLayout(runRoot: string): LifecyclemodelValidateBuildLayout {\n const runId = path.basename(runRoot);\n return {\n runId,\n runRoot,\n modelsDir: path.join(runRoot, 'models'),\n reportsDir: path.join(runRoot, 'reports'),\n modelReportsDir: path.join(runRoot, 'reports', 'model-validations'),\n manifestsDir: path.join(runRoot, 'manifests'),\n runManifestPath: path.join(runRoot, 'manifests', 'run-manifest.json'),\n invocationIndexPath: path.join(runRoot, 'manifests', 'invocation-index.json'),\n autoBuildReportPath: path.join(runRoot, 'reports', 'lifecyclemodel-auto-build-report.json'),\n reportPath: path.join(runRoot, 'reports', 'lifecyclemodel-validate-build-report.json'),\n };\n}\n\nfunction resolveLayout(\n options: RunLifecyclemodelValidateBuildOptions,\n): LifecyclemodelValidateBuildLayout {\n const runDir = nonEmptyString(options.runDir);\n if (!runDir) {\n throw new CliError('Missing required --run-dir for lifecyclemodel validate-build.', {\n code: 'LIFECYCLEMODEL_VALIDATE_RUN_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n\n return buildLayout(path.resolve(runDir));\n}\n\nfunction ensureRunRootExists(layout: LifecyclemodelValidateBuildLayout): void {\n if (!existsSync(layout.runRoot)) {\n throw new CliError(`lifecyclemodel validate-build run root not found: ${layout.runRoot}`, {\n code: 'LIFECYCLEMODEL_VALIDATE_RUN_NOT_FOUND',\n exitCode: 2,\n });\n }\n}\n\nfunction readRequiredRunManifest(layout: LifecyclemodelValidateBuildLayout): JsonObject {\n const manifest = readRequiredJsonObject(\n layout.runManifestPath,\n 'LIFECYCLEMODEL_VALIDATE_RUN_MANIFEST_MISSING',\n 'LIFECYCLEMODEL_VALIDATE_RUN_MANIFEST_INVALID',\n 'run-manifest',\n );\n\n const manifestRunId = nonEmptyString(manifest.runId);\n if (manifestRunId && manifestRunId !== layout.runId) {\n throw new CliError(\n `lifecyclemodel validate-build run manifest runId mismatch: ${layout.runManifestPath}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_RUN_MANIFEST_MISMATCH',\n exitCode: 2,\n details: {\n expected: layout.runId,\n actual: manifestRunId,\n },\n },\n );\n }\n\n return manifest;\n}\n\nfunction readInvocationIndex(layout: LifecyclemodelValidateBuildLayout): JsonObject {\n if (!existsSync(layout.invocationIndexPath)) {\n return {\n schema_version: 1,\n invocations: [],\n };\n }\n\n const value = readJsonArtifact(layout.invocationIndexPath);\n if (!isRecord(value)) {\n throw new CliError(\n `Expected lifecyclemodel validate invocation index JSON object: ${layout.invocationIndexPath}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_INVOCATION_INDEX_INVALID',\n exitCode: 2,\n },\n );\n }\n\n if (value.invocations === undefined) {\n return {\n schema_version: 1,\n invocations: [],\n };\n }\n\n if (!Array.isArray(value.invocations)) {\n throw new CliError(\n `Expected lifecyclemodel validate invocation index to contain an invocations array: ${layout.invocationIndexPath}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_INVOCATION_INDEX_INVALID',\n exitCode: 2,\n },\n );\n }\n\n return value;\n}\n\nfunction discoverModelEntries(layout: LifecyclemodelValidateBuildLayout): ModelBundleEntry[] {\n const runNames = existsSync(layout.modelsDir) ? readdirSync(layout.modelsDir).sort() : [];\n const entries = runNames.flatMap((runName) => {\n const inputDir = path.join(layout.modelsDir, runName, 'tidas_bundle');\n const lifecyclemodelsDir = path.join(inputDir, 'lifecyclemodels');\n if (!existsSync(lifecyclemodelsDir)) {\n return [];\n }\n\n const modelFiles = readdirSync(lifecyclemodelsDir)\n .filter((entry) => entry.endsWith('.json'))\n .sort()\n .map((entry) => path.join(lifecyclemodelsDir, entry));\n\n if (modelFiles.length === 0) {\n throw new CliError(\n `lifecyclemodel validate-build found a bundle without lifecyclemodel JSON files: ${lifecyclemodelsDir}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_MODELS_EMPTY',\n exitCode: 2,\n },\n );\n }\n\n return [{ runName, inputDir, modelFiles }];\n });\n\n if (entries.length === 0) {\n throw new CliError(\n `lifecyclemodel validate-build run does not contain any model bundles: ${layout.modelsDir}`,\n {\n code: 'LIFECYCLEMODEL_VALIDATE_MODELS_NOT_FOUND',\n exitCode: 2,\n },\n );\n }\n\n return entries;\n}\n\nfunction buildInvocationIndex(\n layout: LifecyclemodelValidateBuildLayout,\n invocationIndex: JsonObject,\n options: RunLifecyclemodelValidateBuildOptions,\n now: Date,\n): JsonObject {\n const priorInvocations = Array.isArray(invocationIndex.invocations)\n ? [...invocationIndex.invocations]\n : [];\n const command = ['lifecyclemodel', 'validate-build', '--run-dir', options.runDir];\n if (options.engine) {\n command.push('--engine', options.engine);\n }\n\n return {\n ...invocationIndex,\n schema_version:\n typeof invocationIndex.schema_version === 'number' ? invocationIndex.schema_version : 1,\n invocations: [\n ...priorInvocations,\n {\n command,\n cwd: options.cwd ?? process.cwd(),\n created_at: now.toISOString(),\n run_id: layout.runId,\n run_root: layout.runRoot,\n report_path: layout.reportPath,\n model_reports_dir: layout.modelReportsDir,\n },\n ],\n };\n}\n\nfunction buildNextActions(layout: LifecyclemodelValidateBuildLayout): string[] {\n return [\n `inspect: ${layout.reportPath}`,\n `inspect: ${layout.modelReportsDir}`,\n `run: tiangong-lca lifecyclemodel publish-build --run-dir ${layout.runRoot}`,\n ];\n}\n\nfunction resolveValidationImpl(\n deps: LifecyclemodelValidateBuildDeps,\n): (options: RunValidationOptions) => Promise<ValidationRunReport> {\n return deps.runValidationImpl ?? runValidation;\n}\n\nfunction resolveReportEngine(\n modelReports: LifecyclemodelValidateBuildModelReport[],\n requestedEngine?: string,\n): string {\n return modelReports[0]?.validation.mode ?? requestedEngine ?? 'auto';\n}\n\nexport async function runLifecyclemodelValidateBuild(\n options: RunLifecyclemodelValidateBuildOptions,\n deps: LifecyclemodelValidateBuildDeps = {},\n): Promise<LifecyclemodelValidateBuildReport> {\n const now = options.now ?? new Date();\n const layout = resolveLayout(options);\n ensureRunRootExists(layout);\n readRequiredRunManifest(layout);\n const invocationIndex = readInvocationIndex(layout);\n const validationImpl = resolveValidationImpl(deps);\n const modelEntries = discoverModelEntries(layout);\n\n const modelReports: LifecyclemodelValidateBuildModelReport[] = [];\n for (const entry of modelEntries) {\n const reportFile = path.join(layout.modelReportsDir, `${entry.runName}.json`);\n const validation = await validationImpl({\n inputDir: entry.inputDir,\n engine: options.engine,\n reportFile,\n });\n modelReports.push({\n run_name: entry.runName,\n input_dir: entry.inputDir,\n model_files: entry.modelFiles,\n report_file: reportFile,\n validation,\n });\n }\n\n const okCount = modelReports.filter((entry) => entry.validation.ok).length;\n const report: LifecyclemodelValidateBuildReport = {\n schema_version: 1,\n generated_at_utc: now.toISOString(),\n status: 'completed_lifecyclemodel_validate_build',\n run_id: layout.runId,\n run_root: layout.runRoot,\n ok: okCount === modelReports.length,\n engine: resolveReportEngine(modelReports, options.engine),\n counts: {\n models: modelReports.length,\n ok: okCount,\n failed: modelReports.length - okCount,\n },\n files: {\n run_manifest: layout.runManifestPath,\n invocation_index: layout.invocationIndexPath,\n auto_build_report: existsSync(layout.autoBuildReportPath) ? layout.autoBuildReportPath : null,\n report: layout.reportPath,\n model_reports_dir: layout.modelReportsDir,\n },\n model_reports: modelReports,\n next_actions: buildNextActions(layout),\n };\n\n writeJsonArtifact(\n layout.invocationIndexPath,\n buildInvocationIndex(layout, invocationIndex, options, now),\n );\n writeJsonArtifact(layout.reportPath, report);\n return report;\n}\n\nexport const __testInternals = {\n buildLayout,\n resolveLayout,\n readInvocationIndex,\n discoverModelEntries,\n buildInvocationIndex,\n buildNextActions,\n resolveValidationImpl,\n resolveReportEngine,\n};\n"]}
@@ -269,7 +269,7 @@ function buildProcessAutoBuildRunId(flowFilePath, operation, summary, now = new
269
269
  const operationToken = operation === 'treat' ? 'treat' : 'produce';
270
270
  return `pfw_${flowCode}_${flowUuidShort}_${operationToken}_${buildUtcTimestamp(now)}`;
271
271
  }
272
- function resolveRunRoot(requestDir, runId, outDirOverride, requestRunRoot) {
272
+ function resolveRunRoot(requestDir, outDirOverride, requestRunRoot) {
273
273
  const override = nonEmptyString(outDirOverride);
274
274
  if (override) {
275
275
  return path.resolve(requestDir, override);
@@ -278,7 +278,10 @@ function resolveRunRoot(requestDir, runId, outDirOverride, requestRunRoot) {
278
278
  if (requestValue) {
279
279
  return path.resolve(requestDir, requestValue);
280
280
  }
281
- return path.join(requestDir, 'artifacts', 'process_from_flow', runId);
281
+ throw new CliError('Missing required process auto-build run root. Provide --out-dir or request.workspace_run_root.', {
282
+ code: 'PROCESS_AUTO_BUILD_RUN_ROOT_REQUIRED',
283
+ exitCode: 2,
284
+ });
282
285
  }
283
286
  function normalizeSourceInputType(value) {
284
287
  const normalized = nonEmptyString(value);
@@ -376,6 +379,7 @@ function buildLayout(runRoot, runId) {
376
379
  sourcePolicyPath: path.join(runRoot, 'request', 'source-policy.json'),
377
380
  flowSummaryPath: path.join(runRoot, 'manifests', 'flow-summary.json'),
378
381
  inputManifestPath: path.join(runRoot, 'input', 'input_manifest.json'),
382
+ buildPlanPath: path.join(runRoot, 'manifests', 'process-build-plan.json'),
379
383
  assemblyPlanPath: path.join(runRoot, 'manifests', 'assembly-plan.json'),
380
384
  lineageManifestPath: path.join(runRoot, 'manifests', 'lineage-manifest.json'),
381
385
  invocationIndexPath: path.join(runRoot, 'manifests', 'invocation-index.json'),
@@ -452,6 +456,147 @@ function buildAssemblyPlan(runRoot) {
452
456
  })),
453
457
  };
454
458
  }
459
+ function flowReferencePropertySummary(flowDataset) {
460
+ const flowInformation = isRecord(flowDataset.flowInformation) ? flowDataset.flowInformation : {};
461
+ const quantitativeReference = isRecord(flowInformation.quantitativeReference)
462
+ ? flowInformation.quantitativeReference
463
+ : {};
464
+ const referenceId = nonEmptyString(quantitativeReference.referenceToReferenceFlowProperty);
465
+ const flowProperties = isRecord(flowDataset.flowProperties) ? flowDataset.flowProperties : {};
466
+ const propertyRows = Array.isArray(flowProperties.flowProperty)
467
+ ? flowProperties.flowProperty
468
+ : flowProperties.flowProperty
469
+ ? [flowProperties.flowProperty]
470
+ : [];
471
+ const referenceProperty = propertyRows.find((entry) => isRecord(entry) && nonEmptyString(entry['@dataSetInternalID']) === (referenceId ?? '0'));
472
+ const propertyRef = isRecord(referenceProperty) && isRecord(referenceProperty.referenceToFlowPropertyDataSet)
473
+ ? referenceProperty.referenceToFlowPropertyDataSet
474
+ : {};
475
+ const shortDescription = isRecord(propertyRef['common:shortDescription'])
476
+ ? propertyRef['common:shortDescription']
477
+ : {};
478
+ const propertyText = extractText(shortDescription) ?? extractText(propertyRef['common:shortDescription']);
479
+ return {
480
+ reference_property: propertyText ?? 'Reference flow property',
481
+ reference_property_id: nonEmptyString(propertyRef['@refObjectId']),
482
+ reference_unit: null,
483
+ };
484
+ }
485
+ function buildInitialProcessBuildPlan(normalized, flowArtifactPath) {
486
+ const flowProperty = flowReferencePropertySummary(normalized.flow_dataset);
487
+ const referenceFlowId = normalized.flow_summary.uuid ??
488
+ nonEmptyString(normalized.flow_dataset['@id']) ??
489
+ sanitizeRunToken(normalized.flow_summary.base_name ?? normalized.run_id, 'reference-flow');
490
+ const referenceFlowVersion = normalized.flow_summary.version ?? '00.00.000';
491
+ const baseName = normalized.flow_summary.base_name
492
+ ? `${normalized.operation === 'treat' ? 'Treatment of' : 'Production of'} ${normalized.flow_summary.base_name}`
493
+ : `${normalized.operation === 'treat' ? 'Treatment' : 'Production'} process from reference flow`;
494
+ return {
495
+ schema_version: 1,
496
+ kind: 'process',
497
+ ruleset: {
498
+ id: 'process-authoring/strict',
499
+ version: '1',
500
+ },
501
+ target: {
502
+ geography: 'GLO',
503
+ technology_route: normalized.operation === 'treat'
504
+ ? 'Treatment route to be evidenced during process auto-build'
505
+ : 'Production route to be evidenced during process auto-build',
506
+ classification_path: [
507
+ 'Technosphere',
508
+ normalized.operation === 'treat' ? 'Treatment' : 'Production',
509
+ flowProperty.reference_property,
510
+ normalized.flow_summary.base_name ?? 'Reference flow',
511
+ ],
512
+ },
513
+ identity_decision: {
514
+ decision: 'create_new',
515
+ rationale: 'Initial process auto-build scaffold; identity preflight must be rerun with remote/local candidates before write.',
516
+ },
517
+ evidence_manifest: {
518
+ sources: [
519
+ {
520
+ id: `flow:${referenceFlowId}`,
521
+ type: 'input_flow_dataset',
522
+ path: flowArtifactPath,
523
+ title: normalized.flow_summary.base_name ?? referenceFlowId,
524
+ version: referenceFlowVersion,
525
+ },
526
+ ...normalized.source_inputs.map((source) => ({
527
+ id: source.source_id,
528
+ type: source.type,
529
+ path: source.artifact_path,
530
+ title: source.artifact_file_name,
531
+ intended_roles: source.intended_roles,
532
+ })),
533
+ ],
534
+ field_bindings: [
535
+ { field_path: 'target', source_id: `flow:${referenceFlowId}` },
536
+ { field_path: 'identity_decision.decision', source_id: `flow:${referenceFlowId}` },
537
+ { field_path: 'unit_of_analysis', source_id: `flow:${referenceFlowId}` },
538
+ { field_path: 'name_plan.base_name', source_id: `flow:${referenceFlowId}` },
539
+ { field_path: 'target.geography', source_id: `flow:${referenceFlowId}` },
540
+ { field_path: 'target.technology_route', source_id: `flow:${referenceFlowId}` },
541
+ {
542
+ field_path: 'quantitative_reference_plan.reference_flow_id',
543
+ source_id: `flow:${referenceFlowId}`,
544
+ },
545
+ ],
546
+ },
547
+ unit_of_analysis: {
548
+ target_kind: normalized.operation === 'treat' ? 'treatment' : 'process_from_flow_scaffold',
549
+ decision: 'manual_review',
550
+ functional_unit: {
551
+ what: normalized.operation === 'treat'
552
+ ? `treat ${normalized.flow_summary.base_name ?? 'the reference flow'}`
553
+ : `produce ${normalized.flow_summary.base_name ?? 'the reference flow'}`,
554
+ how_much: `1 ${flowProperty.reference_unit ?? flowProperty.reference_property}`,
555
+ how_well: 'to be determined from source evidence before materialization',
556
+ how_long: 'not determined in the initial scaffold',
557
+ },
558
+ reference_flow: {
559
+ flow_identity: normalized.flow_summary.base_name ?? referenceFlowId,
560
+ reference_unit: flowProperty.reference_unit ?? flowProperty.reference_property,
561
+ reference_amount: 1,
562
+ flow_property: flowProperty.reference_property,
563
+ },
564
+ declared_unit_allowed: false,
565
+ scaling_evidence_status: 'source_required',
566
+ notes: [
567
+ 'Initial scaffold only. A skill/Codex workflow must revise unit_of_analysis before build-plan materialize.',
568
+ ],
569
+ },
570
+ name_plan: {
571
+ base_name: baseName,
572
+ treatment_standards_routes: normalized.operation === 'treat' ? 'treatment route' : 'production route',
573
+ mix_and_location_types: 'global average',
574
+ functional_unit_flow_properties: flowProperty.reference_unit ?? flowProperty.reference_property,
575
+ },
576
+ quantitative_reference_plan: {
577
+ reference_flow_id: referenceFlowId,
578
+ reference_flow_version: referenceFlowVersion,
579
+ reference_flow_name: normalized.flow_summary.base_name ?? referenceFlowId,
580
+ reference_flow_internal_id: '1',
581
+ mean_amount: '1.0',
582
+ resulting_amount: '1.0',
583
+ reference_unit: flowProperty.reference_unit ?? flowProperty.reference_property,
584
+ },
585
+ flow_property_plan: flowProperty,
586
+ exchange_plan: {
587
+ exchanges: [],
588
+ },
589
+ materialization_readiness: {
590
+ status: 'scaffold_only',
591
+ next_required_steps: [
592
+ 'replace scaffold unit_of_analysis with a skill-authored decision artifact',
593
+ 'run process identity-preflight with local and remote candidates',
594
+ 'replace scaffold geography, technology, classification, exchange values, and annual volume with evidence-backed values',
595
+ 'run process build-plan validate/materialize before save-draft or publish-build',
596
+ ],
597
+ },
598
+ };
599
+ }
455
600
  function buildLineageManifest(normalized) {
456
601
  return {
457
602
  schema_version: 1,
@@ -537,13 +682,13 @@ function buildInitialState(normalized, flowArtifactPath, now) {
537
682
  step_markers: buildStepMarkers(now),
538
683
  };
539
684
  }
540
- function buildNextActions(layout, normalized) {
685
+ function buildNextActions(layout) {
541
686
  return [
542
687
  `inspect: ${layout.normalizedRequestPath}`,
543
688
  `inspect: ${layout.statePath}`,
544
689
  `inspect: ${layout.assemblyPlanPath}`,
545
- `future: tiangong process resume-build --run-id ${normalized.run_id}`,
546
- `future: tiangong process publish-build --run-id ${normalized.run_id}`,
690
+ `future: tiangong-lca process resume-build --run-dir ${layout.runRoot}`,
691
+ `future: tiangong-lca process publish-build --run-dir ${layout.runRoot}`,
547
692
  ];
548
693
  }
549
694
  function buildAgentHandoffSummary(normalized, layout, flowArtifactPath, now) {
@@ -572,9 +717,10 @@ function buildAgentHandoffSummary(normalized, layout, flowArtifactPath, now) {
572
717
  request_snapshot: layout.requestSnapshotPath,
573
718
  normalized_request: layout.normalizedRequestPath,
574
719
  assembly_plan: layout.assemblyPlanPath,
720
+ build_plan: layout.buildPlanPath,
575
721
  flow_copy: flowArtifactPath,
576
722
  },
577
- next_actions: buildNextActions(layout, normalized),
723
+ next_actions: buildNextActions(layout),
578
724
  extra: {
579
725
  status: 'prepared_local_process_auto_build_run',
580
726
  request_id: normalized.request_id,
@@ -608,6 +754,7 @@ function buildReport(normalized, layout, flowArtifactPath, now) {
608
754
  source_policy: layout.sourcePolicyPath,
609
755
  flow_summary: layout.flowSummaryPath,
610
756
  input_manifest: layout.inputManifestPath,
757
+ build_plan: layout.buildPlanPath,
611
758
  assembly_plan: layout.assemblyPlanPath,
612
759
  lineage_manifest: layout.lineageManifestPath,
613
760
  invocation_index: layout.invocationIndexPath,
@@ -616,7 +763,7 @@ function buildReport(normalized, layout, flowArtifactPath, now) {
616
763
  handoff_summary: layout.handoffSummaryPath,
617
764
  report: layout.reportPath,
618
765
  },
619
- next_actions: buildNextActions(layout, normalized),
766
+ next_actions: buildNextActions(layout),
620
767
  };
621
768
  }
622
769
  export function normalizeProcessAutoBuildRequest(input, options) {
@@ -630,7 +777,7 @@ export function normalizeProcessAutoBuildRequest(input, options) {
630
777
  const runId = nonEmptyString(options.runIdOverride) ??
631
778
  nonEmptyString(request.run_id) ??
632
779
  buildProcessAutoBuildRunId(flowFile, operation, flowSummary, options.now);
633
- const runRoot = resolveRunRoot(requestDir, runId, options.outDir, request.workspace_run_root);
780
+ const runRoot = resolveRunRoot(requestDir, options.outDir, request.workspace_run_root);
634
781
  const layout = buildLayout(runRoot, runId);
635
782
  return {
636
783
  schema_version: 1,
@@ -676,7 +823,9 @@ export async function runProcessAutoBuild(options) {
676
823
  flow_path: normalized.flow_file,
677
824
  flow_artifact_path: flowArtifactPath,
678
825
  operation: normalized.operation,
826
+ build_plan_path: layout.buildPlanPath,
679
827
  });
828
+ writeJsonArtifact(layout.buildPlanPath, buildInitialProcessBuildPlan(normalized, flowArtifactPath));
680
829
  writeJsonArtifact(layout.assemblyPlanPath, buildAssemblyPlan(layout.runRoot));
681
830
  writeJsonArtifact(layout.lineageManifestPath, buildLineageManifest(normalized));
682
831
  writeJsonArtifact(layout.invocationIndexPath, buildInvocationIndex(normalized, options, layout.reportPath, now));
@@ -708,6 +857,7 @@ export const __testInternals = {
708
857
  buildProcessAutoBuildRunId,
709
858
  buildLayout,
710
859
  buildAssemblyPlan,
860
+ buildInitialProcessBuildPlan,
711
861
  buildLineageManifest,
712
862
  buildInvocationIndex,
713
863
  buildInitialState,