@dailephd/my-dev-kit-lab 0.4.4 → 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 (74) hide show
  1. package/CHANGELOG.md +468 -0
  2. package/README.md +3 -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/stageContextMetrics/calculateAllocationMetrics.js +169 -0
  10. package/dist/src/evaluation/stageContextMetrics/calculateConditionCoverageMetrics.js +74 -0
  11. package/dist/src/evaluation/stageContextMetrics/calculateProducerConditionAgreement.js +113 -0
  12. package/dist/src/evaluation/stageContextMetrics/calculateReadinessAgreement.js +60 -0
  13. package/dist/src/evaluation/stageContextMetrics/calculateRunIntegrityAgreement.js +309 -0
  14. package/dist/src/evaluation/stageContextMetrics/calculateSupplementalRawAgreement.js +12 -2
  15. package/dist/src/evaluation/stageContextMetrics/calculateTruncationClassification.js +100 -0
  16. package/dist/src/evaluation/stageContextMetrics/evaluateProducerReadinessBridge.js +76 -5
  17. package/dist/src/evaluation/stageContextMetrics/index.js +4 -0
  18. package/dist/src/evaluation/stageContextMetrics/runIntegrityAgreementTypes.js +1 -0
  19. package/dist/src/evaluation/stageContextSelectors/contextArtifactConsistency.js +7 -0
  20. package/dist/src/evaluation/stageContextSelectors/index.js +1 -0
  21. package/dist/src/evaluation/stageContextSelectors/orchestratorRunIntegritySelectors.js +64 -0
  22. package/dist/src/evaluation/upstreamArtifacts/index.js +2 -0
  23. package/dist/src/evaluation/upstreamArtifacts/orchestratorRunIntegrityV1.js +33 -0
  24. package/dist/src/evaluation/upstreamArtifacts/readOrchestratorRunIntegrityV1.js +9 -0
  25. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitContextCapsuleV1.js +59 -2
  26. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitRetrievalAuditRecordV1.js +6 -1
  27. package/dist/src/evaluation/upstreamArtifacts/validateOrchestratorRunIntegrityV1.js +177 -0
  28. package/dist/src/report/experiments/buildContextIntegrityReport.js +204 -0
  29. package/dist/src/report/experiments/contextIntegrityReportModel.js +1 -0
  30. package/dist/src/report/experiments/index.js +5 -0
  31. package/dist/src/report/experiments/renderContextIntegrityHtml.js +98 -0
  32. package/dist/src/report/experiments/renderContextIntegrityJsonReport.js +3 -0
  33. package/dist/src/report/experiments/renderContextIntegrityText.js +111 -0
  34. package/dist/src/securityValidation/packageChecks/requiredPackageContents.js +33 -0
  35. package/dist/src/securityValidation/packageChecks/runPackageChecks.js +11 -5
  36. package/docs/METRICS.md +83 -0
  37. package/package.json +4 -2
  38. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/corrected-replay/derived/run-integrity-evidence.json +99 -0
  39. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/corrected-replay/producer/implementation-audit.json +1585 -0
  40. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/corrected-replay/producer/implementation-capsule.json +11455 -0
  41. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/00-request.txt +1 -0
  42. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/architecture-context-packet.txt +82 -0
  43. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/behavior-model.txt +104 -0
  44. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/final-report.txt +41 -0
  45. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/implementation-context-packet.txt +114 -0
  46. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/implementation-report.txt +92 -0
  47. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/judge-report.txt +34 -0
  48. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/pseudocode-packet.txt +244 -0
  49. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/request-brief.txt +40 -0
  50. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/test-context-packet.txt +93 -0
  51. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/test-implementation-report.txt +69 -0
  52. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/test-strategy-packet.txt +354 -0
  53. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/artifacts/verification-report.txt +85 -0
  54. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/derived/run-integrity-evidence.json +98 -0
  55. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/architecture-audit.json +1169 -0
  56. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/architecture-request.json +29 -0
  57. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/implementation-audit.json +1494 -0
  58. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/implementation-capsule.json +11364 -0
  59. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/implementation-request.json +33 -0
  60. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/producer/test-request.json +74 -0
  61. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/reports/architecture-context-retrieval-report.txt +58 -0
  62. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/reports/implementation-context-retrieval-report.txt +75 -0
  63. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/reports/test-context-retrieval-report.txt +84 -0
  64. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/run.json +62 -0
  65. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/tool-versions/my-dev-kit-version.txt +1 -0
  66. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/failed-run/tool-versions/orchestrator-version.txt +1 -0
  67. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/manifests/corrected-replay-manifest.json +19 -0
  68. package/tests/fixtures/ecosystem/context-integrity/v0.4.5/manifests/failed-run-manifest.json +56 -0
  69. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.4/PROVENANCE.txt +18 -0
  70. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.4/context-capsule/complete-v1.0.0.json +556 -0
  71. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.4/retrieval-audit-record/complete-v1.0.0.json +238 -0
  72. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.3/run-integrity/PROVENANCE.txt +31 -0
  73. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.3/run-integrity/ready-pass-final-pass.json +132 -0
  74. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.3/run-integrity/refresh-required-need-context.json +146 -0
@@ -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("&", "&")
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
+ }
@@ -0,0 +1,111 @@
1
+ function line(label, value) {
2
+ return ` ${label}: ${value === null || value === undefined ? "(unavailable)" : String(value)}`;
3
+ }
4
+ function renderAgreement(label, agreement) {
5
+ const lines = [`${label}: ${agreement.outcome} (availability: ${agreement.availability})`];
6
+ if (agreement.reason)
7
+ lines.push(` reason: ${agreement.reason}`);
8
+ if (agreement.contradictions.totalCount > 0) {
9
+ lines.push(` contradictions (${agreement.contradictions.displayedCount} of ${agreement.contradictions.totalCount}, omitted ${agreement.contradictions.omittedCount}):`);
10
+ for (const c of agreement.contradictions.items) {
11
+ lines.push(` - [${c.code}] ${c.fieldPath}: expected=${c.expected ?? "(n/a)"} observed=${c.observed ?? "(n/a)"} -- ${c.reason}`);
12
+ }
13
+ }
14
+ return lines.join("\n");
15
+ }
16
+ export function renderContextIntegrityText(report) {
17
+ const sections = [];
18
+ sections.push([
19
+ "=== 1. Context-integrity summary ===",
20
+ line("Fixture ID", report.fixture.fixtureId),
21
+ line("Fixture kind", report.fixture.kind),
22
+ line("End-to-end category", report.endToEnd?.category ?? "(unavailable)"),
23
+ line("Contradicting components", report.endToEnd ? report.endToEnd.contradictingComponents.join(", ") || "(none)" : "(unavailable)")
24
+ ].join("\n"));
25
+ sections.push([
26
+ "=== 2. Fixture and provenance ===",
27
+ line("Description", report.fixture.description),
28
+ line("my-dev-kit commit", report.fixture.myDevKitCommit),
29
+ line("orchestrator commit", report.fixture.orchestratorCommit),
30
+ line("Target repository identity", report.fixture.targetRepositoryIdentity),
31
+ line("Active index identity", report.fixture.activeIndexIdentity),
32
+ line("Manifest schema version", report.fixture.manifestSchemaVersion),
33
+ line("Tracked artifacts", report.fixture.trackedArtifactCount),
34
+ line("Derived artifacts", report.fixture.derivedArtifactCount),
35
+ line("Byte-exact artifacts", report.fixture.byteExactArtifactCount),
36
+ line("Hash verification", `${report.fixture.hashVerification.ok ? "PASS" : "FAIL"} (${report.fixture.hashVerification.checkedCount} checked)`),
37
+ ...(report.fixture.correctedReplayLimitation ? [` LIMITATION: ${report.fixture.correctedReplayLimitation}`] : [])
38
+ ].join("\n"));
39
+ sections.push([
40
+ "=== 3. Producer allocation and omissions ===",
41
+ line("Producer tool", `${report.producerIdentity.toolName ?? "(unavailable)"} ${report.producerIdentity.toolVersion ?? ""}`.trim()),
42
+ line("Role adequacy status", report.producerIdentity.roleAdequacyStatus),
43
+ line("Allocation availability", report.allocation.availability),
44
+ line("Groups evaluated", report.allocation.groupCount),
45
+ line("Total required omitted", report.allocation.totalRequiredOmitted),
46
+ line("Total optional omitted", report.allocation.totalOptionalOmitted),
47
+ line("Groups with required omission", report.allocation.groupsWithRequiredOmission.join(", ") || "(none)"),
48
+ line("Groups with optional-only omission", report.allocation.groupsWithOptionalOnlyOmission.join(", ") || "(none)"),
49
+ line("Spillover availability", report.spillover.availability),
50
+ line("Groups contributing capacity", report.spillover.groupsContributing.join(", ") || "(none)"),
51
+ line("Groups borrowing capacity", report.spillover.groupsBorrowing.join(", ") || "(none)"),
52
+ line("Truncation state", report.truncation.state),
53
+ line("requiredEvidenceLost", report.truncation.requiredEvidenceLost)
54
+ ].join("\n"));
55
+ sections.push([
56
+ "=== 4. Condition coverage ===",
57
+ line("Availability", report.conditionCoverage.availability),
58
+ line("Required conditions total", report.conditionCoverage.requiredConditionsTotal),
59
+ line("Required conditions satisfied", report.conditionCoverage.requiredConditionsSatisfied),
60
+ line("Required conditions missing", report.conditionCoverage.requiredConditionsMissing.join(", ") || "(none)"),
61
+ line("Required conditions lost", report.conditionCoverage.requiredConditionsLost.join(", ") || "(none)"),
62
+ line("Last-witness-loss count", report.conditionCoverage.lastWitnessLossCount)
63
+ ].join("\n"));
64
+ sections.push([
65
+ "=== 5. Producer/readiness agreement ===",
66
+ renderAgreement("Producer-condition agreement", report.producerConditionAgreement),
67
+ renderAgreement("requiredEvidenceLost agreement", report.requiredEvidenceLossAgreement),
68
+ renderAgreement("Producer/readiness relationship", report.producerReadinessAgreement)
69
+ ].join("\n"));
70
+ sections.push([
71
+ "=== 6. Prompt and judge agreement ===",
72
+ "Note: the orchestrator does not expose a literal upstream promptMode field. stageMayRenderNormalPrompt (a boolean derived from structured blocked-stage evidence) is the bounded substitute used here.",
73
+ renderAgreement("Readiness/prompt agreement", report.readinessPromptAgreement),
74
+ renderAgreement("Readiness/expected-judge agreement", report.readinessExpectedJudgeAgreement),
75
+ renderAgreement("Expected/actual-judge agreement", report.expectedActualJudgeAgreement)
76
+ ].join("\n"));
77
+ sections.push([
78
+ "=== 7. Correction and final-report agreement ===",
79
+ renderAgreement("Judge/correction agreement", report.judgeCorrectionAgreement),
80
+ renderAgreement("Judge/final-eligibility agreement", report.judgeFinalEligibilityAgreement),
81
+ renderAgreement("Eligibility/final-artifact agreement", report.eligibilityFinalArtifactAgreement)
82
+ ].join("\n"));
83
+ sections.push(["=== 8. Lifecycle integrity ===", renderAgreement("Lifecycle-integrity agreement", report.lifecycleIntegrityAgreement)].join("\n"));
84
+ sections.push([
85
+ "=== 9. Determinism and immutability ===",
86
+ line("Determinism availability", report.determinism.availability),
87
+ line("Repeat count", report.determinism.repeatCount),
88
+ line("Deterministic", report.determinism.deterministic),
89
+ line("Fixture self-immutable", report.immutability.fixtureSelfImmutable),
90
+ line("Fixture immutability reason", report.immutability.fixtureImmutabilityReason)
91
+ ].join("\n"));
92
+ const allContradictionCounts = [
93
+ report.producerConditionAgreement,
94
+ report.requiredEvidenceLossAgreement,
95
+ report.producerReadinessAgreement,
96
+ report.readinessPromptAgreement,
97
+ report.readinessExpectedJudgeAgreement,
98
+ report.expectedActualJudgeAgreement,
99
+ report.judgeCorrectionAgreement,
100
+ report.judgeFinalEligibilityAgreement,
101
+ report.eligibilityFinalArtifactAgreement,
102
+ report.lifecycleIntegrityAgreement
103
+ ].reduce((sum, a) => sum + a.contradictions.totalCount, 0);
104
+ sections.push([
105
+ "=== 10. Contradictions and unavailable evidence ===",
106
+ line("Total contradiction count across all components", allContradictionCounts),
107
+ line("Unavailable sections", report.limitations.unavailableSections.join(", ") || "(none)")
108
+ ].join("\n"));
109
+ sections.push(["=== 11. Limitations ===", ...(report.limitations.notes.length > 0 ? report.limitations.notes.map((n) => ` - ${n}`) : [" (none)"])].join("\n"));
110
+ return sections.join("\n\n") + "\n";
111
+ }
@@ -0,0 +1,33 @@
1
+ export const REQUIRED_PACKAGE_CONTENTS = [
2
+ "CHANGELOG.md",
3
+ "LICENSE",
4
+ "README.md",
5
+ "dist/scripts/run-final-demo.js",
6
+ "dist/src/index.js",
7
+ "package.json",
8
+ ];
9
+ function normalizeTarballPath(file) {
10
+ const normalized = file.replace(/\\/g, "/");
11
+ return normalized.startsWith("package/")
12
+ ? normalized.slice("package/".length)
13
+ : normalized;
14
+ }
15
+ export function detectMissingRequiredContents(options) {
16
+ const present = new Set(options.files.map(normalizeTarballPath));
17
+ const required = [...(options.requiredFiles ?? REQUIRED_PACKAGE_CONTENTS)]
18
+ .map(normalizeTarballPath)
19
+ .sort((left, right) => left.localeCompare(right));
20
+ const missing = required.filter((file) => !present.has(file));
21
+ const findings = missing.map((file, index) => ({
22
+ id: `${options.checkId}-required-missing-${index}`,
23
+ title: `Required file missing from npm tarball: package/${file}`,
24
+ severity: "blocker",
25
+ category: "package-content",
26
+ description: `The required release file 'package/${file}' is absent from the npm package inventory`,
27
+ evidence: `Missing required path: package/${file}`,
28
+ affectedFiles: [file],
29
+ recommendation: `Include '${file}' in the package files allowlist or restore the expected build output`,
30
+ releaseImpact: "Blocker: the npm package is incomplete and must not be published",
31
+ }));
32
+ return { missing, findings };
33
+ }
@@ -3,6 +3,7 @@ import { runSecurityCommand, resolveNpmCommand } from "../commandRunner.js";
3
3
  import { writeCheckResult } from "../artifacts.js";
4
4
  import { parseNpmPackDryRun } from "./parseNpmPackDryRun.js";
5
5
  import { detectForbiddenContents } from "./forbiddenPackageContents.js";
6
+ import { detectMissingRequiredContents } from "./requiredPackageContents.js";
6
7
  // Run npm pack --dry-run and inspect the resulting file list for forbidden contents.
7
8
  // Does not publish anything.
8
9
  export async function runPackageChecks(options) {
@@ -32,7 +33,12 @@ export async function runPackageChecks(options) {
32
33
  allowedExceptions: allowedPackageExceptions,
33
34
  checkId: "npm-pack",
34
35
  });
35
- allFindings.push(...contentFindings);
36
+ const { findings: missingRequiredFindings } = detectMissingRequiredContents({
37
+ files: parsed.files,
38
+ checkId: "npm-pack",
39
+ });
40
+ const packageFindings = [...contentFindings, ...missingRequiredFindings];
41
+ allFindings.push(...packageFindings);
36
42
  const packCheck = {
37
43
  id: "npm-pack-dry-run",
38
44
  name: "npm pack --dry-run (tarball file list)",
@@ -41,18 +47,18 @@ export async function runPackageChecks(options) {
41
47
  ? "failed"
42
48
  : parsed.parseError && parsed.files.length === 0
43
49
  ? "warning"
44
- : contentFindings.length > 0
50
+ : packageFindings.length > 0
45
51
  ? "failed"
46
52
  : "passed",
47
- severity: contentFindings.length > 0
48
- ? contentFindings.some((f) => f.severity === "blocker")
53
+ severity: packageFindings.length > 0
54
+ ? packageFindings.some((f) => f.severity === "blocker")
49
55
  ? "blocker"
50
56
  : "major"
51
57
  : "informational",
52
58
  startedAt,
53
59
  finishedAt,
54
60
  durationMs: cmd.durationMs,
55
- findings: contentFindings,
61
+ findings: packageFindings,
56
62
  skippedReason: undefined,
57
63
  command: "npm pack --dry-run",
58
64
  };
package/docs/METRICS.md CHANGED
@@ -358,3 +358,86 @@ Implemented in `src/evaluation/stageContextMetrics` (`calculateOwnerMetrics.ts`,
358
358
  Caveat: a responsibility with no matching raw mapping entry reports `unavailable`/`missingMappingEvidenceCriticalIds`, and is excluded from the denominator rather than treated as unmapped. With zero resolvable denominator entries, `mappedCriticalCompleteness` reports `not-applicable`, not an available zero.
359
359
 
360
360
  No composite score, grade, ranking, or lab-generated readiness verdict is calculated anywhere in this section.
361
+
362
+ ## Context-integrity metrics (v0.4.5)
363
+
364
+ Implemented in `src/evaluation/stageContextMetrics` and composed once per run by the same `evaluateProducerReadinessBridge.ts` used by the `v0.4.4` metrics above. These metrics read only condition-aware producer evidence mirrored exactly from the published `my-dev-kit` `v1.10.4` contract and run-integrity evidence mirrored exactly from the published `my-dev-kit-orchestrator` `v1.2.3` contract; none reimplement upstream witness-adequacy, allocation, judge, correction, or lifecycle policy. Every metric below uses the same `available`/`unavailable`/`not-applicable` availability model as the `v0.4.3`/`v0.4.4` metrics; agreement-style metrics additionally report one of the shared `AgreementOutcomeV1` values (`agreement`, `contradiction`, `insufficient-evidence`, `unsupported-legacy-evidence`, `not-applicable`), never a lab-derived pass/fail verdict.
365
+
366
+ **Allocation and spillover** (`calculateAllocationMetrics.ts`, per-group and aggregate over `ContextCapsule.groupTruncation`):
367
+
368
+ - `requiredGroupCapacity` / `usedReservation` / `unusedCapacity`
369
+ Meaning: per-group hard limit, used count, and computed unused capacity (`limit - usedCount`) read from `EvidenceGroup`.
370
+ Caveat: `requiredGroupCapacity`/`unusedCapacity` report `unavailable` when no hard limit is declared; a negative computed remainder is treated as a data inconsistency and reported `unavailable` with a diagnostic reason rather than a negative number.
371
+ - `borrowedCapacity`
372
+ Meaning: cross-group capacity borrowing.
373
+ Caveat: always reports `unavailable` — no frozen `my-dev-kit` artifact field exposes cross-group borrowing; this is never inferred from other fields.
374
+ - Per-group allocation fields (`reservation`, `initiallySelectedCount`, `unusedReservationContributed`, `borrowedCapacity`, `governingHardBound`, `requiredOmittedCount`, `optionalOmittedCount`, `adequacyAffected`, `aggregateCapacityUsed`, `aggregateCapacityRemaining`)
375
+ Meaning: read directly, field-for-field, from each `GroupTruncationEntry`.
376
+ Caveat: a group entry with none of these additive fields set reports `unavailable` for the whole entry (legacy schema-major-1 evidence), never zero.
377
+ - Aggregate allocation totals (`totalReservation`, `totalInitiallySelected`, `totalUnusedReservationContributed`, `totalBorrowedCapacity`, `totalRequiredOmitted`, `totalOptionalOmitted`, `totalDropped`) and group lists (`groupsContributingUnusedReservation`, `groupsBorrowingCapacity`, `groupsWithRequiredOmission`, `groupsWithOptionalOnlyOmission`, `groupsWithAdequacyAffected`)
378
+ Meaning: sums and group-ID lists across all evidence groups.
379
+ Caveat: `not-applicable` when there are no evidence groups; `unavailable` when no group exposes allocation diagnostics; a total is reported `null` (`partial: true`) rather than partially summed when any contributing group lacks a needed field.
380
+ - `requiredEvidenceOmitted`
381
+ Meaning: fixture-required evidence (from `StageContextExpectationFixtureV1`) missing from observed evidence.
382
+ Caveat: `groupId` on each omitted-evidence entry is always `null` — expectation items do not declare a group, so group linkage is never invented. `not-applicable` when nothing required is missing.
383
+ - Truncation classification (`avoidable` / `genuine-hard-limit` / `unresolved` / `none`)
384
+ Meaning: classifies each `TruncationRecord` using only `limit`, `used`, and `requiredEvidenceLost` — unchanged from the `v0.4.4` classification, now composed alongside the `v0.4.5` allocation/spillover evidence.
385
+ - Spillover diagnostics (`groupsContributing`, `groupsBorrowing`, `totalContributed`, `totalBorrowed`, `contributionCoversBorrowing`)
386
+ Meaning: which groups contributed unused reservation versus borrowed capacity, and whether total contribution covers total borrowing.
387
+ Caveat: `unavailable` when no group exposes `v1.10.3`/`v1.10.4` allocation diagnostics.
388
+
389
+ **Condition coverage** (`calculateConditionCoverageMetrics.ts`, over `roleConditionCoverage`):
390
+
391
+ - `requiredConditionsTotal` / `requiredConditionsSatisfied` / `requiredConditionsMissing` / `requiredConditionsLost`
392
+ Meaning: counts of required conditions by coverage state — `satisfied` (`conditionSatisfied`), `lost-to-allocation` (`lostRequiredCondition`), or `missing-evidence` (neither).
393
+ - `optionalConditionsTotal` / `optionalConditionsSatisfied` / `optionalConditionsMissing`
394
+ Meaning: the same breakdown for non-required conditions.
395
+ - `witnessEvidence`
396
+ Meaning: per-condition witness detail (`witnessPolicy`, `requiredWitnessCount`, `availableWitnessCount`, `retainedWitnessCount`, `retainedWitnessIds`, `adequateWitnessRemains`, `coverageState`, `lossReason`, `evidenceGroupIds`) read directly from each `RoleConditionCoverage` entry.
397
+ Caveat: retained-witness identifiers are never fabricated from counts alone; only IDs the producer actually supplied are reported.
398
+ - `lastWitnessLossCount`
399
+ Meaning: count of required conditions that lost their last adequate witness (`lostRequiredCondition`).
400
+ Caveat: a real, available zero (no last-witness loss) is distinct from `unavailable` (no condition-coverage evidence at all).
401
+ - `conditionToGroupMapping`
402
+ Meaning: whether each condition's `evidenceGroupIds` reference known evidence groups (`mapped`, `unknownGroupIds`).
403
+ - Overall availability
404
+ Caveat: the entire metric block reports `unavailable` when `roleConditionCoverage` is absent — this is the expected, documented case for the `v0.4.5` failed-run fixture, which predates condition-level diagnostics (legacy schema-major-1 producer evidence), never treated as an evaluated-empty result.
405
+
406
+ **Agreement metrics** (comparing producer evidence against itself, and producer evidence against orchestrator run-integrity evidence):
407
+
408
+ - `producerConditionAgreement`
409
+ Meaning: compares `roleAdequacy.status` against condition-coverage evidence; flags `PRODUCER_INADEQUATE_BUT_ALL_REQUIRED_CONDITIONS_RETAINED` and `PRODUCER_ADEQUATE_BUT_REQUIRED_CONDITION_LOST` contradictions.
410
+ Caveat: reports `unsupported-legacy-evidence` (not `contradiction` or `agreement`) when condition-coverage evidence itself is unavailable — this is the case for the failed-run fixture.
411
+ - `requiredEvidenceLossAgreement`
412
+ Meaning: compares `truncation.requiredEvidenceLost` against explicit condition-loss/required-omission evidence; flags `REQUIRED_EVIDENCE_LOST_FALSE_BUT_CONDITION_LOSS_DETECTED` and `REQUIRED_EVIDENCE_LOST_TRUE_BUT_NO_CONDITION_OR_GROUP_LOSS_DETECTED`.
413
+ - `capsuleAuditConditionAgreement`
414
+ Meaning: whether the context capsule and retrieval audit record agree on `roleConditionCoverage`, `truncation`, and `roleAdequacy`, using the existing capsule/audit consistency selector.
415
+ - `readinessPromptAgreement`
416
+ Meaning: compares `gate.readinessClassification` against `stageMayRenderNormalPrompt` (derived from structured blocked-stage evidence — **not** a literal upstream `promptMode` field, which the orchestrator does not expose) for context-sensitive stages (`implementation`, `test-implementation`); flags `READY_BUT_PROMPT_NOT_NORMAL` and `REFRESH_REQUIRED_BUT_PROMPT_NORMAL`.
417
+ Caveat: `not-applicable` for non-context-sensitive stages.
418
+ - `readinessExpectedJudgeAgreement`
419
+ Meaning: checks the gate's own `contextReady`/`expectedJudgeVerdict` invariant; flags `CONTEXT_READY_BUT_EXPECTED_NOT_PASS` and `CONTEXT_NOT_READY_BUT_EXPECTED_NOT_NEED_CONTEXT`.
420
+ - `expectedActualJudgeAgreement`
421
+ Meaning: compares the gate's `expectedJudgeVerdict` against the parsed `authoredJudgeVerdict`; flags malformed/missing judge verdicts and the upstream `JUDGE_VERDICT_CONTRADICTS_RUN_INTEGRITY` code (preserved verbatim when the orchestrator's own `blockingCodes` include it) when an authored `PASS` contradicts a canonical `NEED_CONTEXT` requirement.
422
+ Caveat: `insufficient-evidence` when no `judgeIntegrity` evidence was supplied. A syntactically valid, accepted verdict that legitimately differs from the expected one (e.g. a correction-route or terminal blocked verdict) is not itself flagged as a contradiction.
423
+ - `judgeCorrectionAgreement`
424
+ Meaning: checks that a `PASS` verdict has no active correction route, that a corrective verdict requiring correction has one, and that `acceptedCorrectionStage` matches the structured route's `routedStage`; flags `PASS_WITH_ACTIVE_CORRECTION_ROUTE`, `CORRECTIVE_VERDICT_WITHOUT_ROUTE`, and `CORRECTION_DESTINATION_MISMATCH`.
425
+ - `judgeFinalEligibilityAgreement`
426
+ Meaning: checks that `finalReportEligible` only holds when the authored verdict is `PASS`, parsed, accepted, and matches the expected verdict; flags `ELIGIBLE_WITH_NON_PASS_JUDGE`, `ELIGIBLE_WITH_MALFORMED_OR_MISSING_JUDGE`, `ELIGIBLE_WITH_UNACCEPTED_JUDGE`, and `ELIGIBLE_WITH_UNMATCHED_EXPECTED_VERDICT`.
427
+ - `eligibilityFinalArtifactAgreement`
428
+ Meaning: checks eligibility against final-artifact presence and verdict; flags `ELIGIBLE_BUT_ARTIFACT_MISSING`, `INELIGIBLE_BUT_ARTIFACT_PRESENT`, `NEED_CONTEXT_FOLLOWED_BY_FINAL_PASS` (or the more general `INELIGIBLE_WITH_FINAL_PASS`), and `FINAL_ARTIFACT_MALFORMED_VERDICT`. This is the metric that surfaces the real historical `v1.11.0` Batch 1 failed-run's contradiction: a `NEED_CONTEXT` gate followed by a final report with verdict `PASS`.
429
+ - `lifecycleIntegrityAgreement`
430
+ Meaning: per-stage lifecycle entries (`completionBasis`: `not-complete` / `artifact-presence-only` / `manual-record`) checked against expected run-integrity blocking; flags `MANUAL_MARK_COMPLETE_BYPASS_SUCCEEDED` when a stage that should be blocked (by `gate.blockedStageNames` or final-report ineligibility) resolved to `complete` anyway, whether through a manual mark-complete record or artifact presence alone.
431
+ Caveat: `not-applicable` when no lifecycle evidence was supplied.
432
+ - `endToEndSummary` (`category`: `full-agreement` / `contradiction-present` / `insufficient-evidence` / `unsupported-legacy-evidence`)
433
+ Meaning: aggregates all component agreement outcomes above (plus `producerReadiness` from the `v0.4.4` bridge) — any contradiction anywhere makes the category `contradiction-present`; otherwise any `insufficient-evidence` or `unsupported-legacy-evidence` component determines the category; only when every component agrees is the category `full-agreement`.
434
+ Caveat: this is an aggregation of agreement/contradiction state, not a composite score, grade, ranking, or release verdict — no such value is calculated anywhere in this section.
435
+
436
+ **Fixture assurance:**
437
+
438
+ - Fixture hash verification (`src/evaluation/ecosystemFixtures/verifyFixtureHashes.ts`)
439
+ Meaning: SHA-256 comparison of tracked fixture files against the manifest's recorded hashes.
440
+ Interpretation: `ok: false` means the on-disk fixture bytes no longer match what was frozen; evaluation results built from a failed hash check should not be trusted.
441
+ - Determinism and fixture self-immutability
442
+ Meaning: reuses `calculateStageContextDeterminism`/`canonicalizeStageContextRun` (`v0.4.3`) to confirm repeated evaluations of the same fixture produce identical canonicalized results, and re-runs fixture hash verification to confirm the frozen bytes were not mutated by evaluation.
443
+ Caveat: this is fixture-level self-immutability, not the `v0.4.3` live-target-mutation check — no live target repository is exercised by this evaluation path.
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@dailephd/my-dev-kit-lab",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "type": "module",
5
5
  "description": "Evidence, benchmark, and evaluation companion for my-dev-kit.",
6
6
  "bin": {
7
7
  "my-dev-kit-lab": "dist/scripts/run-final-demo.js"
8
8
  },
9
9
  "files": [
10
+ "CHANGELOG.md",
10
11
  "dist/scripts/",
11
12
  "!dist/scripts/docs/",
12
13
  "dist/src/",
@@ -80,7 +81,8 @@
80
81
  "test:security": "vitest run tests/security/",
81
82
  "test:fuzz:smoke": "tsx scripts/security/runFuzzSmoke.ts",
82
83
  "security:validate": "tsx scripts/security/validate.ts",
83
- "audit": "tsx scripts/audits/runAudit.ts"
84
+ "audit": "tsx scripts/audits/runAudit.ts",
85
+ "report:context-integrity-smoke": "tsx scripts/report-context-integrity-smoke.ts"
84
86
  },
85
87
  "devDependencies": {
86
88
  "@types/node": "^24.0.0",
@@ -0,0 +1,99 @@
1
+ {
2
+ "_derivationNote": "LAB-DERIVED, not a byte-exact capture. Built for the same run identity/target/index/request shape as ../../failed-run using the exact local my-dev-kit v1.10.4 (commit d09068f) condition-aware contract and the exact local my-dev-kit-orchestrator v1.2.3 (commit 2cb82f0) RunIntegrityGate/JudgeIntegrity/FinalReportEligibility contract, following the same hand-distillation convention the orchestrator's own tests/fixtures/v123-batch4/corrected-run fixture uses (see manifests/corrected-replay-manifest.json for full provenance).",
3
+ "schemaVersion": "1.0.0",
4
+ "runFolder": "Z:/Users/newuser/Projects/my-dev-kit-v1/.my-dev-kit-orchestrator/runs/20260730T113740-implement-my-dev-kit-v1-11-0-b",
5
+ "gate": {
6
+ "schemaVersion": "1.0.0",
7
+ "mode": "feature",
8
+ "contextRequired": true,
9
+ "applicableContextKinds": ["implementation", "test"],
10
+ "implementationContext": {
11
+ "schemaVersion": "1.0.0",
12
+ "kind": "implementation",
13
+ "role": "implementation",
14
+ "decision": "ready",
15
+ "classification": "ready",
16
+ "stageId": "stage.feature.implementation",
17
+ "packetPath": "artifacts/implementation-context-packet.txt",
18
+ "reportPath": "reports/implementation-context-retrieval-report.txt",
19
+ "issues": [],
20
+ "warnings": [],
21
+ "blockingIssueCodes": [],
22
+ "affectedResponsibilityIds": [],
23
+ "evaluatedFreshness": "fresh",
24
+ "evaluatedAdequacy": "sufficient-with-assumptions",
25
+ "requiredEvidenceTruncated": "no",
26
+ "readyWithAssumptions": true,
27
+ "provenanceSummary": "resolved from the corrected v1.10.4 condition-aware producer contract",
28
+ "indexIdentity": "Z:/Users/newuser/Projects/my-dev-kit-v1/.my-dev-kit-context/v1.11.0-batch-1-compose-artifact-foundation/implementation"
29
+ },
30
+ "contextReady": true,
31
+ "readinessClassification": "ready",
32
+ "blockedStageNames": [],
33
+ "blockingCodes": [],
34
+ "recommendedCorrectionStage": null,
35
+ "expectedJudgeVerdict": "PASS",
36
+ "warnings": []
37
+ },
38
+ "judgeIntegrity": {
39
+ "schemaVersion": "1.0.0",
40
+ "judgeArtifactPresent": true,
41
+ "judgeVerdictParseStatus": "parsed",
42
+ "authoredJudgeVerdict": "PASS",
43
+ "expectedJudgeVerdict": "PASS",
44
+ "judgeVerdictMatchesExpected": true,
45
+ "judgeVerdictAccepted": true,
46
+ "correctionRequired": false,
47
+ "correctionBlocked": false,
48
+ "acceptedCorrectionStage": null,
49
+ "finalReportEligible": true,
50
+ "blockingCodes": [],
51
+ "acceptedCorrectionRoute": null
52
+ },
53
+ "finalReportEligibility": {
54
+ "eligible": true,
55
+ "contextReady": true,
56
+ "priorArtifactsValid": true,
57
+ "judgeIntegrity": {
58
+ "schemaVersion": "1.0.0",
59
+ "judgeArtifactPresent": true,
60
+ "judgeVerdictParseStatus": "parsed",
61
+ "authoredJudgeVerdict": "PASS",
62
+ "expectedJudgeVerdict": "PASS",
63
+ "judgeVerdictMatchesExpected": true,
64
+ "judgeVerdictAccepted": true,
65
+ "correctionRequired": false,
66
+ "correctionBlocked": false,
67
+ "acceptedCorrectionStage": null,
68
+ "finalReportEligible": true,
69
+ "blockingCodes": [],
70
+ "acceptedCorrectionRoute": null
71
+ },
72
+ "blockingCodes": []
73
+ },
74
+ "finalArtifactPresent": true,
75
+ "finalArtifactVerdict": "PASS",
76
+ "lifecycle": [
77
+ {
78
+ "artifactFile": "artifacts/implementation-report.txt",
79
+ "stageName": "implementation",
80
+ "fileExists": true,
81
+ "manualRecord": null,
82
+ "resolvedState": "complete"
83
+ },
84
+ {
85
+ "artifactFile": "artifacts/test-implementation-report.txt",
86
+ "stageName": "test-implementation",
87
+ "fileExists": true,
88
+ "manualRecord": null,
89
+ "resolvedState": "complete"
90
+ },
91
+ {
92
+ "artifactFile": "artifacts/final-report.txt",
93
+ "stageName": "final-report",
94
+ "fileExists": true,
95
+ "manualRecord": null,
96
+ "resolvedState": "complete"
97
+ }
98
+ ]
99
+ }