@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
@@ -1,6 +1,6 @@
1
1
  import { captureTargetSnapshot, compareTargetSnapshots } from "../../../evaluation/targetImmutability/index.js";
2
2
  import { calculateStageContextDeterminism } from "../../../evaluation/stageContextDeterminism/index.js";
3
- import { evaluateV043StageContextExecution } from "../../../evaluation/stageContextMetrics/index.js";
3
+ import { buildProducerReadinessBridgeInputFromCombinedPayload, evaluateProducerReadinessBridge, evaluateV043StageContextExecution } from "../../../evaluation/stageContextMetrics/index.js";
4
4
  import { executeV043StageContextStrategy } from "./executeV043StageContextStrategy.js";
5
5
  async function buildRunWithTargetImmutability(targetConfig, input) {
6
6
  if (targetConfig === undefined) {
@@ -57,6 +57,15 @@ async function buildRunWithTargetImmutability(targetConfig, input) {
57
57
  targetImmutability: { availability: "available", comparison, reason: null }
58
58
  };
59
59
  }
60
+ // v0.4.4 Batch 3: computed exactly once per run, immediately after execution, from the
61
+ // already-loaded execution payload -- never rereads artifacts, never reruns the strategy.
62
+ function buildProducerReadinessBridgeResult(execution) {
63
+ if (execution.status !== "completed" || execution.strategyId !== "combined-bounded-stage-context")
64
+ return null;
65
+ const payload = execution.payload;
66
+ const bridgeInput = buildProducerReadinessBridgeInputFromCombinedPayload(payload, execution.expectations);
67
+ return evaluateProducerReadinessBridge(bridgeInput);
68
+ }
60
69
  function computeStatus(issues, config) {
61
70
  if (issues.length > 0)
62
71
  return "failed";
@@ -69,23 +78,27 @@ export async function runV043StageContextStrategyWithAssurance(input, config) {
69
78
  const issues = [];
70
79
  let primaryExecution;
71
80
  let primaryEvaluation;
81
+ let primaryProducerReadinessBridge = null;
72
82
  try {
73
83
  for (let runNumber = 1; runNumber <= config.repeatCount; runNumber += 1) {
74
84
  const { execution, targetImmutability } = await buildRunWithTargetImmutability(config.targetImmutability, input);
75
85
  const evaluation = evaluateV043StageContextExecution(execution, { targetImmutability });
86
+ const producerReadinessBridge = buildProducerReadinessBridgeResult(execution);
76
87
  if (runNumber === 1) {
77
88
  primaryExecution = execution;
78
89
  primaryEvaluation = evaluation;
90
+ primaryProducerReadinessBridge = producerReadinessBridge;
79
91
  }
80
92
  runRecords.push({
81
93
  runNumber,
82
94
  executionStatus: execution.status,
83
95
  evaluationStatus: evaluation.status,
84
- targetImmutability
96
+ targetImmutability,
97
+ producerReadinessBridge
85
98
  });
86
99
  determinismCandidates.push({
87
100
  runNumber,
88
- value: { execution, evaluation, targetImmutability }
101
+ value: { execution, evaluation, targetImmutability, producerReadinessBridge }
89
102
  });
90
103
  if (execution.status !== "completed") {
91
104
  issues.push({
@@ -147,6 +160,7 @@ export async function runV043StageContextStrategyWithAssurance(input, config) {
147
160
  repeatCount: config.repeatCount,
148
161
  primaryExecution: primaryExecution,
149
162
  primaryEvaluation: primaryEvaluation,
163
+ primaryProducerReadinessBridge,
150
164
  runRecords,
151
165
  determinism,
152
166
  issues
@@ -175,6 +189,7 @@ export async function runV043StageContextStrategyWithAssurance(input, config) {
175
189
  repeatCount: config.repeatCount,
176
190
  primaryExecution: fallbackExecution,
177
191
  primaryEvaluation: fallbackEvaluation,
192
+ primaryProducerReadinessBridge,
178
193
  runRecords,
179
194
  determinism: fallbackDeterminism,
180
195
  issues: [
@@ -45,7 +45,12 @@ const STRATEGY_CONTRACTS = {
45
45
  fields: [
46
46
  { name: "expectationsPath", kind: "required-path" },
47
47
  { name: "contextArtifacts", kind: "required-array" },
48
- { name: "workflowInstructionPacketPath", kind: "required-path" }
48
+ { name: "workflowInstructionPacketPath", kind: "required-path" },
49
+ { name: "implementationContextPacketPath", kind: "optional-path" },
50
+ { name: "implementationContextRetrievalReportPath", kind: "optional-path" },
51
+ { name: "testContextPacketPath", kind: "optional-path" },
52
+ { name: "testContextRetrievalReportPath", kind: "optional-path" },
53
+ { name: "readiness", kind: "optional-object" }
49
54
  ]
50
55
  }
51
56
  };
@@ -93,7 +98,7 @@ export function validateV043StrategyInput(value) {
93
98
  }
94
99
  }
95
100
  for (const field of contract.fields) {
96
- if (field.kind !== "optional-path" && root[field.name] === undefined) {
101
+ if (field.kind !== "optional-path" && field.kind !== "optional-object" && root[field.name] === undefined) {
97
102
  issues.push({
98
103
  code: "MISSING_REQUIRED_FIELD",
99
104
  fieldPath: field.name,
@@ -114,6 +119,15 @@ export function validateV043StrategyInput(value) {
114
119
  });
115
120
  }
116
121
  }
122
+ else if (field.kind === "optional-object") {
123
+ if (!isPlainObject(fieldValue)) {
124
+ issues.push({
125
+ code: "INVALID_FIELD_TYPE",
126
+ fieldPath: field.name,
127
+ message: `"${field.name}" must be an object.`
128
+ });
129
+ }
130
+ }
117
131
  else if (typeof fieldValue !== "string") {
118
132
  issues.push({
119
133
  code: "INVALID_FIELD_TYPE",
@@ -123,7 +137,7 @@ export function validateV043StrategyInput(value) {
123
137
  }
124
138
  }
125
139
  for (const field of contract.fields) {
126
- if (field.kind === "required-array")
140
+ if (field.kind === "required-array" || field.kind === "optional-object")
127
141
  continue;
128
142
  const fieldValue = root[field.name];
129
143
  if (typeof fieldValue === "string" && fieldValue.length === 0) {
@@ -0,0 +1,204 @@
1
+ // v0.4.5 Batch 5: builds the bounded ContextIntegrityReportV1 from already-calculated
2
+ // Batch 1-4 results. Never recalculates allocation, condition coverage, agreement states,
3
+ // hashes, determinism, or immutability -- it only bounds and reshapes values the caller
4
+ // already computed via evaluateProducerReadinessBridge, verifyFixtureHashes, and
5
+ // calculateStageContextDeterminism.
6
+ import { V043_REPORT_DETAIL_LIMIT } from "./contextStrategyComparisonV043ReportModel.js";
7
+ const CORRECTED_REPLAY_LIMITATION = "This corrected-replay fixture is a hand-distilled representation of the exact validated local my-dev-kit v1.10.4 and my-dev-kit-orchestrator v1.2.3 contracts, applied to the same request, target, and active-index identity as the paired failed-run fixture. It is not a live capture of a complete ten-stage AI-authored implementation workflow, and it is not proof that every future run against these contracts will behave identically.";
8
+ function boundItems(source, limit = V043_REPORT_DETAIL_LIMIT) {
9
+ const items = source.slice(0, limit);
10
+ return { totalCount: source.length, displayedCount: items.length, omittedCount: source.length - items.length, items };
11
+ }
12
+ function toContradiction(c) {
13
+ return { code: c.code, fieldPath: c.fieldPath, expected: c.expected, observed: c.observed, reason: c.reason };
14
+ }
15
+ function agreementFromRunIntegrity(component) {
16
+ return {
17
+ availability: component.availability,
18
+ outcome: component.outcome,
19
+ contradictions: boundItems(component.contradictions.map(toContradiction)),
20
+ reason: component.reason
21
+ };
22
+ }
23
+ function unavailableAgreement(reason) {
24
+ return { availability: "unavailable", outcome: "insufficient-evidence", contradictions: boundItems([]), reason };
25
+ }
26
+ export function buildContextIntegrityReport(input) {
27
+ const { manifest, hashVerification, capsule, bridgeResult } = input;
28
+ const side = bridgeResult.implementation ?? bridgeResult.testImplementation;
29
+ const runIntegrity = bridgeResult.runIntegrityEvaluation;
30
+ const derivedCount = manifest.artifacts.filter((a) => a.derived).length;
31
+ const byteExactCount = manifest.artifacts.filter((a) => a.byteExact).length;
32
+ const allocationAgg = side?.groupAllocationEvaluation.aggregate ?? null;
33
+ const spillover = side?.groupAllocationEvaluation.spillover ?? null;
34
+ const conditionCoverage = side?.conditionCoverageEvaluation ?? null;
35
+ const conditionAwareTruncation = side?.conditionAwareTruncationEvaluation ?? null;
36
+ const unavailableSections = [];
37
+ const notes = [];
38
+ if (!side)
39
+ unavailableSections.push("producer");
40
+ if (!runIntegrity)
41
+ unavailableSections.push("run-integrity");
42
+ if (conditionCoverage?.availability !== "available")
43
+ unavailableSections.push("condition-coverage");
44
+ return {
45
+ schemaVersion: "1.0.0",
46
+ detailLimit: V043_REPORT_DETAIL_LIMIT,
47
+ fixture: {
48
+ fixtureId: manifest.fixtureId,
49
+ kind: input.fixtureKind,
50
+ description: manifest.description,
51
+ myDevKitCommit: manifest.myDevKit.commit,
52
+ orchestratorCommit: manifest.orchestrator.commit,
53
+ targetRepositoryIdentity: manifest.targetRepositoryIdentity,
54
+ activeIndexIdentity: manifest.activeIndexIdentity,
55
+ manifestSchemaVersion: manifest.manifestSchemaVersion,
56
+ trackedArtifactCount: manifest.artifacts.length,
57
+ derivedArtifactCount: derivedCount,
58
+ byteExactArtifactCount: byteExactCount,
59
+ artifacts: boundItems(manifest.artifacts.map((a) => ({
60
+ fixtureRelativePath: a.fixtureRelativePath,
61
+ role: a.role,
62
+ derived: a.derived,
63
+ byteExact: a.byteExact,
64
+ provenanceOnly: a.provenanceOnly
65
+ }))),
66
+ hashVerification: {
67
+ ok: hashVerification.ok,
68
+ checkedCount: hashVerification.checkedCount,
69
+ issues: boundItems(hashVerification.issues.map((i) => ({ code: i.code, fixtureRelativePath: i.fixtureRelativePath, message: i.message })))
70
+ },
71
+ correctedReplayLimitation: input.fixtureKind === "corrected-replay" ? CORRECTED_REPLAY_LIMITATION : ""
72
+ },
73
+ producerIdentity: {
74
+ toolName: capsule?.tool.name ?? null,
75
+ toolVersion: capsule?.tool.version ?? null,
76
+ role: capsule?.request.role ?? null,
77
+ projectRoot: capsule?.index.projectRoot ?? null,
78
+ indexPath: capsule?.index.indexPath ?? null,
79
+ roleAdequacyStatus: capsule?.roleAdequacy.status ?? null
80
+ },
81
+ allocation: {
82
+ availability: allocationAgg?.availability ?? "unavailable",
83
+ groupCount: allocationAgg?.groupCount ?? 0,
84
+ totalRequiredOmitted: allocationAgg?.totalRequiredOmitted ?? null,
85
+ totalOptionalOmitted: allocationAgg?.totalOptionalOmitted ?? null,
86
+ aggregateCapacityUsed: null,
87
+ aggregateCapacityRemaining: null,
88
+ groupsWithRequiredOmission: allocationAgg?.groupsWithRequiredOmission ?? [],
89
+ groupsWithOptionalOnlyOmission: allocationAgg?.groupsWithOptionalOnlyOmission ?? [],
90
+ perGroup: boundItems((side?.groupAllocationEvaluation.perGroup ?? []).map((g) => ({
91
+ groupId: g.groupId,
92
+ availability: g.availability,
93
+ required: g.required,
94
+ reservation: g.reservation,
95
+ initiallySelectedCount: g.initiallySelectedCount,
96
+ unusedReservationContributed: g.unusedReservationContributed,
97
+ borrowedCapacity: g.borrowedCapacity,
98
+ requiredOmittedCount: g.requiredOmittedCount,
99
+ optionalOmittedCount: g.optionalOmittedCount,
100
+ adequacyAffected: g.adequacyAffected
101
+ })))
102
+ },
103
+ spillover: {
104
+ availability: spillover?.availability ?? "unavailable",
105
+ groupsContributing: spillover?.groupsContributing ?? [],
106
+ groupsBorrowing: spillover?.groupsBorrowing ?? [],
107
+ totalContributed: spillover?.totalContributed ?? null,
108
+ totalBorrowed: spillover?.totalBorrowed ?? null,
109
+ contributionCoversBorrowing: spillover?.contributionCoversBorrowing ?? null,
110
+ reason: spillover?.reason ?? null
111
+ },
112
+ truncation: {
113
+ availability: conditionAwareTruncation?.availability ?? "unavailable",
114
+ state: conditionAwareTruncation?.state ?? "unsupported-legacy-diagnostics",
115
+ requiredEvidenceLost: conditionAwareTruncation?.requiredEvidenceLost ?? null,
116
+ requiredOmittedTotal: conditionAwareTruncation?.requiredOmittedTotal ?? null,
117
+ optionalOmittedTotal: conditionAwareTruncation?.optionalOmittedTotal ?? null,
118
+ lostRequiredConditionIds: conditionAwareTruncation?.lostRequiredConditionIds ?? [],
119
+ contradictions: boundItems((conditionAwareTruncation?.contradictionCodes ?? []).map((code) => ({ code, fieldPath: "truncation", expected: null, observed: null, reason: conditionAwareTruncation?.reason ?? "" })))
120
+ },
121
+ conditionCoverage: {
122
+ availability: conditionCoverage?.availability ?? "unavailable",
123
+ requiredConditionsTotal: conditionCoverage?.requiredConditionsTotal.count ?? null,
124
+ requiredConditionsSatisfied: conditionCoverage?.requiredConditionsSatisfied.count ?? null,
125
+ requiredConditionsMissing: conditionCoverage?.requiredConditionsMissing.evidenceKeys ?? [],
126
+ requiredConditionsLost: conditionCoverage?.requiredConditionsLost.evidenceKeys ?? [],
127
+ lastWitnessLossCount: conditionCoverage?.lastWitnessLoss.count ?? null,
128
+ witnessEvidence: boundItems((conditionCoverage?.witnessEvidence ?? []).map((w) => ({
129
+ conditionId: w.conditionId,
130
+ required: w.required,
131
+ coverageState: w.coverageState,
132
+ retainedWitnessCount: w.retainedWitnessCount,
133
+ retainedWitnessIds: boundItems(w.retainedWitnessIds),
134
+ adequateWitnessRemains: w.adequateWitnessRemains,
135
+ lossReason: w.lossReason,
136
+ evidenceGroupIds: w.evidenceGroupIds
137
+ }))),
138
+ reason: conditionCoverage?.reason ?? null
139
+ },
140
+ producerConditionAgreement: side
141
+ ? {
142
+ availability: side.producerConditionAgreement.availability,
143
+ outcome: side.producerConditionAgreement.outcome,
144
+ contradictions: boundItems(side.producerConditionAgreement.contradictionCodes.map((code) => ({ code, fieldPath: "roleAdequacy", expected: null, observed: null, reason: side.producerConditionAgreement.reason ?? "" }))),
145
+ reason: side.producerConditionAgreement.reason
146
+ }
147
+ : unavailableAgreement("No producer side was supplied."),
148
+ requiredEvidenceLossAgreement: side
149
+ ? {
150
+ availability: side.requiredEvidenceLossAgreement.availability,
151
+ outcome: side.requiredEvidenceLossAgreement.outcome,
152
+ contradictions: boundItems(side.requiredEvidenceLossAgreement.contradictionCodes.map((code) => ({ code, fieldPath: "truncation.requiredEvidenceLost", expected: null, observed: null, reason: side.requiredEvidenceLossAgreement.reason ?? "" }))),
153
+ reason: side.requiredEvidenceLossAgreement.reason
154
+ }
155
+ : unavailableAgreement("No producer side was supplied."),
156
+ capsuleAuditAgreement: side
157
+ ? {
158
+ availability: side.capsuleAuditConditionAgreement.availability,
159
+ consistent: side.capsuleAuditConditionAgreement.consistent,
160
+ contradictingFieldPaths: side.capsuleAuditConditionAgreement.contradictingFieldPaths
161
+ }
162
+ : { availability: "unavailable", consistent: null, contradictingFieldPaths: [] },
163
+ supplementalRawAgreement: side?.packetAgreement || side?.reportAgreement
164
+ ? {
165
+ availability: "available",
166
+ contradictingFields: [...(side.packetAgreement?.contradictions ?? []), ...(side.reportAgreement?.contradictions ?? [])].map((f) => f.field),
167
+ upstreamProducerParityPreserved: side.packetAgreement?.upstreamProducerParityPreserved ?? side.reportAgreement?.upstreamProducerParityPreserved ?? null
168
+ }
169
+ : null,
170
+ producerReadinessAgreement: bridgeResult.producerReadinessRelationship
171
+ ? {
172
+ availability: bridgeResult.producerReadinessRelationship.availability,
173
+ outcome: bridgeResult.producerReadinessRelationship.outcome,
174
+ contradictions: boundItems(bridgeResult.producerReadinessRelationship.contradictionCodes.map((code) => ({ code, fieldPath: "readiness", expected: null, observed: null, reason: bridgeResult.producerReadinessRelationship.reason ?? "" }))),
175
+ reason: bridgeResult.producerReadinessRelationship.reason
176
+ }
177
+ : unavailableAgreement("No producer/readiness relationship was calculated."),
178
+ readinessPromptAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.readinessPrompt) : unavailableAgreement("No run-integrity evidence was supplied."),
179
+ readinessExpectedJudgeAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.readinessExpectedJudge) : unavailableAgreement("No run-integrity evidence was supplied."),
180
+ expectedActualJudgeAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.expectedActualJudge) : unavailableAgreement("No run-integrity evidence was supplied."),
181
+ judgeCorrectionAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.judgeCorrection) : unavailableAgreement("No run-integrity evidence was supplied."),
182
+ judgeFinalEligibilityAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.judgeFinalEligibility) : unavailableAgreement("No run-integrity evidence was supplied."),
183
+ eligibilityFinalArtifactAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.eligibilityFinalArtifact) : unavailableAgreement("No run-integrity evidence was supplied."),
184
+ lifecycleIntegrityAgreement: runIntegrity ? agreementFromRunIntegrity(runIntegrity.lifecycleIntegrity) : unavailableAgreement("No run-integrity evidence was supplied."),
185
+ endToEnd: runIntegrity
186
+ ? { category: runIntegrity.endToEndSummary.category, componentOutcomes: runIntegrity.endToEndSummary.componentOutcomes, contradictingComponents: runIntegrity.endToEndSummary.contradictingComponents }
187
+ : null,
188
+ determinism: input.determinism
189
+ ? {
190
+ availability: input.determinism.availability,
191
+ repeatCount: input.determinism.repeatCount,
192
+ deterministic: input.determinism.deterministic,
193
+ baselineSha256: input.determinism.baselineSha256,
194
+ mismatchRunNumbers: input.determinism.mismatchRunNumbers,
195
+ reason: input.determinism.reason
196
+ }
197
+ : { availability: "not-applicable", repeatCount: 1, deterministic: null, baselineSha256: null, mismatchRunNumbers: [], reason: "Determinism was not evaluated for this report." },
198
+ immutability: {
199
+ fixtureSelfImmutable: input.fixtureSelfImmutable ?? null,
200
+ fixtureImmutabilityReason: input.fixtureSelfImmutableReason ?? (input.fixtureSelfImmutable === undefined ? "Fixture self-immutability was not checked for this report." : null)
201
+ },
202
+ limitations: { unavailableSections, notes }
203
+ };
204
+ }
@@ -69,12 +69,134 @@ function buildSummary(executions, evaluations, assurances) {
69
69
  };
70
70
  }
71
71
  function buildStrategyReport(execution, evaluation, assurance) {
72
+ const producerReadinessBridge = buildProducerReadinessBridgeReport(assurance.primaryProducerReadinessBridge);
72
73
  return {
73
74
  strategyId: assurance.strategyId,
74
75
  artifacts: buildArtifactMetadata(execution),
75
76
  execution: buildExecutionSummary(execution),
76
77
  evaluation: buildEvaluationSummary(evaluation),
77
78
  assurance: buildAssuranceSummary(assurance),
79
+ ...(producerReadinessBridge ? { producerReadinessBridge } : {}),
80
+ };
81
+ }
82
+ function buildAllocationFactList(source) {
83
+ return boundItems(source.map((f) => ({ groupId: f.groupId, value: f.value, unit: f.unit, availability: f.availability, reason: f.reason })));
84
+ }
85
+ function buildOwnerEvaluation(owner) {
86
+ return {
87
+ selectedOwnerEvidence: boundItems(owner.selectedOwnerEvidence.map((e) => ({ ownerId: e.ownerId, sourceArtifact: e.sourceArtifact, sourceInstance: e.sourceInstance }))),
88
+ expectedOwnerPresent: buildRatioMetric(owner.expectedOwnerPresent),
89
+ forbiddenOwnerPresent: buildRatioMetric(owner.forbiddenOwnerPresent),
90
+ falsePositiveCount: buildCountMetric(owner.falsePositiveCount),
91
+ falseNegativeCount: buildCountMetric(owner.falseNegativeCount),
92
+ };
93
+ }
94
+ function buildTruncationList(source) {
95
+ return boundItems(source.map((t) => ({
96
+ groupId: t.groupId,
97
+ cause: t.cause,
98
+ availability: t.availability,
99
+ reason: t.reason,
100
+ omittedRequiredEvidenceIds: t.omittedRequiredEvidenceIds,
101
+ limit: t.limit,
102
+ used: t.used,
103
+ available: t.available,
104
+ })));
105
+ }
106
+ function buildSupplementalRawAgreement(agreement) {
107
+ if (agreement === null)
108
+ return null;
109
+ return {
110
+ fields: agreement.fields.map((f) => ({ field: f.field, rawValue: f.rawValue, supplementalValue: f.supplementalValue, agreement: f.agreement, availability: f.availability, reason: f.reason })),
111
+ contradictions: agreement.contradictions.map((f) => ({ field: f.field, rawValue: f.rawValue, supplementalValue: f.supplementalValue, agreement: f.agreement, availability: f.availability, reason: f.reason })),
112
+ upstreamProducerParityPreserved: agreement.upstreamProducerParityPreserved,
113
+ };
114
+ }
115
+ function buildProducerReadinessSide(side) {
116
+ return {
117
+ role: side.role,
118
+ ownerEvaluation: buildOwnerEvaluation(side.ownerEvaluation),
119
+ allocationEvaluation: {
120
+ requiredGroupCapacity: buildAllocationFactList(side.allocationEvaluation.requiredGroupCapacity),
121
+ usedReservation: buildAllocationFactList(side.allocationEvaluation.usedReservation),
122
+ borrowedCapacity: buildAllocationFactList(side.allocationEvaluation.borrowedCapacity),
123
+ unusedCapacity: buildAllocationFactList(side.allocationEvaluation.unusedCapacity),
124
+ },
125
+ truncationEvaluation: buildTruncationList(side.truncationEvaluation),
126
+ packetAgreement: buildSupplementalRawAgreement(side.packetAgreement),
127
+ reportAgreement: buildSupplementalRawAgreement(side.reportAgreement),
128
+ };
129
+ }
130
+ function buildReadinessAgreement(agreement) {
131
+ return {
132
+ structuralAgreement: agreement.structuralAgreement.map((s) => ({
133
+ field: s.field,
134
+ expectedValue: s.expectedValue,
135
+ observedValue: s.observedValue,
136
+ agreement: s.agreement,
137
+ availability: s.availability,
138
+ reason: s.reason,
139
+ })),
140
+ decisionAgreement: {
141
+ availability: agreement.decisionAgreement.availability,
142
+ observedDecision: agreement.decisionAgreement.observedDecision,
143
+ allowedDecisions: agreement.decisionAgreement.allowedDecisions,
144
+ decisionAgreement: agreement.decisionAgreement.decisionAgreement,
145
+ observedIssueCodes: agreement.decisionAgreement.observedIssueCodes,
146
+ expectedIssueCodes: agreement.decisionAgreement.expectedIssueCodes,
147
+ issueCodesAgreement: agreement.decisionAgreement.issueCodesAgreement,
148
+ observedPrimaryIssueCode: agreement.decisionAgreement.observedPrimaryIssueCode,
149
+ expectedPrimaryIssueCode: agreement.decisionAgreement.expectedPrimaryIssueCode,
150
+ primaryIssueAgreement: agreement.decisionAgreement.primaryIssueAgreement,
151
+ reason: agreement.decisionAgreement.reason,
152
+ },
153
+ invalidReady: {
154
+ availability: agreement.invalidReady.availability,
155
+ invalidReady: agreement.invalidReady.invalidReady,
156
+ missingExpectedIssueCodes: agreement.invalidReady.missingExpectedIssueCodes,
157
+ reason: agreement.invalidReady.reason,
158
+ },
159
+ validBlocked: {
160
+ availability: agreement.validBlocked.availability,
161
+ validBlocked: agreement.validBlocked.validBlocked,
162
+ validRefreshRequired: agreement.validBlocked.validRefreshRequired,
163
+ observedDecision: agreement.validBlocked.observedDecision,
164
+ reason: agreement.validBlocked.reason,
165
+ },
166
+ };
167
+ }
168
+ function buildCriticalityEvaluation(criticality) {
169
+ return {
170
+ overlayAgreement: boundItems(criticality.overlayAgreement.map((e) => ({
171
+ responsibilityId: e.responsibilityId,
172
+ expectedCriticality: e.expectedCriticality,
173
+ observedCriticality: e.observedCriticality,
174
+ agreement: e.agreement,
175
+ availability: e.availability,
176
+ reason: e.reason,
177
+ }))),
178
+ missingCriticalityResponsibilityIds: criticality.missingCriticalityResponsibilityIds,
179
+ conflictingCriticalityResponsibilityIds: criticality.conflictingCriticalityResponsibilityIds,
180
+ unexpectedCriticalityResponsibilityIds: criticality.unexpectedCriticalityResponsibilityIds,
181
+ mappedCriticalCompleteness: buildRatioMetric(criticality.mappedCriticalCompleteness),
182
+ fullyMappedCriticalIds: criticality.fullyMappedCriticalIds,
183
+ partiallyMappedCriticalIds: criticality.partiallyMappedCriticalIds,
184
+ unmappedCriticalIds: criticality.unmappedCriticalIds,
185
+ missingMappingEvidenceCriticalIds: criticality.missingMappingEvidenceCriticalIds,
186
+ };
187
+ }
188
+ function buildProducerReadinessBridgeReport(bridge) {
189
+ if (bridge === null || bridge === undefined)
190
+ return null;
191
+ return {
192
+ status: bridge.status,
193
+ reason: bridge.reason,
194
+ implementation: bridge.implementation ? buildProducerReadinessSide(bridge.implementation) : null,
195
+ testImplementation: bridge.testImplementation ? buildProducerReadinessSide(bridge.testImplementation) : null,
196
+ readinessAgreement: bridge.readinessAgreement ? buildReadinessAgreement(bridge.readinessAgreement) : null,
197
+ criticalityEvaluation: bridge.criticalityEvaluation ? buildCriticalityEvaluation(bridge.criticalityEvaluation) : null,
198
+ warnings: boundItems(bridge.warnings),
199
+ evidenceReferences: boundItems(bridge.evidenceReferences),
78
200
  };
79
201
  }
80
202
  function buildExecutionSummary(execution) {
@@ -6,3 +6,8 @@ export * from "./contextStrategyComparisonV043ReportModel.js";
6
6
  export { buildContextStrategyComparisonV043Report } from "./buildContextStrategyComparisonV043Report.js";
7
7
  export { renderContextStrategyComparisonV043Html } from "./renderContextStrategyComparisonV043Html.js";
8
8
  export { renderPluginExperimentReportText } from "./renderPluginExperimentReportText.js";
9
+ export * from "./contextIntegrityReportModel.js";
10
+ export { buildContextIntegrityReport } from "./buildContextIntegrityReport.js";
11
+ export { renderContextIntegrityJsonReport } from "./renderContextIntegrityJsonReport.js";
12
+ export { renderContextIntegrityText } from "./renderContextIntegrityText.js";
13
+ export { renderContextIntegrityHtml } from "./renderContextIntegrityHtml.js";
@@ -0,0 +1,98 @@
1
+ function escapeHtml(value) {
2
+ return String(value ?? "")
3
+ .replaceAll("&", "&amp;")
4
+ .replaceAll("<", "&lt;")
5
+ .replaceAll(">", "&gt;")
6
+ .replaceAll('"', "&quot;")
7
+ .replaceAll("'", "&#39;");
8
+ }
9
+ function table(headers, rows) {
10
+ return `<table><thead><tr>${headers.map((h) => `<th>${escapeHtml(h)}</th>`).join("")}</tr></thead><tbody>${rows
11
+ .map((row) => `<tr>${row.map((cell) => `<td>${escapeHtml(cell)}</td>`).join("")}</tr>`)
12
+ .join("")}</tbody></table>`;
13
+ }
14
+ function renderAgreementSection(label, agreement) {
15
+ const rows = agreement.contradictions.items.map((c) => [c.code, c.fieldPath, c.expected ?? "", c.observed ?? "", c.reason]);
16
+ return `<section><h3>${escapeHtml(label)}</h3>${table(["Availability", "Outcome", "Reason"], [[agreement.availability, agreement.outcome, agreement.reason ?? ""]])}${agreement.contradictions.totalCount > 0
17
+ ? `<p class="muted">Contradictions displayed ${agreement.contradictions.displayedCount} of ${agreement.contradictions.totalCount} (omitted ${agreement.contradictions.omittedCount}).</p>${table(["Code", "Field path", "Expected", "Observed", "Reason"], rows)}`
18
+ : ""}</section>`;
19
+ }
20
+ export function renderContextIntegrityHtml(report) {
21
+ const endToEndLabel = report.endToEnd?.category ?? "unavailable";
22
+ return `<!doctype html>
23
+ <html lang="en">
24
+ <head>
25
+ <meta charset="utf-8" />
26
+ <title>Context-integrity report: ${escapeHtml(report.fixture.fixtureId)}</title>
27
+ <style>
28
+ body { font-family: system-ui, sans-serif; margin: 2rem; color: #1a1a1a; }
29
+ table { border-collapse: collapse; margin: 0.5rem 0 1rem; width: 100%; }
30
+ th, td { border: 1px solid #ccc; padding: 0.35rem 0.5rem; text-align: left; font-size: 0.9rem; }
31
+ .muted { color: #666; font-size: 0.85rem; }
32
+ .badge { display: inline-block; padding: 0.15rem 0.5rem; border-radius: 0.25rem; font-weight: 600; }
33
+ .badge-full-agreement { background: #d7f5dd; color: #1b6b32; }
34
+ .badge-contradiction-present { background: #fbdada; color: #8f1d1d; }
35
+ .badge-insufficient-evidence, .badge-unsupported-legacy-evidence { background: #eee; color: #444; }
36
+ section { margin-bottom: 1.5rem; }
37
+ </style>
38
+ </head>
39
+ <body>
40
+ <h1>Context-integrity report: ${escapeHtml(report.fixture.fixtureId)} (${escapeHtml(report.fixture.kind)})</h1>
41
+ <p>End-to-end result: <span class="badge badge-${escapeHtml(endToEndLabel)}">${escapeHtml(endToEndLabel)}</span></p>
42
+ ${report.fixture.correctedReplayLimitation ? `<p class="muted"><strong>Limitation:</strong> ${escapeHtml(report.fixture.correctedReplayLimitation)}</p>` : ""}
43
+
44
+ <section><h2>Fixture and provenance</h2>${table(["Field", "Value"], [
45
+ ["my-dev-kit commit", report.fixture.myDevKitCommit ?? ""],
46
+ ["orchestrator commit", report.fixture.orchestratorCommit ?? ""],
47
+ ["Target repository identity", report.fixture.targetRepositoryIdentity ?? ""],
48
+ ["Active index identity", report.fixture.activeIndexIdentity ?? ""],
49
+ ["Tracked artifacts", String(report.fixture.trackedArtifactCount)],
50
+ ["Derived artifacts", String(report.fixture.derivedArtifactCount)],
51
+ ["Byte-exact artifacts", String(report.fixture.byteExactArtifactCount)],
52
+ ["Hash verification", report.fixture.hashVerification.ok ? "PASS" : "FAIL"]
53
+ ])}</section>
54
+
55
+ <section><h2>Producer allocation and omissions</h2>${table(["Field", "Value"], [
56
+ ["Role adequacy status", report.producerIdentity.roleAdequacyStatus ?? "(unavailable)"],
57
+ ["Groups evaluated", String(report.allocation.groupCount)],
58
+ ["Total required omitted", String(report.allocation.totalRequiredOmitted ?? "(unavailable)")],
59
+ ["Total optional omitted", String(report.allocation.totalOptionalOmitted ?? "(unavailable)")],
60
+ ["Groups with required omission", report.allocation.groupsWithRequiredOmission.join(", ") || "(none)"],
61
+ ["Groups with optional-only omission", report.allocation.groupsWithOptionalOnlyOmission.join(", ") || "(none)"],
62
+ ["Truncation state", report.truncation.state],
63
+ ["requiredEvidenceLost", String(report.truncation.requiredEvidenceLost)]
64
+ ])}</section>
65
+
66
+ <section><h2>Condition coverage</h2>${table(["Field", "Value"], [
67
+ ["Availability", report.conditionCoverage.availability],
68
+ ["Required conditions total", String(report.conditionCoverage.requiredConditionsTotal ?? "(unavailable)")],
69
+ ["Required conditions satisfied", String(report.conditionCoverage.requiredConditionsSatisfied ?? "(unavailable)")],
70
+ ["Required conditions missing", report.conditionCoverage.requiredConditionsMissing.join(", ") || "(none)"],
71
+ ["Required conditions lost", report.conditionCoverage.requiredConditionsLost.join(", ") || "(none)"],
72
+ ["Last-witness-loss count", String(report.conditionCoverage.lastWitnessLossCount ?? "(unavailable)")]
73
+ ])}</section>
74
+
75
+ ${renderAgreementSection("Producer-condition agreement", report.producerConditionAgreement)}
76
+ ${renderAgreementSection("requiredEvidenceLost agreement", report.requiredEvidenceLossAgreement)}
77
+ ${renderAgreementSection("Producer/readiness relationship", report.producerReadinessAgreement)}
78
+ <p class="muted">Note: the orchestrator does not expose a literal upstream <code>promptMode</code> field. <code>stageMayRenderNormalPrompt</code> (derived from structured blocked-stage evidence) is the bounded substitute used below.</p>
79
+ ${renderAgreementSection("Readiness/prompt agreement", report.readinessPromptAgreement)}
80
+ ${renderAgreementSection("Readiness/expected-judge agreement", report.readinessExpectedJudgeAgreement)}
81
+ ${renderAgreementSection("Expected/actual-judge agreement", report.expectedActualJudgeAgreement)}
82
+ ${renderAgreementSection("Judge/correction agreement", report.judgeCorrectionAgreement)}
83
+ ${renderAgreementSection("Judge/final-eligibility agreement", report.judgeFinalEligibilityAgreement)}
84
+ ${renderAgreementSection("Eligibility/final-artifact agreement", report.eligibilityFinalArtifactAgreement)}
85
+ ${renderAgreementSection("Lifecycle-integrity agreement", report.lifecycleIntegrityAgreement)}
86
+
87
+ <section><h2>Determinism and immutability</h2>${table(["Field", "Value"], [
88
+ ["Determinism availability", report.determinism.availability],
89
+ ["Repeat count", String(report.determinism.repeatCount)],
90
+ ["Deterministic", String(report.determinism.deterministic)],
91
+ ["Fixture self-immutable", String(report.immutability.fixtureSelfImmutable)]
92
+ ])}</section>
93
+
94
+ <section><h2>Limitations</h2>${report.limitations.notes.length > 0 ? `<ul>${report.limitations.notes.map((n) => `<li>${escapeHtml(n)}</li>`).join("")}</ul>` : "<p>(none)</p>"}</section>
95
+ </body>
96
+ </html>
97
+ `;
98
+ }
@@ -0,0 +1,3 @@
1
+ export function renderContextIntegrityJsonReport(report) {
2
+ return JSON.stringify(report, null, 2);
3
+ }