@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
@@ -94,3 +94,172 @@ export function calculateRequiredEvidenceOmitted(matches, sourceArtifactTruncate
94
94
  export function findAllocationExpectationForGroup(expectations, groupId) {
95
95
  return (expectations ?? []).find((e) => e.groupId === groupId);
96
96
  }
97
+ // v0.4.5 Batch 2: per-group/aggregate allocation and spillover evidence, read directly from
98
+ // ContextCapsule.groupTruncation (the Batch 1 mirror of the v1.10.3/v1.10.4 required-first
99
+ // allocator diagnostics). A group entry that lacks every additive allocation field is
100
+ // legacy/unavailable, never fabricated as zero. RetrievalAuditRecord has no groupTruncation
101
+ // field, so this evidence is context-capsule-only (sourceArtifact is always fixed).
102
+ function hasAnyAllocationField(entry) {
103
+ return (entry.required !== undefined ||
104
+ entry.reservation !== undefined ||
105
+ entry.initiallySelectedCount !== undefined ||
106
+ entry.unusedReservationContributed !== undefined ||
107
+ entry.borrowedCapacity !== undefined ||
108
+ entry.requiredOmittedCount !== undefined ||
109
+ entry.optionalOmittedCount !== undefined ||
110
+ entry.adequacyAffected !== undefined ||
111
+ entry.governingHardBound !== undefined ||
112
+ entry.aggregateCapacityUsed !== undefined ||
113
+ entry.aggregateCapacityRemaining !== undefined);
114
+ }
115
+ function calculatePerGroupAllocation(entries, sourceInstance) {
116
+ return entries.map((entry) => {
117
+ const available = hasAnyAllocationField(entry);
118
+ return {
119
+ groupId: entry.groupId,
120
+ sourceArtifact: "context-capsule",
121
+ sourceInstance,
122
+ availability: available ? "available" : "unavailable",
123
+ required: entry.required ?? null,
124
+ reservation: entry.reservation ?? null,
125
+ initiallySelectedCount: entry.initiallySelectedCount ?? null,
126
+ unusedReservationContributed: entry.unusedReservationContributed ?? null,
127
+ borrowedCapacity: entry.borrowedCapacity ?? null,
128
+ governingHardBound: entry.governingHardBound ?? null,
129
+ requiredOmittedCount: entry.requiredOmittedCount ?? null,
130
+ optionalOmittedCount: entry.optionalOmittedCount ?? null,
131
+ droppedCount: entry.droppedCount,
132
+ droppedEvidenceIds: entry.droppedEvidenceIds ?? [],
133
+ adequacyAffected: entry.adequacyAffected ?? null,
134
+ aggregateCapacityUsed: entry.aggregateCapacityUsed ?? null,
135
+ aggregateCapacityRemaining: entry.aggregateCapacityRemaining ?? null,
136
+ reason: available ? null : `Group "${entry.groupId}" exposes no v1.10.3/v1.10.4 allocation diagnostics (legacy schema-major-1 evidence).`
137
+ };
138
+ });
139
+ }
140
+ function sumIfComplete(entries, field) {
141
+ if (entries.length === 0)
142
+ return null;
143
+ let total = 0;
144
+ for (const entry of entries) {
145
+ const value = entry[field];
146
+ if (typeof value !== "number")
147
+ return null;
148
+ total += value;
149
+ }
150
+ return total;
151
+ }
152
+ function calculateAggregateAllocation(entries) {
153
+ if (entries.length === 0) {
154
+ return {
155
+ availability: "not-applicable",
156
+ groupCount: 0,
157
+ totalReservation: null,
158
+ totalInitiallySelected: null,
159
+ totalUnusedReservationContributed: null,
160
+ totalBorrowedCapacity: null,
161
+ totalRequiredOmitted: null,
162
+ totalOptionalOmitted: null,
163
+ totalDropped: null,
164
+ groupsContributingUnusedReservation: [],
165
+ groupsBorrowingCapacity: [],
166
+ groupsWithRequiredOmission: [],
167
+ groupsWithOptionalOnlyOmission: [],
168
+ groupsWithAdequacyAffected: [],
169
+ partial: false,
170
+ reason: "No evidence groups were supplied."
171
+ };
172
+ }
173
+ const anyAllocationEvidence = entries.some(hasAnyAllocationField);
174
+ if (!anyAllocationEvidence) {
175
+ return {
176
+ availability: "unavailable",
177
+ groupCount: entries.length,
178
+ totalReservation: null,
179
+ totalInitiallySelected: null,
180
+ totalUnusedReservationContributed: null,
181
+ totalBorrowedCapacity: null,
182
+ totalRequiredOmitted: null,
183
+ totalOptionalOmitted: null,
184
+ totalDropped: null,
185
+ groupsContributingUnusedReservation: [],
186
+ groupsBorrowingCapacity: [],
187
+ groupsWithRequiredOmission: [],
188
+ groupsWithOptionalOnlyOmission: [],
189
+ groupsWithAdequacyAffected: [],
190
+ partial: false,
191
+ reason: "No group exposes v1.10.3/v1.10.4 allocation diagnostics (legacy schema-major-1 evidence)."
192
+ };
193
+ }
194
+ const totalReservation = sumIfComplete(entries, "reservation");
195
+ const totalInitiallySelected = sumIfComplete(entries, "initiallySelectedCount");
196
+ const totalUnusedReservationContributed = sumIfComplete(entries, "unusedReservationContributed");
197
+ const totalBorrowedCapacity = sumIfComplete(entries, "borrowedCapacity");
198
+ const totalRequiredOmitted = sumIfComplete(entries, "requiredOmittedCount");
199
+ const totalOptionalOmitted = sumIfComplete(entries, "optionalOmittedCount");
200
+ const totalDropped = sumIfComplete(entries, "droppedCount");
201
+ const totals = [
202
+ totalReservation,
203
+ totalInitiallySelected,
204
+ totalUnusedReservationContributed,
205
+ totalBorrowedCapacity,
206
+ totalRequiredOmitted,
207
+ totalOptionalOmitted
208
+ ];
209
+ const partial = totals.some((t) => t === null);
210
+ return {
211
+ availability: "available",
212
+ groupCount: entries.length,
213
+ totalReservation,
214
+ totalInitiallySelected,
215
+ totalUnusedReservationContributed,
216
+ totalBorrowedCapacity,
217
+ totalRequiredOmitted,
218
+ totalOptionalOmitted,
219
+ totalDropped,
220
+ groupsContributingUnusedReservation: entries.filter((e) => (e.unusedReservationContributed ?? 0) > 0).map((e) => e.groupId),
221
+ groupsBorrowingCapacity: entries.filter((e) => (e.borrowedCapacity ?? 0) > 0).map((e) => e.groupId),
222
+ groupsWithRequiredOmission: entries.filter((e) => (e.requiredOmittedCount ?? 0) > 0).map((e) => e.groupId),
223
+ groupsWithOptionalOnlyOmission: entries
224
+ .filter((e) => (e.optionalOmittedCount ?? 0) > 0 && (e.requiredOmittedCount ?? 0) === 0)
225
+ .map((e) => e.groupId),
226
+ groupsWithAdequacyAffected: entries.filter((e) => e.adequacyAffected === true).map((e) => e.groupId),
227
+ partial,
228
+ reason: partial ? "At least one group lacks the full allocation field set; incomplete totals are reported as null rather than partially summed." : null
229
+ };
230
+ }
231
+ function calculateSpillover(entries) {
232
+ const anyAllocationEvidence = entries.some(hasAnyAllocationField);
233
+ if (!anyAllocationEvidence) {
234
+ return {
235
+ availability: "unavailable",
236
+ groupsContributing: [],
237
+ groupsBorrowing: [],
238
+ totalContributed: null,
239
+ totalBorrowed: null,
240
+ contributionCoversBorrowing: null,
241
+ reason: "No group exposes v1.10.3/v1.10.4 allocation diagnostics (legacy schema-major-1 evidence)."
242
+ };
243
+ }
244
+ const groupsContributing = entries.filter((e) => (e.unusedReservationContributed ?? 0) > 0).map((e) => e.groupId);
245
+ const groupsBorrowing = entries.filter((e) => (e.borrowedCapacity ?? 0) > 0).map((e) => e.groupId);
246
+ const totalContributed = sumIfComplete(entries, "unusedReservationContributed");
247
+ const totalBorrowed = sumIfComplete(entries, "borrowedCapacity");
248
+ return {
249
+ availability: "available",
250
+ groupsContributing,
251
+ groupsBorrowing,
252
+ totalContributed,
253
+ totalBorrowed,
254
+ contributionCoversBorrowing: totalContributed !== null && totalBorrowed !== null ? totalContributed >= totalBorrowed : null,
255
+ reason: null
256
+ };
257
+ }
258
+ export function calculateGroupAllocationMetrics(groupTruncation, sourceInstance) {
259
+ const entries = groupTruncation ?? [];
260
+ return {
261
+ perGroup: calculatePerGroupAllocation(entries, sourceInstance),
262
+ aggregate: calculateAggregateAllocation(entries),
263
+ spillover: calculateSpillover(entries)
264
+ };
265
+ }
@@ -0,0 +1,74 @@
1
+ function unavailableCoverageMetrics(reason) {
2
+ const unavailableCount = { availability: "unavailable", count: null, evidenceKeys: [], reason };
3
+ return {
4
+ availability: "unavailable",
5
+ requiredConditionsTotal: unavailableCount,
6
+ requiredConditionsSatisfied: unavailableCount,
7
+ requiredConditionsMissing: unavailableCount,
8
+ requiredConditionsLost: unavailableCount,
9
+ optionalConditionsTotal: unavailableCount,
10
+ optionalConditionsSatisfied: unavailableCount,
11
+ optionalConditionsMissing: unavailableCount,
12
+ witnessEvidence: [],
13
+ lastWitnessLoss: unavailableCount,
14
+ conditionToGroupMapping: [],
15
+ reason
16
+ };
17
+ }
18
+ function countMetric(ids) {
19
+ return { availability: "available", count: ids.length, evidenceKeys: ids, reason: null };
20
+ }
21
+ function coverageState(condition) {
22
+ if (condition.conditionSatisfied)
23
+ return "satisfied";
24
+ if (condition.lostRequiredCondition)
25
+ return "lost-to-allocation";
26
+ return "missing-evidence";
27
+ }
28
+ export function calculateConditionCoverageMetrics(roleConditionCoverage, availableEvidenceGroupIds) {
29
+ if (roleConditionCoverage === undefined) {
30
+ return unavailableCoverageMetrics("No roleConditionCoverage evidence was supplied (legacy schema-major-1 artifact, or the producer did not emit condition-level diagnostics).");
31
+ }
32
+ const required = roleConditionCoverage.filter((c) => c.required);
33
+ const optional = roleConditionCoverage.filter((c) => !c.required);
34
+ const requiredSatisfied = required.filter((c) => c.conditionSatisfied);
35
+ const requiredLost = required.filter((c) => c.lostRequiredCondition);
36
+ const requiredMissing = required.filter((c) => !c.conditionSatisfied && !c.lostRequiredCondition);
37
+ const optionalSatisfied = optional.filter((c) => c.conditionSatisfied);
38
+ const optionalMissing = optional.filter((c) => !c.conditionSatisfied);
39
+ const witnessEvidence = roleConditionCoverage.map((c) => ({
40
+ conditionId: c.conditionId,
41
+ role: c.role,
42
+ required: c.required,
43
+ witnessPolicy: c.witnessPolicy,
44
+ requiredWitnessCount: c.requiredWitnessCount,
45
+ availableWitnessCount: c.availableWitnessCount,
46
+ retainedWitnessCount: c.retainedWitnessCount,
47
+ retainedWitnessIds: c.retainedWitnessIds,
48
+ adequateWitnessRemains: c.conditionSatisfied,
49
+ coverageState: coverageState(c),
50
+ lossReason: c.lossReason,
51
+ evidenceGroupIds: c.evidenceGroupIds
52
+ }));
53
+ const conditionToGroupMapping = roleConditionCoverage.map((c) => ({
54
+ conditionId: c.conditionId,
55
+ required: c.required,
56
+ evidenceGroupIds: c.evidenceGroupIds,
57
+ mapped: c.evidenceGroupIds.length > 0,
58
+ unknownGroupIds: availableEvidenceGroupIds === undefined ? [] : c.evidenceGroupIds.filter((id) => !availableEvidenceGroupIds.includes(id))
59
+ }));
60
+ return {
61
+ availability: "available",
62
+ requiredConditionsTotal: countMetric(required.map((c) => c.conditionId)),
63
+ requiredConditionsSatisfied: countMetric(requiredSatisfied.map((c) => c.conditionId)),
64
+ requiredConditionsMissing: countMetric(requiredMissing.map((c) => c.conditionId)),
65
+ requiredConditionsLost: countMetric(requiredLost.map((c) => c.conditionId)),
66
+ optionalConditionsTotal: countMetric(optional.map((c) => c.conditionId)),
67
+ optionalConditionsSatisfied: countMetric(optionalSatisfied.map((c) => c.conditionId)),
68
+ optionalConditionsMissing: countMetric(optionalMissing.map((c) => c.conditionId)),
69
+ witnessEvidence,
70
+ lastWitnessLoss: countMetric(requiredLost.map((c) => c.conditionId)),
71
+ conditionToGroupMapping,
72
+ reason: null
73
+ };
74
+ }
@@ -0,0 +1,113 @@
1
+ import { checkMyDevKitContextArtifactConsistency } from "../stageContextSelectors/contextArtifactConsistency.js";
2
+ const ADEQUATE_STATUSES = [
3
+ "context sufficient for implementation",
4
+ "context sufficient with listed assumptions"
5
+ ];
6
+ const INADEQUATE_STATUSES = [
7
+ "context insufficient and more retrieval required",
8
+ "context conflict found and user or upstream stage decision required"
9
+ ];
10
+ export function calculateProducerConditionAgreement(roleAdequacyStatus, conditionCoverage) {
11
+ if (roleAdequacyStatus === undefined) {
12
+ return {
13
+ availability: "unavailable",
14
+ outcome: "insufficient-evidence",
15
+ observedRoleAdequacyStatus: null,
16
+ contradictionCodes: [],
17
+ reason: "No roleAdequacy.status was supplied."
18
+ };
19
+ }
20
+ if (conditionCoverage.availability !== "available") {
21
+ return {
22
+ availability: "unavailable",
23
+ outcome: "unsupported-legacy-evidence",
24
+ observedRoleAdequacyStatus: roleAdequacyStatus,
25
+ contradictionCodes: [],
26
+ reason: conditionCoverage.reason ?? "No condition-coverage evidence was available to compare against roleAdequacy.status."
27
+ };
28
+ }
29
+ const requiredTotal = conditionCoverage.requiredConditionsTotal.count ?? 0;
30
+ const requiredSatisfied = conditionCoverage.requiredConditionsSatisfied.count ?? 0;
31
+ const requiredLost = conditionCoverage.requiredConditionsLost.count ?? 0;
32
+ const allRequiredSatisfied = requiredTotal > 0 && requiredSatisfied === requiredTotal;
33
+ const producerSaysAdequate = ADEQUATE_STATUSES.includes(roleAdequacyStatus);
34
+ const producerSaysInadequate = INADEQUATE_STATUSES.includes(roleAdequacyStatus);
35
+ const contradictionCodes = [];
36
+ if (producerSaysInadequate && allRequiredSatisfied && requiredLost === 0) {
37
+ contradictionCodes.push("PRODUCER_INADEQUATE_BUT_ALL_REQUIRED_CONDITIONS_RETAINED");
38
+ }
39
+ if (producerSaysAdequate && requiredLost > 0) {
40
+ contradictionCodes.push("PRODUCER_ADEQUATE_BUT_REQUIRED_CONDITION_LOST");
41
+ }
42
+ const outcome = contradictionCodes.length > 0 ? "contradiction" : "agreement";
43
+ return {
44
+ availability: "available",
45
+ outcome,
46
+ observedRoleAdequacyStatus: roleAdequacyStatus,
47
+ contradictionCodes,
48
+ reason: outcome === "contradiction"
49
+ ? "Producer role-adequacy status contradicts its own explicit condition-coverage evidence; both sides are retained."
50
+ : null
51
+ };
52
+ }
53
+ export function calculateRequiredEvidenceLossAgreement(requiredEvidenceLost, conditionCoverage, requiredOmittedCount) {
54
+ if (requiredEvidenceLost === undefined) {
55
+ return {
56
+ availability: "unavailable",
57
+ outcome: "insufficient-evidence",
58
+ requiredEvidenceLost: null,
59
+ explicitConditionLossDetected: null,
60
+ requiredOmittedCount: requiredOmittedCount ?? null,
61
+ contradictionCodes: [],
62
+ reason: "No truncation.requiredEvidenceLost rollup was supplied."
63
+ };
64
+ }
65
+ if (conditionCoverage.availability !== "available") {
66
+ return {
67
+ availability: "unavailable",
68
+ outcome: "unsupported-legacy-evidence",
69
+ requiredEvidenceLost,
70
+ explicitConditionLossDetected: null,
71
+ requiredOmittedCount: requiredOmittedCount ?? null,
72
+ contradictionCodes: [],
73
+ reason: conditionCoverage.reason ?? "No condition-coverage evidence was available to compare against requiredEvidenceLost."
74
+ };
75
+ }
76
+ const explicitConditionLossDetected = (conditionCoverage.requiredConditionsLost.count ?? 0) > 0;
77
+ const contradictionCodes = [];
78
+ if (!requiredEvidenceLost && explicitConditionLossDetected) {
79
+ contradictionCodes.push("REQUIRED_EVIDENCE_LOST_FALSE_BUT_CONDITION_LOSS_DETECTED");
80
+ }
81
+ if (requiredEvidenceLost && !explicitConditionLossDetected && (requiredOmittedCount ?? 0) === 0) {
82
+ contradictionCodes.push("REQUIRED_EVIDENCE_LOST_TRUE_BUT_NO_CONDITION_OR_GROUP_LOSS_DETECTED");
83
+ }
84
+ const outcome = contradictionCodes.length > 0 ? "contradiction" : "agreement";
85
+ return {
86
+ availability: "available",
87
+ outcome,
88
+ requiredEvidenceLost,
89
+ explicitConditionLossDetected,
90
+ requiredOmittedCount: requiredOmittedCount ?? null,
91
+ contradictionCodes,
92
+ reason: outcome === "contradiction" ? "truncation.requiredEvidenceLost contradicts explicit condition-loss/required-omission evidence; both sides are retained." : null
93
+ };
94
+ }
95
+ const RELEVANT_CAPSULE_AUDIT_FIELDS = new Set(["roleConditionCoverage", "truncation", "roleAdequacy"]);
96
+ export function calculateCapsuleAuditConditionAgreement(capsule, audit) {
97
+ if (capsule === undefined || audit === undefined) {
98
+ const reason = capsule === undefined && audit === undefined
99
+ ? "Neither a context capsule nor a retrieval audit record was supplied."
100
+ : capsule === undefined
101
+ ? "No context capsule was supplied."
102
+ : "No retrieval audit record was supplied.";
103
+ return { availability: "unavailable", consistent: null, contradictingFieldPaths: [], reason };
104
+ }
105
+ const result = checkMyDevKitContextArtifactConsistency(capsule, audit);
106
+ const contradictingFieldPaths = result.issues.filter((issue) => RELEVANT_CAPSULE_AUDIT_FIELDS.has(issue.fieldPath)).map((issue) => issue.fieldPath);
107
+ return {
108
+ availability: "available",
109
+ consistent: contradictingFieldPaths.length === 0,
110
+ contradictingFieldPaths,
111
+ reason: null
112
+ };
113
+ }
@@ -2,6 +2,10 @@
2
2
  // output (Batch 1) -- this module only compares it against an explicit fixture-declared
3
3
  // expectation. It never calls, imports, or reimplements contextReadiness.ts.
4
4
  import { checkSupplementalReadinessIdentityConsistency } from "../upstreamArtifacts/index.js";
5
+ const READINESS_ADEQUATE_STATUSES = [
6
+ "context sufficient for implementation",
7
+ "context sufficient with listed assumptions"
8
+ ];
5
9
  function unavailableStructural(field, reason) {
6
10
  return { field, expectedValue: null, observedValue: null, agreement: null, availability: "unavailable", reason };
7
11
  }
@@ -142,6 +146,62 @@ export function calculateValidBlocked(readiness, expectation) {
142
146
  const valid = allowsRefreshRequired && issueCodesMatch && primaryMatches;
143
147
  return { availability: "available", validBlocked: valid, validRefreshRequired: valid, observedDecision: readiness.decision, reason: null };
144
148
  }
149
+ // v0.4.5 Batch 2 (section 18): compares producer role adequacy (as already reconciled with
150
+ // condition-coverage evidence by calculateProducerConditionAgreement) against the supplied
151
+ // orchestrator readiness decision already accepted by the v0.4.4 bridge. This never decides
152
+ // what readiness "should" have been -- it only reports the observed relationship.
153
+ export function calculateProducerReadinessRelationship(roleAdequacyStatus, producerConditionAgreement, readiness) {
154
+ if (roleAdequacyStatus === undefined || readiness === undefined) {
155
+ return {
156
+ availability: "unavailable",
157
+ outcome: "insufficient-evidence",
158
+ observedRoleAdequacyStatus: roleAdequacyStatus ?? null,
159
+ observedReadinessDecision: readiness?.decision ?? null,
160
+ contradictionCodes: [],
161
+ reason: roleAdequacyStatus === undefined && readiness === undefined
162
+ ? "Neither roleAdequacy.status nor a readiness result was supplied."
163
+ : roleAdequacyStatus === undefined
164
+ ? "No roleAdequacy.status was supplied."
165
+ : "No readiness result was supplied."
166
+ };
167
+ }
168
+ if (producerConditionAgreement.outcome === "contradiction") {
169
+ return {
170
+ availability: "available",
171
+ outcome: "insufficient-evidence",
172
+ observedRoleAdequacyStatus: roleAdequacyStatus,
173
+ observedReadinessDecision: readiness.decision,
174
+ contradictionCodes: [],
175
+ reason: "Producer role-adequacy already contradicts its own condition-coverage evidence; the readiness relationship cannot be attributed to either side."
176
+ };
177
+ }
178
+ if (producerConditionAgreement.outcome === "unsupported-legacy-evidence" || producerConditionAgreement.outcome === "insufficient-evidence") {
179
+ return {
180
+ availability: "unavailable",
181
+ outcome: producerConditionAgreement.outcome,
182
+ observedRoleAdequacyStatus: roleAdequacyStatus,
183
+ observedReadinessDecision: readiness.decision,
184
+ contradictionCodes: [],
185
+ reason: producerConditionAgreement.reason
186
+ };
187
+ }
188
+ const producerAdequate = READINESS_ADEQUATE_STATUSES.includes(roleAdequacyStatus);
189
+ const readinessReady = readiness.decision === "ready";
190
+ const contradictionCodes = [];
191
+ if (producerAdequate && !readinessReady)
192
+ contradictionCodes.push("PRODUCER_ADEQUATE_BUT_READINESS_NOT_READY");
193
+ if (!producerAdequate && readinessReady)
194
+ contradictionCodes.push("PRODUCER_INADEQUATE_BUT_READINESS_READY");
195
+ const outcome = contradictionCodes.length > 0 ? "contradiction" : "agreement";
196
+ return {
197
+ availability: "available",
198
+ outcome,
199
+ observedRoleAdequacyStatus: roleAdequacyStatus,
200
+ observedReadinessDecision: readiness.decision,
201
+ contradictionCodes,
202
+ reason: outcome === "contradiction" ? "Producer role adequacy and supplied orchestrator readiness disagree; both sides are retained without a lab-owned verdict." : null
203
+ };
204
+ }
145
205
  export function calculateReadinessAgreementMetrics(readiness, expectation, supplementalPacket, packetSourcePath) {
146
206
  return {
147
207
  structuralAgreement: calculateReadinessStructuralAgreement(readiness, supplementalPacket, packetSourcePath),