@dailephd/my-dev-kit-lab 0.4.3 → 0.4.5

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 (97) hide show
  1. package/CHANGELOG.md +468 -0
  2. package/README.md +8 -1
  3. package/dist/scripts/report-context-integrity-smoke.js +70 -0
  4. package/dist/src/evaluation/ecosystemFixtures/index.js +3 -0
  5. package/dist/src/evaluation/ecosystemFixtures/loadContextIntegrityFixture.js +102 -0
  6. package/dist/src/evaluation/ecosystemFixtures/manifestTypes.js +1 -0
  7. package/dist/src/evaluation/ecosystemFixtures/validateManifest.js +82 -0
  8. package/dist/src/evaluation/ecosystemFixtures/verifyFixtureHashes.js +45 -0
  9. package/dist/src/evaluation/stageContextExpectations/producerReadinessExpectationTypes.js +8 -0
  10. package/dist/src/evaluation/stageContextExpectations/validation.js +200 -0
  11. package/dist/src/evaluation/stageContextMetrics/calculateAllocationMetrics.js +265 -0
  12. package/dist/src/evaluation/stageContextMetrics/calculateConditionCoverageMetrics.js +74 -0
  13. package/dist/src/evaluation/stageContextMetrics/calculateCriticalityMetrics.js +112 -0
  14. package/dist/src/evaluation/stageContextMetrics/calculateOwnerMetrics.js +84 -0
  15. package/dist/src/evaluation/stageContextMetrics/calculateProducerConditionAgreement.js +113 -0
  16. package/dist/src/evaluation/stageContextMetrics/calculateReadinessAgreement.js +212 -0
  17. package/dist/src/evaluation/stageContextMetrics/calculateRunIntegrityAgreement.js +309 -0
  18. package/dist/src/evaluation/stageContextMetrics/calculateSupplementalRawAgreement.js +60 -0
  19. package/dist/src/evaluation/stageContextMetrics/calculateTruncationClassification.js +144 -0
  20. package/dist/src/evaluation/stageContextMetrics/evaluateProducerReadinessBridge.js +198 -0
  21. package/dist/src/evaluation/stageContextMetrics/index.js +11 -0
  22. package/dist/src/evaluation/stageContextMetrics/producerReadinessMetricTypes.js +1 -0
  23. package/dist/src/evaluation/stageContextMetrics/runIntegrityAgreementTypes.js +1 -0
  24. package/dist/src/evaluation/stageContextSelectors/contextArtifactConsistency.js +17 -0
  25. package/dist/src/evaluation/stageContextSelectors/index.js +1 -0
  26. package/dist/src/evaluation/stageContextSelectors/orchestratorRunIntegritySelectors.js +64 -0
  27. package/dist/src/evaluation/upstreamArtifacts/index.js +8 -0
  28. package/dist/src/evaluation/upstreamArtifacts/orchestratorContextReadinessResultV1.js +247 -0
  29. package/dist/src/evaluation/upstreamArtifacts/orchestratorRunIntegrityV1.js +33 -0
  30. package/dist/src/evaluation/upstreamArtifacts/readImplementationContextPacketV1.js +9 -0
  31. package/dist/src/evaluation/upstreamArtifacts/readImplementationContextRetrievalReportV1.js +9 -0
  32. package/dist/src/evaluation/upstreamArtifacts/readOrchestratorRunIntegrityV1.js +9 -0
  33. package/dist/src/evaluation/upstreamArtifacts/readSupplementalContextTextFile.js +29 -0
  34. package/dist/src/evaluation/upstreamArtifacts/readTestContextPacketV1.js +9 -0
  35. package/dist/src/evaluation/upstreamArtifacts/readTestContextRetrievalReportV1.js +9 -0
  36. package/dist/src/evaluation/upstreamArtifacts/supplementalContextTextParser.js +75 -0
  37. package/dist/src/evaluation/upstreamArtifacts/supplementalContextTypes.js +152 -0
  38. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitContextCapsuleV1.js +59 -2
  39. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitRetrievalAuditRecordV1.js +15 -3
  40. package/dist/src/evaluation/upstreamArtifacts/validateOrchestratorRunIntegrityV1.js +177 -0
  41. package/dist/src/evaluation/upstreamArtifacts/validateSupplementalContextDocumentV1.js +148 -0
  42. package/dist/src/experiments/plugins/contextStrategyComparison/loadV043StrategyArtifacts.js +117 -6
  43. package/dist/src/experiments/plugins/contextStrategyComparison/runV043StageContextStrategyWithAssurance.js +18 -3
  44. package/dist/src/experiments/plugins/contextStrategyComparison/validateV043StrategyInput.js +17 -3
  45. package/dist/src/report/experiments/buildContextIntegrityReport.js +204 -0
  46. package/dist/src/report/experiments/buildContextStrategyComparisonV043Report.js +122 -0
  47. package/dist/src/report/experiments/contextIntegrityReportModel.js +1 -0
  48. package/dist/src/report/experiments/index.js +5 -0
  49. package/dist/src/report/experiments/renderContextIntegrityHtml.js +98 -0
  50. package/dist/src/report/experiments/renderContextIntegrityJsonReport.js +3 -0
  51. package/dist/src/report/experiments/renderContextIntegrityText.js +111 -0
  52. package/dist/src/report/experiments/renderContextStrategyComparisonV043Html.js +62 -0
  53. package/dist/src/report/experiments/renderPluginExperimentReportText.js +67 -0
  54. package/dist/src/securityValidation/packageChecks/requiredPackageContents.js +33 -0
  55. package/dist/src/securityValidation/packageChecks/runPackageChecks.js +11 -5
  56. package/docs/METRICS.md +111 -0
  57. package/package.json +5 -3
  58. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/corrected-replay/derived/run-integrity-evidence.json +99 -0
  59. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/corrected-replay/producer/implementation-audit.json +1585 -0
  60. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/corrected-replay/producer/implementation-capsule.json +11455 -0
  61. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/00-request.txt +1 -0
  62. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/architecture-context-packet.txt +82 -0
  63. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/behavior-model.txt +104 -0
  64. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/final-report.txt +41 -0
  65. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/implementation-context-packet.txt +114 -0
  66. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/implementation-report.txt +92 -0
  67. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/judge-report.txt +34 -0
  68. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/pseudocode-packet.txt +244 -0
  69. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/request-brief.txt +40 -0
  70. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/test-context-packet.txt +93 -0
  71. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/test-implementation-report.txt +69 -0
  72. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/test-strategy-packet.txt +354 -0
  73. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/verification-report.txt +85 -0
  74. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/derived/run-integrity-evidence.json +98 -0
  75. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/architecture-audit.json +1169 -0
  76. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/architecture-request.json +29 -0
  77. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/implementation-audit.json +1494 -0
  78. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/implementation-capsule.json +11364 -0
  79. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/implementation-request.json +33 -0
  80. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/test-request.json +74 -0
  81. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/reports/architecture-context-retrieval-report.txt +58 -0
  82. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/reports/implementation-context-retrieval-report.txt +75 -0
  83. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/reports/test-context-retrieval-report.txt +84 -0
  84. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/run.json +62 -0
  85. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/tool-versions/my-dev-kit-version.txt +1 -0
  86. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/tool-versions/orchestrator-version.txt +1 -0
  87. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/manifests/corrected-replay-manifest.json +19 -0
  88. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/manifests/failed-run-manifest.json +56 -0
  89. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.4/PROVENANCE.txt +18 -0
  90. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.4/context-capsule/complete-v1.0.0.json +556 -0
  91. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.4/retrieval-audit-record/complete-v1.0.0.json +238 -0
  92. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/PROVENANCE.txt +13 -0
  93. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/context-capsule.json +7874 -0
  94. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/retrieval-audit-record.json +1076 -0
  95. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.3/run-integrity/PROVENANCE.txt +31 -0
  96. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.3/run-integrity/ready-pass-final-pass.json +132 -0
  97. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.3/run-integrity/refresh-required-need-context.json +146 -0
@@ -909,7 +909,7 @@ function validateTestInfrastructureSummary(ctx, value, fieldPath) {
909
909
  }
910
910
  function validateGroupTruncationEntry(ctx, value, fieldPath) {
911
911
  const obj = requiredObject(ctx, value, fieldPath);
912
- return {
912
+ const result = {
913
913
  groupId: requiredString(ctx, requiredField(ctx, obj, "groupId", joinFieldPath(fieldPath, "groupId")), joinFieldPath(fieldPath, "groupId")),
914
914
  limit: requiredNullableNumber(ctx, requiredField(ctx, obj, "limit", joinFieldPath(fieldPath, "limit")), joinFieldPath(fieldPath, "limit")),
915
915
  availableCount: requiredNonnegativeInteger(ctx, requiredField(ctx, obj, "availableCount", joinFieldPath(fieldPath, "availableCount")), joinFieldPath(fieldPath, "availableCount")),
@@ -917,6 +917,54 @@ function validateGroupTruncationEntry(ctx, value, fieldPath) {
917
917
  truncated: requiredBoolean(ctx, requiredField(ctx, obj, "truncated", joinFieldPath(fieldPath, "truncated")), joinFieldPath(fieldPath, "truncated")),
918
918
  droppedCount: requiredNonnegativeInteger(ctx, requiredField(ctx, obj, "droppedCount", joinFieldPath(fieldPath, "droppedCount")), joinFieldPath(fieldPath, "droppedCount"))
919
919
  };
920
+ if (optionalField(obj, "droppedEvidenceIds") !== undefined) {
921
+ result.droppedEvidenceIds = requiredStringArray(ctx, obj.droppedEvidenceIds, joinFieldPath(fieldPath, "droppedEvidenceIds"));
922
+ }
923
+ if (optionalField(obj, "required") !== undefined)
924
+ result.required = optionalBoolean(ctx, obj.required, joinFieldPath(fieldPath, "required"));
925
+ if (optionalField(obj, "reservation") !== undefined)
926
+ result.reservation = optionalNumber(ctx, obj.reservation, joinFieldPath(fieldPath, "reservation"));
927
+ if (optionalField(obj, "initiallySelectedCount") !== undefined)
928
+ result.initiallySelectedCount = optionalNumber(ctx, obj.initiallySelectedCount, joinFieldPath(fieldPath, "initiallySelectedCount"));
929
+ if (optionalField(obj, "unusedReservationContributed") !== undefined)
930
+ result.unusedReservationContributed = optionalNumber(ctx, obj.unusedReservationContributed, joinFieldPath(fieldPath, "unusedReservationContributed"));
931
+ if (optionalField(obj, "borrowedCapacity") !== undefined)
932
+ result.borrowedCapacity = optionalNumber(ctx, obj.borrowedCapacity, joinFieldPath(fieldPath, "borrowedCapacity"));
933
+ if (optionalField(obj, "requiredOmittedCount") !== undefined)
934
+ result.requiredOmittedCount = optionalNumber(ctx, obj.requiredOmittedCount, joinFieldPath(fieldPath, "requiredOmittedCount"));
935
+ if (optionalField(obj, "optionalOmittedCount") !== undefined)
936
+ result.optionalOmittedCount = optionalNumber(ctx, obj.optionalOmittedCount, joinFieldPath(fieldPath, "optionalOmittedCount"));
937
+ if (optionalField(obj, "adequacyAffected") !== undefined)
938
+ result.adequacyAffected = optionalBoolean(ctx, obj.adequacyAffected, joinFieldPath(fieldPath, "adequacyAffected"));
939
+ if (optionalField(obj, "governingHardBound") !== undefined)
940
+ result.governingHardBound = optionalNumber(ctx, obj.governingHardBound, joinFieldPath(fieldPath, "governingHardBound"));
941
+ if (optionalField(obj, "aggregateCapacityUsed") !== undefined)
942
+ result.aggregateCapacityUsed = optionalNumber(ctx, obj.aggregateCapacityUsed, joinFieldPath(fieldPath, "aggregateCapacityUsed"));
943
+ if (optionalField(obj, "aggregateCapacityRemaining") !== undefined)
944
+ result.aggregateCapacityRemaining = optionalNumber(ctx, obj.aggregateCapacityRemaining, joinFieldPath(fieldPath, "aggregateCapacityRemaining"));
945
+ return result;
946
+ }
947
+ const ROLE_CONDITION_IDS = ["implementation.selected-owner", "implementation.required-contract"];
948
+ const ROLE_CONDITION_WITNESS_POLICIES = ["at-least-one"];
949
+ const ROLE_CONDITION_COVERAGE_LOSS_REASONS = ["bounded-allocation-omitted-required-witnesses"];
950
+ const ROLE_CONDITION_ROLES = ["architecture", "implementation", "test-implementation"];
951
+ export function validateRoleConditionCoverage(ctx, value, fieldPath) {
952
+ const obj = requiredObject(ctx, value, fieldPath);
953
+ return {
954
+ conditionId: requiredLiteral(ctx, requiredField(ctx, obj, "conditionId", joinFieldPath(fieldPath, "conditionId")), joinFieldPath(fieldPath, "conditionId"), ROLE_CONDITION_IDS),
955
+ role: requiredLiteral(ctx, requiredField(ctx, obj, "role", joinFieldPath(fieldPath, "role")), joinFieldPath(fieldPath, "role"), ROLE_CONDITION_ROLES),
956
+ required: requiredBoolean(ctx, requiredField(ctx, obj, "required", joinFieldPath(fieldPath, "required")), joinFieldPath(fieldPath, "required")),
957
+ evidenceGroupIds: requiredStringArray(ctx, requiredField(ctx, obj, "evidenceGroupIds", joinFieldPath(fieldPath, "evidenceGroupIds")), joinFieldPath(fieldPath, "evidenceGroupIds")),
958
+ witnessPolicy: requiredLiteral(ctx, requiredField(ctx, obj, "witnessPolicy", joinFieldPath(fieldPath, "witnessPolicy")), joinFieldPath(fieldPath, "witnessPolicy"), ROLE_CONDITION_WITNESS_POLICIES),
959
+ requiredWitnessCount: requiredNonnegativeInteger(ctx, requiredField(ctx, obj, "requiredWitnessCount", joinFieldPath(fieldPath, "requiredWitnessCount")), joinFieldPath(fieldPath, "requiredWitnessCount")),
960
+ availableWitnessCount: requiredNonnegativeInteger(ctx, requiredField(ctx, obj, "availableWitnessCount", joinFieldPath(fieldPath, "availableWitnessCount")), joinFieldPath(fieldPath, "availableWitnessCount")),
961
+ retainedWitnessCount: requiredNonnegativeInteger(ctx, requiredField(ctx, obj, "retainedWitnessCount", joinFieldPath(fieldPath, "retainedWitnessCount")), joinFieldPath(fieldPath, "retainedWitnessCount")),
962
+ retainedWitnessIds: requiredStringArray(ctx, requiredField(ctx, obj, "retainedWitnessIds", joinFieldPath(fieldPath, "retainedWitnessIds")), joinFieldPath(fieldPath, "retainedWitnessIds")),
963
+ conditionSatisfied: requiredBoolean(ctx, requiredField(ctx, obj, "conditionSatisfied", joinFieldPath(fieldPath, "conditionSatisfied")), joinFieldPath(fieldPath, "conditionSatisfied")),
964
+ lostRequiredCondition: requiredBoolean(ctx, requiredField(ctx, obj, "lostRequiredCondition", joinFieldPath(fieldPath, "lostRequiredCondition")), joinFieldPath(fieldPath, "lostRequiredCondition")),
965
+ lossReason: requiredNullableLiteral(ctx, requiredField(ctx, obj, "lossReason", joinFieldPath(fieldPath, "lossReason")), joinFieldPath(fieldPath, "lossReason"), ROLE_CONDITION_COVERAGE_LOSS_REASONS),
966
+ evaluationOrder: requiredNumber(ctx, requiredField(ctx, obj, "evaluationOrder", joinFieldPath(fieldPath, "evaluationOrder")), joinFieldPath(fieldPath, "evaluationOrder"))
967
+ };
920
968
  }
921
969
  export function validateProvenanceRecord(ctx, value, fieldPath) {
922
970
  const obj = requiredObject(ctx, value, fieldPath);
@@ -1040,11 +1088,15 @@ function validateCapsuleTruncationRecord(ctx, value, fieldPath) {
1040
1088
  }
1041
1089
  export function validateTruncationSummary(ctx, value, fieldPath) {
1042
1090
  const obj = requiredObject(ctx, value, fieldPath);
1043
- return {
1091
+ const result = {
1044
1092
  truncated: requiredBoolean(ctx, requiredField(ctx, obj, "truncated", joinFieldPath(fieldPath, "truncated")), joinFieldPath(fieldPath, "truncated")),
1045
1093
  records: requiredArray(ctx, requiredField(ctx, obj, "records", joinFieldPath(fieldPath, "records")), joinFieldPath(fieldPath, "records")).map((item, i) => validateCapsuleTruncationRecord(ctx, item, arrayFieldPath(joinFieldPath(fieldPath, "records"), i))),
1046
1094
  warnings: requiredStringArray(ctx, requiredField(ctx, obj, "warnings", joinFieldPath(fieldPath, "warnings")), joinFieldPath(fieldPath, "warnings"))
1047
1095
  };
1096
+ if (optionalField(obj, "requiredEvidenceLost") !== undefined) {
1097
+ result.requiredEvidenceLost = optionalBoolean(ctx, obj.requiredEvidenceLost, joinFieldPath(fieldPath, "requiredEvidenceLost"));
1098
+ }
1099
+ return result;
1048
1100
  }
1049
1101
  function validateFullFileFallbackRecord(ctx, value, fieldPath) {
1050
1102
  const obj = requiredObject(ctx, value, fieldPath);
@@ -1178,6 +1230,11 @@ export function validateMyDevKitContextCapsuleV1(value, sourcePath) {
1178
1230
  testInfrastructure: validateTestInfrastructureSummary(ctx, requiredField(ctx, value, "testInfrastructure", "testInfrastructure"), "testInfrastructure"),
1179
1231
  unresolvedItems: requiredArray(ctx, requiredField(ctx, value, "unresolvedItems", "unresolvedItems"), "unresolvedItems").map((item, i) => validateUnresolvedEvidenceItem(ctx, item, arrayFieldPath("unresolvedItems", i))),
1180
1232
  groupTruncation: requiredArray(ctx, requiredField(ctx, value, "groupTruncation", "groupTruncation"), "groupTruncation").map((item, i) => validateGroupTruncationEntry(ctx, item, arrayFieldPath("groupTruncation", i))),
1233
+ ...(optionalField(value, "roleConditionCoverage") !== undefined
1234
+ ? {
1235
+ roleConditionCoverage: requiredArray(ctx, value.roleConditionCoverage, "roleConditionCoverage").map((item, i) => validateRoleConditionCoverage(ctx, item, arrayFieldPath("roleConditionCoverage", i)))
1236
+ }
1237
+ : {}),
1181
1238
  responsibilityMappings: validateResponsibilityMappingSummary(ctx, requiredField(ctx, value, "responsibilityMappings", "responsibilityMappings"), "responsibilityMappings"),
1182
1239
  roleAdequacy: validateRoleAdequacyStatement(ctx, requiredField(ctx, value, "roleAdequacy", "roleAdequacy"), "roleAdequacy"),
1183
1240
  freshness: validateFreshnessSummary(ctx, requiredField(ctx, value, "freshness", "freshness"), "freshness"),
@@ -1,6 +1,6 @@
1
1
  import { parseSupportedMajorOneSchemaVersion } from "./schemaVersion.js";
2
- import { ArtifactValidationError, arrayFieldPath, joinFieldPath, requiredArray, requiredField, requiredLiteral, requiredObject, requiredRecord, requiredScalarLike, requiredString, requiredStringArray } from "./runtimeValidation.js";
3
- import { validateBudgetSummary, validateContextAdequacyStatement, validateContextCapsuleRequest, validateFreshnessSummary, validateFullFileFallbackSummary, validateProvenanceRecord, validateResponsibilityMappingSummary, validateRoleAdequacyStatement, validateRoleContextSummary, validateTruncationSummary } from "./validateMyDevKitContextCapsuleV1.js";
2
+ import { ArtifactValidationError, arrayFieldPath, joinFieldPath, optionalField, optionalString, requiredArray, requiredField, requiredLiteral, requiredObject, requiredRecord, requiredScalarLike, requiredString, requiredStringArray } from "./runtimeValidation.js";
3
+ import { validateBudgetSummary, validateContextAdequacyStatement, validateContextCapsuleRequest, validateFreshnessSummary, validateFullFileFallbackSummary, validateProvenanceRecord, validateResponsibilityMappingSummary, validateRoleAdequacyStatement, validateRoleConditionCoverage, validateRoleContextSummary, validateTruncationSummary } from "./validateMyDevKitContextCapsuleV1.js";
4
4
  const ARTIFACT_KIND = "my-dev-kit-retrieval-audit-record-v1";
5
5
  const AUDIT_STEP_STATUSES = ["ok", "skipped", "failed"];
6
6
  function validateContextCapsuleTool(ctx, value, fieldPath) {
@@ -12,10 +12,17 @@ function validateContextCapsuleTool(ctx, value, fieldPath) {
12
12
  }
13
13
  function validateRetrievalAuditRecordIndex(ctx, value, fieldPath) {
14
14
  const obj = requiredObject(ctx, value, fieldPath);
15
- return {
15
+ const result = {
16
16
  indexPath: requiredString(ctx, requiredField(ctx, obj, "indexPath", joinFieldPath(fieldPath, "indexPath")), joinFieldPath(fieldPath, "indexPath")),
17
17
  manifestPath: requiredString(ctx, requiredField(ctx, obj, "manifestPath", joinFieldPath(fieldPath, "manifestPath")), joinFieldPath(fieldPath, "manifestPath"))
18
18
  };
19
+ if (optionalField(obj, "manifestSchemaVersion") !== undefined) {
20
+ result.manifestSchemaVersion = optionalString(ctx, obj.manifestSchemaVersion, joinFieldPath(fieldPath, "manifestSchemaVersion"));
21
+ }
22
+ if (optionalField(obj, "projectRoot") !== undefined) {
23
+ result.projectRoot = optionalString(ctx, obj.projectRoot, joinFieldPath(fieldPath, "projectRoot"));
24
+ }
25
+ return result;
19
26
  }
20
27
  function validateAuditStepRecord(ctx, value, fieldPath) {
21
28
  const obj = requiredRecord(ctx, value, fieldPath);
@@ -76,6 +83,11 @@ export function validateMyDevKitRetrievalAuditRecordV1(value, sourcePath) {
76
83
  contextAdequacy: validateContextAdequacyStatement(ctx, requiredField(ctx, value, "contextAdequacy", "contextAdequacy"), "contextAdequacy"),
77
84
  roleContext: validateRoleContextSummary(ctx, requiredField(ctx, value, "roleContext", "roleContext"), "roleContext"),
78
85
  responsibilityMappings: validateResponsibilityMappingSummary(ctx, requiredField(ctx, value, "responsibilityMappings", "responsibilityMappings"), "responsibilityMappings"),
86
+ ...(optionalField(value, "roleConditionCoverage") !== undefined
87
+ ? {
88
+ roleConditionCoverage: requiredArray(ctx, value.roleConditionCoverage, "roleConditionCoverage").map((item, i) => validateRoleConditionCoverage(ctx, item, arrayFieldPath("roleConditionCoverage", i)))
89
+ }
90
+ : {}),
79
91
  roleAdequacy: validateRoleAdequacyStatement(ctx, requiredField(ctx, value, "roleAdequacy", "roleAdequacy"), "roleAdequacy"),
80
92
  freshness: validateFreshnessSummary(ctx, requiredField(ctx, value, "freshness", "freshness"), "freshness"),
81
93
  budget: validateBudgetSummary(ctx, requiredField(ctx, value, "budget", "budget"), "budget"),
@@ -0,0 +1,177 @@
1
+ import { parseSupportedMajorOneSchemaVersion } from "./schemaVersion.js";
2
+ import { ArtifactValidationError, arrayFieldPath, joinFieldPath, optionalField, optionalString, requiredArray, requiredBoolean, requiredField, requiredLiteral, requiredNullableLiteral, requiredNullableString, requiredObject, requiredString, requiredStringArray } from "./runtimeValidation.js";
3
+ import { validateOrchestratorContextReadinessResultV1 } from "./orchestratorContextReadinessResultV1.js";
4
+ import { ARTIFACT_LIFECYCLE_STATES, CONTEXT_SENSITIVE_STAGE_NAMES, CORRECTABLE_STAGES, JUDGE_VERDICT_PARSE_STATUSES, JUDGE_VERDICTS, MANUAL_ARTIFACT_LIFECYCLE_STATES, ROUTE_STATUSES, RUN_INTEGRITY_READINESS_CLASSIFICATIONS } from "./orchestratorRunIntegrityV1.js";
5
+ const ARTIFACT_KIND = "orchestrator-run-integrity-evidence-v1";
6
+ const EXPECTED_JUDGE_VERDICTS = ["PASS", "NEED_CONTEXT"];
7
+ const APPLICABLE_CONTEXT_KINDS = ["implementation", "test"];
8
+ function validateContextReadinessNested(ctx, value, fieldPath) {
9
+ const result = validateOrchestratorContextReadinessResultV1(value, `${ctx.sourcePath}#${fieldPath}`);
10
+ if (!result.ok) {
11
+ throw new ArtifactValidationError({
12
+ ok: false,
13
+ artifactKind: ctx.artifactKind,
14
+ sourcePath: ctx.sourcePath,
15
+ code: result.code,
16
+ message: `Nested readiness field "${fieldPath}" is invalid: ${result.message}`,
17
+ fieldPath,
18
+ expected: result.expected,
19
+ actual: result.actual
20
+ });
21
+ }
22
+ return result.artifact;
23
+ }
24
+ function validateCorrectionRouteResult(ctx, value, fieldPath) {
25
+ const obj = requiredObject(ctx, value, fieldPath);
26
+ return {
27
+ verdict: requiredNullableLiteral(ctx, requiredField(ctx, obj, "verdict", joinFieldPath(fieldPath, "verdict")), joinFieldPath(fieldPath, "verdict"), JUDGE_VERDICTS),
28
+ recommendedStage: requiredNullableString(ctx, requiredField(ctx, obj, "recommendedStage", joinFieldPath(fieldPath, "recommendedStage")), joinFieldPath(fieldPath, "recommendedStage")),
29
+ routedStage: requiredNullableLiteral(ctx, requiredField(ctx, obj, "routedStage", joinFieldPath(fieldPath, "routedStage")), joinFieldPath(fieldPath, "routedStage"), CORRECTABLE_STAGES),
30
+ routeStatus: requiredLiteral(ctx, requiredField(ctx, obj, "routeStatus", joinFieldPath(fieldPath, "routeStatus")), joinFieldPath(fieldPath, "routeStatus"), ROUTE_STATUSES),
31
+ warnings: requiredStringArray(ctx, requiredField(ctx, obj, "warnings", joinFieldPath(fieldPath, "warnings")), joinFieldPath(fieldPath, "warnings")),
32
+ errors: requiredStringArray(ctx, requiredField(ctx, obj, "errors", joinFieldPath(fieldPath, "errors")), joinFieldPath(fieldPath, "errors")),
33
+ isBlocked: requiredBoolean(ctx, requiredField(ctx, obj, "isBlocked", joinFieldPath(fieldPath, "isBlocked")), joinFieldPath(fieldPath, "isBlocked")),
34
+ strictFail: requiredBoolean(ctx, requiredField(ctx, obj, "strictFail", joinFieldPath(fieldPath, "strictFail")), joinFieldPath(fieldPath, "strictFail"))
35
+ };
36
+ }
37
+ function validateGate(ctx, value, fieldPath) {
38
+ const obj = requiredObject(ctx, value, fieldPath);
39
+ const result = {
40
+ schemaVersion: requiredLiteral(ctx, requiredField(ctx, obj, "schemaVersion", joinFieldPath(fieldPath, "schemaVersion")), joinFieldPath(fieldPath, "schemaVersion"), ["1.0.0"]),
41
+ mode: requiredString(ctx, requiredField(ctx, obj, "mode", joinFieldPath(fieldPath, "mode")), joinFieldPath(fieldPath, "mode")),
42
+ contextRequired: requiredBoolean(ctx, requiredField(ctx, obj, "contextRequired", joinFieldPath(fieldPath, "contextRequired")), joinFieldPath(fieldPath, "contextRequired")),
43
+ applicableContextKinds: requiredArray(ctx, requiredField(ctx, obj, "applicableContextKinds", joinFieldPath(fieldPath, "applicableContextKinds")), joinFieldPath(fieldPath, "applicableContextKinds")).map((item, i) => requiredLiteral(ctx, item, arrayFieldPath(joinFieldPath(fieldPath, "applicableContextKinds"), i), APPLICABLE_CONTEXT_KINDS)),
44
+ contextReady: requiredBoolean(ctx, requiredField(ctx, obj, "contextReady", joinFieldPath(fieldPath, "contextReady")), joinFieldPath(fieldPath, "contextReady")),
45
+ readinessClassification: requiredLiteral(ctx, requiredField(ctx, obj, "readinessClassification", joinFieldPath(fieldPath, "readinessClassification")), joinFieldPath(fieldPath, "readinessClassification"), RUN_INTEGRITY_READINESS_CLASSIFICATIONS),
46
+ blockedStageNames: requiredArray(ctx, requiredField(ctx, obj, "blockedStageNames", joinFieldPath(fieldPath, "blockedStageNames")), joinFieldPath(fieldPath, "blockedStageNames")).map((item, i) => requiredLiteral(ctx, item, arrayFieldPath(joinFieldPath(fieldPath, "blockedStageNames"), i), CONTEXT_SENSITIVE_STAGE_NAMES)),
47
+ blockingCodes: requiredStringArray(ctx, requiredField(ctx, obj, "blockingCodes", joinFieldPath(fieldPath, "blockingCodes")), joinFieldPath(fieldPath, "blockingCodes")),
48
+ recommendedCorrectionStage: requiredNullableString(ctx, requiredField(ctx, obj, "recommendedCorrectionStage", joinFieldPath(fieldPath, "recommendedCorrectionStage")), joinFieldPath(fieldPath, "recommendedCorrectionStage")),
49
+ expectedJudgeVerdict: requiredLiteral(ctx, requiredField(ctx, obj, "expectedJudgeVerdict", joinFieldPath(fieldPath, "expectedJudgeVerdict")), joinFieldPath(fieldPath, "expectedJudgeVerdict"), EXPECTED_JUDGE_VERDICTS),
50
+ warnings: requiredStringArray(ctx, requiredField(ctx, obj, "warnings", joinFieldPath(fieldPath, "warnings")), joinFieldPath(fieldPath, "warnings"))
51
+ };
52
+ if (optionalField(obj, "implementationContext") !== undefined) {
53
+ result.implementationContext = validateContextReadinessNested(ctx, obj.implementationContext, joinFieldPath(fieldPath, "implementationContext"));
54
+ }
55
+ if (optionalField(obj, "testContext") !== undefined) {
56
+ result.testContext = validateContextReadinessNested(ctx, obj.testContext, joinFieldPath(fieldPath, "testContext"));
57
+ }
58
+ if (optionalField(obj, "primaryBlocker") !== undefined) {
59
+ // primaryBlocker reuses ContextReadinessBlockerSummary's exact shape (owned by
60
+ // orchestratorContextReadinessResultV1.ts's blockerSummary field); walked structurally
61
+ // here rather than re-validated through a second nested-artifact call, since it is not
62
+ // itself a standalone readiness artifact.
63
+ const blockerObj = requiredObject(ctx, obj.primaryBlocker, joinFieldPath(fieldPath, "primaryBlocker"));
64
+ result.primaryBlocker = blockerObj;
65
+ }
66
+ return result;
67
+ }
68
+ function validateJudgeIntegrity(ctx, value, fieldPath) {
69
+ const obj = requiredObject(ctx, value, fieldPath);
70
+ const result = {
71
+ schemaVersion: requiredLiteral(ctx, requiredField(ctx, obj, "schemaVersion", joinFieldPath(fieldPath, "schemaVersion")), joinFieldPath(fieldPath, "schemaVersion"), ["1.0.0"]),
72
+ judgeArtifactPresent: requiredBoolean(ctx, requiredField(ctx, obj, "judgeArtifactPresent", joinFieldPath(fieldPath, "judgeArtifactPresent")), joinFieldPath(fieldPath, "judgeArtifactPresent")),
73
+ judgeVerdictParseStatus: requiredLiteral(ctx, requiredField(ctx, obj, "judgeVerdictParseStatus", joinFieldPath(fieldPath, "judgeVerdictParseStatus")), joinFieldPath(fieldPath, "judgeVerdictParseStatus"), JUDGE_VERDICT_PARSE_STATUSES),
74
+ authoredJudgeVerdict: requiredNullableLiteral(ctx, requiredField(ctx, obj, "authoredJudgeVerdict", joinFieldPath(fieldPath, "authoredJudgeVerdict")), joinFieldPath(fieldPath, "authoredJudgeVerdict"), JUDGE_VERDICTS),
75
+ expectedJudgeVerdict: requiredLiteral(ctx, requiredField(ctx, obj, "expectedJudgeVerdict", joinFieldPath(fieldPath, "expectedJudgeVerdict")), joinFieldPath(fieldPath, "expectedJudgeVerdict"), EXPECTED_JUDGE_VERDICTS),
76
+ judgeVerdictMatchesExpected: requiredBoolean(ctx, requiredField(ctx, obj, "judgeVerdictMatchesExpected", joinFieldPath(fieldPath, "judgeVerdictMatchesExpected")), joinFieldPath(fieldPath, "judgeVerdictMatchesExpected")),
77
+ judgeVerdictAccepted: requiredBoolean(ctx, requiredField(ctx, obj, "judgeVerdictAccepted", joinFieldPath(fieldPath, "judgeVerdictAccepted")), joinFieldPath(fieldPath, "judgeVerdictAccepted")),
78
+ correctionRequired: requiredBoolean(ctx, requiredField(ctx, obj, "correctionRequired", joinFieldPath(fieldPath, "correctionRequired")), joinFieldPath(fieldPath, "correctionRequired")),
79
+ correctionBlocked: requiredBoolean(ctx, requiredField(ctx, obj, "correctionBlocked", joinFieldPath(fieldPath, "correctionBlocked")), joinFieldPath(fieldPath, "correctionBlocked")),
80
+ acceptedCorrectionStage: requiredNullableString(ctx, requiredField(ctx, obj, "acceptedCorrectionStage", joinFieldPath(fieldPath, "acceptedCorrectionStage")), joinFieldPath(fieldPath, "acceptedCorrectionStage")),
81
+ finalReportEligible: requiredBoolean(ctx, requiredField(ctx, obj, "finalReportEligible", joinFieldPath(fieldPath, "finalReportEligible")), joinFieldPath(fieldPath, "finalReportEligible")),
82
+ blockingCodes: requiredStringArray(ctx, requiredField(ctx, obj, "blockingCodes", joinFieldPath(fieldPath, "blockingCodes")), joinFieldPath(fieldPath, "blockingCodes")),
83
+ acceptedCorrectionRoute: (() => {
84
+ const routeValue = requiredField(ctx, obj, "acceptedCorrectionRoute", joinFieldPath(fieldPath, "acceptedCorrectionRoute"));
85
+ return routeValue === null ? null : validateCorrectionRouteResult(ctx, routeValue, joinFieldPath(fieldPath, "acceptedCorrectionRoute"));
86
+ })()
87
+ };
88
+ if (optionalField(obj, "primaryReason") !== undefined) {
89
+ result.primaryReason = optionalString(ctx, obj.primaryReason, joinFieldPath(fieldPath, "primaryReason"));
90
+ }
91
+ return result;
92
+ }
93
+ function validateFinalReportEligibility(ctx, value, fieldPath) {
94
+ const obj = requiredObject(ctx, value, fieldPath);
95
+ const result = {
96
+ eligible: requiredBoolean(ctx, requiredField(ctx, obj, "eligible", joinFieldPath(fieldPath, "eligible")), joinFieldPath(fieldPath, "eligible")),
97
+ contextReady: requiredBoolean(ctx, requiredField(ctx, obj, "contextReady", joinFieldPath(fieldPath, "contextReady")), joinFieldPath(fieldPath, "contextReady")),
98
+ priorArtifactsValid: requiredBoolean(ctx, requiredField(ctx, obj, "priorArtifactsValid", joinFieldPath(fieldPath, "priorArtifactsValid")), joinFieldPath(fieldPath, "priorArtifactsValid")),
99
+ judgeIntegrity: validateJudgeIntegrity(ctx, requiredField(ctx, obj, "judgeIntegrity", joinFieldPath(fieldPath, "judgeIntegrity")), joinFieldPath(fieldPath, "judgeIntegrity")),
100
+ blockingCodes: requiredStringArray(ctx, requiredField(ctx, obj, "blockingCodes", joinFieldPath(fieldPath, "blockingCodes")), joinFieldPath(fieldPath, "blockingCodes"))
101
+ };
102
+ if (optionalField(obj, "primaryReason") !== undefined) {
103
+ result.primaryReason = optionalString(ctx, obj.primaryReason, joinFieldPath(fieldPath, "primaryReason"));
104
+ }
105
+ return result;
106
+ }
107
+ function validateArtifactStateRecord(ctx, value, fieldPath) {
108
+ const obj = requiredObject(ctx, value, fieldPath);
109
+ const result = {
110
+ state: requiredLiteral(ctx, requiredField(ctx, obj, "state", joinFieldPath(fieldPath, "state")), joinFieldPath(fieldPath, "state"), MANUAL_ARTIFACT_LIFECYCLE_STATES),
111
+ updatedAt: requiredString(ctx, requiredField(ctx, obj, "updatedAt", joinFieldPath(fieldPath, "updatedAt")), joinFieldPath(fieldPath, "updatedAt"))
112
+ };
113
+ if (optionalField(obj, "reason") !== undefined)
114
+ result.reason = optionalString(ctx, obj.reason, joinFieldPath(fieldPath, "reason"));
115
+ if (optionalField(obj, "source") !== undefined)
116
+ result.source = optionalString(ctx, obj.source, joinFieldPath(fieldPath, "source"));
117
+ return result;
118
+ }
119
+ function validateLifecycleEntry(ctx, value, fieldPath) {
120
+ const obj = requiredObject(ctx, value, fieldPath);
121
+ const manualRecordValue = requiredField(ctx, obj, "manualRecord", joinFieldPath(fieldPath, "manualRecord"));
122
+ const result = {
123
+ artifactFile: requiredString(ctx, requiredField(ctx, obj, "artifactFile", joinFieldPath(fieldPath, "artifactFile")), joinFieldPath(fieldPath, "artifactFile")),
124
+ stageName: requiredString(ctx, requiredField(ctx, obj, "stageName", joinFieldPath(fieldPath, "stageName")), joinFieldPath(fieldPath, "stageName")),
125
+ fileExists: requiredBoolean(ctx, requiredField(ctx, obj, "fileExists", joinFieldPath(fieldPath, "fileExists")), joinFieldPath(fieldPath, "fileExists")),
126
+ manualRecord: manualRecordValue === null ? null : validateArtifactStateRecord(ctx, manualRecordValue, joinFieldPath(fieldPath, "manualRecord")),
127
+ resolvedState: requiredLiteral(ctx, requiredField(ctx, obj, "resolvedState", joinFieldPath(fieldPath, "resolvedState")), joinFieldPath(fieldPath, "resolvedState"), ARTIFACT_LIFECYCLE_STATES)
128
+ };
129
+ if (optionalField(obj, "blockingReason") !== undefined) {
130
+ result.blockingReason = optionalString(ctx, obj.blockingReason, joinFieldPath(fieldPath, "blockingReason"));
131
+ }
132
+ return result;
133
+ }
134
+ export function validateOrchestratorRunIntegrityEvidenceV1(value, sourcePath) {
135
+ const ctx = { artifactKind: ARTIFACT_KIND, sourcePath };
136
+ try {
137
+ const schemaVersionResult = parseSupportedMajorOneSchemaVersion(requiredField(ctx, value, "schemaVersion", "schemaVersion"), ARTIFACT_KIND, sourcePath);
138
+ if ("ok" in schemaVersionResult)
139
+ return schemaVersionResult;
140
+ const evidence = {
141
+ schemaVersion: requiredString(ctx, value.schemaVersion, "schemaVersion"),
142
+ runFolder: requiredString(ctx, requiredField(ctx, value, "runFolder", "runFolder"), "runFolder"),
143
+ gate: validateGate(ctx, requiredField(ctx, value, "gate", "gate"), "gate"),
144
+ lifecycle: requiredArray(ctx, requiredField(ctx, value, "lifecycle", "lifecycle"), "lifecycle").map((item, i) => validateLifecycleEntry(ctx, item, arrayFieldPath("lifecycle", i)))
145
+ };
146
+ if (optionalField(value, "judgeIntegrity") !== undefined) {
147
+ evidence.judgeIntegrity = validateJudgeIntegrity(ctx, value.judgeIntegrity, "judgeIntegrity");
148
+ }
149
+ if (optionalField(value, "finalReportEligibility") !== undefined) {
150
+ evidence.finalReportEligibility = validateFinalReportEligibility(ctx, value.finalReportEligibility, "finalReportEligibility");
151
+ }
152
+ if (optionalField(value, "finalArtifactPresent") !== undefined) {
153
+ evidence.finalArtifactPresent = requiredBoolean(ctx, value.finalArtifactPresent, "finalArtifactPresent");
154
+ }
155
+ if (optionalField(value, "finalArtifactVerdict") !== undefined) {
156
+ evidence.finalArtifactVerdict = requiredNullableLiteral(ctx, value.finalArtifactVerdict, "finalArtifactVerdict", JUDGE_VERDICTS);
157
+ }
158
+ // Per the exact-mirror contract, the returned artifact is always the original parsed
159
+ // reference, not a rebuilt object. The construction above exists only to walk and
160
+ // type-check every field.
161
+ void evidence;
162
+ return {
163
+ ok: true,
164
+ artifactKind: ARTIFACT_KIND,
165
+ sourcePath,
166
+ schemaVersion: value.schemaVersion,
167
+ schemaMajor: 1,
168
+ artifact: value,
169
+ rawArtifact: value
170
+ };
171
+ }
172
+ catch (error) {
173
+ if (error instanceof ArtifactValidationError)
174
+ return error.failure;
175
+ throw error;
176
+ }
177
+ }
@@ -0,0 +1,148 @@
1
+ import { makeFailure } from "./runtimeValidation.js";
2
+ import { parseSupplementalContextText } from "./supplementalContextTextParser.js";
3
+ import { REQUIRED_METADATA_BY_DOCUMENT_KIND, REQUIRED_SECTIONS_BY_DOCUMENT_KIND, ROLE_BY_DOCUMENT_KIND, SUPPLEMENTAL_CONTEXT_PACKET_SCHEMA_SUPPORTED_MAJOR, SUPPLEMENTAL_CONTEXT_RETRIEVAL_REPORT_SCHEMA_SUPPORTED_MAJOR, VALID_ADEQUACY_VALUES, VALID_DECLARED_STATUSES, VALID_FRESHNESS_VALUES, VALID_REPOSITORY_SCOPES, VALID_TRUNCATION_VALUES, isRetrievalReportKind, isTestKind } from "./supplementalContextTypes.js";
4
+ const SCHEMA_VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+$/;
5
+ function supportedMajorForKind(kind) {
6
+ return isRetrievalReportKind(kind)
7
+ ? SUPPLEMENTAL_CONTEXT_RETRIEVAL_REPORT_SCHEMA_SUPPORTED_MAJOR
8
+ : SUPPLEMENTAL_CONTEXT_PACKET_SCHEMA_SUPPORTED_MAJOR;
9
+ }
10
+ function literalOrFail(artifactKind, sourcePath, fieldPath, value, allowed, errorCode = "INVALID_LITERAL_VALUE") {
11
+ if (allowed.includes(value))
12
+ return value;
13
+ return {
14
+ ok: false,
15
+ artifactKind,
16
+ sourcePath,
17
+ code: errorCode,
18
+ message: `Field "${fieldPath}" in artifact "${artifactKind}" at "${sourcePath}" has invalid value "${value}". Expected one of: ${allowed.join(", ")}.`,
19
+ fieldPath,
20
+ expected: allowed.join(" | "),
21
+ actual: value
22
+ };
23
+ }
24
+ function isFailure(value) {
25
+ return typeof value === "object" && value !== null && value.ok === false;
26
+ }
27
+ export function validateSupplementalContextDocumentV1(artifactKind, expectedKind, text, sourcePath) {
28
+ const parsed = parseSupplementalContextText(text);
29
+ if (parsed.metadataOrder.length === 0 && parsed.sectionOrder.length === 0) {
30
+ return makeFailure(artifactKind, sourcePath, "MALFORMED_TEXT_ARTIFACT", `Artifact "${artifactKind}" at "${sourcePath}" contains no recognizable "Key: value" metadata or "## Heading" sections.`);
31
+ }
32
+ // Kind/role identity is checked before general required-metadata/section completeness so
33
+ // that feeding one document kind's file to another kind's reader is reported as a
34
+ // structural identity mismatch (DOCUMENT_KIND_MISMATCH / DOCUMENT_ROLE_MISMATCH) rather
35
+ // than as an incidental "missing metadata key" from the wrong kind's required-field list.
36
+ const declaredKind = parsed.metadata["Document kind"];
37
+ if (declaredKind !== expectedKind) {
38
+ return makeFailure(artifactKind, sourcePath, "DOCUMENT_KIND_MISMATCH", `Artifact "${artifactKind}" at "${sourcePath}" declares document kind "${declaredKind}" but this reader expects "${expectedKind}".`, "Document kind", expectedKind, declaredKind);
39
+ }
40
+ const expectedRole = ROLE_BY_DOCUMENT_KIND[expectedKind];
41
+ const declaredRole = parsed.metadata["Role"];
42
+ if (declaredRole !== expectedRole) {
43
+ return makeFailure(artifactKind, sourcePath, "DOCUMENT_ROLE_MISMATCH", `Artifact "${artifactKind}" at "${sourcePath}" declares role "${declaredRole}" but this reader expects "${expectedRole}".`, "Role", expectedRole, declaredRole);
44
+ }
45
+ const requiredMetadata = REQUIRED_METADATA_BY_DOCUMENT_KIND[expectedKind];
46
+ for (const key of requiredMetadata) {
47
+ if (!(key in parsed.metadata)) {
48
+ return makeFailure(artifactKind, sourcePath, "MISSING_REQUIRED_METADATA", `Artifact "${artifactKind}" at "${sourcePath}" is missing required metadata key "${key}".`, key, "present");
49
+ }
50
+ }
51
+ const requiredSections = REQUIRED_SECTIONS_BY_DOCUMENT_KIND[expectedKind];
52
+ for (const heading of requiredSections) {
53
+ if (!(heading in parsed.sections)) {
54
+ return makeFailure(artifactKind, sourcePath, "MISSING_REQUIRED_SECTION", `Artifact "${artifactKind}" at "${sourcePath}" is missing required section heading "## ${heading}".`, heading, "present");
55
+ }
56
+ }
57
+ const schemaVersion = parsed.metadata["Schema version"];
58
+ if (!SCHEMA_VERSION_PATTERN.test(schemaVersion)) {
59
+ return makeFailure(artifactKind, sourcePath, "INVALID_SCHEMA_VERSION", `Artifact "${artifactKind}" at "${sourcePath}" has an invalid "Schema version": expected strict "x.y.z" semantic version.`, "Schema version", "^[0-9]+\\.[0-9]+\\.[0-9]+$", schemaVersion);
60
+ }
61
+ const major = Number(schemaVersion.split(".")[0]);
62
+ const supportedMajor = supportedMajorForKind(expectedKind);
63
+ if (major !== supportedMajor) {
64
+ return makeFailure(artifactKind, sourcePath, "UNSUPPORTED_SCHEMA_MAJOR", `Artifact "${artifactKind}" at "${sourcePath}" has unsupported schema major "${major}" in "Schema version": supported major is ${supportedMajor}.`, "Schema version", String(supportedMajor), schemaVersion);
65
+ }
66
+ const status = literalOrFail(artifactKind, sourcePath, "Status", parsed.metadata["Status"], VALID_DECLARED_STATUSES, "UNKNOWN_STATUS_VALUE");
67
+ if (isFailure(status))
68
+ return status;
69
+ const repositoryScope = literalOrFail(artifactKind, sourcePath, "Repository scope", parsed.metadata["Repository scope"], VALID_REPOSITORY_SCOPES);
70
+ if (isFailure(repositoryScope))
71
+ return repositoryScope;
72
+ const freshness = literalOrFail(artifactKind, sourcePath, "Freshness", parsed.metadata["Freshness"], VALID_FRESHNESS_VALUES);
73
+ if (isFailure(freshness))
74
+ return freshness;
75
+ const adequacy = literalOrFail(artifactKind, sourcePath, "Adequacy", parsed.metadata["Adequacy"], VALID_ADEQUACY_VALUES);
76
+ if (isFailure(adequacy))
77
+ return adequacy;
78
+ const requiredEvidenceTruncated = literalOrFail(artifactKind, sourcePath, "Required evidence truncated", parsed.metadata["Required evidence truncated"], VALID_TRUNCATION_VALUES);
79
+ if (isFailure(requiredEvidenceTruncated))
80
+ return requiredEvidenceTruncated;
81
+ const indexIdentity = parsed.metadata["Index identity"];
82
+ if (!indexIdentity || indexIdentity.length === 0) {
83
+ return makeFailure(artifactKind, sourcePath, "MISSING_CANONICAL_IDENTITY", `Artifact "${artifactKind}" at "${sourcePath}" is missing a non-empty canonical "Index identity".`, "Index identity", "present");
84
+ }
85
+ const document = {
86
+ documentKind: expectedKind,
87
+ role: expectedRole,
88
+ schemaVersion,
89
+ schemaMajor: 1,
90
+ status,
91
+ repositoryScope,
92
+ freshness,
93
+ adequacy,
94
+ requiredEvidenceTruncated,
95
+ contextCapsuleSchemaVersion: parsed.metadata["Context capsule schema version"],
96
+ retrievalAuditSchemaVersion: parsed.metadata["Retrieval audit schema version"],
97
+ toolName: parsed.metadata["Tool name"],
98
+ toolVersion: parsed.metadata["Tool version"],
99
+ indexIdentity,
100
+ rawMetadata: parsed.metadata,
101
+ sections: parsed.sections,
102
+ sectionOrder: parsed.sectionOrder,
103
+ metadataOrder: parsed.metadataOrder,
104
+ warnings: []
105
+ };
106
+ if (isRetrievalReportKind(expectedKind)) {
107
+ document.requestSchemaVersion = parsed.metadata["Request schema version"];
108
+ const fullFileFallbackUsed = literalOrFail(artifactKind, sourcePath, "Full-file fallback used", parsed.metadata["Full-file fallback used"], VALID_TRUNCATION_VALUES);
109
+ if (isFailure(fullFileFallbackUsed))
110
+ return fullFileFallbackUsed;
111
+ document.fullFileFallbackUsed = fullFileFallbackUsed;
112
+ const determinismChecked = literalOrFail(artifactKind, sourcePath, "Determinism checked", parsed.metadata["Determinism checked"], VALID_TRUNCATION_VALUES);
113
+ if (isFailure(determinismChecked))
114
+ return determinismChecked;
115
+ document.determinismChecked = determinismChecked;
116
+ }
117
+ if (isTestKind(expectedKind)) {
118
+ const responsibilityMappingsTruncated = literalOrFail(artifactKind, sourcePath, "Responsibility mappings truncated", parsed.metadata["Responsibility mappings truncated"], VALID_TRUNCATION_VALUES);
119
+ if (isFailure(responsibilityMappingsTruncated))
120
+ return responsibilityMappingsTruncated;
121
+ document.responsibilityMappingsTruncated = responsibilityMappingsTruncated;
122
+ // Preserved verbatim, never validated against the orchestrator's internal
123
+ // CriticalResponsibilityMappingState enum -- see supplementalContextTypes.ts.
124
+ const criticalStatus = parsed.metadata["Critical responsibility mapping status"];
125
+ if (!criticalStatus || criticalStatus.length === 0) {
126
+ return makeFailure(artifactKind, sourcePath, "MISSING_REQUIRED_METADATA", `Artifact "${artifactKind}" at "${sourcePath}" is missing a non-empty "Critical responsibility mapping status".`, "Critical responsibility mapping status", "present");
127
+ }
128
+ document.criticalResponsibilityMappingStatus = criticalStatus;
129
+ }
130
+ if (parsed.duplicateMetadataKeys.length > 0) {
131
+ document.warnings.push(`Duplicate metadata keys were ignored (first occurrence kept): ${parsed.duplicateMetadataKeys.join(", ")}.`);
132
+ }
133
+ if (parsed.duplicateSectionHeadings.length > 0) {
134
+ document.warnings.push(`Duplicate section headings were ignored (first occurrence kept): ${parsed.duplicateSectionHeadings.join(", ")}.`);
135
+ }
136
+ if (parsed.emptyMetadataKeys.length > 0) {
137
+ document.warnings.push(`Metadata keys had empty values: ${parsed.emptyMetadataKeys.join(", ")}.`);
138
+ }
139
+ return {
140
+ ok: true,
141
+ artifactKind,
142
+ sourcePath,
143
+ schemaVersion,
144
+ schemaMajor: 1,
145
+ artifact: document,
146
+ rawArtifact: { metadata: parsed.metadata, sections: parsed.sections }
147
+ };
148
+ }
@@ -1,4 +1,4 @@
1
- import { readMyDevKitContextCapsuleV1, readMyDevKitRetrievalAuditRecordV1, readOrchestratorWorkflowInstructionPacketV1 } from "../../../evaluation/upstreamArtifacts/index.js";
1
+ import { readImplementationContextPacketV1, readImplementationContextRetrievalReportV1, readMyDevKitContextCapsuleV1, readMyDevKitRetrievalAuditRecordV1, readOrchestratorWorkflowInstructionPacketV1, readTestContextPacketV1, readTestContextRetrievalReportV1, validateOrchestratorContextReadinessResultV1 } from "../../../evaluation/upstreamArtifacts/index.js";
2
2
  import { checkMyDevKitContextArtifactConsistency } from "../../../evaluation/stageContextSelectors/index.js";
3
3
  import { readStageContextExpectationFixtureV1 } from "../../../evaluation/stageContextExpectations/index.js";
4
4
  import { readV043FullWorkflowLibraryFixture } from "./readV043FullWorkflowLibraryFixture.js";
@@ -265,20 +265,131 @@ export async function loadV043StrategyArtifacts(input) {
265
265
  details: packetResult
266
266
  });
267
267
  }
268
+ // v0.4.4 Batch 3: producer-readiness bridge inputs -- every one is optional (section
269
+ // 11.2). Only a supplied-but-unreadable source becomes a load failure; an absent
270
+ // source is simply left off the payload for the bridge evaluator to treat as
271
+ // unavailable/not-applicable.
272
+ let implementationContextPacketSourcePath;
273
+ let implementationContextPacket;
274
+ if (input.implementationContextPacketPath !== undefined) {
275
+ const result = await readImplementationContextPacketV1(input.implementationContextPacketPath);
276
+ if (!result.ok) {
277
+ issues.push({
278
+ code: "IMPLEMENTATION_CONTEXT_PACKET_READ_FAILED",
279
+ fieldPath: "implementationContextPacket",
280
+ message: `Failed to read implementation-context packet: ${result.message}`,
281
+ sourcePath: result.sourcePath,
282
+ details: result
283
+ });
284
+ }
285
+ else {
286
+ implementationContextPacketSourcePath = result.sourcePath;
287
+ implementationContextPacket = result.artifact;
288
+ }
289
+ }
290
+ let implementationContextRetrievalReportSourcePath;
291
+ let implementationContextRetrievalReport;
292
+ if (input.implementationContextRetrievalReportPath !== undefined) {
293
+ const result = await readImplementationContextRetrievalReportV1(input.implementationContextRetrievalReportPath);
294
+ if (!result.ok) {
295
+ issues.push({
296
+ code: "IMPLEMENTATION_CONTEXT_RETRIEVAL_REPORT_READ_FAILED",
297
+ fieldPath: "implementationContextRetrievalReport",
298
+ message: `Failed to read implementation-context retrieval report: ${result.message}`,
299
+ sourcePath: result.sourcePath,
300
+ details: result
301
+ });
302
+ }
303
+ else {
304
+ implementationContextRetrievalReportSourcePath = result.sourcePath;
305
+ implementationContextRetrievalReport = result.artifact;
306
+ }
307
+ }
308
+ let testContextPacketSourcePath;
309
+ let testContextPacket;
310
+ if (input.testContextPacketPath !== undefined) {
311
+ const result = await readTestContextPacketV1(input.testContextPacketPath);
312
+ if (!result.ok) {
313
+ issues.push({
314
+ code: "TEST_CONTEXT_PACKET_READ_FAILED",
315
+ fieldPath: "testContextPacket",
316
+ message: `Failed to read test-context packet: ${result.message}`,
317
+ sourcePath: result.sourcePath,
318
+ details: result
319
+ });
320
+ }
321
+ else {
322
+ testContextPacketSourcePath = result.sourcePath;
323
+ testContextPacket = result.artifact;
324
+ }
325
+ }
326
+ let testContextRetrievalReportSourcePath;
327
+ let testContextRetrievalReport;
328
+ if (input.testContextRetrievalReportPath !== undefined) {
329
+ const result = await readTestContextRetrievalReportV1(input.testContextRetrievalReportPath);
330
+ if (!result.ok) {
331
+ issues.push({
332
+ code: "TEST_CONTEXT_RETRIEVAL_REPORT_READ_FAILED",
333
+ fieldPath: "testContextRetrievalReport",
334
+ message: `Failed to read test-context retrieval report: ${result.message}`,
335
+ sourcePath: result.sourcePath,
336
+ details: result
337
+ });
338
+ }
339
+ else {
340
+ testContextRetrievalReportSourcePath = result.sourcePath;
341
+ testContextRetrievalReport = result.artifact;
342
+ }
343
+ }
344
+ let readiness;
345
+ if (input.readiness !== undefined) {
346
+ const readinessResult = validateOrchestratorContextReadinessResultV1(input.readiness, "programmatic-input:readiness");
347
+ if (!readinessResult.ok) {
348
+ issues.push({
349
+ code: "READINESS_INPUT_INVALID",
350
+ fieldPath: "readiness",
351
+ message: `Readiness programmatic input is invalid: ${readinessResult.message}`,
352
+ details: readinessResult
353
+ });
354
+ }
355
+ else {
356
+ readiness = readinessResult.artifact;
357
+ }
358
+ }
268
359
  if (issues.length > 0 || !expectationsResult.ok || !packetResult.ok || pairs.length !== input.contextArtifacts.length) {
269
360
  return buildFailureResult(input, issues);
270
361
  }
362
+ const payload = {
363
+ contextArtifacts: pairs,
364
+ workflowInstructionPacketSourcePath: packetResult.sourcePath,
365
+ workflowInstructionPacket: packetResult.artifact
366
+ };
367
+ if (implementationContextPacket !== undefined) {
368
+ payload.implementationContextPacketSourcePath = implementationContextPacketSourcePath;
369
+ payload.implementationContextPacket = implementationContextPacket;
370
+ }
371
+ if (implementationContextRetrievalReport !== undefined) {
372
+ payload.implementationContextRetrievalReportSourcePath = implementationContextRetrievalReportSourcePath;
373
+ payload.implementationContextRetrievalReport = implementationContextRetrievalReport;
374
+ }
375
+ if (testContextPacket !== undefined) {
376
+ payload.testContextPacketSourcePath = testContextPacketSourcePath;
377
+ payload.testContextPacket = testContextPacket;
378
+ }
379
+ if (testContextRetrievalReport !== undefined) {
380
+ payload.testContextRetrievalReportSourcePath = testContextRetrievalReportSourcePath;
381
+ payload.testContextRetrievalReport = testContextRetrievalReport;
382
+ }
383
+ if (readiness !== undefined) {
384
+ payload.readiness = readiness;
385
+ }
271
386
  return {
272
387
  status: "completed",
273
388
  strategyId: input.strategyId,
274
389
  input,
275
390
  expectationsSourcePath: expectationsResult.sourcePath,
276
391
  expectations: expectationsResult.fixture,
277
- payload: {
278
- contextArtifacts: pairs,
279
- workflowInstructionPacketSourcePath: packetResult.sourcePath,
280
- workflowInstructionPacket: packetResult.artifact
281
- },
392
+ payload,
282
393
  warnings: []
283
394
  };
284
395
  }