From 419d9d006d0a56b64850bd4e53e9b5f07d01a5d6 Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Tue, 18 Aug 2026 12:58:41 +0900 Subject: [PATCH] ci: give test:tech-log its own gate command and junit evidence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TechLog suite already ran in CI, but only inside `test:coverage`'s combined `vitest run tests/runtime-schema tests/unit … tests/features/tech-log` invocation on FE-GATE-005. A TechLog regression therefore surfaced as a coverage-gate failure, and the only junit that carried it was coverage.xml, which reports every other suite at the same time. `test-tech-log` now sits on FE-GATE-007 beside `test-reference-feature`, the sibling it mirrors — both drive a suite under `tests/features/` — and declares `artifacts/tests/tech-log.xml`, which `test:tech-log` already wrote, as its own command-generated junit evidence. The gate log now names `$ corepack pnpm test:tech-log` as its own step and the failure lands on the suite that produced it. Adding a command and an artifact moves the exact-count authority to 84 definitions / 96 references / 130 artifacts (109 evidence references), and changes the canonical gate shape digest because FE-GATE-007's commandIds and evidenceArtifactIds are part of it. There is no tooling to regenerate that digest, so it was recomputed by hand under the standing procedure: a fresh transcription of `canonicalGateShapeSha256` first reproduced the committed f3cc9075… from the unedited config/ci/gates.json — proving the transcription, not just agreeing with whatever the check compares against — and only then hashed the edited file to 98d19911…. `corepack pnpm ci:gate -- FE-GATE-007` passes end to end; the generated workflow bytes are unchanged, since the yml dispatches gates rather than commands. Co-Authored-By: Claude Opus 5 (1M context) --- config/ci/gates.json | 16 ++++++++++++++++ scripts/contracts/ci-gates.ts | 19 ++++++++++++++----- tests/unit/ci-workflow-generation.test.ts | 10 ++++++---- .../unit/task3-selective-integration.test.ts | 8 +++++--- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/config/ci/gates.json b/config/ci/gates.json index a1d6d2c..c3b8032 100644 --- a/config/ci/gates.json +++ b/config/ci/gates.json @@ -174,6 +174,11 @@ "script": "test:reference-feature", "expect": "pass" }, + { + "id": "test-tech-log", + "script": "test:tech-log", + "expect": "pass" + }, { "id": "test-recipes", "script": "test:recipes", @@ -901,6 +906,15 @@ "test-reference-feature" ] }, + { + "id": "artifact-artifacts-tests-tech-log-xml", + "path": "artifacts/tests/tech-log.xml", + "schemaId": "junit", + "production": "command-generated", + "producerCommandIds": [ + "test-tech-log" + ] + }, { "id": "artifact-artifacts-tests-optional-recipes-xml", "path": "artifacts/tests/optional-recipes.xml", @@ -1852,6 +1866,7 @@ "test-integration", "test-http-scenario-evidence", "test-reference-feature", + "test-tech-log", "test-recipes" ], "logArtifactId": "artifact-artifacts-quality-gates-FE-GATE-007-txt", @@ -1861,6 +1876,7 @@ "artifact-artifacts-quality-http-scenario-evidence-json", "artifact-artifacts-quality-http-scenario-evidence-fixture-json", "artifact-artifacts-tests-reference-feature-xml", + "artifact-artifacts-tests-tech-log-xml", "artifact-artifacts-tests-optional-recipes-xml" ], "retentionClassId": "merge-cycle" diff --git a/scripts/contracts/ci-gates.ts b/scripts/contracts/ci-gates.ts index ddb9996..9d11ae2 100644 --- a/scripts/contracts/ci-gates.ts +++ b/scripts/contracts/ci-gates.ts @@ -452,7 +452,11 @@ const CANONICAL_GATE_SHAPE_SHA256 = // `check-tech-log-contract`. Recomputed with `canonicalGateShapeSha256` // below, verified by first reproducing the previous constant from the // previous `config/ci/gates.json` before hashing the new one. - "f3cc90758084e16757e71a8a3fe772d8e408f0c51b044294f329309027ce6563"; + // Alignment follow-up item 2: recomputed again after FE-GATE-007 gained + // `test-tech-log` and its junit evidence, by the same method — the previous + // constant f3cc9075… was reproduced from the previous gates.json first, so + // the transcription that produced this value is known to be the real one. + "98d19911c37a18f579fe51b3e3b8164ff0515579557512bc4040b407d4399be9"; function canonicalGateShapeSha256(gates: CiGateContract["gates"]): string { const normalized = gates.map( @@ -489,15 +493,20 @@ function canonicalAuthorityBaselineFailures(contract: CiGateContract): string[] // Final fix wave, item 1: FE-GATE-010 gained `check-tech-log-contract`, the // drift gate that pins the vendored canonical Studio contract to its digest. // Until it was referenced by a gate it ran only when typed by hand. - if (contract.commands.length !== 83 || commandReferenceCount !== 95) { + // Alignment follow-up, item 2: FE-GATE-007 gained `test-tech-log`. The suite + // already ran inside `test:coverage`'s combined vitest invocation, so a + // TechLog failure was reported as a coverage-gate failure with no junit of + // its own to name it. + if (contract.commands.length !== 84 || commandReferenceCount !== 96) { failures.push( - `command authority baseline must contain exactly 83 definitions and 95 references; received ${contract.commands.length} definitions and ${commandReferenceCount} references`, + `command authority baseline must contain exactly 84 definitions and 96 references; received ${contract.commands.length} definitions and ${commandReferenceCount} references`, ); } // Template merge. 126 product artifacts plus the two the template added. // Task 11 added one more: the TECH_LOG_STUDIO_ASSETS manual a11y evidence file. - if (contract.artifacts.length !== 129) { - failures.push(`artifact authority baseline must contain exactly 129 artifacts; received ${contract.artifacts.length}`); + // Alignment follow-up, item 2 added the TechLog junit report. + if (contract.artifacts.length !== 130) { + failures.push(`artifact authority baseline must contain exactly 130 artifacts; received ${contract.artifacts.length}`); } if (contract.stages.length !== 5) { failures.push(`stage authority baseline must contain exactly 5 stages; received ${contract.stages.length}`); diff --git a/tests/unit/ci-workflow-generation.test.ts b/tests/unit/ci-workflow-generation.test.ts index 25af7bd..0f81f8d 100644 --- a/tests/unit/ci-workflow-generation.test.ts +++ b/tests/unit/ci-workflow-generation.test.ts @@ -190,14 +190,16 @@ describe("CI gate contract", () => { ); expect(contract.jobs).toHaveLength(9); // Final fix wave item 1: FE-GATE-010 gained `check-tech-log-contract`. - expect(contract.commands).toHaveLength(83); - expect(contract.gates.reduce((total, gate) => total + gate.commandIds.length, 0)).toBe(95); + // Alignment follow-up item 2: FE-GATE-007 gained `test-tech-log`. + expect(contract.commands).toHaveLength(84); + expect(contract.gates.reduce((total, gate) => total + gate.commandIds.length, 0)).toBe(96); expect(contract.commands.filter(({ expect }) => expect === "fail")).toHaveLength(23); // Template merge. Recounted from the merged config/ci/gates.json rather // than taking either side's number. // Task 11 added TECH_LOG_STUDIO_ASSETS's manual accessibility evidence. - expect(contract.gates.reduce((total, gate) => total + gate.evidenceArtifactIds.length, 0)).toBe(108); - expect(contract.artifacts).toHaveLength(129); + // Alignment follow-up item 2 added the TechLog junit report. + expect(contract.gates.reduce((total, gate) => total + gate.evidenceArtifactIds.length, 0)).toBe(109); + expect(contract.artifacts).toHaveLength(130); expect(contract.stages).toHaveLength(5); expect(contract.retention.classes).toHaveLength(5); expect(index.gates.get("FE-GATE-015")?.commandIds).toHaveLength(2); diff --git a/tests/unit/task3-selective-integration.test.ts b/tests/unit/task3-selective-integration.test.ts index 207d88f..1877493 100644 --- a/tests/unit/task3-selective-integration.test.ts +++ b/tests/unit/task3-selective-integration.test.ts @@ -186,10 +186,12 @@ describe("selective Task 3 contract closure", () => { // template's 2. Task 11 added TECH_LOG_STUDIO_ASSETS's manual // accessibility evidence, bringing the total to 129. // Final fix wave item 1 added `check-tech-log-contract` to FE-GATE-010. + // Alignment follow-up item 2 added `test-tech-log` and its junit report to + // FE-GATE-007, bringing the totals to 84/96/130. expect(canonical.gates).toHaveLength(27); - expect(canonical.commands).toHaveLength(83); - expect(canonical.gates.reduce((sum, gate) => sum + gate.commandIds.length, 0)).toBe(95); - expect(canonical.artifacts).toHaveLength(129); + expect(canonical.commands).toHaveLength(84); + expect(canonical.gates.reduce((sum, gate) => sum + gate.commandIds.length, 0)).toBe(96); + expect(canonical.artifacts).toHaveLength(130); expect(canonical.stages).toHaveLength(5); expect(canonical.retention.classes).toHaveLength(5);