@tiangong-lca/cli 0.0.11 → 0.0.13

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 (60) hide show
  1. package/README.md +18 -7
  2. package/assets/tidas-schemas/tidas_contacts.json +312 -0
  3. package/assets/tidas-schemas/tidas_contacts_category.json +126 -0
  4. package/assets/tidas-schemas/tidas_data_types.json +359 -0
  5. package/assets/tidas-schemas/tidas_flowproperties.json +303 -0
  6. package/assets/tidas-schemas/tidas_flowproperties_category.json +61 -0
  7. package/assets/tidas-schemas/tidas_flows.json +809 -0
  8. package/assets/tidas-schemas/tidas_flows_elementary_category.json +720 -0
  9. package/assets/tidas-schemas/tidas_flows_product_category.json +59623 -0
  10. package/assets/tidas-schemas/tidas_lciamethods.json +1326 -0
  11. package/assets/tidas-schemas/tidas_lciamethods_category.json +685 -0
  12. package/assets/tidas-schemas/tidas_lifecyclemodels.json +1374 -0
  13. package/assets/tidas-schemas/tidas_locations_category.json +2593 -0
  14. package/assets/tidas-schemas/tidas_processes.json +1646 -0
  15. package/assets/tidas-schemas/tidas_processes_category.json +10795 -0
  16. package/assets/tidas-schemas/tidas_sources.json +228 -0
  17. package/assets/tidas-schemas/tidas_sources_category.json +100 -0
  18. package/assets/tidas-schemas/tidas_unitgroups.json +338 -0
  19. package/assets/tidas-schemas/tidas_unitgroups_category.json +61 -0
  20. package/dist/src/cli.js +847 -13
  21. package/dist/src/cli.js.map +1 -1
  22. package/dist/src/lib/dataset-classification.js +947 -0
  23. package/dist/src/lib/dataset-classification.js.map +1 -0
  24. package/dist/src/lib/dataset-command.js +11 -0
  25. package/dist/src/lib/dataset-command.js.map +1 -1
  26. package/dist/src/lib/dataset-contract.js +2 -0
  27. package/dist/src/lib/dataset-contract.js.map +1 -1
  28. package/dist/src/lib/dataset-curation-queue.js +359 -2
  29. package/dist/src/lib/dataset-curation-queue.js.map +1 -1
  30. package/dist/src/lib/dataset-import-lca.js +18 -0
  31. package/dist/src/lib/dataset-import-lca.js.map +1 -1
  32. package/dist/src/lib/dataset-local.js +94 -1
  33. package/dist/src/lib/dataset-local.js.map +1 -1
  34. package/dist/src/lib/dataset-maintenance-clear-account.js +506 -0
  35. package/dist/src/lib/dataset-maintenance-clear-account.js.map +1 -0
  36. package/dist/src/lib/dataset-patch.js +797 -0
  37. package/dist/src/lib/dataset-patch.js.map +1 -0
  38. package/dist/src/lib/dataset-remote-verify.js +188 -3
  39. package/dist/src/lib/dataset-remote-verify.js.map +1 -1
  40. package/dist/src/lib/dataset-save-draft-run.js +725 -0
  41. package/dist/src/lib/dataset-save-draft-run.js.map +1 -0
  42. package/dist/src/lib/dataset-validate.js +32 -2
  43. package/dist/src/lib/dataset-validate.js.map +1 -1
  44. package/dist/src/lib/flow-publish-version.js +7 -2
  45. package/dist/src/lib/flow-publish-version.js.map +1 -1
  46. package/dist/src/lib/flow-qa.js +8 -0
  47. package/dist/src/lib/flow-qa.js.map +1 -1
  48. package/dist/src/lib/identity-preflight.js +895 -117
  49. package/dist/src/lib/identity-preflight.js.map +1 -1
  50. package/dist/src/lib/lifecyclemodel-qa.js +159 -34
  51. package/dist/src/lib/lifecyclemodel-qa.js.map +1 -1
  52. package/dist/src/lib/process-required-fields.js +62 -12
  53. package/dist/src/lib/process-required-fields.js.map +1 -1
  54. package/dist/src/lib/process-save-draft-run.js +10 -0
  55. package/dist/src/lib/process-save-draft-run.js.map +1 -1
  56. package/dist/src/lib/process-save-draft.js +59 -3
  57. package/dist/src/lib/process-save-draft.js.map +1 -1
  58. package/dist/src/lib/supabase-client.js +19 -8
  59. package/dist/src/lib/supabase-client.js.map +1 -1
  60. package/package.json +2 -1
package/dist/src/cli.js CHANGED
@@ -41,7 +41,7 @@ import { runFlowApplyProcessFlowRepairs, runFlowPlanProcessFlowRepairs, runFlowR
41
41
  import { executeRemoteCommand, getRemoteCommandHelp } from './lib/remote.js';
42
42
  import { runValidation, } from './lib/validation.js';
43
43
  import { runDatasetValidate, } from './lib/dataset-validate.js';
44
- import { runDatasetCurationQueueBuild, } from './lib/dataset-curation-queue.js';
44
+ import { runDatasetCurationQueueBuild, runDatasetCurationQueueNext, runDatasetCurationQueueVerify, } from './lib/dataset-curation-queue.js';
45
45
  import { runDatasetReferencesRewrite, } from './lib/dataset-references-rewrite.js';
46
46
  import { runDatasetRemoteRefresh, } from './lib/dataset-remote-refresh.js';
47
47
  import { runDatasetRemoteVerify, } from './lib/dataset-remote-verify.js';
@@ -50,6 +50,10 @@ import { runDatasetEvidenceSearch, } from './lib/dataset-evidence-search.js';
50
50
  import { runDatasetContract, } from './lib/dataset-contract.js';
51
51
  import { runDatasetImportLcaConvert, } from './lib/dataset-import-lca.js';
52
52
  import { runDatasetAuthor, } from './lib/dataset-author.js';
53
+ import { runDatasetPatchApply, } from './lib/dataset-patch.js';
54
+ import { runDatasetSaveDraft, } from './lib/dataset-save-draft-run.js';
55
+ import { runDatasetClassificationApply, runDatasetClassificationAudit, runDatasetClassificationChildren, runDatasetClassificationPath, } from './lib/dataset-classification.js';
56
+ import { runDatasetMaintenanceClearAccount, } from './lib/dataset-maintenance-clear-account.js';
53
57
  function renderMainHelp(dotEnvStatus) {
54
58
  return `TianGong LCA CLI
55
59
 
@@ -69,7 +73,7 @@ Implemented Commands:
69
73
  doctor show environment diagnostics
70
74
  search flow | process | lifecyclemodel
71
75
  process get | list | identity-preflight | build-plan | scope-statistics | dedup-review | auto-build | resume-build | publish-build | complete-required-fields | save-draft | batch-build | refresh-references | verify-rows
72
- dataset contract get | context-pack | curation-queue build | import-lca convert | author | validate | verify-remote | bilingual extract/apply/validate | evidence-search plan/run | references rewrite/refresh-remote
76
+ dataset contract get | context-pack | classification children/path/audit/apply | curation-queue build/next/verify | import-lca convert | author | patch apply | save-draft | validate | verify-remote | bilingual extract/apply/validate | evidence-search plan/run | references rewrite/refresh-remote | maintenance clear-account
73
77
  flow get | list | identity-preflight | build-plan | fetch-rows | materialize-decisions | remediate | publish-version | publish-reviewed-data | build-alias-map | scan-process-flow-refs | plan-process-flow-repairs | apply-process-flow-repairs | regen-product | validate-processes
74
78
  lifecyclemodel auto-build | validate-build | publish-build | save-draft | graph | build-resulting-process | publish-resulting-process | orchestrate
75
79
  qa process | flow | lifecyclemodel
@@ -80,6 +84,7 @@ Implemented Commands:
80
84
  Planned Surface (not implemented yet):
81
85
  auth whoami | doctor-auth
82
86
  job get | wait | logs
87
+ dataset maintenance plan | apply | verify
83
88
 
84
89
  Planned commands currently print an explicit "not implemented yet" message and exit with code 2.
85
90
 
@@ -104,9 +109,16 @@ Examples:
104
109
  tiangong-lca dataset validate --input ./rows.jsonl --type auto --out-dir /abs/path/to/dataset-validate
105
110
  tiangong-lca dataset contract get --type process --include schema,methodology,ruleset --out-dir ./contract
106
111
  tiangong-lca dataset context-pack --type process --profile ai-import --out-dir ./context-pack
112
+ tiangong-lca dataset classification children --type process --parent A --out-dir ./classification --json
113
+ tiangong-lca dataset classification path --type process --code 1080 --out-dir ./classification --json
114
+ tiangong-lca dataset classification audit --type location --input ./rows/processes.jsonl --out-dir ./classification --json
115
+ tiangong-lca dataset classification apply --input ./rows/processes.jsonl --decisions ./classification-decisions.jsonl --out ./rows/processes.classified.jsonl --type process --out-dir ./classification --json
107
116
  tiangong-lca dataset curation-queue build --processes ./processes.jsonl --flows ./flows.jsonl --out-dir ./curation-queue
117
+ tiangong-lca dataset curation-queue next --queue-dir ./curation-queue --type support
118
+ tiangong-lca dataset curation-queue verify --queue-dir ./curation-queue --type process
108
119
  tiangong-lca dataset import-lca convert --input ./external-package --output-dir ./converted --from-format auto --target tidas
109
120
  tiangong-lca dataset author --input ./source.pdf --target-types process,flow --out-dir ./authoring
121
+ tiangong-lca dataset save-draft --input ./contacts.jsonl --type contact --out-dir /abs/path/to/contact-save-draft --commit
110
122
  tiangong-lca dataset verify-remote --input ./rows.jsonl --out-dir /abs/path/to/dataset-remote-verify
111
123
  tiangong-lca dataset bilingual extract --input ./rows/processes.jsonl --type process --out-dir ./translation
112
124
  tiangong-lca dataset bilingual apply --input ./rows/processes.jsonl --translations ./translation/trans-reviewed.jsonl --out ./rows/processes.translated.jsonl
@@ -114,6 +126,8 @@ Examples:
114
126
  tiangong-lca dataset evidence-search plan --query "中国2026年电力结构数据" --out-dir ./evidence-search
115
127
  tiangong-lca dataset evidence-search run --input ./evidence-search.request.json --results ./search-results.json --out-dir ./evidence-search
116
128
  tiangong-lca dataset references rewrite --input ./rows.jsonl --from flow:<old-id>@<old-version> --to flow:<new-id>@<new-version> --out-dir /abs/path/to/dataset-rewrite
129
+ tiangong-lca dataset maintenance clear-account --out-dir /abs/path/to/account-clear --json
130
+ tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation redo-import --out-dir /abs/path/to/dataset-maintenance
117
131
  tiangong-lca lifecyclemodel auto-build --input ./lifecyclemodel-auto-build.request.json --out-dir /abs/path/to/lifecyclemodel-run
118
132
  tiangong-lca lifecyclemodel validate-build --run-dir /abs/path/to/lifecyclemodel-run
119
133
  tiangong-lca lifecyclemodel publish-build --run-dir /abs/path/to/lifecyclemodel-run
@@ -138,7 +152,7 @@ Examples:
138
152
  tiangong-lca qa process --rows-file ./processes.jsonl --out-dir ./qa
139
153
  tiangong-lca qa process --run-root /abs/path/to/process-run --run-id <run_id> --out-dir ./qa
140
154
  tiangong-lca qa flow --rows-file ./flows.json --out-dir ./qa
141
- tiangong-lca qa lifecyclemodel --run-dir /abs/path/to/lifecyclemodel-run --out-dir ./lifecyclemodel-qa
155
+ tiangong-lca qa lifecyclemodel --rows-file ./lifecyclemodels.jsonl --out-dir ./lifecyclemodel-qa
142
156
  tiangong-lca publish run --input ./publish-request.json --dry-run
143
157
  tiangong-lca validation run --input-dir ./package --engine auto
144
158
  tiangong-lca admin embedding-run --input ./jobs.json
@@ -246,9 +260,14 @@ function renderDatasetHelp() {
246
260
  Implemented Subcommands:
247
261
  contract get Write TIDAS schema / methodology / ruleset contract artifacts
248
262
  context-pack Write an AI-ready TIDAS contract context pack
263
+ classification Navigate bundled TIDAS classification schemas or apply selected classifications
249
264
  curation-queue build Build entity-level AI curation queue artifacts for Foundry imports
265
+ curation-queue next Return the next runnable support/flow/process queue task
266
+ curation-queue verify Verify queue task checkpoints for a scope
250
267
  import-lca convert Convert supported external LCA packages through tidas-tools
251
268
  author Extract source evidence and prepare TIDAS context packs for AI authoring
269
+ patch apply Apply AI-authored structured dataset patches deterministically
270
+ save-draft Save contact/source/support or other canonical dataset rows through the platform dataset command path
252
271
  validate Validate local flow / process / lifecyclemodel rows with the TIDAS SDK
253
272
  verify-remote Verify dataset roots and TIDAS references against remote published versions
254
273
  bilingual extract Extract bilingual translation units from local rows
@@ -257,13 +276,25 @@ Implemented Subcommands:
257
276
  evidence-search Plan or record field-level public evidence retrieval
258
277
  references rewrite Rewrite flow references in local process and lifecyclemodel rows
259
278
  references refresh-remote Refresh local TIDAS reference versions to latest reachable remote rows
279
+ maintenance clear-account Dry-run or clear current authenticated account-owned dataset rows through RLS
280
+
281
+ Planned Subcommands:
282
+ maintenance plan/apply/verify Plan, execute, and verify RLS-scoped dataset delete/redo maintenance
260
283
 
261
284
  Examples:
262
285
  tiangong-lca dataset contract get --type process --include schema,methodology,ruleset --out-dir ./contract --help
263
286
  tiangong-lca dataset context-pack --type process --profile ai-import --out-dir ./context-pack --help
287
+ tiangong-lca dataset classification children --type process --parent A --out-dir ./classification --help
288
+ tiangong-lca dataset classification path --type process --code 1080 --out-dir ./classification --help
289
+ tiangong-lca dataset classification audit --type location --input ./rows/processes.jsonl --out-dir ./classification --help
290
+ tiangong-lca dataset classification apply --input ./rows/processes.jsonl --decisions ./classification-decisions.jsonl --out ./rows/processes.classified.jsonl --type process --out-dir ./classification --help
264
291
  tiangong-lca dataset curation-queue build --processes ./rows/processes.jsonl --flows ./rows/flows.jsonl --support ./rows/sources.jsonl --out-dir ./curation-queue --help
292
+ tiangong-lca dataset curation-queue next --queue-dir ./curation-queue --type flow --json
293
+ tiangong-lca dataset curation-queue verify --queue-dir ./curation-queue --task-id process:abc@00.00.001 --json
265
294
  tiangong-lca dataset import-lca convert --input ./external-package --output-dir ./converted --from-format auto --target tidas --help
266
295
  tiangong-lca dataset author --input ./source.pdf --target-types process,flow --out-dir ./authoring --help
296
+ tiangong-lca dataset patch apply --input ./rows.jsonl --patch ./ai-patches.json --out ./rows.patched.jsonl --out-dir ./patch-apply --help
297
+ tiangong-lca dataset save-draft --input ./contacts.jsonl --type contact --out-dir ./contact-save-draft --commit --help
267
298
  tiangong-lca dataset validate --input ./rows.jsonl --type auto --out-dir ./dataset-validate --help
268
299
  tiangong-lca dataset verify-remote --input ./rows.jsonl --out-dir ./dataset-remote-verify --help
269
300
  tiangong-lca dataset bilingual extract --input ./rows.jsonl --type process --out-dir ./translation --help
@@ -273,6 +304,69 @@ Examples:
273
304
  tiangong-lca dataset evidence-search run --input ./request.json --results ./search-results.json --out-dir ./evidence-search --help
274
305
  tiangong-lca dataset references rewrite --input ./rows.jsonl --from flow:<old-id>@<old-version> --to flow:<new-id>@<new-version> --out-dir ./dataset-rewrite --help
275
306
  tiangong-lca dataset references refresh-remote --input ./rows.jsonl --out ./rows.refreshed.jsonl --out-dir ./dataset-reference-refresh --help
307
+ tiangong-lca dataset maintenance clear-account --out-dir ./account-clear --json --help
308
+ tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation redo-import --out-dir ./dataset-maintenance --help
309
+ `.trim();
310
+ }
311
+ function renderDatasetMaintenanceHelp() {
312
+ return `Usage:
313
+ tiangong-lca dataset maintenance <clear-account|plan|apply|verify> [options]
314
+
315
+ Status:
316
+ clear-account is implemented for current authenticated account cleanup.
317
+ plan/apply/verify remain reserved for row-level RLS-scoped cleanup and redo workflows and currently exit with code 2 for executable actions.
318
+
319
+ Implemented Actions:
320
+ clear-account Dry-run or delete current authenticated account-owned lifecyclemodels, processes, flows, sources, and contacts.
321
+
322
+ Planned Actions:
323
+ plan Build an immutable maintenance plan from a scope manifest, visible remote snapshot, dependency impact report, and intended operation.
324
+ apply Execute an approved plan through current-user RLS and platform dataset command paths; never bypass RLS or delete rows outside the visible scope.
325
+ verify Re-fetch affected rows and references, then prove that deleted, updated, skipped, protected, and redone rows match the plan.
326
+
327
+ Required Artifact Contract:
328
+ - maintenance-plan.json
329
+ - rls-visible-snapshot.json
330
+ - protected-rows.jsonl
331
+ - reference-impact-report.json
332
+ - dry-run-report.json
333
+ - commit-report.json
334
+ - readback-verify-report.json
335
+
336
+ Examples:
337
+ tiangong-lca dataset maintenance clear-account --out-dir ./account-clear --json
338
+ tiangong-lca dataset maintenance clear-account --commit --confirm user@example.com --out-dir ./account-clear
339
+ tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation redo-import --out-dir ./dataset-maintenance
340
+ tiangong-lca dataset maintenance apply --plan ./dataset-maintenance/maintenance-plan.json --commit
341
+ tiangong-lca dataset maintenance verify --plan ./dataset-maintenance/maintenance-plan.json --out-dir ./dataset-maintenance/verify
342
+ `.trim();
343
+ }
344
+ function renderDatasetMaintenanceClearAccountHelp() {
345
+ return `Usage:
346
+ tiangong-lca dataset maintenance clear-account [options]
347
+
348
+ Behavior:
349
+ Dry-run by default. With --commit, deletes only rows visible to the current authenticated user and filtered by user_id through RLS.
350
+ Tables are deleted in reference-safe order: lifecyclemodels, processes, flows, sources, contacts.
351
+ Unit groups and flow properties are not deleted by this command because they are treated as protected support data.
352
+
353
+ Options:
354
+ --state-code <n> Optional repeatable state_code filter. Omit to clear all state codes for the current account.
355
+ --out-dir <dir> Artifact directory (default: ./dataset-maintenance/clear-account)
356
+ --page-size <n> Snapshot page size, 1-5000 (default: 1000)
357
+ --timeout-ms <n> Request timeout in milliseconds (default: 10000)
358
+ --commit Execute deletion. Without this flag the command only writes a dry-run report.
359
+ --dry-run Explicit dry-run mode
360
+ --confirm <email> Required with --commit; must match the current authenticated account email
361
+ --json Print compact JSON
362
+ -h, --help
363
+
364
+ Outputs written under --out-dir:
365
+ - rls-visible-snapshot.json
366
+ - dry-run-report.json
367
+ - approval-record.json (commit only)
368
+ - commit-report.json (commit only)
369
+ - readback-verify-report.json (commit only)
276
370
  `.trim();
277
371
  }
278
372
  function renderDatasetContractHelp() {
@@ -317,11 +411,74 @@ Outputs written under --out-dir:
317
411
  - outputs/contract-report.json
318
412
  `.trim();
319
413
  }
414
+ function renderDatasetClassificationHelp() {
415
+ return `Usage:
416
+ tiangong-lca dataset classification children --type <type> [options]
417
+ tiangong-lca dataset classification path --type <type> --code <code> [options]
418
+ tiangong-lca dataset classification audit --type location --input <file> [options]
419
+ tiangong-lca dataset classification apply --input <file> --decisions <file> --out <file> [options]
420
+
421
+ Classification types:
422
+ process, flow-product, flow-elementary, source, contact, unitgroup, flowproperty, lciamethod, location
423
+
424
+ Actions:
425
+ children List the next selectable children for a parent code. Omit --parent for top level.
426
+ path Resolve one schema code into the full root-to-leaf classification path.
427
+ audit Scan local rows for schema-derived location fields that are not valid TIDAS location codes.
428
+ apply Apply AI/human classification decisions to local TIDAS rows deterministically.
429
+
430
+ Options for children:
431
+ --type <type> Classification schema type
432
+ --parent <code> Parent code to inspect
433
+ --query <text> Filter direct children by code or label
434
+ --limit <n> Limit returned children
435
+ --out-dir <dir> Optional artifact directory
436
+ --json Print compact JSON
437
+
438
+ Options for path:
439
+ --type <type> Classification schema type
440
+ --code <code> Leaf or intermediate classification code
441
+ --out-dir <dir> Optional artifact directory
442
+ --json Print compact JSON
443
+
444
+ Options for audit:
445
+ --type location Audit schema-derived location values against tidas_locations_category.json
446
+ --input <file> Local rows as JSON or JSONL
447
+ --out-dir <dir> Optional artifact directory
448
+ --json Print compact JSON
449
+
450
+ Options for apply:
451
+ --input <file> Local rows as JSON or JSONL
452
+ --decisions <file> JSON/JSONL decisions with row_index or dataset_id plus code/classes
453
+ --out <file> Output JSONL path for classified rows
454
+ --type <type> Default classification type when decisions omit category_type
455
+ --out-dir <dir> Artifact directory; defaults to the output file directory
456
+ --json Print compact JSON
457
+ -h, --help
458
+
459
+ Decision contract:
460
+ Decisions may target row_index or dataset_id. They may provide code, leaf_code, class_id, cat_id,
461
+ or a classes/common:class/common:category path. The CLI normalizes the path against the bundled
462
+ TIDAS schema copied from tidas-tools before writing it back. Location decisions use location
463
+ target fields derived from the bundled TIDAS schemas, plus TIDAS LCIA geography fields; use
464
+ --type location and target_path when a row contains more than one location field.
465
+
466
+ Outputs:
467
+ - children/path report under outputs/ when --out-dir is provided
468
+ - outputs/location-audit-findings.jsonl for audit
469
+ - outputs/location-audit-report.json for audit
470
+ - classified rows at --out for apply
471
+ - outputs/classification-apply-evidence.jsonl
472
+ - outputs/classification-apply-report.json
473
+ `.trim();
474
+ }
320
475
  function renderDatasetCurationQueueHelp() {
321
476
  return `Usage:
322
477
  tiangong-lca dataset curation-queue build --processes <file> --out-dir <dir> [options]
478
+ tiangong-lca dataset curation-queue next --queue-dir <dir> [--type <type>|--task-id <id>]
479
+ tiangong-lca dataset curation-queue verify --queue-dir <dir> [--type <type>|--task-id <id>]
323
480
 
324
- Options:
481
+ Options for build:
325
482
  --processes <file> Process rows JSON/JSONL
326
483
  --flows <file> Local flow rows JSON/JSONL used by process references
327
484
  --support <file> Repeatable support rows JSON/JSONL, for source/contact/unitgroup/flowproperty rows
@@ -332,6 +489,13 @@ Options:
332
489
  --json Print compact JSON
333
490
  -h, --help
334
491
 
492
+ Options for next/verify:
493
+ --queue-dir <dir> Queue artifact directory produced by build
494
+ --type <type> support | flow | process
495
+ --task-id <id> Exact task id such as process:<uuid>@00.00.001
496
+ --json Print compact JSON
497
+ -h, --help
498
+
335
499
  Outputs written under --out-dir:
336
500
  - outputs/curation-queue-manifest.json
337
501
  - outputs/curation-queue-tasks.jsonl
@@ -342,7 +506,8 @@ Outputs written under --out-dir:
342
506
  - entities/<supports|flows|processes>/<id>__<version>/entity-run-plan.json
343
507
 
344
508
  Contract:
345
- This command builds the queue only. AI authoring must write structured patches or build plans,
509
+ build creates queue artifacts. next/verify consume those artifacts and entity checkpoint.json files.
510
+ They do not run AI or write the database. AI authoring must write structured patches or build plans,
346
511
  and remote writes remain blocked until deterministic apply, schema/QA, prewrite verify, and readback gates pass.
347
512
  `.trim();
348
513
  }
@@ -359,6 +524,10 @@ Options:
359
524
  --mapping-dir <dir> Optional custom mapping/reference data directory
360
525
  --language <lang> Default language for generated text (default: en)
361
526
  --validation-jobs <n> Parallel validation jobs passed to tidas-tools (default: 1)
527
+ --process-bundles Write per-process dependency bundles (default: enabled)
528
+ --process-bundles-dir <dir>
529
+ Custom per-process bundle directory (default: <output-dir>/process-bundles)
530
+ --no-process-bundles Disable per-process dependency bundle generation
362
531
  --detect-only Only detect the input format and write the report
363
532
  --fail-on-warning Return non-zero when converter warnings are present
364
533
  --python <bin> Python executable (default: python3)
@@ -371,6 +540,7 @@ Outputs written under --output-dir:
371
540
  - tidas/ when target includes TIDAS and not detect-only
372
541
  - ilcd/ when target includes ILCD and not detect-only
373
542
  - mapping.csv when not detect-only
543
+ - process-bundles/ when not detect-only and process bundles are enabled
374
544
  - outputs/import-lca-report.json
375
545
  `.trim();
376
546
  }
@@ -399,6 +569,35 @@ Environment:
399
569
  TIANGONG_LCA_UNSTRUCTURED_API_BASE_URL and TIANGONG_LCA_UNSTRUCTURED_API_KEY
400
570
  `.trim();
401
571
  }
572
+ function renderDatasetPatchHelp() {
573
+ return `Usage:
574
+ tiangong-lca dataset patch apply --input <file> --patch <file> --out <file> [options]
575
+
576
+ Options:
577
+ --input <file> Local rows as JSON or JSONL
578
+ --patch <file> AI-authored JSON patch set with row_index or dataset_id selectors
579
+ --out <file> Output JSONL path for patched rows
580
+ --out-dir <dir> Artifact directory; defaults to the output file directory
581
+ --authoring-package-dir <dir> Resolve relative authoring_package paths from this directory
582
+ --require-authoring-package Require each patch set to point at a matching authoring package
583
+ --require-action-item-closure Require patch operations to close package action_items
584
+ --json Print compact JSON
585
+ -h, --help
586
+
587
+ Patch contract:
588
+ Patch payloads must declare patch_status=completed before deterministic apply.
589
+ Patch sets must target a row by row_index or dataset_id and use operations[].
590
+ Supported operations are test, add, replace, and remove. Non-test operations require basis or evidence.
591
+ Foundry AI patches should include resolution.mode and resolution.used_context_kinds; these are copied to patch evidence.
592
+ Strict Foundry mode also requires authoring package lineage and explicit action item closure.
593
+ If any operation is invalid, the command reports blocked and writes the original rows unchanged.
594
+
595
+ Outputs:
596
+ - patched rows at --out
597
+ - outputs/patch-evidence.jsonl
598
+ - outputs/dataset-patch-apply-report.json
599
+ `.trim();
600
+ }
402
601
  function renderDatasetRemoteVerifyHelp() {
403
602
  return `Usage:
404
603
  tiangong-lca dataset verify-remote --input <file> --out-dir <dir> [options]
@@ -407,6 +606,9 @@ Options:
407
606
  --input <file> Local rows as JSON or JSONL; objects with rows[] are also accepted
408
607
  --out-dir <dir> Artifact directory for the remote verification report
409
608
  --root-policy <mode> existing | candidate (default: existing)
609
+ --compare-root-payload Compare each root row payload hash against the remote row
610
+ --target-user-id <id> Require root readback rows to belong to this user
611
+ --state-code <code> Require root readback rows to have this state_code
410
612
  --json Print compact JSON
411
613
  -h, --help
412
614
 
@@ -419,13 +621,37 @@ Outputs written under --out-dir:
419
621
  - outputs/blockers.jsonl
420
622
  `.trim();
421
623
  }
624
+ function renderDatasetSaveDraftHelp() {
625
+ return `Usage:
626
+ tiangong-lca dataset save-draft --input <file> --type <type> [options]
627
+
628
+ Options:
629
+ --input <file> Canonical TIDAS rows JSON/JSONL
630
+ --type <type> auto, contact, source, flow, process
631
+ --out-dir <dir> Artifact directory
632
+ --commit Execute remote save-draft writes
633
+ --dry-run Validate and plan without remote writes (default)
634
+ --json Print compact JSON
635
+ -h, --help
636
+
637
+ Outputs written under --out-dir:
638
+ - outputs/dataset-save-draft/selected-rows.jsonl
639
+ - outputs/dataset-save-draft/progress.jsonl
640
+ - outputs/dataset-save-draft/failures.jsonl
641
+ - outputs/dataset-save-draft/summary.json
642
+
643
+ Contract:
644
+ This generic dataset path writes only mutable rows such as contact/source/flow/process. Unit group and flow property rows are reference-only; select existing database rows and rewrite references instead of creating My Data support rows.
645
+ Process and lifecyclemodel imports may still use their dedicated save-draft commands when the workflow needs their specialized reports.
646
+ `.trim();
647
+ }
422
648
  function renderDatasetValidateHelp() {
423
649
  return `Usage:
424
650
  tiangong-lca dataset validate --input <file> [options]
425
651
 
426
652
  Options:
427
653
  --input <file> Local rows as JSON or JSONL; objects with rows[] are also accepted
428
- --type <type> auto | flow | process | lifecyclemodel (default: auto)
654
+ --type <type> auto | contact | source | unitgroup | flowproperty | flow | process | lifecyclemodel (default: auto)
429
655
  --out-dir <dir> Optional artifact directory for validation report and row splits
430
656
  --json Print compact JSON
431
657
  -h, --help
@@ -652,6 +878,9 @@ Options:
652
878
  Override the remote search query; defaults to target identity text
653
879
  --remote-limit <n>
654
880
  Limit remote candidate rows after fetch
881
+ --remote-data-source <tg|co|my|te>
882
+ Search TianGong public, community, my data, or team data (default: tg)
883
+ --timeout-ms <n> Remote search/auth timeout in milliseconds
655
884
  --out-dir <dir> Optional artifact directory for identity decision outputs
656
885
  --json Print compact JSON
657
886
  -h, --help
@@ -981,7 +1210,7 @@ function renderQaHelp() {
981
1210
  Implemented Subcommands:
982
1211
  process Run deterministic process QA for build runs or rows-file snapshots
983
1212
  flow Run deterministic flow QA for local governance snapshots
984
- lifecyclemodel Run deterministic lifecyclemodel QA for one local build run
1213
+ lifecyclemodel Run deterministic lifecyclemodel QA for build runs or rows-file snapshots
985
1214
 
986
1215
  Examples:
987
1216
  tiangong-lca qa process --help
@@ -1033,9 +1262,10 @@ Options:
1033
1262
  }
1034
1263
  function renderQaLifecyclemodelHelp() {
1035
1264
  return `Usage:
1036
- tiangong-lca qa lifecyclemodel --run-dir <dir> --out-dir <dir> [options]
1265
+ tiangong-lca qa lifecyclemodel (--rows-file <file> | --run-dir <dir>) --out-dir <dir> [options]
1037
1266
 
1038
1267
  Options:
1268
+ --rows-file <file> Lifecyclemodel rows JSON/JSONL file; payload-level QA for import snapshots
1039
1269
  --run-dir <dir> Existing lifecyclemodel auto-build run directory
1040
1270
  --out-dir <dir> QA artifact output directory
1041
1271
  --start-ts <iso> Optional run start timestamp
@@ -1045,7 +1275,7 @@ Options:
1045
1275
  -h, --help
1046
1276
 
1047
1277
  This command:
1048
- - reads one existing lifecyclemodel build run under models/*/tidas_bundle/lifecyclemodels
1278
+ - reads one lifecyclemodel rows snapshot or existing build run under models/*/tidas_bundle/lifecyclemodels
1049
1279
  - aggregates validate-build findings when reports/lifecyclemodel-validate-build-report.json is present
1050
1280
  - emits artifact-first model summaries, findings, markdown QA notes, and a structured report
1051
1281
  `.trim();
@@ -1333,6 +1563,9 @@ Options:
1333
1563
  Override the remote search query; defaults to target identity text
1334
1564
  --remote-limit <n>
1335
1565
  Limit remote candidate rows after fetch
1566
+ --remote-data-source <tg|co|my|te>
1567
+ Search TianGong public, community, my data, or team data (default: tg)
1568
+ --timeout-ms <n> Remote search/auth timeout in milliseconds
1336
1569
  --out-dir <dir> Optional artifact directory for identity decision outputs
1337
1570
  --json Print compact JSON
1338
1571
  -h, --help
@@ -1425,6 +1658,8 @@ Options:
1425
1658
  --out-dir <dir> Run root written relative to cwd when a relative path is passed
1426
1659
  --commit Execute remote save-draft writes
1427
1660
  --dry-run Keep the command local-only (default)
1661
+ --target-user-id <id>
1662
+ Require --commit to run as this user and update an owned draft
1428
1663
  --json Print compact JSON
1429
1664
  -h, --help
1430
1665
 
@@ -1461,7 +1696,7 @@ Options:
1461
1696
  Annual supply / production volume policy:
1462
1697
  1. keep an existing valid annualized annualSupplyOrProductionVolume, for example "3.6 MJ/year";
1463
1698
  2. use an explicit value from row-level authoring evidence or evidenceManifest field bindings;
1464
- 3. otherwise complete from the quantitative reference flow meanAmount/resultingAmount and unit.
1699
+ 3. otherwise write "9999 missing-data-sentinel/year", an intentionally non-physical searchable sentinel for later database-side curation.
1465
1700
 
1466
1701
  Outputs:
1467
1702
  - completed rows at --out
@@ -1821,6 +2056,45 @@ function parseDatasetValidateFlags(args) {
1821
2056
  outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
1822
2057
  };
1823
2058
  }
2059
+ function parseDatasetSaveDraftFlags(args) {
2060
+ let values;
2061
+ try {
2062
+ ({ values } = parseArgs({
2063
+ args,
2064
+ allowPositionals: false,
2065
+ strict: true,
2066
+ options: {
2067
+ help: { type: 'boolean', short: 'h' },
2068
+ json: { type: 'boolean' },
2069
+ input: { type: 'string' },
2070
+ type: { type: 'string' },
2071
+ 'out-dir': { type: 'string' },
2072
+ commit: { type: 'boolean' },
2073
+ 'dry-run': { type: 'boolean' },
2074
+ },
2075
+ }));
2076
+ }
2077
+ catch (error) {
2078
+ throw new CliError(String(error), {
2079
+ code: 'INVALID_ARGS',
2080
+ exitCode: 2,
2081
+ });
2082
+ }
2083
+ if (values.commit && values['dry-run']) {
2084
+ throw new CliError('Cannot pass both --commit and --dry-run.', {
2085
+ code: 'INVALID_DATASET_SAVE_DRAFT_MODE',
2086
+ exitCode: 2,
2087
+ });
2088
+ }
2089
+ return {
2090
+ help: Boolean(values.help),
2091
+ json: Boolean(values.json),
2092
+ inputPath: typeof values.input === 'string' ? values.input : '',
2093
+ type: typeof values.type === 'string' ? values.type : undefined,
2094
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2095
+ commit: Boolean(values.commit),
2096
+ };
2097
+ }
1824
2098
  function parseDatasetContractFlags(args) {
1825
2099
  let values;
1826
2100
  try {
@@ -1855,6 +2129,141 @@ function parseDatasetContractFlags(args) {
1855
2129
  outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
1856
2130
  };
1857
2131
  }
2132
+ function parseDatasetClassificationChildrenFlags(args) {
2133
+ let values;
2134
+ try {
2135
+ ({ values } = parseArgs({
2136
+ args,
2137
+ allowPositionals: false,
2138
+ strict: true,
2139
+ options: {
2140
+ help: { type: 'boolean', short: 'h' },
2141
+ json: { type: 'boolean' },
2142
+ type: { type: 'string' },
2143
+ parent: { type: 'string' },
2144
+ query: { type: 'string' },
2145
+ limit: { type: 'string' },
2146
+ 'out-dir': { type: 'string' },
2147
+ },
2148
+ }));
2149
+ }
2150
+ catch (error) {
2151
+ throw new CliError(String(error), {
2152
+ code: 'INVALID_ARGS',
2153
+ exitCode: 2,
2154
+ });
2155
+ }
2156
+ const limit = typeof values.limit === 'string' ? Number.parseInt(values.limit, 10) : null;
2157
+ if (limit !== null && (!Number.isInteger(limit) || limit <= 0)) {
2158
+ throw new CliError('--limit must be a positive integer.', {
2159
+ code: 'DATASET_CLASSIFICATION_LIMIT_INVALID',
2160
+ exitCode: 2,
2161
+ });
2162
+ }
2163
+ return {
2164
+ help: Boolean(values.help),
2165
+ json: Boolean(values.json),
2166
+ type: typeof values.type === 'string' ? values.type : '',
2167
+ parent: typeof values.parent === 'string' ? values.parent : null,
2168
+ query: typeof values.query === 'string' ? values.query : null,
2169
+ limit,
2170
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2171
+ };
2172
+ }
2173
+ function parseDatasetClassificationPathFlags(args) {
2174
+ let values;
2175
+ try {
2176
+ ({ values } = parseArgs({
2177
+ args,
2178
+ allowPositionals: false,
2179
+ strict: true,
2180
+ options: {
2181
+ help: { type: 'boolean', short: 'h' },
2182
+ json: { type: 'boolean' },
2183
+ type: { type: 'string' },
2184
+ code: { type: 'string' },
2185
+ 'out-dir': { type: 'string' },
2186
+ },
2187
+ }));
2188
+ }
2189
+ catch (error) {
2190
+ throw new CliError(String(error), {
2191
+ code: 'INVALID_ARGS',
2192
+ exitCode: 2,
2193
+ });
2194
+ }
2195
+ return {
2196
+ help: Boolean(values.help),
2197
+ json: Boolean(values.json),
2198
+ type: typeof values.type === 'string' ? values.type : '',
2199
+ code: typeof values.code === 'string' ? values.code : '',
2200
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2201
+ };
2202
+ }
2203
+ function parseDatasetClassificationAuditFlags(args) {
2204
+ let values;
2205
+ try {
2206
+ ({ values } = parseArgs({
2207
+ args,
2208
+ allowPositionals: false,
2209
+ strict: true,
2210
+ options: {
2211
+ help: { type: 'boolean', short: 'h' },
2212
+ json: { type: 'boolean' },
2213
+ input: { type: 'string' },
2214
+ type: { type: 'string' },
2215
+ 'out-dir': { type: 'string' },
2216
+ },
2217
+ }));
2218
+ }
2219
+ catch (error) {
2220
+ throw new CliError(String(error), {
2221
+ code: 'INVALID_ARGS',
2222
+ exitCode: 2,
2223
+ });
2224
+ }
2225
+ return {
2226
+ help: Boolean(values.help),
2227
+ json: Boolean(values.json),
2228
+ inputPath: typeof values.input === 'string' ? values.input : '',
2229
+ type: typeof values.type === 'string' ? values.type : 'location',
2230
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2231
+ };
2232
+ }
2233
+ function parseDatasetClassificationApplyFlags(args) {
2234
+ let values;
2235
+ try {
2236
+ ({ values } = parseArgs({
2237
+ args,
2238
+ allowPositionals: false,
2239
+ strict: true,
2240
+ options: {
2241
+ help: { type: 'boolean', short: 'h' },
2242
+ json: { type: 'boolean' },
2243
+ input: { type: 'string' },
2244
+ decisions: { type: 'string' },
2245
+ out: { type: 'string' },
2246
+ type: { type: 'string' },
2247
+ 'out-dir': { type: 'string' },
2248
+ },
2249
+ }));
2250
+ }
2251
+ catch (error) {
2252
+ throw new CliError(String(error), {
2253
+ code: 'INVALID_ARGS',
2254
+ exitCode: 2,
2255
+ });
2256
+ }
2257
+ return {
2258
+ help: Boolean(values.help),
2259
+ json: Boolean(values.json),
2260
+ inputPath: typeof values.input === 'string' ? values.input : '',
2261
+ decisionsPath: typeof values.decisions === 'string' ? values.decisions : '',
2262
+ outPath: typeof values.out === 'string' ? values.out : '',
2263
+ type: typeof values.type === 'string' ? values.type : null,
2264
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2265
+ };
2266
+ }
1858
2267
  function parseDatasetCurationQueueBuildFlags(args) {
1859
2268
  let values;
1860
2269
  try {
@@ -1902,6 +2311,46 @@ function parseDatasetCurationQueueBuildFlags(args) {
1902
2311
  processLimit,
1903
2312
  };
1904
2313
  }
2314
+ function parseDatasetCurationQueueRuntimeFlags(args) {
2315
+ let values;
2316
+ try {
2317
+ ({ values } = parseArgs({
2318
+ args,
2319
+ allowPositionals: false,
2320
+ strict: true,
2321
+ options: {
2322
+ help: { type: 'boolean', short: 'h' },
2323
+ json: { type: 'boolean' },
2324
+ 'queue-dir': { type: 'string' },
2325
+ type: { type: 'string' },
2326
+ 'task-id': { type: 'string' },
2327
+ },
2328
+ }));
2329
+ }
2330
+ catch (error) {
2331
+ throw new CliError(String(error), {
2332
+ code: 'INVALID_ARGS',
2333
+ exitCode: 2,
2334
+ });
2335
+ }
2336
+ const entityType = typeof values.type === 'string' ? values.type : undefined;
2337
+ if (entityType !== undefined &&
2338
+ entityType !== 'support' &&
2339
+ entityType !== 'flow' &&
2340
+ entityType !== 'process') {
2341
+ throw new CliError('--type must be support, flow, or process.', {
2342
+ code: 'DATASET_CURATION_QUEUE_TYPE_INVALID',
2343
+ exitCode: 2,
2344
+ });
2345
+ }
2346
+ return {
2347
+ help: Boolean(values.help),
2348
+ json: Boolean(values.json),
2349
+ queueDir: typeof values['queue-dir'] === 'string' ? values['queue-dir'] : '',
2350
+ entityType,
2351
+ taskId: typeof values['task-id'] === 'string' ? values['task-id'] : undefined,
2352
+ };
2353
+ }
1905
2354
  function parseDatasetImportLcaConvertFlags(args) {
1906
2355
  let values;
1907
2356
  try {
@@ -1920,6 +2369,9 @@ function parseDatasetImportLcaConvertFlags(args) {
1920
2369
  'mapping-dir': { type: 'string' },
1921
2370
  language: { type: 'string' },
1922
2371
  'validation-jobs': { type: 'string' },
2372
+ 'process-bundles': { type: 'boolean' },
2373
+ 'process-bundles-dir': { type: 'string' },
2374
+ 'no-process-bundles': { type: 'boolean' },
1923
2375
  'detect-only': { type: 'boolean' },
1924
2376
  'fail-on-warning': { type: 'boolean' },
1925
2377
  python: { type: 'string' },
@@ -1940,6 +2392,18 @@ function parseDatasetImportLcaConvertFlags(args) {
1940
2392
  exitCode: 2,
1941
2393
  });
1942
2394
  }
2395
+ if (values['process-bundles'] && values['no-process-bundles']) {
2396
+ throw new CliError('--process-bundles and --no-process-bundles cannot both be set.', {
2397
+ code: 'DATASET_IMPORT_LCA_PROCESS_BUNDLES_INVALID',
2398
+ exitCode: 2,
2399
+ });
2400
+ }
2401
+ if (values['no-process-bundles'] && typeof values['process-bundles-dir'] === 'string') {
2402
+ throw new CliError('--process-bundles-dir cannot be used with --no-process-bundles.', {
2403
+ code: 'DATASET_IMPORT_LCA_PROCESS_BUNDLES_INVALID',
2404
+ exitCode: 2,
2405
+ });
2406
+ }
1943
2407
  return {
1944
2408
  help: Boolean(values.help),
1945
2409
  json: Boolean(values.json),
@@ -1951,6 +2415,12 @@ function parseDatasetImportLcaConvertFlags(args) {
1951
2415
  mappingDir: typeof values['mapping-dir'] === 'string' ? values['mapping-dir'] : undefined,
1952
2416
  language: typeof values.language === 'string' ? values.language : undefined,
1953
2417
  validationJobs,
2418
+ processBundles: values['no-process-bundles']
2419
+ ? false
2420
+ : values['process-bundles']
2421
+ ? true
2422
+ : undefined,
2423
+ processBundlesDir: typeof values['process-bundles-dir'] === 'string' ? values['process-bundles-dir'] : undefined,
1954
2424
  detectOnly: Boolean(values['detect-only']),
1955
2425
  failOnWarning: Boolean(values['fail-on-warning']),
1956
2426
  pythonBin: typeof values.python === 'string' ? values.python : undefined,
@@ -2004,6 +2474,44 @@ function parseDatasetAuthorFlags(args) {
2004
2474
  timeoutMs,
2005
2475
  };
2006
2476
  }
2477
+ function parseDatasetPatchApplyFlags(args) {
2478
+ let values;
2479
+ try {
2480
+ ({ values } = parseArgs({
2481
+ args,
2482
+ allowPositionals: false,
2483
+ strict: true,
2484
+ options: {
2485
+ help: { type: 'boolean', short: 'h' },
2486
+ json: { type: 'boolean' },
2487
+ input: { type: 'string' },
2488
+ patch: { type: 'string' },
2489
+ out: { type: 'string' },
2490
+ 'out-dir': { type: 'string' },
2491
+ 'authoring-package-dir': { type: 'string' },
2492
+ 'require-authoring-package': { type: 'boolean' },
2493
+ 'require-action-item-closure': { type: 'boolean' },
2494
+ },
2495
+ }));
2496
+ }
2497
+ catch (error) {
2498
+ throw new CliError(String(error), {
2499
+ code: 'INVALID_ARGS',
2500
+ exitCode: 2,
2501
+ });
2502
+ }
2503
+ return {
2504
+ help: Boolean(values.help),
2505
+ json: Boolean(values.json),
2506
+ inputPath: typeof values.input === 'string' ? values.input : '',
2507
+ patchPath: typeof values.patch === 'string' ? values.patch : '',
2508
+ outPath: typeof values.out === 'string' ? values.out : '',
2509
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2510
+ authoringPackageDir: typeof values['authoring-package-dir'] === 'string' ? values['authoring-package-dir'] : null,
2511
+ requireAuthoringPackage: Boolean(values['require-authoring-package']),
2512
+ requireActionItemClosure: Boolean(values['require-action-item-closure']),
2513
+ };
2514
+ }
2007
2515
  function parseDatasetRemoteVerifyFlags(args) {
2008
2516
  let values;
2009
2517
  try {
@@ -2017,6 +2525,9 @@ function parseDatasetRemoteVerifyFlags(args) {
2017
2525
  input: { type: 'string' },
2018
2526
  'out-dir': { type: 'string' },
2019
2527
  'root-policy': { type: 'string' },
2528
+ 'compare-root-payload': { type: 'boolean' },
2529
+ 'target-user-id': { type: 'string' },
2530
+ 'state-code': { type: 'string' },
2020
2531
  },
2021
2532
  }));
2022
2533
  }
@@ -2034,12 +2545,25 @@ function parseDatasetRemoteVerifyFlags(args) {
2034
2545
  });
2035
2546
  }
2036
2547
  const rootPolicy = rawRootPolicy;
2548
+ let stateCode = null;
2549
+ if (typeof values['state-code'] === 'string') {
2550
+ stateCode = Number.parseInt(values['state-code'], 10);
2551
+ if (!Number.isInteger(stateCode) || stateCode < 0) {
2552
+ throw new CliError('--state-code must be a non-negative integer.', {
2553
+ code: 'DATASET_REMOTE_VERIFY_STATE_CODE_INVALID',
2554
+ exitCode: 2,
2555
+ });
2556
+ }
2557
+ }
2037
2558
  return {
2038
2559
  help: Boolean(values.help),
2039
2560
  json: Boolean(values.json),
2040
2561
  inputPath: typeof values.input === 'string' ? values.input : '',
2041
2562
  outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : '',
2042
2563
  rootPolicy,
2564
+ compareRootPayload: Boolean(values['compare-root-payload']),
2565
+ targetUserId: typeof values['target-user-id'] === 'string' ? values['target-user-id'] : null,
2566
+ stateCode,
2043
2567
  };
2044
2568
  }
2045
2569
  function parseDatasetBilingualExtractFlags(args) {
@@ -2284,6 +2808,78 @@ function parseDatasetReferencesRefreshRemoteFlags(args) {
2284
2808
  rootPolicy,
2285
2809
  };
2286
2810
  }
2811
+ function parseDatasetMaintenanceClearAccountFlags(args) {
2812
+ let values;
2813
+ try {
2814
+ ({ values } = parseArgs({
2815
+ args,
2816
+ allowPositionals: false,
2817
+ strict: true,
2818
+ options: {
2819
+ help: { type: 'boolean', short: 'h' },
2820
+ json: { type: 'boolean' },
2821
+ 'out-dir': { type: 'string' },
2822
+ 'state-code': { type: 'string', multiple: true },
2823
+ 'page-size': { type: 'string' },
2824
+ 'timeout-ms': { type: 'string' },
2825
+ commit: { type: 'boolean' },
2826
+ 'dry-run': { type: 'boolean' },
2827
+ confirm: { type: 'string' },
2828
+ },
2829
+ }));
2830
+ }
2831
+ catch (error) {
2832
+ throw new CliError(String(error), {
2833
+ code: 'INVALID_ARGS',
2834
+ exitCode: 2,
2835
+ });
2836
+ }
2837
+ if (values.commit && values['dry-run']) {
2838
+ throw new CliError('Cannot pass both --commit and --dry-run.', {
2839
+ code: 'DATASET_MAINTENANCE_CLEAR_ACCOUNT_MODE_CONFLICT',
2840
+ exitCode: 2,
2841
+ });
2842
+ }
2843
+ const rawStateCodes = Array.isArray(values['state-code'])
2844
+ ? values['state-code'].filter((value) => typeof value === 'string')
2845
+ : [];
2846
+ const stateCodes = rawStateCodes.map((value) => {
2847
+ if (!/^-?\d+$/u.test(value.trim())) {
2848
+ throw new CliError('--state-code must be an integer.', {
2849
+ code: 'DATASET_MAINTENANCE_STATE_CODE_INVALID',
2850
+ exitCode: 2,
2851
+ details: value,
2852
+ });
2853
+ }
2854
+ return Number.parseInt(value.trim(), 10);
2855
+ });
2856
+ const parseOptionalInteger = (value, flagName) => {
2857
+ if (typeof value !== 'string') {
2858
+ return undefined;
2859
+ }
2860
+ if (!/^\d+$/u.test(value.trim())) {
2861
+ throw new CliError(`${flagName} must be a positive integer.`, {
2862
+ code: 'DATASET_MAINTENANCE_INTEGER_INVALID',
2863
+ exitCode: 2,
2864
+ details: {
2865
+ flag: flagName,
2866
+ value,
2867
+ },
2868
+ });
2869
+ }
2870
+ return Number.parseInt(value.trim(), 10);
2871
+ };
2872
+ return {
2873
+ help: Boolean(values.help),
2874
+ json: Boolean(values.json),
2875
+ outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
2876
+ stateCodes: stateCodes.length > 0 ? stateCodes : null,
2877
+ pageSize: parseOptionalInteger(values['page-size'], '--page-size'),
2878
+ timeoutMs: parseOptionalInteger(values['timeout-ms'], '--timeout-ms'),
2879
+ commit: Boolean(values.commit),
2880
+ confirm: typeof values.confirm === 'string' ? values.confirm : null,
2881
+ };
2882
+ }
2287
2883
  function parseIdentityPreflightFlags(args) {
2288
2884
  let values;
2289
2885
  try {
@@ -2299,6 +2895,8 @@ function parseIdentityPreflightFlags(args) {
2299
2895
  'remote-candidates': { type: 'boolean' },
2300
2896
  'remote-query': { type: 'string' },
2301
2897
  'remote-limit': { type: 'string' },
2898
+ 'remote-data-source': { type: 'string' },
2899
+ 'timeout-ms': { type: 'string' },
2302
2900
  'out-dir': { type: 'string' },
2303
2901
  },
2304
2902
  }));
@@ -2323,6 +2921,19 @@ function parseIdentityPreflightFlags(args) {
2323
2921
  }
2324
2922
  return parsed;
2325
2923
  };
2924
+ const parseTimeoutMs = (value) => {
2925
+ if (typeof value !== 'string') {
2926
+ return undefined;
2927
+ }
2928
+ const parsed = Number.parseInt(value, 10);
2929
+ if (!Number.isInteger(parsed) || parsed <= 0) {
2930
+ throw new CliError('Expected --timeout-ms to be a positive integer.', {
2931
+ code: 'INVALID_IDENTITY_PREFLIGHT_TIMEOUT',
2932
+ exitCode: 2,
2933
+ });
2934
+ }
2935
+ return parsed;
2936
+ };
2326
2937
  return {
2327
2938
  help: Boolean(values.help),
2328
2939
  json: Boolean(values.json),
@@ -2331,9 +2942,11 @@ function parseIdentityPreflightFlags(args) {
2331
2942
  candidateInputPaths: Array.isArray(candidateInputValue)
2332
2943
  ? candidateInputValue.filter((entry) => typeof entry === 'string')
2333
2944
  : [],
2334
- remoteCandidateSearch: Boolean(values['remote-candidates']),
2945
+ remoteCandidateSearch: values['remote-candidates'] === true ? true : undefined,
2335
2946
  remoteQuery: typeof values['remote-query'] === 'string' ? values['remote-query'] : null,
2336
2947
  remoteLimit: parseRemoteLimit(values['remote-limit']),
2948
+ remoteDataSource: typeof values['remote-data-source'] === 'string' ? values['remote-data-source'] : null,
2949
+ timeoutMs: parseTimeoutMs(values['timeout-ms']),
2337
2950
  };
2338
2951
  }
2339
2952
  function parseBuildPlanFlags(args) {
@@ -3177,6 +3790,7 @@ function parseQaLifecyclemodelFlags(args) {
3177
3790
  options: {
3178
3791
  help: { type: 'boolean', short: 'h' },
3179
3792
  json: { type: 'boolean' },
3793
+ 'rows-file': { type: 'string' },
3180
3794
  'run-dir': { type: 'string' },
3181
3795
  'out-dir': { type: 'string' },
3182
3796
  'start-ts': { type: 'string' },
@@ -3194,6 +3808,7 @@ function parseQaLifecyclemodelFlags(args) {
3194
3808
  return {
3195
3809
  help: Boolean(values.help),
3196
3810
  json: Boolean(values.json),
3811
+ rowsFile: typeof values['rows-file'] === 'string' ? values['rows-file'] : undefined,
3197
3812
  runDir: typeof values['run-dir'] === 'string' ? values['run-dir'] : '',
3198
3813
  outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : '',
3199
3814
  startTs: typeof values['start-ts'] === 'string' ? values['start-ts'] : undefined,
@@ -3745,6 +4360,7 @@ function parseProcessSaveDraftFlags(args) {
3745
4360
  'out-dir': { type: 'string' },
3746
4361
  commit: { type: 'boolean' },
3747
4362
  'dry-run': { type: 'boolean' },
4363
+ 'target-user-id': { type: 'string' },
3748
4364
  },
3749
4365
  }));
3750
4366
  }
@@ -3766,6 +4382,7 @@ function parseProcessSaveDraftFlags(args) {
3766
4382
  inputPath: typeof values.input === 'string' ? values.input : '',
3767
4383
  outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : null,
3768
4384
  commit: Boolean(values.commit),
4385
+ targetUserId: typeof values['target-user-id'] === 'string' ? values['target-user-id'] : null,
3769
4386
  };
3770
4387
  }
3771
4388
  function parseProcessRequiredFieldsFlags(args) {
@@ -3989,6 +4606,8 @@ export async function executeCli(argv, deps) {
3989
4606
  const flowBuildPlanMaterializeImpl = deps.runFlowBuildPlanMaterializeImpl ?? runFlowBuildPlanMaterialize;
3990
4607
  const datasetValidateImpl = deps.runDatasetValidateImpl ?? runDatasetValidate;
3991
4608
  const datasetCurationQueueBuildImpl = deps.runDatasetCurationQueueBuildImpl ?? runDatasetCurationQueueBuild;
4609
+ const datasetCurationQueueNextImpl = deps.runDatasetCurationQueueNextImpl ?? runDatasetCurationQueueNext;
4610
+ const datasetCurationQueueVerifyImpl = deps.runDatasetCurationQueueVerifyImpl ?? runDatasetCurationQueueVerify;
3992
4611
  const datasetReferencesRewriteImpl = deps.runDatasetReferencesRewriteImpl ?? runDatasetReferencesRewrite;
3993
4612
  const datasetRemoteRefreshImpl = deps.runDatasetRemoteRefreshImpl ?? runDatasetRemoteRefresh;
3994
4613
  const datasetRemoteVerifyImpl = deps.runDatasetRemoteVerifyImpl ?? runDatasetRemoteVerify;
@@ -3999,6 +4618,13 @@ export async function executeCli(argv, deps) {
3999
4618
  const datasetContractImpl = deps.runDatasetContractImpl ?? runDatasetContract;
4000
4619
  const datasetImportLcaConvertImpl = deps.runDatasetImportLcaConvertImpl ?? runDatasetImportLcaConvert;
4001
4620
  const datasetAuthorImpl = deps.runDatasetAuthorImpl ?? runDatasetAuthor;
4621
+ const datasetPatchApplyImpl = deps.runDatasetPatchApplyImpl ?? runDatasetPatchApply;
4622
+ const datasetSaveDraftImpl = deps.runDatasetSaveDraftImpl ?? runDatasetSaveDraft;
4623
+ const datasetClassificationChildrenImpl = deps.runDatasetClassificationChildrenImpl ?? runDatasetClassificationChildren;
4624
+ const datasetClassificationPathImpl = deps.runDatasetClassificationPathImpl ?? runDatasetClassificationPath;
4625
+ const datasetClassificationAuditImpl = deps.runDatasetClassificationAuditImpl ?? runDatasetClassificationAudit;
4626
+ const datasetClassificationApplyImpl = deps.runDatasetClassificationApplyImpl ?? runDatasetClassificationApply;
4627
+ const datasetMaintenanceClearAccountImpl = deps.runDatasetMaintenanceClearAccountImpl ?? runDatasetMaintenanceClearAccount;
4002
4628
  if (flags.version) {
4003
4629
  return { exitCode: 0, stdout: `${loadCliPackageVersion(import.meta.url)}\n`, stderr: '' };
4004
4630
  }
@@ -4090,17 +4716,127 @@ export async function executeCli(argv, deps) {
4090
4716
  stderr: '',
4091
4717
  };
4092
4718
  }
4719
+ if (command === 'dataset' && subcommand === 'classification') {
4720
+ const action = commandArgs[0] ?? '';
4721
+ if (!action || action === '--help' || action === '-h') {
4722
+ return { exitCode: 0, stdout: `${renderDatasetClassificationHelp()}\n`, stderr: '' };
4723
+ }
4724
+ if (action === 'children') {
4725
+ const datasetFlags = parseDatasetClassificationChildrenFlags(commandArgs.slice(1));
4726
+ if (datasetFlags.help) {
4727
+ return { exitCode: 0, stdout: `${renderDatasetClassificationHelp()}\n`, stderr: '' };
4728
+ }
4729
+ const report = await datasetClassificationChildrenImpl({
4730
+ type: datasetFlags.type,
4731
+ parent: datasetFlags.parent,
4732
+ query: datasetFlags.query,
4733
+ limit: datasetFlags.limit,
4734
+ outDir: datasetFlags.outDir,
4735
+ });
4736
+ return {
4737
+ exitCode: report.status === 'blocked' ? 1 : 0,
4738
+ stdout: stringifyJson(report, datasetFlags.json),
4739
+ stderr: '',
4740
+ };
4741
+ }
4742
+ if (action === 'path') {
4743
+ const datasetFlags = parseDatasetClassificationPathFlags(commandArgs.slice(1));
4744
+ if (datasetFlags.help) {
4745
+ return { exitCode: 0, stdout: `${renderDatasetClassificationHelp()}\n`, stderr: '' };
4746
+ }
4747
+ const report = await datasetClassificationPathImpl({
4748
+ type: datasetFlags.type,
4749
+ code: datasetFlags.code,
4750
+ outDir: datasetFlags.outDir,
4751
+ });
4752
+ return {
4753
+ exitCode: report.status === 'blocked' ? 1 : 0,
4754
+ stdout: stringifyJson(report, datasetFlags.json),
4755
+ stderr: '',
4756
+ };
4757
+ }
4758
+ if (action === 'audit') {
4759
+ const datasetFlags = parseDatasetClassificationAuditFlags(commandArgs.slice(1));
4760
+ if (datasetFlags.help) {
4761
+ return { exitCode: 0, stdout: `${renderDatasetClassificationHelp()}\n`, stderr: '' };
4762
+ }
4763
+ const report = await datasetClassificationAuditImpl({
4764
+ inputPath: datasetFlags.inputPath,
4765
+ type: datasetFlags.type,
4766
+ outDir: datasetFlags.outDir,
4767
+ });
4768
+ return {
4769
+ exitCode: report.status === 'blocked' ? 1 : 0,
4770
+ stdout: stringifyJson(report, datasetFlags.json),
4771
+ stderr: '',
4772
+ };
4773
+ }
4774
+ if (action === 'apply') {
4775
+ const datasetFlags = parseDatasetClassificationApplyFlags(commandArgs.slice(1));
4776
+ if (datasetFlags.help) {
4777
+ return { exitCode: 0, stdout: `${renderDatasetClassificationHelp()}\n`, stderr: '' };
4778
+ }
4779
+ const report = await datasetClassificationApplyImpl({
4780
+ inputPath: datasetFlags.inputPath,
4781
+ decisionsPath: datasetFlags.decisionsPath,
4782
+ outPath: datasetFlags.outPath,
4783
+ type: datasetFlags.type,
4784
+ outDir: datasetFlags.outDir,
4785
+ });
4786
+ return {
4787
+ exitCode: report.status === 'blocked' ? 1 : 0,
4788
+ stdout: stringifyJson(report, datasetFlags.json),
4789
+ stderr: '',
4790
+ };
4791
+ }
4792
+ throw new CliError("dataset classification action must be 'children', 'path', 'audit', or 'apply'.", {
4793
+ code: 'DATASET_CLASSIFICATION_ACTION_INVALID',
4794
+ exitCode: 2,
4795
+ });
4796
+ }
4093
4797
  if (command === 'dataset' && subcommand === 'curation-queue') {
4094
4798
  const action = commandArgs[0] ?? '';
4095
4799
  if (!action || action === '--help' || action === '-h') {
4096
4800
  return { exitCode: 0, stdout: `${renderDatasetCurationQueueHelp()}\n`, stderr: '' };
4097
4801
  }
4098
- if (action !== 'build') {
4099
- throw new CliError("dataset curation-queue action must be 'build'.", {
4802
+ if (action !== 'build' && action !== 'next' && action !== 'verify') {
4803
+ throw new CliError("dataset curation-queue action must be 'build', 'next', or 'verify'.", {
4100
4804
  code: 'DATASET_CURATION_QUEUE_ACTION_INVALID',
4101
4805
  exitCode: 2,
4102
4806
  });
4103
4807
  }
4808
+ if (action === 'next') {
4809
+ const datasetFlags = parseDatasetCurationQueueRuntimeFlags(commandArgs.slice(1));
4810
+ if (datasetFlags.help) {
4811
+ return { exitCode: 0, stdout: `${renderDatasetCurationQueueHelp()}\n`, stderr: '' };
4812
+ }
4813
+ const report = await datasetCurationQueueNextImpl({
4814
+ queueDir: datasetFlags.queueDir,
4815
+ entityType: datasetFlags.entityType,
4816
+ taskId: datasetFlags.taskId,
4817
+ });
4818
+ return {
4819
+ exitCode: report.status === 'blocked' ? 1 : 0,
4820
+ stdout: stringifyJson(report, datasetFlags.json),
4821
+ stderr: '',
4822
+ };
4823
+ }
4824
+ if (action === 'verify') {
4825
+ const datasetFlags = parseDatasetCurationQueueRuntimeFlags(commandArgs.slice(1));
4826
+ if (datasetFlags.help) {
4827
+ return { exitCode: 0, stdout: `${renderDatasetCurationQueueHelp()}\n`, stderr: '' };
4828
+ }
4829
+ const report = await datasetCurationQueueVerifyImpl({
4830
+ queueDir: datasetFlags.queueDir,
4831
+ entityType: datasetFlags.entityType,
4832
+ taskId: datasetFlags.taskId,
4833
+ });
4834
+ return {
4835
+ exitCode: report.status === 'blocked' ? 1 : 0,
4836
+ stdout: stringifyJson(report, datasetFlags.json),
4837
+ stderr: '',
4838
+ };
4839
+ }
4104
4840
  const datasetFlags = parseDatasetCurationQueueBuildFlags(commandArgs.slice(1));
4105
4841
  if (datasetFlags.help) {
4106
4842
  return { exitCode: 0, stdout: `${renderDatasetCurationQueueHelp()}\n`, stderr: '' };
@@ -4144,6 +4880,8 @@ export async function executeCli(argv, deps) {
4144
4880
  mappingDir: datasetFlags.mappingDir,
4145
4881
  language: datasetFlags.language,
4146
4882
  validationJobs: datasetFlags.validationJobs,
4883
+ processBundles: datasetFlags.processBundles,
4884
+ processBundlesDir: datasetFlags.processBundlesDir,
4147
4885
  detectOnly: datasetFlags.detectOnly,
4148
4886
  failOnWarning: datasetFlags.failOnWarning,
4149
4887
  pythonBin: datasetFlags.pythonBin,
@@ -4178,6 +4916,55 @@ export async function executeCli(argv, deps) {
4178
4916
  stderr: '',
4179
4917
  };
4180
4918
  }
4919
+ if (command === 'dataset' && subcommand === 'patch') {
4920
+ const action = commandArgs[0] ?? '';
4921
+ if (!action || action === '--help' || action === '-h') {
4922
+ return { exitCode: 0, stdout: `${renderDatasetPatchHelp()}\n`, stderr: '' };
4923
+ }
4924
+ if (action !== 'apply') {
4925
+ throw new CliError("dataset patch action must be 'apply'.", {
4926
+ code: 'DATASET_PATCH_ACTION_INVALID',
4927
+ exitCode: 2,
4928
+ });
4929
+ }
4930
+ const datasetFlags = parseDatasetPatchApplyFlags(commandArgs.slice(1));
4931
+ if (datasetFlags.help) {
4932
+ return { exitCode: 0, stdout: `${renderDatasetPatchHelp()}\n`, stderr: '' };
4933
+ }
4934
+ const report = await datasetPatchApplyImpl({
4935
+ inputPath: datasetFlags.inputPath,
4936
+ patchPath: datasetFlags.patchPath,
4937
+ outPath: datasetFlags.outPath,
4938
+ outDir: datasetFlags.outDir,
4939
+ authoringPackageDir: datasetFlags.authoringPackageDir,
4940
+ requireAuthoringPackage: datasetFlags.requireAuthoringPackage,
4941
+ requireActionItemClosure: datasetFlags.requireActionItemClosure,
4942
+ });
4943
+ return {
4944
+ exitCode: report.status === 'blocked' ? 1 : 0,
4945
+ stdout: stringifyJson(report, datasetFlags.json),
4946
+ stderr: '',
4947
+ };
4948
+ }
4949
+ if (command === 'dataset' && subcommand === 'save-draft') {
4950
+ const datasetFlags = parseDatasetSaveDraftFlags(commandArgs);
4951
+ if (datasetFlags.help) {
4952
+ return { exitCode: 0, stdout: `${renderDatasetSaveDraftHelp()}\n`, stderr: '' };
4953
+ }
4954
+ const report = await datasetSaveDraftImpl({
4955
+ inputPath: datasetFlags.inputPath,
4956
+ type: datasetFlags.type,
4957
+ outDir: datasetFlags.outDir,
4958
+ commit: datasetFlags.commit,
4959
+ env: deps.env,
4960
+ fetchImpl: deps.fetchImpl,
4961
+ });
4962
+ return {
4963
+ exitCode: report.status === 'completed_with_failures' ? 1 : 0,
4964
+ stdout: stringifyJson(report, datasetFlags.json),
4965
+ stderr: '',
4966
+ };
4967
+ }
4181
4968
  if (command === 'dataset' && subcommand === 'validate') {
4182
4969
  const datasetFlags = parseDatasetValidateFlags(commandArgs);
4183
4970
  if (datasetFlags.help) {
@@ -4203,6 +4990,9 @@ export async function executeCli(argv, deps) {
4203
4990
  inputPath: datasetFlags.inputPath,
4204
4991
  outDir: datasetFlags.outDir,
4205
4992
  rootPolicy: datasetFlags.rootPolicy,
4993
+ compareRootPayload: datasetFlags.compareRootPayload,
4994
+ targetUserId: datasetFlags.targetUserId,
4995
+ stateCode: datasetFlags.stateCode,
4206
4996
  env: deps.env,
4207
4997
  fetchImpl: deps.fetchImpl,
4208
4998
  });
@@ -4360,6 +5150,44 @@ export async function executeCli(argv, deps) {
4360
5150
  stderr: '',
4361
5151
  };
4362
5152
  }
5153
+ if (command === 'dataset' && subcommand === 'maintenance') {
5154
+ const action = commandArgs[0] ?? '';
5155
+ if (!action || action === '--help' || action === '-h') {
5156
+ return { exitCode: 0, stdout: `${renderDatasetMaintenanceHelp()}\n`, stderr: '' };
5157
+ }
5158
+ if (action === 'clear-account') {
5159
+ const datasetFlags = parseDatasetMaintenanceClearAccountFlags(commandArgs.slice(1));
5160
+ if (datasetFlags.help) {
5161
+ return {
5162
+ exitCode: 0,
5163
+ stdout: `${renderDatasetMaintenanceClearAccountHelp()}\n`,
5164
+ stderr: '',
5165
+ };
5166
+ }
5167
+ const report = await datasetMaintenanceClearAccountImpl({
5168
+ outDir: datasetFlags.outDir,
5169
+ stateCodes: datasetFlags.stateCodes,
5170
+ pageSize: datasetFlags.pageSize,
5171
+ timeoutMs: datasetFlags.timeoutMs,
5172
+ commit: datasetFlags.commit,
5173
+ confirm: datasetFlags.confirm,
5174
+ env: deps.env,
5175
+ fetchImpl: deps.fetchImpl,
5176
+ });
5177
+ return {
5178
+ exitCode: report.status === 'completed_with_failures' ? 1 : 0,
5179
+ stdout: stringifyJson(report, datasetFlags.json),
5180
+ stderr: '',
5181
+ };
5182
+ }
5183
+ if (!['plan', 'apply', 'verify'].includes(action)) {
5184
+ throw new CliError("dataset maintenance action must be 'clear-account', 'plan', 'apply', or 'verify'.", {
5185
+ code: 'DATASET_MAINTENANCE_ACTION_INVALID',
5186
+ exitCode: 2,
5187
+ });
5188
+ }
5189
+ return plannedCommand('dataset', `maintenance ${action}`);
5190
+ }
4363
5191
  if (command === 'lifecyclemodel' && !subcommand) {
4364
5192
  return { exitCode: 0, stdout: `${renderLifecyclemodelHelp()}\n`, stderr: '' };
4365
5193
  }
@@ -4609,6 +5437,8 @@ export async function executeCli(argv, deps) {
4609
5437
  remoteCandidateSearch: processFlags.remoteCandidateSearch,
4610
5438
  remoteQuery: processFlags.remoteQuery,
4611
5439
  remoteLimit: processFlags.remoteLimit,
5440
+ remoteDataSource: processFlags.remoteDataSource,
5441
+ timeoutMs: processFlags.timeoutMs,
4612
5442
  env: deps.env,
4613
5443
  fetchImpl: deps.fetchImpl,
4614
5444
  });
@@ -4796,6 +5626,7 @@ export async function executeCli(argv, deps) {
4796
5626
  inputPath: processFlags.inputPath,
4797
5627
  outDir: processFlags.outDir,
4798
5628
  commit: processFlags.commit,
5629
+ targetUserId: processFlags.targetUserId,
4799
5630
  env: deps.env,
4800
5631
  fetchImpl: deps.fetchImpl,
4801
5632
  });
@@ -4927,6 +5758,8 @@ export async function executeCli(argv, deps) {
4927
5758
  remoteCandidateSearch: flowFlags.remoteCandidateSearch,
4928
5759
  remoteQuery: flowFlags.remoteQuery,
4929
5760
  remoteLimit: flowFlags.remoteLimit,
5761
+ remoteDataSource: flowFlags.remoteDataSource,
5762
+ timeoutMs: flowFlags.timeoutMs,
4930
5763
  env: deps.env,
4931
5764
  fetchImpl: deps.fetchImpl,
4932
5765
  });
@@ -5324,6 +6157,7 @@ export async function executeCli(argv, deps) {
5324
6157
  return { exitCode: 0, stdout: `${renderQaLifecyclemodelHelp()}\n`, stderr: '' };
5325
6158
  }
5326
6159
  const report = await lifecyclemodelQaImpl({
6160
+ ...(qaFlags.rowsFile ? { rowsFile: qaFlags.rowsFile } : {}),
5327
6161
  runDir: qaFlags.runDir,
5328
6162
  outDir: qaFlags.outDir,
5329
6163
  startTs: qaFlags.startTs,