@dailephd/my-dev-kit-lab 0.4.4 → 0.4.6

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 (225) hide show
  1. package/CHANGELOG.md +484 -0
  2. package/README.md +39 -3
  3. package/dist/scripts/cli.js +9 -0
  4. package/dist/src/audits/core/typescriptJavaScriptAnalyzer.js +30 -12
  5. package/dist/src/cli/help.js +300 -0
  6. package/dist/src/cli/index.js +2 -0
  7. package/dist/src/cli/runLabCli.js +229 -0
  8. package/dist/src/commands/runAuditCommand.js +132 -0
  9. package/dist/src/commands/runControlledExperimentCommand.js +7 -3
  10. package/dist/{scripts/experiments/describeExperiment.js → src/commands/runExperimentDescribeCommand.js} +14 -10
  11. package/dist/{scripts/experiments/listExperiments.js → src/commands/runExperimentListCommand.js} +3 -6
  12. package/dist/{scripts/experiments/runExperiment.js → src/commands/runExperimentRunCommand.js} +80 -22
  13. package/dist/src/commands/runFinalDemoCommand.js +2 -3
  14. package/dist/src/commands/runSecurityValidationCommand.js +271 -0
  15. package/dist/src/evaluation/ecosystemFixtures/index.js +3 -0
  16. package/dist/src/evaluation/ecosystemFixtures/loadContextIntegrityFixture.js +102 -0
  17. package/dist/src/evaluation/ecosystemFixtures/manifestTypes.js +1 -0
  18. package/dist/src/evaluation/ecosystemFixtures/validateManifest.js +82 -0
  19. package/dist/src/evaluation/ecosystemFixtures/verifyFixtureHashes.js +45 -0
  20. package/dist/src/evaluation/stageContextMetrics/calculateAllocationMetrics.js +169 -0
  21. package/dist/src/evaluation/stageContextMetrics/calculateConditionCoverageMetrics.js +74 -0
  22. package/dist/src/evaluation/stageContextMetrics/calculateProducerConditionAgreement.js +113 -0
  23. package/dist/src/evaluation/stageContextMetrics/calculateReadinessAgreement.js +60 -0
  24. package/dist/src/evaluation/stageContextMetrics/calculateRunIntegrityAgreement.js +309 -0
  25. package/dist/src/evaluation/stageContextMetrics/calculateSupplementalRawAgreement.js +12 -2
  26. package/dist/src/evaluation/stageContextMetrics/calculateTruncationClassification.js +100 -0
  27. package/dist/src/evaluation/stageContextMetrics/evaluateProducerReadinessBridge.js +76 -5
  28. package/dist/src/evaluation/stageContextMetrics/index.js +4 -0
  29. package/dist/src/evaluation/stageContextMetrics/runIntegrityAgreementTypes.js +1 -0
  30. package/dist/src/evaluation/stageContextSelectors/contextArtifactConsistency.js +7 -0
  31. package/dist/src/evaluation/stageContextSelectors/index.js +1 -0
  32. package/dist/src/evaluation/stageContextSelectors/orchestratorRunIntegritySelectors.js +64 -0
  33. package/dist/src/evaluation/upstreamArtifacts/index.js +2 -0
  34. package/dist/src/evaluation/upstreamArtifacts/orchestratorRunIntegrityV1.js +33 -0
  35. package/dist/src/evaluation/upstreamArtifacts/readOrchestratorRunIntegrityV1.js +9 -0
  36. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitContextCapsuleV1.js +59 -2
  37. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitRetrievalAuditRecordV1.js +6 -1
  38. package/dist/src/evaluation/upstreamArtifacts/validateOrchestratorRunIntegrityV1.js +177 -0
  39. package/dist/src/report/experiments/buildContextIntegrityReport.js +204 -0
  40. package/dist/src/report/experiments/contextIntegrityReportModel.js +1 -0
  41. package/dist/src/report/experiments/index.js +5 -0
  42. package/dist/src/report/experiments/renderContextIntegrityHtml.js +98 -0
  43. package/dist/src/report/experiments/renderContextIntegrityJsonReport.js +3 -0
  44. package/dist/src/report/experiments/renderContextIntegrityText.js +111 -0
  45. package/dist/src/runtime/index.js +3 -0
  46. package/dist/src/runtime/labExecutionContext.js +22 -0
  47. package/dist/src/runtime/packageResource.js +22 -0
  48. package/dist/src/runtime/packageRoot.js +37 -0
  49. package/dist/src/securityValidation/packageChecks/requiredPackageContents.js +46 -0
  50. package/dist/src/securityValidation/packageChecks/runPackageChecks.js +11 -5
  51. package/docs/METRICS.md +83 -0
  52. package/package.json +10 -8
  53. package/dist/scripts/audits/runAudit.js +0 -135
  54. package/dist/scripts/build-gallery.js +0 -3
  55. package/dist/scripts/capture-demo-report.js +0 -3
  56. package/dist/scripts/evaluate-token-savings.js +0 -2
  57. package/dist/scripts/generate-experiment-plots.js +0 -3
  58. package/dist/scripts/generate-prompt-variants.js +0 -2
  59. package/dist/scripts/render-experiment-report.js +0 -2
  60. package/dist/scripts/run-agent-prompt.js +0 -2
  61. package/dist/scripts/run-controlled-experiment.js +0 -2
  62. package/dist/scripts/run-lab-demo.js +0 -5
  63. package/dist/scripts/run-visualization-demos.js +0 -3
  64. package/dist/scripts/security/resolveToolRoot.js +0 -16
  65. package/dist/scripts/security/runCodeql.js +0 -58
  66. package/dist/scripts/security/runDependencyChecks.js +0 -58
  67. package/dist/scripts/security/runFuzzSmoke.js +0 -29
  68. package/dist/scripts/security/runPackageChecks.js +0 -57
  69. package/dist/scripts/security/runSemgrep.js +0 -64
  70. package/dist/scripts/security/validate.js +0 -266
  71. package/dist/scripts/verify-benchmarks.js +0 -202
  72. package/examples/demo-report-input.json +0 -78
  73. package/examples/lab-demo-cases.json +0 -35
  74. package/examples/real-agent-campaign-cases.json +0 -118
  75. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/debug/res/xml/ambiguous_backup_rules.xml +0 -4
  76. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/ambiguous_backup_rules.xml +0 -4
  77. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/backup_rules.xml +0 -5
  78. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/broad_backup_rules.xml +0 -4
  79. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/data_extraction_rules.xml +0 -10
  80. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-a/src/main/res/xml/unsupported_domain_rules.xml +0 -4
  81. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-b/src/main/res/xml/malformed_backup_rules.xml +0 -4
  82. package/tests/fixtures/android/advanced-security-fixtures/backup-configuration/module-b/src/main/res/xml/unsupported_root.xml +0 -4
  83. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/debug/res/xml/ambiguous_config.xml +0 -4
  84. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/ambiguous_config.xml +0 -4
  85. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/base_cleartext_false.xml +0 -8
  86. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/broad_and_duplicate_domains.xml +0 -8
  87. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/empty_domain.xml +0 -6
  88. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/malformed_pin.xml +0 -11
  89. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-a/src/main/res/xml/network_security_config.xml +0 -26
  90. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-b/src/main/res/xml/malformed_network_security_config.xml +0 -6
  91. package/tests/fixtures/android/advanced-security-fixtures/network-security/module-b/src/main/res/xml/unsupported_root.xml +0 -4
  92. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/groovy-release-debuggable-dynamic.gradle +0 -7
  93. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/groovy-release-debuggable-false.gradle +0 -9
  94. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/groovy-release-debuggable-true.gradle +0 -13
  95. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/kotlin-release-debuggable-false.gradle.kts +0 -7
  96. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/kotlin-release-debuggable-true.gradle.kts +0 -10
  97. package/tests/fixtures/android/advanced-security-fixtures/release-configuration/missing-release-build-type.gradle.kts +0 -7
  98. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-a/src/debug/res/xml/network_security_config.xml +0 -8
  99. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-a/src/main/res/xml/backup_rules.xml +0 -4
  100. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-a/src/main/res/xml/network_security_config.xml +0 -8
  101. package/tests/fixtures/android/advanced-security-fixtures/resource-resolution/module-b/src/main/res/xml/malformed_network_security_config.xml +0 -7
  102. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/SampleActivity.java +0 -8
  103. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/SampleActivity.kt +0 -9
  104. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/build.gradle +0 -11
  105. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/build.gradle.kts +0 -11
  106. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/google-services.json +0 -16
  107. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates/local.properties +0 -3
  108. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates-bounds/module/binary.properties +0 -0
  109. package/tests/fixtures/android/advanced-security-fixtures/secret-candidates-bounds/module/oversized.json +0 -1
  110. package/tests/fixtures/android/advanced-security-fixtures/signing-configuration/app/fake-release-keystore.jks +0 -1
  111. package/tests/fixtures/android/advanced-security-fixtures/signing-configuration/build/generated-fake.keystore +0 -1
  112. package/tests/fixtures/android/compose-app/app/build.gradle.kts +0 -21
  113. package/tests/fixtures/android/compose-app/app/src/main/AndroidManifest.xml +0 -22
  114. package/tests/fixtures/android/compose-app/app/src/main/java/com/example/composeapp/MainActivity.kt +0 -11
  115. package/tests/fixtures/android/compose-app/build.gradle.kts +0 -4
  116. package/tests/fixtures/android/compose-app/gradle/wrapper/gradle-wrapper.properties +0 -4
  117. package/tests/fixtures/android/compose-app/settings.gradle.kts +0 -2
  118. package/tests/fixtures/android/gradle-metadata-fixtures/catalog-only-plugin/build.gradle.kts +0 -3
  119. package/tests/fixtures/android/gradle-metadata-fixtures/catalog-only-plugin/gradle/libs.versions.toml +0 -5
  120. package/tests/fixtures/android/gradle-metadata-fixtures/comment-safety.gradle.kts +0 -21
  121. package/tests/fixtures/android/gradle-metadata-fixtures/dynamic-values.gradle.kts +0 -17
  122. package/tests/fixtures/android/gradle-metadata-fixtures/groovy-literal.gradle +0 -23
  123. package/tests/fixtures/android/gradle-metadata-fixtures/wrapper-malformed.properties +0 -4
  124. package/tests/fixtures/android/gradle-metadata-fixtures/wrapper-missing-url.properties +0 -3
  125. package/tests/fixtures/android/gradle-metadata-fixtures/wrapper-with-checksum.properties +0 -5
  126. package/tests/fixtures/android/java-app/app/build.gradle +0 -16
  127. package/tests/fixtures/android/java-app/app/src/main/AndroidManifest.xml +0 -19
  128. package/tests/fixtures/android/java-app/app/src/main/java/com/example/javaapp/MainActivity.java +0 -4
  129. package/tests/fixtures/android/java-app/build.gradle +0 -3
  130. package/tests/fixtures/android/java-app/gradle/wrapper/gradle-wrapper.properties +0 -4
  131. package/tests/fixtures/android/java-app/settings.gradle +0 -2
  132. package/tests/fixtures/android/library/build.gradle.kts +0 -3
  133. package/tests/fixtures/android/library/gradle/wrapper/gradle-wrapper.properties +0 -4
  134. package/tests/fixtures/android/library/mylibrary/build.gradle.kts +0 -13
  135. package/tests/fixtures/android/library/mylibrary/src/main/AndroidManifest.xml +0 -2
  136. package/tests/fixtures/android/library/settings.gradle.kts +0 -2
  137. package/tests/fixtures/android/manifest-audit-fixtures/incomplete-intent-filter.xml +0 -14
  138. package/tests/fixtures/android/manifest-audit-fixtures/malformed-exported.xml +0 -10
  139. package/tests/fixtures/android/manifest-audit-fixtures/malformed.xml +0 -5
  140. package/tests/fixtures/android/manifest-audit-fixtures/missing-application.xml +0 -7
  141. package/tests/fixtures/android/manifest-audit-fixtures/missing-component-name.xml +0 -11
  142. package/tests/fixtures/android/manifest-audit-fixtures/permission-coverage.xml +0 -29
  143. package/tests/fixtures/android/manifest-audit-fixtures/risky-components.xml +0 -62
  144. package/tests/fixtures/android/manifest-audit-fixtures/risky-deep-links.xml +0 -45
  145. package/tests/fixtures/android/manifest-audit-fixtures/unresolved-placeholder.xml +0 -14
  146. package/tests/fixtures/android/manifest-audit-fixtures/unusual-namespace-prefix.xml +0 -11
  147. package/tests/fixtures/android/multi-module/app/build.gradle.kts +0 -22
  148. package/tests/fixtures/android/multi-module/app/src/androidTest/java/com/example/multimodule/app/ExampleInstrumentedTest.kt +0 -3
  149. package/tests/fixtures/android/multi-module/app/src/main/AndroidManifest.xml +0 -11
  150. package/tests/fixtures/android/multi-module/app/src/test/java/com/example/multimodule/app/ExampleUnitTest.kt +0 -3
  151. package/tests/fixtures/android/multi-module/build.gradle.kts +0 -5
  152. package/tests/fixtures/android/multi-module/core/build.gradle.kts +0 -14
  153. package/tests/fixtures/android/multi-module/core/src/main/AndroidManifest.xml +0 -2
  154. package/tests/fixtures/android/multi-module/feature-login/build.gradle.kts +0 -18
  155. package/tests/fixtures/android/multi-module/feature-login/src/main/AndroidManifest.xml +0 -2
  156. package/tests/fixtures/android/multi-module/gradle/libs.versions.toml +0 -8
  157. package/tests/fixtures/android/multi-module/gradle/wrapper/gradle-wrapper.properties +0 -4
  158. package/tests/fixtures/android/multi-module/settings.gradle.kts +0 -4
  159. package/tests/fixtures/android/non-android-gradle/build.gradle.kts +0 -3
  160. package/tests/fixtures/android/non-android-gradle/core/build.gradle.kts +0 -3
  161. package/tests/fixtures/android/non-android-gradle/core/src/main/java/com/example/core/Core.java +0 -4
  162. package/tests/fixtures/android/non-android-gradle/gradle/wrapper/gradle-wrapper.properties +0 -4
  163. package/tests/fixtures/android/non-android-gradle/settings.gradle.kts +0 -2
  164. package/tests/fixtures/android/partial/app/build.gradle.kts +0 -7
  165. package/tests/fixtures/android/partial/settings.gradle.kts +0 -2
  166. package/tests/fixtures/android/xml-view-app/app/build.gradle.kts +0 -17
  167. package/tests/fixtures/android/xml-view-app/app/src/main/AndroidManifest.xml +0 -31
  168. package/tests/fixtures/android/xml-view-app/app/src/main/kotlin/com/example/xmlviewapp/MainActivity.kt +0 -7
  169. package/tests/fixtures/android/xml-view-app/app/src/main/res/layout/activity_main.xml +0 -4
  170. package/tests/fixtures/android/xml-view-app/build.gradle.kts +0 -4
  171. package/tests/fixtures/android/xml-view-app/gradle/wrapper/gradle-wrapper.properties +0 -4
  172. package/tests/fixtures/android/xml-view-app/settings.gradle.kts +0 -2
  173. package/tests/fixtures/audits/mixed-language/mixed-docs-claims/README.md +0 -16
  174. package/tests/fixtures/audits/mixed-language/mixed-docs-claims/build.gradle.kts +0 -4
  175. package/tests/fixtures/audits/mixed-language/mixed-docs-claims/src/main/java/com/example/Widget.java +0 -7
  176. package/tests/fixtures/audits/mixed-language/mixed-docs-claims/src/main/kotlin/com/example/Gadget.kt +0 -7
  177. package/tests/fixtures/audits/mixed-language/mixed-generated-vendor/README.md +0 -10
  178. package/tests/fixtures/audits/mixed-language/mixed-generated-vendor/build/Main.class +0 -1
  179. package/tests/fixtures/audits/mixed-language/mixed-generated-vendor/dist/index.js +0 -1
  180. package/tests/fixtures/audits/mixed-language/mixed-generated-vendor/generated/schema.ts +0 -1
  181. package/tests/fixtures/audits/mixed-language/mixed-generated-vendor/src/index.ts +0 -3
  182. package/tests/fixtures/audits/mixed-language/mixed-generated-vendor/vendor/lib.py +0 -2
  183. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/README.md +0 -10
  184. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/build.gradle.kts +0 -8
  185. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/settings.gradle.kts +0 -1
  186. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/src/main/java/com/example/FooService.java +0 -7
  187. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/src/main/kotlin/com/example/BarService.kt +0 -7
  188. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/src/test/java/com/example/FooServiceTest.java +0 -8
  189. package/tests/fixtures/audits/mixed-language/mixed-java-kotlin/src/test/kotlin/com/example/BarServiceTest.kt +0 -8
  190. package/tests/fixtures/audits/mixed-language/mixed-python-ts/README.md +0 -8
  191. package/tests/fixtures/audits/mixed-language/mixed-python-ts/src/app.py +0 -7
  192. package/tests/fixtures/audits/mixed-language/mixed-python-ts/src/index.ts +0 -3
  193. package/tests/fixtures/audits/mixed-language/mixed-python-ts/tests/test_app.py +0 -5
  194. package/tests/fixtures/audits/mixed-language/mixed-ts-js/README.md +0 -7
  195. package/tests/fixtures/audits/mixed-language/mixed-ts-js/src/helper.js +0 -5
  196. package/tests/fixtures/audits/mixed-language/mixed-ts-js/src/index.ts +0 -3
  197. package/tests/fixtures/audits/mixed-language/mixed-ts-js/tests/index.sample.ts +0 -5
  198. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/README.md +0 -10
  199. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/build.gradle.kts +0 -4
  200. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/pytests/test_app.py +0 -5
  201. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/src/app.py +0 -2
  202. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/src/helper.js +0 -5
  203. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/src/index.ts +0 -3
  204. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/src/main/java/com/example/Multiplier.java +0 -7
  205. package/tests/fixtures/audits/mixed-language/mixed-ts-python-jvm/src/main/kotlin/com/example/Divider.kt +0 -7
  206. package/tests/fixtures/fake-adversarial-cli.js +0 -152
  207. package/tests/fixtures/fake-my-dev-kit-cli.js +0 -83
  208. package/tests/fixtures/full-workflow-library/complete-v1.0.0.json +0 -24
  209. package/tests/fixtures/full-workflow-library/future-minor-v1.1.0-additive.json +0 -25
  210. package/tests/fixtures/stage-context-expectations/complete-v1.0.0.json +0 -230
  211. package/tests/fixtures/stage-context-expectations/future-minor-v1.1.0-additive.json +0 -232
  212. package/tests/fixtures/stage-context-expectations/invalid/malformed-json.txt +0 -1
  213. package/tests/fixtures/stage-context-expectations/invalid/non-object-root.json +0 -1
  214. package/tests/fixtures/stage-context-expectations/minimal-v1.0.0.json +0 -18
  215. package/tests/fixtures/upstream-artifacts/invalid/malformed-json.txt +0 -1
  216. package/tests/fixtures/upstream-artifacts/invalid/non-object-root.json +0 -1
  217. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/context-capsule/complete-v1.0.0.json +0 -504
  218. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/context-capsule/future-minor-v1.1.0-additive.json +0 -955
  219. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/retrieval-audit-record/complete-v1.0.0.json +0 -190
  220. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/retrieval-audit-record/future-minor-v1.1.0-additive.json +0 -327
  221. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/PROVENANCE.txt +0 -13
  222. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/context-capsule.json +0 -7874
  223. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/retrieval-audit-record.json +0 -1076
  224. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.1/workflow-instruction-packet/complete-v1.0.0.json +0 -160
  225. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.1/workflow-instruction-packet/future-minor-v1.1.0-additive.json +0 -186
@@ -1,4 +1,3 @@
1
- import ts from "typescript";
2
1
  // ---------------------------------------------------------------------------
3
2
  // v0.3.1 Batch 3 -- TypeScript/JavaScript source analyzer.
4
3
  //
@@ -36,7 +35,25 @@ export const TYPESCRIPT_JAVASCRIPT_ANALYZER = {
36
35
  supportedExtensions: SUPPORTED_EXTENSIONS,
37
36
  analyzeFile,
38
37
  };
39
- function analyzeFile(input) {
38
+ // v0.4.6 Batch 5 -- the `typescript` package is a devDependency, not a
39
+ // runtime dependency: an installed my-dev-kit-lab consumer does not have it.
40
+ // The compiler API is loaded lazily (once, memoized) only when a file is
41
+ // actually analyzed, rather than imported at module scope, so merely
42
+ // loading this module (which happens on every CLI invocation, since the
43
+ // language analyzer registry is wired in unconditionally) never requires
44
+ // `typescript` to be present. Only the *type* import above is needed at the
45
+ // top level -- type-only imports are erased entirely at compile time.
46
+ let cachedTypeScriptModule;
47
+ async function loadTypeScript() {
48
+ if (!cachedTypeScriptModule) {
49
+ const imported = await import("typescript");
50
+ cachedTypeScriptModule =
51
+ imported.default ??
52
+ imported;
53
+ }
54
+ return cachedTypeScriptModule;
55
+ }
56
+ async function analyzeFile(input) {
40
57
  const { relativePath, language, role, content, inventoryEntry } = input;
41
58
  if (Buffer.byteLength(content, "utf8") > MAX_ANALYZABLE_BYTES) {
42
59
  return {
@@ -61,17 +78,18 @@ function analyzeFile(input) {
61
78
  ],
62
79
  };
63
80
  }
64
- const scriptKind = resolveScriptKind(inventoryEntry.extension);
81
+ const ts = await loadTypeScript();
82
+ const scriptKind = resolveScriptKind(ts, inventoryEntry.extension);
65
83
  const sourceFile = ts.createSourceFile(relativePath, content, ts.ScriptTarget.Latest, true, scriptKind);
66
- const diagnostics = getSyntaxDiagnostics(relativePath, sourceFile);
84
+ const diagnostics = getSyntaxDiagnostics(ts, relativePath, sourceFile);
67
85
  const imports = [];
68
86
  const exports = [];
69
87
  const declarations = [];
70
88
  const references = [];
71
89
  const lineOf = (node) => sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
72
90
  function pushDeclaration(node, name, kind) {
73
- const isExported = hasModifier(node, ts.SyntaxKind.ExportKeyword);
74
- const isDefault = hasModifier(node, ts.SyntaxKind.DefaultKeyword);
91
+ const isExported = hasModifier(ts, node, ts.SyntaxKind.ExportKeyword);
92
+ const isDefault = hasModifier(ts, node, ts.SyntaxKind.DefaultKeyword);
75
93
  if (name) {
76
94
  declarations.push({ name, kind, exported: isExported, line: lineOf(node) });
77
95
  }
@@ -141,7 +159,7 @@ function analyzeFile(input) {
141
159
  exports.push({ name, kind: "default", line: lineOf(node) });
142
160
  }
143
161
  function handleVariableStatement(node) {
144
- const isExported = hasModifier(node, ts.SyntaxKind.ExportKeyword);
162
+ const isExported = hasModifier(ts, node, ts.SyntaxKind.ExportKeyword);
145
163
  const isConst = (node.declarationList.flags & ts.NodeFlags.Const) !== 0;
146
164
  for (const decl of node.declarationList.declarations) {
147
165
  // Destructuring patterns (`const { a, b } = x`) are conservatively
@@ -247,7 +265,7 @@ function analyzeFile(input) {
247
265
  diagnostics,
248
266
  };
249
267
  }
250
- function resolveScriptKind(extension) {
268
+ function resolveScriptKind(ts, extension) {
251
269
  switch (extension) {
252
270
  case ".tsx":
253
271
  return ts.ScriptKind.TSX;
@@ -264,7 +282,7 @@ function resolveScriptKind(extension) {
264
282
  return ts.ScriptKind.TS;
265
283
  }
266
284
  }
267
- function hasModifier(node, kind) {
285
+ function hasModifier(ts, node, kind) {
268
286
  if (!ts.canHaveModifiers(node))
269
287
  return false;
270
288
  const modifiers = ts.getModifiers(node);
@@ -280,11 +298,11 @@ function hasModifier(node, kind) {
280
298
  // transpileModule() over this repo's own ~375 TS/JS files, which matters
281
299
  // because collectSourceFacts.ts calls this analyzer once per eligible file
282
300
  // on every audit run (including this repo's own self-audit).
283
- function getSyntaxDiagnostics(relativePath, sourceFile) {
301
+ function getSyntaxDiagnostics(ts, relativePath, sourceFile) {
284
302
  const parseDiagnostics = sourceFile.parseDiagnostics ?? [];
285
- return parseDiagnostics.map((diagnostic) => toSourceFactDiagnostic(relativePath, diagnostic));
303
+ return parseDiagnostics.map((diagnostic) => toSourceFactDiagnostic(ts, relativePath, diagnostic));
286
304
  }
287
- function toSourceFactDiagnostic(relativePath, diagnostic) {
305
+ function toSourceFactDiagnostic(ts, relativePath, diagnostic) {
288
306
  const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
289
307
  const line = diagnostic.file && diagnostic.start !== undefined
290
308
  ? diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1
@@ -0,0 +1,300 @@
1
+ export function renderTopLevelHelp() {
2
+ return [
3
+ "my-dev-kit-lab - benchmark, evidence, and evaluation companion for my-dev-kit.",
4
+ "",
5
+ "Usage:",
6
+ " my-dev-kit-lab --help",
7
+ " my-dev-kit-lab --version",
8
+ " my-dev-kit-lab [--workspace <path>] security validate [options]",
9
+ " my-dev-kit-lab [--workspace <path>] audit [options]",
10
+ " my-dev-kit-lab [--workspace <path>] experiment list",
11
+ " my-dev-kit-lab [--workspace <path>] experiment describe --experiment <id>",
12
+ " my-dev-kit-lab [--workspace <path>] experiment run --experiment <id> [options]",
13
+ " my-dev-kit-lab [--workspace <path>] experiment controlled --cases <path> --out <dir> [options]",
14
+ " my-dev-kit-lab [--workspace <path>] report render --experiment <dir> --out <dir> [options]",
15
+ " my-dev-kit-lab [--workspace <path>] plots generate --experiment <dir> --out <dir>",
16
+ " my-dev-kit-lab [--workspace <path>] gallery build --out <dir> [options]",
17
+ " my-dev-kit-lab demo final --cases <path> --out <dir> --kit-command <command> [options]",
18
+ "",
19
+ "Options:",
20
+ " -h, --help Show this help message",
21
+ " -V, --version Show the installed my-dev-kit-lab package version",
22
+ " --workspace <path> Writable my-dev-kit-lab workspace root (default: <home>/.my-dev-kit-lab).",
23
+ " Must appear before the command when used.",
24
+ "",
25
+ "Commands:",
26
+ " security validate Run security validation",
27
+ " audit Run a project audit",
28
+ " experiment list List registered experiment plugins",
29
+ " experiment describe Describe a registered experiment plugin",
30
+ " experiment run Run a registered experiment plugin",
31
+ " experiment controlled Run a controlled context-strategy-comparison experiment",
32
+ " report render Render an experiment report from controlled-experiment artifacts",
33
+ " plots generate Generate experiment plot artifacts",
34
+ " gallery build Build a gallery manifest/index",
35
+ " demo final Run the full final demo workflow",
36
+ "",
37
+ "Run \"my-dev-kit-lab <command> --help\" (or \"my-dev-kit-lab <family> <command> --help\") for details.",
38
+ "",
39
+ "Note: the historical direct invocation form (flags without \"demo final\", e.g.",
40
+ "\"my-dev-kit-lab --cases <path> --out <dir> --kit-command <command>\") remains",
41
+ "supported for backward compatibility."
42
+ ].join("\n");
43
+ }
44
+ export function renderDemoHelp() {
45
+ return [
46
+ "my-dev-kit-lab demo - demo command family",
47
+ "",
48
+ "Usage:",
49
+ " my-dev-kit-lab demo final [options]",
50
+ " my-dev-kit-lab demo --help",
51
+ "",
52
+ "Commands:",
53
+ " final Run the full final demo. Run \"my-dev-kit-lab demo final --help\" for details."
54
+ ].join("\n");
55
+ }
56
+ export function renderFinalDemoHelp() {
57
+ return [
58
+ "my-dev-kit-lab demo final - run the full final demo workflow",
59
+ "",
60
+ "Usage:",
61
+ " my-dev-kit-lab demo final --cases <path> --out <dir> --kit-command <command> [options]",
62
+ "",
63
+ "Required:",
64
+ " --cases <path> Path to the evaluation cases file",
65
+ " --out <dir> Output directory for demo artifacts",
66
+ " --kit-command <command> Command used to invoke my-dev-kit for the visualization demos",
67
+ "",
68
+ "Options:",
69
+ " --agents <list> Comma-separated agent ids (default: fake-agent)",
70
+ " --strategies <list> Comma-separated strategies: raw-full-file,my-dev-kit-guided (default: both)",
71
+ " --complexities <list> Comma-separated complexity levels: short,medium,long,multi-step (default: short)",
72
+ " --case <ids> Comma-separated case ids to run",
73
+ " --benchmark-project <ids> Comma-separated benchmark project ids to run",
74
+ " --max-runs <n> Maximum number of runs",
75
+ " --screenshot / --no-screenshot Enable/disable report screenshot capture (default: disabled)",
76
+ " --include-real-agents Allow real agent ids (codex, claude)",
77
+ " --continue-on-failure / --no-continue-on-failure Continue after a failed run (default: continue-on-failure)",
78
+ " --timeout-ms <ms> Per-run timeout in milliseconds",
79
+ "",
80
+ "The legacy direct invocation form (the same flags without a leading \"demo final\")",
81
+ "remains supported for backward compatibility."
82
+ ].join("\n");
83
+ }
84
+ export function renderExperimentHelp() {
85
+ return [
86
+ "my-dev-kit-lab experiment - experiment command family",
87
+ "",
88
+ "Usage:",
89
+ " my-dev-kit-lab experiment list",
90
+ " my-dev-kit-lab experiment describe --experiment <id>",
91
+ " my-dev-kit-lab experiment run --experiment <id> [options]",
92
+ " my-dev-kit-lab experiment controlled [options]",
93
+ " my-dev-kit-lab experiment --help",
94
+ "",
95
+ "Commands:",
96
+ " list List registered experiment plugins.",
97
+ " Run \"my-dev-kit-lab experiment list --help\" for details.",
98
+ " describe Describe a registered experiment plugin.",
99
+ " Run \"my-dev-kit-lab experiment describe --help\" for details.",
100
+ " run Run a registered experiment plugin through the generic runner.",
101
+ " Run \"my-dev-kit-lab experiment run --help\" for details.",
102
+ " controlled Run a controlled context-strategy-comparison experiment.",
103
+ " Run \"my-dev-kit-lab experiment controlled --help\" for details."
104
+ ].join("\n");
105
+ }
106
+ export function renderExperimentListHelp() {
107
+ return [
108
+ "my-dev-kit-lab experiment list - list registered experiment plugins",
109
+ "",
110
+ "Usage:",
111
+ " my-dev-kit-lab experiment list [--json]",
112
+ "",
113
+ "Options:",
114
+ " --json Print the experiment list as JSON instead of a human-readable summary"
115
+ ].join("\n");
116
+ }
117
+ export function renderExperimentDescribeHelp() {
118
+ return [
119
+ "my-dev-kit-lab experiment describe - describe a registered experiment plugin",
120
+ "",
121
+ "Usage:",
122
+ " my-dev-kit-lab experiment describe --experiment <id> [--json]",
123
+ "",
124
+ "Required:",
125
+ " --experiment <id> Registered experiment plugin id (see \"my-dev-kit-lab experiment list\")",
126
+ "",
127
+ "Options:",
128
+ " --json Print the description as JSON instead of a human-readable summary"
129
+ ].join("\n");
130
+ }
131
+ export function renderExperimentRunHelp() {
132
+ return [
133
+ "my-dev-kit-lab experiment run - run a registered experiment plugin through the generic runner",
134
+ "",
135
+ "Usage:",
136
+ " my-dev-kit-lab experiment run --experiment <id> [options]",
137
+ "",
138
+ "Required:",
139
+ " --experiment <id> Registered experiment plugin id (see \"my-dev-kit-lab experiment list\")",
140
+ "",
141
+ "Options:",
142
+ " --target <path> Local target project path (default: self)",
143
+ " --out <dir> Output directory for experiment artifacts",
144
+ " (default: beneath the workspace when installed)",
145
+ " --cases <path> Path to the evaluation cases file",
146
+ " (default: the bundled package resource)",
147
+ " --project-profiles <path> Path to the benchmark project profiles file",
148
+ " (default: the bundled package resource)",
149
+ " --case <ids> Comma-separated case ids to run",
150
+ " --benchmark-project <ids> Comma-separated benchmark project ids to run",
151
+ " --agents <list> Comma-separated agent ids (default: fake-agent)",
152
+ " --strategies <list> Comma-separated strategies: raw-full-file,my-dev-kit-guided",
153
+ " --complexities <list> Comma-separated complexity levels: short,medium,long,multi-step",
154
+ " --timeout-ms <ms> Per-run timeout in milliseconds",
155
+ " --max-runs <n> Maximum number of runs",
156
+ " --continue-on-failure / --no-continue-on-failure Continue after a failed run (default: continue-on-failure)",
157
+ " --require-agents Fail if no real agent command templates are configured",
158
+ " --include-real-agents Allow real agent ids (codex, claude)",
159
+ " --command-template-codex <template> Command template used to invoke the codex agent",
160
+ " --command-template-claude <template> Command template used to invoke the claude agent",
161
+ " --no-screenshot Accepted for compatibility; the plugin-aware report",
162
+ " path does not capture screenshots yet"
163
+ ].join("\n");
164
+ }
165
+ export function renderExperimentControlledHelp() {
166
+ return [
167
+ "my-dev-kit-lab experiment controlled - run a controlled context-strategy-comparison experiment",
168
+ "",
169
+ "Usage:",
170
+ " my-dev-kit-lab experiment controlled --cases <path> --out <dir> [options]",
171
+ "",
172
+ "Required:",
173
+ " --cases <path> Path to the evaluation cases file",
174
+ " --out <dir> Output directory for experiment artifacts",
175
+ "",
176
+ "Options:",
177
+ " --project-profiles <path> Path to the benchmark project profiles file",
178
+ " (default: the bundled package resource)",
179
+ " --case <ids> Comma-separated case ids to run",
180
+ " --benchmark-project <ids> Comma-separated benchmark project ids to run",
181
+ " --agents <list> Comma-separated agent ids (default: fake-agent)",
182
+ " --strategies <list> Comma-separated strategies: raw-full-file,my-dev-kit-guided",
183
+ " --complexities <list> Comma-separated complexity levels: short,medium,long,multi-step",
184
+ " --timeout-ms <ms> Per-run timeout in milliseconds",
185
+ " --max-runs <n> Maximum number of runs",
186
+ " --continue-on-failure / --no-continue-on-failure Continue after a failed run (default: continue-on-failure)",
187
+ " --require-agents Fail if no real agent command templates are configured",
188
+ " --include-real-agents Allow real agent ids (codex, claude)",
189
+ " --command-template-codex <template> Command template used to invoke the codex agent",
190
+ " --command-template-claude <template> Command template used to invoke the claude agent"
191
+ ].join("\n");
192
+ }
193
+ export function renderReportHelp() {
194
+ return [
195
+ "my-dev-kit-lab report - report command family",
196
+ "",
197
+ "Usage:",
198
+ " my-dev-kit-lab report render [options]",
199
+ " my-dev-kit-lab report --help",
200
+ "",
201
+ "Commands:",
202
+ " render Render an HTML/JSON experiment report from controlled-experiment artifacts.",
203
+ " Run \"my-dev-kit-lab report render --help\" for details."
204
+ ].join("\n");
205
+ }
206
+ export function renderReportRenderHelp() {
207
+ return [
208
+ "my-dev-kit-lab report render - render an HTML/JSON experiment report from controlled-experiment artifacts",
209
+ "",
210
+ "Usage:",
211
+ " my-dev-kit-lab report render --experiment <dir> --out <dir> [options]",
212
+ "",
213
+ "Required:",
214
+ " --experiment <dir> Path to a controlled-experiment output directory",
215
+ " --out <dir> Output directory for the rendered report",
216
+ "",
217
+ "Options:",
218
+ " --title <title> Report title",
219
+ " --subtitle <subtitle> Report subtitle",
220
+ " --screenshot / --no-screenshot Enable/disable PNG screenshot capture (default: disabled)",
221
+ " --require-screenshot Fail unless a screenshot was captured (implies --screenshot)",
222
+ " --max-prompt-chars <n> Maximum characters of prompt text to include",
223
+ " --max-file-tree-entries <n> Maximum file tree entries to include",
224
+ " --plots <dir> Optional plots directory to include in the report",
225
+ " --visualizations <dir> Optional visualization-demos directory to include in the report"
226
+ ].join("\n");
227
+ }
228
+ export function renderPlotsHelp() {
229
+ return [
230
+ "my-dev-kit-lab plots - plots command family",
231
+ "",
232
+ "Usage:",
233
+ " my-dev-kit-lab plots generate [options]",
234
+ " my-dev-kit-lab plots --help",
235
+ "",
236
+ "Commands:",
237
+ " generate Generate experiment plot artifacts from controlled-experiment artifacts.",
238
+ " Run \"my-dev-kit-lab plots generate --help\" for details."
239
+ ].join("\n");
240
+ }
241
+ export function renderPlotsGenerateHelp() {
242
+ return [
243
+ "my-dev-kit-lab plots generate - generate chart/plot artifacts from controlled-experiment artifacts",
244
+ "",
245
+ "Usage:",
246
+ " my-dev-kit-lab plots generate --experiment <dir> --out <dir>",
247
+ "",
248
+ "Required:",
249
+ " --experiment <dir> Path to a controlled-experiment output directory",
250
+ " --out <dir> Output directory for plot artifacts"
251
+ ].join("\n");
252
+ }
253
+ export function renderGalleryHelp() {
254
+ return [
255
+ "my-dev-kit-lab gallery - gallery command family",
256
+ "",
257
+ "Usage:",
258
+ " my-dev-kit-lab gallery build [options]",
259
+ " my-dev-kit-lab gallery --help",
260
+ "",
261
+ "Commands:",
262
+ " build Build a gallery manifest/index from report, plots, and visualization artifacts.",
263
+ " Run \"my-dev-kit-lab gallery build --help\" for details."
264
+ ].join("\n");
265
+ }
266
+ export function renderGalleryBuildHelp() {
267
+ return [
268
+ "my-dev-kit-lab gallery build - build a gallery manifest/index from existing artifacts",
269
+ "",
270
+ "Usage:",
271
+ " my-dev-kit-lab gallery build --out <dir> [options]",
272
+ "",
273
+ "Required:",
274
+ " --out <dir> Output directory for the gallery manifest and index",
275
+ "",
276
+ "Options:",
277
+ " --report <dir> Path to a rendered report directory",
278
+ " --plots <dir> Path to a plots output directory",
279
+ " --visualizations <dir> Path to a visualization-demos output directory",
280
+ " --experiment <dir> Path to a controlled-experiment output directory"
281
+ ].join("\n");
282
+ }
283
+ export function renderSecurityHelp() {
284
+ return [
285
+ "my-dev-kit-lab security - security command family",
286
+ "",
287
+ "Usage:",
288
+ " my-dev-kit-lab security validate [options]",
289
+ " my-dev-kit-lab security --help",
290
+ "",
291
+ "Commands:",
292
+ " validate Run security validation. Run \"my-dev-kit-lab security validate --help\" for details."
293
+ ].join("\n");
294
+ }
295
+ export function renderUnknownCommandError(command) {
296
+ return [
297
+ `Unknown command: ${command}`,
298
+ "Run \"my-dev-kit-lab --help\" for usage."
299
+ ].join("\n");
300
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./runLabCli.js";
2
+ export * from "./help.js";
@@ -0,0 +1,229 @@
1
+ import { readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { runFinalDemoCommand } from "../commands/runFinalDemoCommand.js";
4
+ import { runAuditCommandFromArgs } from "../commands/runAuditCommand.js";
5
+ import { runSecurityValidationCommandFromArgs } from "../commands/runSecurityValidationCommand.js";
6
+ import { runControlledExperimentCommand } from "../commands/runControlledExperimentCommand.js";
7
+ import { runExperimentListCommandFromArgs } from "../commands/runExperimentListCommand.js";
8
+ import { runExperimentDescribeCommandFromArgs } from "../commands/runExperimentDescribeCommand.js";
9
+ import { runExperimentRunCommandFromArgs } from "../commands/runExperimentRunCommand.js";
10
+ import { runRenderExperimentReportCommand } from "../commands/renderExperimentReportCommand.js";
11
+ import { runGenerateExperimentPlotsCommand } from "../commands/generateExperimentPlotsCommand.js";
12
+ import { runBuildGalleryCommand } from "../commands/buildGalleryCommand.js";
13
+ import { createLabExecutionContext, discoverPackageRoot } from "../runtime/index.js";
14
+ import { renderDemoHelp, renderExperimentControlledHelp, renderExperimentDescribeHelp, renderExperimentHelp, renderExperimentListHelp, renderExperimentRunHelp, renderFinalDemoHelp, renderGalleryBuildHelp, renderGalleryHelp, renderPlotsGenerateHelp, renderPlotsHelp, renderReportHelp, renderReportRenderHelp, renderSecurityHelp, renderTopLevelHelp, renderUnknownCommandError } from "./help.js";
15
+ export const CLI_USAGE_EXIT_CODE = 2;
16
+ /**
17
+ * Recognized legacy final-demo flag tokens (mirrors parseRunFinalDemoArgs in
18
+ * src/commands/runFinalDemoCommand.ts). Used only to detect the historical
19
+ * direct invocation form; the legacy argument list itself is delegated to the
20
+ * existing final-demo parser unchanged, never reinterpreted here.
21
+ */
22
+ const LEGACY_FINAL_DEMO_FLAGS = new Set([
23
+ "--cases",
24
+ "--out",
25
+ "--kit-command",
26
+ "--agents",
27
+ "--strategies",
28
+ "--complexities",
29
+ "--case",
30
+ "--benchmark-project",
31
+ "--max-runs",
32
+ "--screenshot",
33
+ "--no-screenshot",
34
+ "--include-real-agents",
35
+ "--continue-on-failure",
36
+ "--no-continue-on-failure",
37
+ "--timeout-ms"
38
+ ]);
39
+ const DEFAULT_WRITERS = {
40
+ stdout: (message) => {
41
+ console.log(message);
42
+ },
43
+ stderr: (message) => {
44
+ console.error(message);
45
+ }
46
+ };
47
+ export async function runLabCli(argv, options = {}) {
48
+ const writers = options.writers ?? DEFAULT_WRITERS;
49
+ const globalOptions = parseGlobalOptions(argv);
50
+ if (!globalOptions.ok) {
51
+ writers.stderr(globalOptions.error);
52
+ return CLI_USAGE_EXIT_CODE;
53
+ }
54
+ const remaining = globalOptions.remaining;
55
+ const context = createLabExecutionContext(globalOptions.workspaceRoot !== undefined ? { workspaceRoot: globalOptions.workspaceRoot } : {});
56
+ const [command, ...rest] = remaining;
57
+ if (remaining.length === 0 || command === "--help" || command === "-h") {
58
+ writers.stdout(renderTopLevelHelp());
59
+ return 0;
60
+ }
61
+ if (command === "--version" || command === "-V") {
62
+ writers.stdout(readPackageVersion());
63
+ return 0;
64
+ }
65
+ if (command === "security") {
66
+ return runSecurityFamily(rest, writers, context);
67
+ }
68
+ if (command === "audit") {
69
+ return runAuditCommandFromArgs(rest, { context, defaultOutRoot: context.workspaceRoot });
70
+ }
71
+ if (command === "experiment") {
72
+ return runExperimentFamily(rest, writers, context);
73
+ }
74
+ if (command === "report") {
75
+ return runReportFamily(rest, writers);
76
+ }
77
+ if (command === "plots") {
78
+ return runPlotsFamily(rest, writers);
79
+ }
80
+ if (command === "gallery") {
81
+ return runGalleryFamily(rest, writers);
82
+ }
83
+ if (command === "demo") {
84
+ return runDemoCommand(rest, writers);
85
+ }
86
+ if (LEGACY_FINAL_DEMO_FLAGS.has(command)) {
87
+ return runFinalDemoCommand(remaining);
88
+ }
89
+ writers.stderr(renderUnknownCommandError(command));
90
+ return CLI_USAGE_EXIT_CODE;
91
+ }
92
+ /**
93
+ * Only recognizes a leading "--workspace <path>" pair (must be argv[0]).
94
+ * A --workspace token appearing anywhere else is left untouched for normal
95
+ * command/legacy routing to handle (or reject), per the batch requirement
96
+ * that global options must precede the command.
97
+ */
98
+ function parseGlobalOptions(argv) {
99
+ if (argv[0] !== "--workspace") {
100
+ return { ok: true, remaining: argv };
101
+ }
102
+ const value = argv[1];
103
+ if (value === undefined) {
104
+ return { ok: false, error: "Missing value for --workspace. Expected a path after --workspace." };
105
+ }
106
+ return { ok: true, workspaceRoot: value, remaining: argv.slice(2) };
107
+ }
108
+ async function runDemoCommand(argv, writers) {
109
+ const [subcommand, ...rest] = argv;
110
+ if (argv.length === 0 || subcommand === "--help" || subcommand === "-h") {
111
+ writers.stdout(renderDemoHelp());
112
+ return 0;
113
+ }
114
+ if (subcommand === "final") {
115
+ if (rest[0] === "--help" || rest[0] === "-h") {
116
+ writers.stdout(renderFinalDemoHelp());
117
+ return 0;
118
+ }
119
+ return runFinalDemoCommand(rest);
120
+ }
121
+ writers.stderr(renderUnknownCommandError(`demo ${subcommand}`));
122
+ return CLI_USAGE_EXIT_CODE;
123
+ }
124
+ async function runSecurityFamily(argv, writers, context) {
125
+ const [subcommand, ...rest] = argv;
126
+ if (argv.length === 0 || subcommand === "--help" || subcommand === "-h") {
127
+ writers.stdout(renderSecurityHelp());
128
+ return 0;
129
+ }
130
+ if (subcommand === "validate") {
131
+ return runSecurityValidationCommandFromArgs(rest, { context, defaultOutRoot: context.workspaceRoot });
132
+ }
133
+ writers.stderr(renderUnknownCommandError(`security ${subcommand}`));
134
+ return CLI_USAGE_EXIT_CODE;
135
+ }
136
+ async function runExperimentFamily(argv, writers, context) {
137
+ const [subcommand, ...rest] = argv;
138
+ if (argv.length === 0 || subcommand === "--help" || subcommand === "-h") {
139
+ writers.stdout(renderExperimentHelp());
140
+ return 0;
141
+ }
142
+ if (subcommand === "list") {
143
+ if (rest[0] === "--help" || rest[0] === "-h") {
144
+ writers.stdout(renderExperimentListHelp());
145
+ return 0;
146
+ }
147
+ return runExperimentListCommandFromArgs(rest);
148
+ }
149
+ if (subcommand === "describe") {
150
+ if (rest[0] === "--help" || rest[0] === "-h") {
151
+ writers.stdout(renderExperimentDescribeHelp());
152
+ return 0;
153
+ }
154
+ return runExperimentDescribeCommandFromArgs(rest);
155
+ }
156
+ if (subcommand === "run") {
157
+ if (rest[0] === "--help" || rest[0] === "-h") {
158
+ writers.stdout(renderExperimentRunHelp());
159
+ return 0;
160
+ }
161
+ return runExperimentRunCommandFromArgs(rest, { context, installedDefaultOutputRoot: context.workspaceRoot });
162
+ }
163
+ if (subcommand === "controlled") {
164
+ if (rest[0] === "--help" || rest[0] === "-h") {
165
+ writers.stdout(renderExperimentControlledHelp());
166
+ return 0;
167
+ }
168
+ return runControlledExperimentCommand(rest);
169
+ }
170
+ writers.stderr(renderUnknownCommandError(`experiment ${subcommand}`));
171
+ return CLI_USAGE_EXIT_CODE;
172
+ }
173
+ async function runReportFamily(argv, writers) {
174
+ const [subcommand, ...rest] = argv;
175
+ if (argv.length === 0 || subcommand === "--help" || subcommand === "-h") {
176
+ writers.stdout(renderReportHelp());
177
+ return 0;
178
+ }
179
+ if (subcommand === "render") {
180
+ if (rest[0] === "--help" || rest[0] === "-h") {
181
+ writers.stdout(renderReportRenderHelp());
182
+ return 0;
183
+ }
184
+ return runRenderExperimentReportCommand(rest);
185
+ }
186
+ writers.stderr(renderUnknownCommandError(`report ${subcommand}`));
187
+ return CLI_USAGE_EXIT_CODE;
188
+ }
189
+ async function runPlotsFamily(argv, writers) {
190
+ const [subcommand, ...rest] = argv;
191
+ if (argv.length === 0 || subcommand === "--help" || subcommand === "-h") {
192
+ writers.stdout(renderPlotsHelp());
193
+ return 0;
194
+ }
195
+ if (subcommand === "generate") {
196
+ if (rest[0] === "--help" || rest[0] === "-h") {
197
+ writers.stdout(renderPlotsGenerateHelp());
198
+ return 0;
199
+ }
200
+ return runGenerateExperimentPlotsCommand(rest);
201
+ }
202
+ writers.stderr(renderUnknownCommandError(`plots ${subcommand}`));
203
+ return CLI_USAGE_EXIT_CODE;
204
+ }
205
+ async function runGalleryFamily(argv, writers) {
206
+ const [subcommand, ...rest] = argv;
207
+ if (argv.length === 0 || subcommand === "--help" || subcommand === "-h") {
208
+ writers.stdout(renderGalleryHelp());
209
+ return 0;
210
+ }
211
+ if (subcommand === "build") {
212
+ if (rest[0] === "--help" || rest[0] === "-h") {
213
+ writers.stdout(renderGalleryBuildHelp());
214
+ return 0;
215
+ }
216
+ return runBuildGalleryCommand(rest);
217
+ }
218
+ writers.stderr(renderUnknownCommandError(`gallery ${subcommand}`));
219
+ return CLI_USAGE_EXIT_CODE;
220
+ }
221
+ function readPackageVersion() {
222
+ const packageRoot = discoverPackageRoot();
223
+ const packageJsonPath = path.join(packageRoot, "package.json");
224
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
225
+ if (typeof parsed.version !== "string" || parsed.version.length === 0) {
226
+ throw new Error(`Unable to read a valid version from ${packageJsonPath}`);
227
+ }
228
+ return parsed.version;
229
+ }