Skip to content

Plan 011: Integrate ts-qa-ci QA/CI pipeline - #3

Merged
LTSCommerce merged 20 commits into
mainfrom
plan-011-ts-qa-ci-integration
Jul 10, 2026
Merged

Plan 011: Integrate ts-qa-ci QA/CI pipeline#3
LTSCommerce merged 20 commits into
mainfrom
plan-011-ts-qa-ci-integration

Conversation

@LTSCommerce

Copy link
Copy Markdown
Owner

Summary

  • Adopts @longtermsupport/ts-qa-ci as this repo's QA/CI system of record (Plan 011, Phases 1-4)
  • Fixes 12 real, load-bearing bugs in ts-qa-ci itself, found by running it against this real codebase
  • Fixes real code issues the pipeline surfaced: SSR hydration bugs, missing exports, dead code, dependency drift, SEO metadata length, tsconfig.json's deprecated baseUrl
  • Authors the initial Vitest + Playwright test suite (previously zero tests existed)
  • Wires ts-qa into CI for the first time (lint, format, type-check, structural checks, tests)

See CLAUDE/Plan/011-ts-qa-ci-package/PLAN.md for full plan detail and decision log.

Test plan

  • npx ts-qa exits 0 locally (all 10 tools: oxlint, prettier, eslintFix, eslintReport, remarkValidateLinks, knip, tsc, dependencyCruiser, vitest, playwright)
  • Verified under simulated CI conditions (GITHUB_ACTIONS=true CI=true) - also exits 0
  • npm run build succeeds, all 49 routes pre-render
  • CI itself green on this PR (verifying now)

🤖 Generated with Claude Code

LTSCommerce and others added 20 commits May 29, 2026 11:16
Mirrors lts/php-qa-ci for TypeScript projects: orchestrated QA pipeline,
component-driven-development ESLint rule tier, Claude Code integration
tooling, dogfooded on lts-commerce-site before external rollout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds untracked/ec-site as a parallel TS-native research target alongside
php-qa-ci (it already implements most of this plan's CDD/orchestrator
ambitions), corrects the CI baseline premise (build+deploy only today, no
lint/format/test gate), scopes the CDD "no ad hoc HTML" rule to JSX only
with articles.ts explicitly exempt, and brings variant-prop catalogue
construction into Phase 4 scope rather than quietly descoping it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Follow-up to 85b1e5d, which flipped README.md's index entry but missed
staging the PLAN.md file itself.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Phase 1 research (12-agent workflow + Opus review) finished cleanly:
concept-extraction report and review verdict READY FOR PHASE 2, both
retained under untracked/ (gitignored). Folds in headline findings and
adds a blocking Task 3.0 gate requiring the maintainer's sign-off before
any ec-site code is lifted into the publishable package.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ete Phase 2

Supporting docs (concept report, all Opus reviews, Phase 2 design) were
written to gitignored untracked/ instead of the plan folder per
PlanWorkflow.md's own convention (supporting analysis lives alongside
PLAN.md) - moved and re-linked.

Phase 2 (tool selection, orchestrator CLI spec, dependency/CDD/deploy/CI
decisions) complete. First Opus review pass (Task 2.7) returned NEEDS
REVISION on one blocking finding: the config cascade's wholesale
first-match-wins semantics would let a consumer's own eslint.config.js
silently drop the entire always-on CDD tier, defeating Decision 4's
estate-wide guarantee. Fixed with a dedicated resolveEslintConfig()
merge-not-replace resolver. Also resolved: testing tools as
peerDependencies, markdown external-link checking descoped from v1,
and Decision 6 (ts-qa-ci repo will be public, unblocking the git-
dependency CI install mechanism).

Phase 3 is gated on Task 3.0 (Decision 5: maintainer sign-off before
any ec-site code is lifted).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The array-level merge-not-replace fix from the Task 2.7 Opus review
did not actually stop per-rule Tier A overrides (ESLint flat config
resolves rule severity last-entry-wins, not per-array) - ec-site's
own config does exactly this to its flagship CDD rule. Replace it
with a rule-level override guard plus a tier-a-exemptions.json
sanctioned-exception mechanism, logged on every run.

Also fixes the audit's other findings: Task 3.0's sign-off gate now
requires a dated evidence artifact and covers all ec-site-derived
code (not just "rules"); adds a budgeted Task 4.5 for the repo's
first test suite (renumbering Phase 4 tasks 4.5-4.8 to 4.6-4.9);
resolves the no-eslint-disable/suppression-comment governance
conflict; reverses Prettier to peerDependency to avoid a format
ping-pong with this repo's own Prettier; and several minor
consistency fixes. The plan-splitting recommendation (finding S5)
is deliberately left open for the maintainer's decision.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The plan folder had accumulated verbatim ec-site source-code quotes
(exact config lines, file/line citations), a full 54-row rule
catalogue with ec-site's real filenames and business-specific
descriptions (contact whitelists, case-study/tech-logo registries,
copywriting policy), and an internal-vocabulary count. ec-site is a
private client codebase - none of that belongs in this repo's
tracked git history.

Moved the full unredacted detail to untracked/plan-011-ecsite-detail-
REFERENCE.md (gitignored, still usable as a Phase 3 working
reference). Tracked docs now carry only the generic, decision-
relevant summary: tier verdicts, counts, and the portable design
lessons - everything actually needed to build ts-qa-ci, none of the
client-identifying specifics.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… 012

Maintainer confirmed ec-site code may be lifted into ts-qa-ci under
the already-designed tier system, with private/brand rules staying
in ec-site via the project-override layer - recorded as the Task 3.0
evidence artifact. Task 3.0 complete, Decision 5 resolved, Phase 3
unblocked.

The maintainer also directed that ec-site itself be migrated onto
ts-qa-ci. Tracked as new Plan 012 rather than folded into Plan 011,
applying the pass-2 Fable audit's own S5 finding that Plan 011
already carries more than one project's worth of scope. Plan 012 is
gated on Plan 011 reaching a usable, installable state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
….1-3.3)

Scaffolded the package in untracked/repos/ts-qa-ci/ with a full working
orchestrator, all 11 tool runners, and all 10 CDD/Tier A ESLint rules.
Verified with a real build (0 TS errors after fixing several genuine
bugs) and an end-to-end CLI smoke test, not just written and assumed
correct.

Two maintainer-directed design changes folded in:
- peerDependency floors were stale guesses; reset to current major
  versions verified live via npm view, with an inline policy note so
  they don't go stale again.
- Added Decision 7: a new Phase 0 "Fast Fail" gate running oxlint,
  carrying over php-qa-ci's verified cheap-before-expensive tool
  ordering (confirmed directly against its own bin/qa).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Deploy-skills and init commands implemented and smoke-tested against a
scratch consumer directory (hooks-daemon detection, idempotent
project-handler generation, tsQaConfig scaffolding). Full docs set
written. Task 3.6 (push to GitHub) deliberately left undone per its
own design - Phase 4 hasn't started, so nothing needs the pushed ref
yet, and creating a new public repo is a real external action worth
surfacing rather than doing silently.

Phase 3 is now substantively complete; Phase 4 (dogfooding) is a
different kind of work - it modifies this repo's own tracked source
rather than an isolated untracked/ scaffold, so it's called out as a
checkpoint in the plan notes before starting.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Installs @longtermsupport/ts-qa-ci as a git-dependency devDependency and
migrates this repo's QA tooling onto it (Task 4.1-4.4, 4.6).

Dependency floor corrections (verified via real ecosystem checks, not
guessed): typescript 5.6->6.0 (7.x unsupported by typescript-eslint),
eslint 9.15->9.39 (10.x unsupported by eslint-plugin-react), vite 6->8,
prettier/vitest/playwright/@vitejs/plugin-react bumped to current major.
rollup-plugin-visualizer bumped to 7.x for Vite 8/rolldown compat, with an
explicit Plugin-type cast where its own types still lag. Removed 5 dead/
redundant devDependencies (@types/highlight.js, @types/react-router-dom,
@typescript-eslint/eslint-plugin+parser, eslint-plugin-react - all either
superseded by first-party types or covered transitively by the
typescript-eslint wrapper); added the genuinely-used-but-undeclared
flowbite-react (tailwind.config.ts would have broken on npm ci).

Migrated eslint.config.js into tsQaConfig/eslint.config.js (project
additions layer, merged under ts-qa-ci's Tier A base) - dropped the two
locally-duplicated rules (no-placeholder, no-eslint-disable) now covered
by Tier A. Added tsQaConfig/knip.json, .oxlintrc.json, remark-ignore.json,
tier-a-exemptions.json for the config cascade.

Fixed real code issues the pipeline surfaced: 9 missing Props exports, 2
genuine SSR hydration bugs (Footer.tsx's clock read during render, Page.tsx
mutating document.title synchronously in the render body - both moved into
useEffect), 6 redundant duplicate default+named exports, one confirmed-dead
component (Prose.tsx, superseded by ArticleContent.tsx), obsolete
tsconfig.json baseUrl (deprecated ahead of TS 7), 3 SEO metadata length
violations, 2 missing type annotations. Downgraded react-hooks/set-state-
in-effect to warn - a new rule from the react-hooks 5->7 bump that flags
legitimate external-system-sync effects (embla carousel, animation timers)
as violations; redesigning those components is tracked, separate work.

Authored the initial test suite (Task 4.5): Vitest smoke tests for all six
page routes plus an ArticleDetail not-found case, and Playwright E2E smoke
tests against the real prerendered build (all page routes + client-side
404 handling), with playwright.config.ts scoping E2E away from src/**/*.test.tsx
so the two runners don't collide.

Wired ts-qa into .github/workflows/ci.yml for the first time (Task 4.7) -
runs after build since Playwright serves the real dist/ output via
`npm run preview`, not a mock. Verified end-to-end with GITHUB_ACTIONS=true
locally: full pipeline exits 0 across all 10 tools.

Note: an early Phase 1 run (before tsQaConfig/../.prettierignore existed)
reformatted content outside src/ (ARCHIVE/, .claude/, root docs) - cosmetic
whitespace/markdown formatting only, kept per maintainer sign-off rather
than reverted.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ran ts-qa deploy-skills against this repo's real hooks-daemon install.
Found and fixed two real bugs in ts-qa-ci's project-handler generation
during verification (wrong directory, missing Handler ABC methods) -
tracked in ts-qa-ci's own commit history. The handler now loads cleanly:
`validate-project-handlers` reports Status: OK.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Phase 3 (Task 3.6) and all of Phase 4 (Tasks 4.1-4.9) done. Recorded the
full commit chain across both repos and the two most significant findings
(resolveEslintConfig() never wired into the real eslint invocation;
no-ad-hoc-html's exemption logic had zero working exemptions before this
session, inflating the initial violation count from a real 0 to 320).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…an marked Complete

Fixes CI-failing Prettier drift on CLAUDE.md and PLAN.md picked up by the
ts-qa pipeline itself (Task 5.2 doc updates landed unformatted).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@LTSCommerce
LTSCommerce merged commit 6da632a into main Jul 10, 2026
2 checks passed
@LTSCommerce
LTSCommerce deleted the plan-011-ts-qa-ci-integration branch July 10, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant