381 lines
31 KiB
Markdown
381 lines
31 KiB
Markdown
# Frontend Thin Platform Consumer Migration Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. Use `superpowers:using-git-worktrees` before editing.
|
||
|
||
**Goal:** Convert `clean-architecture-frontend-template` into a thin consumer of `test-assurance-platform` and `cicd-platform` while preserving product source, tests, fixtures, raw product artifact codecs, and all origin-unknown worktree changes.
|
||
|
||
**Architecture:** Product manifests declare risks, obligations, suites, components, outputs, and platform capabilities. Product scripts execute one bounded product purpose and emit raw artifacts. Test assurance owns selection through assessment; CI/CD owns workflow through promotion. Shadow mode has one candidate writer—the platform—and legacy release/promotion code is read-only until removed. The central required workflow is installed by the platform and is never copied into this repository.
|
||
|
||
**Tech Stack:** TypeScript 7.0.2, Node.js 24.14.0, pnpm 11.17.0, Vitest 4.1.10, Playwright 1.62.0, YAML/JSON Schema, `testctl` v3, `cicdctl`.
|
||
|
||
## Global Constraints
|
||
|
||
- Repository: `/home/donghyeon/workspace/desktop-server-git/clean-architecture-frontend-template`; every command runs from its isolated migration worktree root unless it is explicitly marked read-only against the original dirty worktree.
|
||
- Begin only from a clean worktree whose HEAD contains the approved spec amendment and all three 2026-08-02 plans in one immutable planning commit; never modify or clean the original dirty worktree.
|
||
- Consume the immutable Test Assurance Task 10 release and CI/CD Task 11 P1/shadow release from the two companion plans.
|
||
- Resolve `CICDCTL_BIN` and `TESTCTL_BIN` to absolute executable paths from the signed CICD catalog, and resolve `CICDCTL_DIGEST` and `TESTCTL_DIGEST` from the same catalog. Before every plan/manifest command, `sha256sum` must equal the signed value; PATH fallback is forbidden.
|
||
- Do not claim P2/active or delete the legacy path until actual Gitea/runner/scanner/signer/provider evidence and required-status installation are observed.
|
||
- Use only the exact capability IDs approved in the design.
|
||
|
||
- Keep production code, product tests/assertions, mocks, scenarios, fixtures, Vitest/Playwright config, V8 instrumentation inputs, and runtime/release artifact codecs.
|
||
- Remove local workflow compilation, risk selection, waiver/normalization/assessment, test scheduling, provider invocation, signing, retention, candidate publication, and promotion engines after cutover.
|
||
- `check:types` remains a CI Node responsibility. `check:architecture` alone maps to `architecture-typescript`.
|
||
- Artifact browser suites consume the platform candidate; their Playwright `webServer` must never rebuild it.
|
||
- The product does not add `.gitea/workflows/required-delivery-guard.yaml` or any equivalent copied central workflow.
|
||
- Rollback changes only the signed platform catalog/version pin and promotes a previous immutable subject through `release-control`; it never re-enables a legacy writer.
|
||
|
||
---
|
||
|
||
### Task 1: Preserve and classify the existing dirty Task 3 work
|
||
|
||
**Files:**
|
||
|
||
- Create in the clean migration worktree: `docs/migration/task3-wip-provenance.json`
|
||
- Create: `docs/migration/task3-wip-disposition.md`
|
||
- Read only: original dirty worktree tracked diff and untracked files
|
||
|
||
**Ledger contract:** Each entry records `path`, `workingBlobSha256`, and an ordered `hunks` array. Every hunk records `oldRange`, `newRange`, `diffSha256`, `owner` (`product`, `test-assurance`, `cicd`, `unrelated-or-unknown`), `provenance`, and `disposition` (`preserve-in-original`, `reimplement-in-platform`, `retain-product-codec`, `remove-after-cutover`). Mixed-responsibility files therefore have multiple hunk owners. The ledger does not copy source content or create a patch archive.
|
||
|
||
- [ ] Verify the migration worktree entry commit before inspecting WIP:
|
||
|
||
```bash
|
||
git show HEAD:docs/superpowers/specs/2026-08-02-platform-owned-frontend-assurance-delivery-design.md
|
||
git show HEAD:docs/superpowers/plans/2026-08-02-frontend-platform-consumer-migration.md
|
||
git show HEAD:docs/superpowers/plans/2026-08-02-test-assurance-frontend-capabilities.md
|
||
git show HEAD:docs/superpowers/plans/2026-08-02-cicd-frontend-assurance-delivery.md
|
||
git status --short
|
||
```
|
||
|
||
Expected: all four documents exist and migration-worktree status is empty.
|
||
- [ ] Capture `git status --short`, `git diff --name-status`, `git diff --numstat`, `git diff | sha256sum`, per-hunk unified diffs, and `git hash-object` for each present untracked/modified file without writing to the original worktree.
|
||
- [ ] Add a failing migration test in `tests/unit/platform-migration-provenance.test.ts` that requires every hunk to have one owner/provenance/disposition, permits mixed owners per file, and rejects a blanket `frontend`/`keep-all` classification.
|
||
- [ ] Run:
|
||
|
||
```bash
|
||
corepack pnpm exec vitest run tests/unit/platform-migration-provenance.test.ts
|
||
```
|
||
|
||
Expected: RED because the ledger does not exist.
|
||
|
||
- [ ] Create the ledger and disposition document with `apply_patch`. Explicitly classify workflow/gate/test-normalization/provider/promotion WIP to its platform owner and origin-unknown files as preserved in the original worktree.
|
||
- [ ] Recompute every original working-blob and hunk digest, re-run the test, and compare original status plus digests with the capture; expected PASS with no drift.
|
||
- [ ] Commit only the ledger, disposition, and test:
|
||
|
||
```bash
|
||
git add docs/migration/task3-wip-provenance.json docs/migration/task3-wip-disposition.md tests/unit/platform-migration-provenance.test.ts
|
||
git commit -m "docs: preserve Task 3 migration provenance"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 2: Declare the CI/CD platform consumer
|
||
|
||
**Files:**
|
||
|
||
- Create: `delivery-platform.yaml`
|
||
- Create: `tests/unit/delivery-platform-manifest.test.ts`
|
||
|
||
**Selected capabilities:**
|
||
|
||
```text
|
||
ci-standard-core
|
||
ci-node-typescript
|
||
ci-frontend
|
||
ci-test-assurance
|
||
ci-dependency-vulnerability
|
||
ci-sbom
|
||
ci-provenance
|
||
ci-artifact-signing
|
||
ci-static-artifact-supply-chain
|
||
ci-static-site-publish
|
||
delivery-release-control
|
||
```
|
||
|
||
The manifest declares one frontend component rooted at `.`, one static-site output rooted at `dist`, pnpm frozen install, `lint`, `check:types`, `build`, the size/environment/determinism policy, and a signed `platformVersion` that exists in the released CI/CD catalog. It does not contain a workflow DAG, provider command, test command, or mutable tool image.
|
||
|
||
- [ ] Add RED tests that invoke `$CICDCTL_BIN manifest compile` after digest verification and reject missing capabilities, a floating platform version, product-owned test stages, arbitrary shell/provider commands, or a second candidate output.
|
||
- [ ] Run:
|
||
|
||
```bash
|
||
corepack pnpm exec vitest run tests/unit/delivery-platform-manifest.test.ts
|
||
```
|
||
|
||
Expected: RED because `delivery-platform.yaml` is absent.
|
||
|
||
- [ ] Add the manifest only; do not add a package script that could resolve an arbitrary PATH binary or local compilation logic.
|
||
- [ ] Compile the manifest with `"$CICDCTL_BIN" manifest compile --manifest delivery-platform.yaml --source-revision "$PLATFORM_SOURCE_REVISION" --output artifacts/platform/effective-project.json`; expected PASS at shadow activation.
|
||
- [ ] Commit:
|
||
|
||
```bash
|
||
git add delivery-platform.yaml tests/unit/delivery-platform-manifest.test.ts
|
||
git commit -m "chore(platform): declare frontend delivery capabilities"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3: Declare risks, obligations, change surfaces, and source suites
|
||
|
||
**Files:**
|
||
|
||
- Create: `test-assurance.yaml`
|
||
- Create generated: `test-assurance.lock.json`
|
||
- Create: `config/test-assurance/risks/frontend.json`
|
||
- Create: `config/test-assurance/obligations/frontend.json`
|
||
- Create: `config/test-assurance/suites/source.json`
|
||
- Create: `config/test-assurance/suites/artifact-templates.json`
|
||
- Create: `config/test-assurance/change-surfaces/frontend.json`
|
||
- Create: `config/test-assurance/legacy-command-disposition.json`
|
||
- Create: `scripts/run-contract-negative-fixtures.ts`
|
||
- Create: `scripts/reporters/vitest-discovery-reporter.ts`
|
||
- Create: `scripts/write-production-module-inventory.ts`
|
||
- Modify: `scripts/check-architecture.ts`
|
||
- Modify: `vitest.config.ts`
|
||
- Create: `tests/unit/test-assurance-source-manifest.test.ts`
|
||
- Create: `tests/unit/raw-source-reporters.test.ts`
|
||
- Create: `tests/unit/legacy-command-migration-completeness.test.ts`
|
||
- Modify: `package.json`
|
||
|
||
**Source suite mapping:**
|
||
|
||
| Suite ID | Product argv | Capability |
|
||
|---|---|---|
|
||
| `runtime-schema` | `corepack pnpm test:runtime-schema` | `unit-typescript-vitest` |
|
||
| `unit` | `corepack pnpm test:unit` | `unit-typescript-vitest` |
|
||
| `reference-feature` | `corepack pnpm test:reference-feature` | `unit-typescript-vitest` |
|
||
| `optional-recipes` | `corepack pnpm test:recipes` | `unit-typescript-vitest` |
|
||
| `component` | `corepack pnpm test:component` | `component-react-vitest` |
|
||
| `integration` | `corepack pnpm test:integration` | `integration-http-msw` |
|
||
| `http-scenarios` | `corepack pnpm test:http-scenario-evidence` | `integration-http-msw` |
|
||
| `architecture` | `corepack pnpm check:architecture` | `architecture-typescript` |
|
||
| `coverage` | `corepack pnpm test:coverage` | `coverage-v8` |
|
||
| `contract-negative-fixtures` | `corepack pnpm test:contract-negative-fixtures` | `unit-typescript-vitest` |
|
||
|
||
Every source suite declares `executionPhase: SOURCE`, an empty `requiredInputArtifacts`, a bounded argv array, timeouts, environment allowlist, and exact raw artifacts. `check:types` is absent because CI owns it. `test-assurance.yaml` references `artifact-templates.json` through `artifactSuiteTemplateFiles`; those templates are completed in Task 4.
|
||
|
||
- [ ] Add RED tests for exact capability IDs, one purpose per suite, no aggregate `test:all`, no `check:types`, no shell string, no `--passWithNoTests` on required suites, exact report paths, and source phase with zero input artifacts.
|
||
- [ ] Parse every unique command and argument tuple in legacy `config/ci/gates.json` and require exactly one disposition: `ci-node`, `test-assurance-suite`, `cicd-release-or-security`, `product-dev-only`, or `retired-with-platform-evidence`. Missing or duplicate classification fails.
|
||
- [ ] Add `test:contract-negative-fixtures` as one bounded product harness: it runs every expected-fail type/coverage/design-system/i18n/diagnostics/registry/route fixture, asserts the exact expected exit code and diagnostic identity from the disposition file, and exits 0 only when all negative contracts fail for the intended reason.
|
||
- [ ] Classify `test:browser-capabilities` into the three artifact browser suites, `test:storybook` as a retained source test harness until an explicit platform disposition is proven, and `playwright.dev.config.ts` as `product-dev-only`; no legacy gate command disappears without platform evidence.
|
||
- [ ] Add RED reporter tests requiring Vitest discovery IDs/counts alongside JUnit, a canonical production-module inventory alongside V8 coverage, an architecture graph/violations report, and typed HTTP receipts. These are raw observations only and contain no PASS/waiver/threshold decision.
|
||
- [ ] Run the focused test; expected RED.
|
||
- [ ] Add declarations. Remove `--passWithNoTests` from required source suite scripts while retaining optional behavior only for suites whose obligation explicitly permits no applicable tests. Wire the Vitest reporter into each required Vitest suite, make `check:architecture` emit the typed graph/violation JSON, and rewrite `test:coverage` to emit V8 summary plus production inventory without calling the local risk/threshold assessor.
|
||
- [ ] Use released `testctl validate`, `lock`, and `compile` to generate the lock; never type toolchain digests by hand.
|
||
- [ ] Re-run the focused test and:
|
||
|
||
```bash
|
||
"$TESTCTL_BIN" validate --repository . --out artifacts/platform/source-validation.json
|
||
"$TESTCTL_BIN" lock --repository . --out test-assurance.lock.json
|
||
"$TESTCTL_BIN" compile --repository . --lock test-assurance.lock.json --out artifacts/platform/compiled-policy.json
|
||
```
|
||
|
||
Expected: PASS with v3 and exact Node/pnpm/TypeScript/Vitest/Playwright pins.
|
||
- [ ] Commit:
|
||
|
||
```bash
|
||
git add test-assurance.yaml test-assurance.lock.json config/test-assurance scripts/reporters/vitest-discovery-reporter.ts scripts/write-production-module-inventory.ts scripts/check-architecture.ts scripts/run-contract-negative-fixtures.ts vitest.config.ts tests/unit/test-assurance-source-manifest.test.ts tests/unit/raw-source-reporters.test.ts tests/unit/legacy-command-migration-completeness.test.ts package.json
|
||
git commit -m "chore(test-assurance): declare frontend source suites"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 4: Make browser suites consume the immutable candidate
|
||
|
||
**Files:**
|
||
|
||
- Modify: `playwright.config.ts`
|
||
- Modify: `playwright.capabilities.config.ts`
|
||
- Modify: `playwright.visual.config.ts`
|
||
- Modify: `playwright.storybook.config.ts` only if it remains a required artifact suite
|
||
- Create: `scripts/serve-test-candidate.ts`
|
||
- Create: `scripts/reporters/playwright-evidence-reporter.ts`
|
||
- Create: `tests/support/browser/mutation-evidence.ts`
|
||
- Modify: `tests/e2e/reference-form.spec.ts`
|
||
- Modify: `package.json`
|
||
- Modify: `config/test-assurance/suites/artifact-templates.json`
|
||
- Modify: `config/test-assurance/obligations/frontend.json`
|
||
- Create: `tests/unit/artifact-suite-contract.test.ts`
|
||
|
||
**Artifact suite mapping:**
|
||
|
||
| Suite ID | Product argv | Capability |
|
||
|---|---|---|
|
||
| `e2e-chromium` | `corepack pnpm test:e2e:chromium` | `e2e-playwright-chromium` |
|
||
| `e2e-firefox` | `corepack pnpm test:e2e:firefox` | `e2e-playwright-firefox` |
|
||
| `e2e-webkit` | `corepack pnpm test:e2e:webkit` | `e2e-playwright-webkit` |
|
||
| `accessibility` | `corepack pnpm test:a11y` | `accessibility-web` |
|
||
| `visual-regression` | `corepack pnpm test:visual` | `visual-regression-web` |
|
||
|
||
All five repository templates declare `executionPhase: ARTIFACT` and one input declaration containing `artifactId: frontend-site` and `mediaType: application/vnd.delivery.static-site.v1+tar`. Templates contain no `sha256` field. After the platform builds the candidate, CI creates an artifact `ExecutionRequest` containing the actual candidate SHA-256; testctl materializes executable v3 `SuiteDefinition` and `WorkItem` documents with that exact digest.
|
||
|
||
- [ ] Add RED tests requiring separate Chromium/Firefox/WebKit commands and artifacts, rejecting a SHA/digest placeholder in committed templates, rejecting build commands in Playwright `webServer`, requiring candidate-root environment input, and checking typed Playwright JSON/JUnit, trace/screenshot/console/network indexes, browser provider identity, write mutation receipts, accessibility/manual-review identity, and visual baseline/diff identity.
|
||
- [ ] Run the focused test; expected RED because browser configuration currently rebuilds the site.
|
||
- [ ] Implement `serve-test-candidate.ts` as a bounded read-only static server over the executor-verified candidate directory. It reads the candidate root from the allowlisted environment and never verifies or substitutes the platform digest itself.
|
||
- [ ] Change `playwright.config.ts` and `playwright.capabilities.config.ts` to call that server and add per-browser package scripts using `--project`; each browser suite includes both `tests/e2e/` and `tests/browser-capabilities/`. Add the product-owned Playwright reporter and mutation-evidence helper so tests emit traces, screenshots, console/network indexes, response/mutation/reload receipts, accessibility findings/manual records, and visual baselines/diffs without assessing them. Extend `reference-form.spec.ts` with the existing production-shaped create handler: observe the successful HTTP response, read the created resource, reload, read it again, and write one typed receipt keyed by the test/scenario ID.
|
||
- [ ] Validate/lock/compile with testctl and run each product suite against a local candidate materialized by the platform fixture.
|
||
- [ ] Commit:
|
||
|
||
```bash
|
||
git add playwright.config.ts playwright.capabilities.config.ts playwright.visual.config.ts playwright.storybook.config.ts scripts/serve-test-candidate.ts scripts/reporters/playwright-evidence-reporter.ts tests/support/browser/mutation-evidence.ts tests/e2e/reference-form.spec.ts package.json config/test-assurance tests/unit/artifact-suite-contract.test.ts
|
||
git commit -m "refactor(browser): test the immutable platform candidate"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 5: Separate raw reporters and freeze legacy assurance as read-only
|
||
|
||
**Files:**
|
||
|
||
- Retain/refactor: `scripts/run-http-scenario-evidence.ts`
|
||
- Retain/refactor: `scripts/lib/http-scenario-evidence.ts`
|
||
- Retain/refactor: `scripts/write-a11y-report.ts`
|
||
- Create: `scripts/lib/manual-a11y-record.ts`
|
||
- Retain: product V8 instrumentation and module-inventory code in `vite.config.ts`, `vitest.config.ts`, and product codecs
|
||
- Retain read-only until Task 8: `scripts/check-test-evidence.ts`, `scripts/verify-browser-capability-evidence.ts`, `scripts/check-risk-coverage.ts`, `scripts/lib/risk-coverage.ts`, `scripts/lib/local-policy-evidence.ts`, `scripts/lib/manual-a11y-evidence.ts`, `scripts/verify-a11y-manual.ts`
|
||
- Create: `scripts/run-legacy-assurance-probe.ts`
|
||
- Modify: `package.json`
|
||
- Create: `tests/unit/raw-product-evidence-contract.test.ts`
|
||
- Create: `tests/unit/legacy-assurance-readonly.test.ts`
|
||
|
||
**Boundary:** Product emitters may validate their own artifact schema and cross-fields, but the new manifests may not invoke local obligation satisfaction, waiver, quarantine, retry/flaky, coverage threshold, scenario completeness, browser matrix completeness, or evidence freshness logic. Legacy assessors remain callable only through `run-legacy-assurance-probe.ts`, which writes comparison output to a dedicated read-only shadow namespace and has no candidate/provider/promotion operation.
|
||
|
||
- [ ] Add RED boundary tests proving raw emitters contain no verdict semantics, new manifests never invoke a legacy assessor, and every legacy assessor is reachable only from the comparison probe.
|
||
- [ ] Run `corepack pnpm exec vitest run tests/unit/raw-product-evidence-contract.test.ts tests/unit/legacy-assurance-readonly.test.ts`; expected RED before the boundary is enforced.
|
||
- [ ] Move any reusable false-green fixture to the Test Assurance platform implementation commit; in this repository keep only the product input fixture needed to reproduce the report.
|
||
- [ ] Extract production-module inventory generation from `check-risk-coverage.ts` and raw manual-review codecs from `manual-a11y-evidence.ts`; keep threshold/completeness logic unchanged solely for the read-only probe until parity.
|
||
- [ ] Update suite declarations to point directly at raw artifacts and ensure no automated workflow invokes the legacy probe.
|
||
- [ ] Re-run `corepack pnpm exec vitest run tests/unit/raw-product-evidence-contract.test.ts tests/unit/legacy-assurance-readonly.test.ts tests/unit/test-assurance-source-manifest.test.ts tests/unit/artifact-suite-contract.test.ts`; expected PASS.
|
||
- [ ] Commit:
|
||
|
||
```bash
|
||
git add scripts/run-http-scenario-evidence.ts scripts/lib/http-scenario-evidence.ts scripts/write-a11y-report.ts scripts/lib/manual-a11y-record.ts scripts/write-production-module-inventory.ts scripts/run-legacy-assurance-probe.ts package.json tests/unit/raw-product-evidence-contract.test.ts tests/unit/legacy-assurance-readonly.test.ts config/test-assurance
|
||
git commit -m "refactor(testing): isolate raw and legacy assurance paths"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 6: Run one-writer shadow parity
|
||
|
||
**Files:**
|
||
|
||
- Create: `docs/operations/platform-shadow-parity.md`
|
||
- Create: `docs/operations/evidence/platform-shadow-readiness.json` only from an actual platform run
|
||
- Create: `tests/unit/platform-shadow-contract.test.ts`
|
||
- Modify: `delivery-platform.yaml` and `test-assurance.lock.json` only to pin the released shadow versions
|
||
|
||
**Parity identity:** source revision, delivery manifest/catalog digests, test manifest/lock/policy digests, selected suite IDs, discovered/executed counts, terminal classifications, coverage production-module universe, HTTP declared/executed IDs, three browser results, candidate/member digests, source and artifact plan/evidence/assessment digests, supply-chain/provider digests, and promotion readiness. Exclude timestamp, duration, temp path, and runner identity.
|
||
|
||
- [ ] Add RED tests proving there is no product-local central workflow, the platform is the only command allowed to build/freeze a candidate in shadow, legacy release/promotion commands are read-only probes, and no product script invokes a provider or mutates desired state.
|
||
- [ ] Before shadow execution, query actual Gitea registration/status state and require: legacy `quality-gates.yml` registration `disabled`; legacy required status `detached`; central workflow installed externally with activation `shadow`; no product `required-delivery-guard.yaml`; legacy candidate/provider/promotion invocation count `0`; platform candidate writer count exactly `1`. Record actual workflow/status IDs and writer identity.
|
||
- [ ] Run the released platform fixture against this exact source revision for a passing run and deliberate failures: zero discovery, missing report, retry-only pass, missing browser, changed candidate, wrong provider digest, and response loss.
|
||
- [ ] Have the platform runner invoke `run-legacy-assurance-probe.ts` read-only and compare its test classifications with platform assessment. Do not register/run the legacy workflow and do not run legacy candidate creation, publication, or promotion.
|
||
- [ ] Record the actual signed parity report digest and environment identities only after the run exists. If the required external environment is unavailable, leave this task incomplete and retain shadow activation.
|
||
- [ ] Re-run focused contract tests; expected PASS for repository constraints even if P2 evidence remains blocked.
|
||
- [ ] Commit the shadow contract and runbook before external evidence:
|
||
|
||
```bash
|
||
git add docs/operations/platform-shadow-parity.md tests/unit/platform-shadow-contract.test.ts delivery-platform.yaml test-assurance.lock.json
|
||
git commit -m "test(shadow): define parity and one-writer contract"
|
||
```
|
||
|
||
- [ ] Only after the real run creates `docs/operations/evidence/platform-shadow-readiness.json`, verify its digest/signature and commit that file alone as `test(shadow): record platform parity evidence`. If the environment is unavailable, do not create or stage the file and leave Task 6 incomplete.
|
||
|
||
---
|
||
|
||
### Task 7: Activate the platform and prove platform-only rollback
|
||
|
||
**Files:**
|
||
|
||
- Modify: `delivery-platform.yaml` only to select the signed active catalog version
|
||
- Modify: `test-assurance.lock.json` only through the verified testctl binary
|
||
- Modify: `docs/operations/release-cache-rollback.md`
|
||
- Modify: `docs/operations/platform-shadow-parity.md`
|
||
- Create: `tests/unit/platform-rollback-contract.test.ts`
|
||
- Create from a real drill only: `docs/operations/evidence/platform-cutover-rollback.json`
|
||
|
||
**Cutover gate:** all ten frontend test capabilities are R1 or higher; every selected CI/CD capability is P1/shadow or higher; source revision and manifest/catalog/lock digests match; the passing run and every named fault fixture have zero parity mismatch; legacy writer count is zero and platform writer count is one; named P2 Gitea/runner/scanner/signer/provider evidence exists; central status `platform/delivery-pipeline` is installed; the previous signed platform pin rollback drill verifies served-content digest; and the WIP ledger has zero unclassified hunks.
|
||
|
||
**Rollback sequence:** pause new promotions → reconcile every indeterminate operation ID → pin the previous signed platform catalog/version → verify and use the previous `CICDCTL_BIN`/`TESTCTL_BIN` digests → compile both manifests → promote the previous stable immutable subject through `release-control` → verify served-content digest → resume. No product workflow, legacy writer, rebuild, repackage, or mutable tag is permitted.
|
||
|
||
- [ ] Add RED tests rejecting rollback text/code that restores `quality-gates.yml`, invokes `ci:gate`, enables a legacy writer, rebuilds a candidate, or omits signed catalog, executable, and subject digest checks.
|
||
- [ ] Activate the externally installed central workflow/status only after every cutover-gate predicate is machine-verified; do not delete repository files in this task.
|
||
- [ ] Run a staging rollback to the previous signed platform pin and previous immutable subject, then roll forward again. Record operation IDs, catalog/executable/release/served-content digests, Gitea status ID, writer identity, and reconciliation outcome.
|
||
- [ ] Run `corepack pnpm exec vitest run tests/unit/platform-shadow-contract.test.ts tests/unit/platform-rollback-contract.test.ts`; expected PASS.
|
||
- [ ] Commit runbook/test first. Commit `platform-cutover-rollback.json` separately only after a real signed drill exists; otherwise leave Task 7 incomplete.
|
||
|
||
---
|
||
|
||
### Task 8: Remove local assurance and delivery engines after rollback evidence
|
||
|
||
**Entry gate:** Task 7 has a signed evidence digest and served-content equality; removing local engines is forbidden before it.
|
||
|
||
**Files:**
|
||
|
||
- Delete: `.gitea/workflows/quality-gates.yml`
|
||
- Delete: `config/ci/gates.json`
|
||
- Delete: `scripts/generate-ci-workflow.ts`, `scripts/check-ci-contract.ts`, `scripts/run-ci-gate.ts`, `scripts/contracts/ci-gates.ts`
|
||
- Delete: `scripts/lib/ci-contract-report.ts`, `scripts/lib/ci-gate-log.ts`, `scripts/lib/ci-step-result.ts`, `scripts/lib/ci-artifact-validator.ts`, `scripts/lib/ci-candidate-archive-cli.ts`, `scripts/lib/ci-candidate-archive.ts`, `scripts/lib/package-script-graph.ts`
|
||
- Delete: `scripts/check-test-evidence.ts`, `scripts/verify-browser-capability-evidence.ts`, `scripts/check-risk-coverage.ts`, `scripts/lib/risk-coverage.ts`, `scripts/lib/local-policy-evidence.ts`, `scripts/verify-a11y-manual.ts`, `scripts/run-legacy-assurance-probe.ts`
|
||
- Delete after raw codec extraction: `scripts/lib/manual-a11y-evidence.ts`
|
||
- Delete: `scripts/create-release-candidate.ts`, `scripts/verify-reproducible-build.ts`, `scripts/verify-ci-candidate-archive.ts`, `scripts/verify-release-candidate.ts`, `scripts/run-and-validate-provider.ts`, `scripts/stage-verified-promotion.ts`, `scripts/verify-provider-evidence.ts`, `scripts/verify-supply-chain-promotion.ts`, `scripts/lib/release-candidate.ts`, `scripts/lib/promotion-stager.ts`, `scripts/lib/promotion-verifier.ts`, `scripts/lib/provider-evidence.ts`, `scripts/lib/provider-upload-validator.ts`
|
||
- Delete: `scripts/security-scan.ts`, `scripts/generate-supply-chain.ts`, `scripts/verify-supply-chain-artifacts.ts`, `scripts/verify-archived-local-evidence.ts`, `scripts/check-supply-chain-provider-fixtures.ts`, `scripts/lib/local-release-evidence.ts`, `scripts/lib/release-input-evidence.ts`, `scripts/lib/supply-chain.ts`
|
||
- Delete: `tests/unit/ci-workflow-generation.test.ts`, `tests/unit/__snapshots__/ci-workflow-generation.test.ts.snap`, `tests/unit/ci-step-result.test.ts`, and `tests/fixtures/ci-contract/`
|
||
- Preserve/refactor: `scripts/contracts/release-artifacts.ts`, `scripts/generate-build-manifest.ts`, `scripts/generate-artifact-schemas.ts`, `scripts/lib/build-manifest-outputs.ts`, `scripts/lib/release-runtime-coherence.ts`, `scripts/lib/manual-a11y-record.ts`, and their product-schema tests
|
||
- Modify: `package.json`
|
||
- Modify: `docs/operations/ci-quality-gates.md`
|
||
- Modify: `docs/security/supply-chain.md`
|
||
- Create: `tests/unit/platform-engine-removal.test.ts`
|
||
|
||
- [ ] Recompute original dirty-worktree blob/hunk digests and stop on drift. Compare the current migration diff to the exact allowed path/hunk set in the ledger before deleting anything.
|
||
- [ ] Add a RED removal test that rejects workflow-DAG types, Gitea expressions, artifact upload/download orchestration, test normalizers/assessors, provider/promotion mutation, exact job counts, `ci:gate`, and workflow generator/checker scripts in product paths.
|
||
- [ ] Extract the raw manual accessibility record codec to `scripts/lib/manual-a11y-record.ts`, then delete only the assessment/expiry-completeness engine. Delete all other listed platform-owned files hunk-by-hunk; preserve product behavior, assertions, fixtures, and raw artifact codecs.
|
||
- [ ] Remove `generate:ci-workflow`, `check:ci-workflow`, `ci:gate`, local `check:ci`, legacy assessor, provider/promotion, supply-chain, and candidate orchestration scripts from `package.json`. Keep build, lint/typecheck, one-purpose suites, raw reporters, and developer-only commands.
|
||
- [ ] Run `corepack pnpm exec vitest run tests/unit/platform-engine-removal.test.ts tests/unit/delivery-platform-manifest.test.ts tests/unit/test-assurance-source-manifest.test.ts tests/unit/artifact-suite-contract.test.ts`, then `corepack pnpm check:types` and `corepack pnpm lint`; expected PASS.
|
||
- [ ] Verify `git diff --name-status` exactly matches the ledger's Task 8 allowlist. Stage only the explicit files listed in this task; never use `git add scripts`, `git add tests`, or `git add -A`.
|
||
- [ ] Commit as `refactor(platform): remove copied assurance and delivery engines`.
|
||
|
||
---
|
||
|
||
### Task 9: Finalize documentation, provenance, and consumer verification
|
||
|
||
**Files:**
|
||
|
||
- Modify: `docs/operations/release-cache-rollback.md`
|
||
- Modify: `docs/operations/platform-shadow-parity.md`
|
||
- Modify: `docs/security/supply-chain.md`
|
||
- Modify: `README.md`
|
||
- Modify and close: `docs/migration/task3-wip-provenance.json`
|
||
- Modify: `docs/migration/task3-wip-disposition.md`
|
||
|
||
- [ ] Mark every WIP hunk `retained`, `reimplemented-in-platform`, `removed-after-cutover`, or `preserved-in-original`; require zero open disposition and reverify original dirty-worktree hashes.
|
||
- [ ] Verify both binaries before invoking them:
|
||
|
||
```bash
|
||
printf '%s %s\n' "$CICDCTL_DIGEST" "$CICDCTL_BIN" | sha256sum --check
|
||
printf '%s %s\n' "$TESTCTL_DIGEST" "$TESTCTL_BIN" | sha256sum --check
|
||
```
|
||
|
||
- [ ] Run final repository verification:
|
||
|
||
```bash
|
||
corepack pnpm install --frozen-lockfile
|
||
corepack pnpm check:types
|
||
corepack pnpm lint
|
||
corepack pnpm test:all
|
||
corepack pnpm exec vitest run tests/unit/delivery-platform-manifest.test.ts tests/unit/test-assurance-source-manifest.test.ts tests/unit/artifact-suite-contract.test.ts tests/unit/platform-engine-removal.test.ts tests/unit/platform-rollback-contract.test.ts
|
||
"$TESTCTL_BIN" validate --repository . --out artifacts/platform/final-validation.json
|
||
"$CICDCTL_BIN" manifest compile --manifest delivery-platform.yaml --source-revision "$PLATFORM_SOURCE_REVISION" --output artifacts/platform/effective-project.json
|
||
git diff --check
|
||
```
|
||
|
||
Expected: PASS. `PLATFORM_SOURCE_REVISION` is the exact 40-hex revision recorded by the platform run, not a branch or mutable lookup. Product tree contains manifests and product tests, not copied platform engines.
|
||
- [ ] Commit the two migration ledger files and exact modified docs/README as `docs(platform): finalize consumer cutover`.
|
||
|
||
## Cross-repository execution order
|
||
|
||
1. Complete and release the Test Assurance plan through R1/v3 conformance.
|
||
2. Complete and release the CI/CD plan through P1/shadow vertical conformance.
|
||
3. Execute frontend Tasks 1–5 and validate both manifests locally.
|
||
4. Execute Task 6 only with external one-writer state verified.
|
||
5. Execute Task 7 only after every named P2 gate exists and prove rollback before deletion.
|
||
6. Execute Tasks 8–9 only after signed rollback evidence. Until then, the correct state is shadow with legacy comparison code retained and no false active claim.
|