Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

Test & quality alignment plan

Offen
#1 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Anfängerfreundlichkeit
35/100
Issue-Typ
Refactoring
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
bun, eslint, nextjs, react, tailwindcss, typescript

Rechercherichtung

Beginne mit den referenzierten root package.json, apps/web/package.json und bun.lock und prüfe anschließend die phasenweisen Gates sowie die vorhandenen Dateien in apps/web/src/lib. Führe zuerst die Prüfungen für Phase 0 aus, gefolgt von den im Plan beschriebenen lokalen Verifizierungsbefehlen; die Arbeit ist abgeschlossen, wenn die geplanten Test-, Lint-, Type-Check-, Build- und report-only-Quality-Gates erfolgreich durchlaufen, ohne CI einzuführen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Test & Quality Alignment Plan — dbuild

  • Project: Dbuild.dev (/home/didi/workspace/dbuild, origin DimitriGilbert/dbuild)
  • Date: 2026-09-05
  • Generated by the fleet test-and-quality alignment initiative (28-repo audit + synthesis)
  • Audit report: ../.test-alignment-audit/reports/dbuild.md
  • Fleet synthesis / decisions: ../.test-alignment-audit/synthesis-decisions.md
  • Stack reality: BTS v2.22.10 next-only monorepo — Next.js 15.1.3 / React 19 / Tailwind v4 / Turborepo, Bun-managed (packageManager: [email protected], bun.lock), statically exported to GitHub Pages (dbuild.dev). One app (apps/web), empty packages/. ~9k LOC, 0 test files, no hooks, dead lint script (no CI — by owner design, D5; the gate is local commands).

Revised 2026-09-05: CI removed by owner decision — quality gates are local commands run by the owner/agents; no GitHub Actions.


1. Adopted decisions (synthesis D1–D7, adapted to a Bun-managed Next.js static site)

Decision Adoption for dbuild
D1 — Runner & layout bun:test (Bun's built-in runner), NOT vitest. D1 explicitly rules: "Bun repos: bun:test stays … do not introduce vitest" (precedent: email-sdk + FeedElity, 806 cases combined). Adding vitest would bolt a Vite toolchain onto a repo with zero test infra for no benefit. Tests colocated as *.test.ts(x) next to source. Root one-command entry bun run test via turbo. Environment: node-only — no jsdom, no RTL. This is the explicit pick synthesis §5 demands from Next-variant repos: v1 has zero component tests (static site; the value is pure logic), so the DOM stack would be dead weight.
D2 — Coverage Report-only. Bun's coverage reporter is explicitly not threshold-grade (synthesis §5). Run bun test --coverage, record the measured baseline in AGENTS.md, never gate on it. Revisit thresholds when Bun coverage matures.
D3 — Lint ESLint 9 flat config + typescript-eslint ^8 + eslint-plugin-react-hooks (fleet standard). This retires the dead lint: "next lint" script (no ESLint dep or config exists — audit P1) and un-dangles the lint task in turbo.json. Prettier deferred in v1 per D3's allowance — stated in AGENTS.md rather than pretended.
D4 — Quality metrics knip + jscpd, report-only, local report scripts run on demand by the owner/agents (writing a git-ignored local report). No CRAP (requires threshold-grade coverage Bun can't give), no mutation testing (dbuild is not one of the five nominated cores), no circular-dep tooling in v1. jscpd uses the launch-mommy canonical config (minLines: 8, minTokens: 80, exitCode: 0).
D5 — no CI by design (owner decision 2026-09-05) GitHub Actions rejected fleet-wide: no .github/workflows, no reusable-workflow convergence target, no scheduled jobs. Enforcement = the root-level headless verification entrypoint (bun run verify: lint → check-types → test → build, composed in Phase 4) run by the owner and by agents; the plan's phase validation gates are run by implementer/validator agents before any phase is declared done. GH Pages deploys stay manual, guarded by a green bun run verify.
D6 — Shared config Adopt @dg/config presets opportunistically (D6: "when it touches lint/tsconfig/vitest anyway") — Phase 1 touches lint, so if @dg/config is published at execution time, the ESLint config extends it; otherwise write the local flat config and note it for later convergence. Non-blocking either way.
D7 — Hooks No git hooks. Local gates run by the owner/agents are the only authoritative gate. AGENTS.md states it explicitly: "the headless local verification command (bun run verify) is the quality gate; hooks are local convenience." A repo with no hooks and a green local run is compliant.
Deviations from the synthesis (declared, not silent)
  1. Runner: the dbuild delta block (§4) says "Seed vitest (Bun-compatible)"; the core D1 decision and §5 non-goals say Bun repos keep bun:test and must not introduce vitest. Follow D1: bun:test. Rationale above; zero install, native TS + tsconfig paths support, fleet precedent.
  2. CI workflow Removed by the 2026-09-05 revision: no workflow is created (D5); the Bun-vs-pnpm reusable-workflow mismatch that motivated this deviation is moot — the gate is the local bun run verify entrypoint.
  3. Package manager: Bun stays. Switching to the pnpm fleet default would mean regenerating the lockfile, re-verifying the GH Pages build chain, and retraining habits for zero test-quality gain — synthesis §5 explicitly lists dbuild among "stay Bun". Kept.
  4. No packages/config: dbuild has no shared-config package (empty packages/) — the fleet cross-constant doesn't apply; apps/web/tsconfig.json stays hand-maintained. Optional tightening (noUncheckedIndexedAccess) is deliberately not in scope: it would churn 9k LOC with no test payoff in v1.
  5. Renovate: the local>DimitriGilbert preset reference requires the org preset to exist first (fleet-level task). If it doesn't at execution time, land the one-liner anyway and expect a Renovate warning until the preset lands — or temporarily extend config:recommended and switch in a follow-up.

2. Test-runner decision in one line

bun test over src/lib/* pure logic in node env; no jsdom/RTL; coverage report-only. The testable core (grounded in the audit + read of the code):

  • apps/web/src/lib/seo.ts (375 LOC) — fully pure: formatCanonicalUrl, formatTitle, formatAbsoluteImageUrl, formatOpenGraphLocale, serializeJsonLd, parseTaxonomySlug/formatTaxonomySlug, create*JsonLd, createStaticPageMetadata, createNotFoundMetadata. Highest-value, zero-mock target.
  • apps/web/src/lib/xml-sitemap.ts (58 LOC) — pure string builders (createUrlSet, createSitemapIndex); createXmlResponse uses the global Response, which Bun provides.
  • apps/web/src/lib/blog.ts (598 LOC) — exported slugify; module-private pure helpers that must be exported (behavior-preserving, mechanical): readString, readDateString, readStringArray, readFrontmatter, calculateReadTime, generateTOC, chooseCanonicalTagName. fs-backed getters (getAllPosts etc.) get one deterministic integration test over the in-repo content/blog corpus (55 files, static data — hermetic enough; assert structure, not exact counts).
  • apps/web/src/lib/projects.ts (62 LOC) — reads in-repo data/projects.json: cheap deterministic tests.
  • apps/web/src/lib/mindmap.ts (440 LOC) — fs + dagre heavy, single re-export surface: deferred to a later ratchet; not worth a refactor in v1.
  • apps/web/scripts/validate-content.js — the de-facto content suite (audit: "a genuine validation program"); predicates are pure but the script exports nothing and self-invokes. Phase 3 splits it so it becomes testable and build-gated.

3. Phased plan

Orchestration model per the subagent-orchestration skill: every phase = 1 implementer dispatch → implementer runs gatekeeping commands → 1 validator dispatch (different agent; must read the code, not just run commands) → fix loop (fixer repairs ALL validator findings at once; re-validate; max 3 attempts) → phase done. All phases are sequential (each builds on the previous gate). Every implementer/fixer dispatch carries the NO-SLOP policy verbatim (no any/as any, no TODO/FIXME, no unused imports, import type for type-only imports, no dev servers — all of which AGENTS.md also mandates). No commits/pushes unless the owner asks; the fleet initiative's rule against destroying uncommitted work applies (the tree currently has uncommitted content/source edits — phases must build around them, never reset them).

Phase 0 — Resolve the Next.js two-major drift + workspace hygiene

Goal: one Next major in the lockfile; root stops shadowing the app's dependency versions; no npm in a Bun repo.

Tasks

  1. package.json (root): delete the dependencies block entirely — it hoists next ^16.1.3, react ^19.2.3, react-dom ^19.2.3, @types/node ^25.0.9 while apps/web pins next 15.1.3 / react ^19.0.3 / @types/node ^22.19.7 (two Next majors and two @types/node majors confirmed in bun.lock). Nothing at root imports them (root has no source; only turbo devDep + scripts/optimize-image.sh). Keep the resolutions block (correct place for Bun overrides). Optionally rename root package from Dbuild.dev to dbuild to kill the root/app name collision (nothing references the root name).
  2. apps/web/package.json: fix the setup script — "setup": "bun run init && bun run setup-content && bun run validate-content" (currently npm run … in a Bun repo; audit P3).
  3. From repo root: bun install to regenerate bun.lock; verify exactly one next version (15.1.3) and one @types/node version remain.
  4. Do NOT touch AGENTS.md/CLAUDE.md here — the docs sweep is Phase 5 (one coherent edit instead of churn).

Orchestration: implementer → validator. Validator must read both package.json files, diff-check no other script referenced the removed root deps, and confirm lockfile state.

Validation gate (from repo root): bun install --frozen-lockfile → bun run check-types → bun run build; plus grep -o '"next@[0-9.]*"' bun.lock | sort -u yields exactly [email protected].

Effort: S (small, but it unblocks everything else — the lockfile must be sane before any gated run from a clean checkout with --frozen-lockfile).

Phase 1 — Implement ESLint 9 flat config; retire the dead next lint

Goal: lint runs, lints, and passes; the turbo lint task stops being dangling; the "no linting" claim in AGENTS.md becomes false in the good direction.

Tasks

  1. Install (repo root, Bun workspace): bun add -d -w eslint@^9 @eslint/js@^9 typescript-eslint@^8 eslint-plugin-react-hooks@^5 globals
  2. Create apps/web/eslint.config.mjs (flat config): @eslint/js recommended + typescript-eslint type-checked (recommendedTypeChecked with projectService: true — feasible: single tsconfig at apps/web/tsconfig.json) + eslint-plugin-react-hooks recommended (it's a React repo). Ignores: node_modules/, .next/, out/, next-env.d.ts, content/. Plain-JS scripts/*.js get js.configs.recommended if type-checked parsing of JS proves noisy — implementer's call, requirement is zero errors, zero rule disables without cause.
  3. apps/web/package.json: replace "lint": "next lint" with "lint": "eslint .".
  4. package.json (root): add "lint": "turbo lint" (the turbo lint task already exists — it becomes real).
  5. apps/web/next.config.mjs: keep eslint.ignoreDuringBuilds: true deliberately — lint is a standalone gate step (in bun run verify), not a build-time side effect; add nothing.
  6. If @dg/config (D6) is published by execution time, extend its ESLint preset instead of hand-rolling; note the choice in the config header comment (comment rule: AGENTS.md bans comments in production code — a one-line provenance note in config files is acceptable, or omit).
  7. AGENTS.md: replace the "No Linting/Formatting Config" section with the reality (ESLint 9 flat, bun run lint, Prettier deliberately deferred in v1 — D3's "say so rather than pretend").

Orchestration: implementer → validator. Validator must read the config and spot-check that the rules actually fire (e.g. introduce nothing; verify ignores don't swallow src/), and enforce NO-SLOP.

Validation gate: bun run lint (root, via turbo) exits 0 with zero errors → bun run check-types → bun run build. Any pre-existing lint errors are fixed, not suppressed (AGENTS.md: never silence; fix the cause — same doctrine as the fleet).

Effort: M (type-checked lint over 9k LOC can surface a tail of real findings to fix).

Phase 2 — Seed bun:test over src/lib pure logic

Goal: the repo's first real test suite; headless one-command entry from root.

Tasks

  1. apps/web/package.json: add "test": "bun test" and "test:coverage": "bun test --coverage". Root package.json: add "test": "turbo test". turbo.json: add a "test" task (no dependsOn build; cacheable).
  2. apps/web/bunfig.toml: coverage report-only config ([test] coverage settings; reporters text; no thresholds — D2 Bun exception).
  3. Create colocated suites (bun:test, node env, static imports only — AGENTS.md forbids await import/require):
    • src/lib/seo.test.ts — canonical URL formatting, title suffixing, OG locale mapping, taxonomy slug parse/format roundtrip, serializeJsonLd output, each create*JsonLd/create*Metadata factory's required fields (~25–35 cases).
    • src/lib/xml-sitemap.test.ts — URL-set rendering, sitemap index, createXmlResponse (Bun's global Response).
    • src/lib/blog.test.ts — slugify (assert current behavior, e.g. non-ASCII stripping, as regression pins); newly exported generateTOC, calculateReadTime, readFrontmatter, chooseCanonicalTagName (make them named exports — behavior-preserving, mechanical diff in src/lib/blog.ts); one integration test over the real content/blog corpus via getAllPosts(): every non-draft post has title/date/tags/summary — assert structure, never exact counts (content churns weekly).
    • src/lib/projects.test.ts — getAllProjects non-empty, getProjectById hit/miss→null, tag filter, unique tag list.
  4. Explicitly no jsdom / no @testing-library/* / no component tests in v1 (the pick synthesis §5 requires; static site, zero DOM logic under test).
  5. NO-SLOP applies doubly: AGENTS.md itself bans any/as any — tests use real types from the source modules.

Orchestration: this is the one phase worth two sub-phases, each with its own validator, plus a mandatory phase-wide validator reading both together (skill Rule 3): (a) infra (scripts, bunfig, turbo) + seo + xml-sitemap; (b) blog (incl. the export refactor) + projects + corpus integration. Phase-wide validator checks: import coherence, no duplicated fixtures, coverage config sane.

Validation gate: bun run test (root) green; bun run test:coverage produces a report (record the numbers, gate nothing); bun run check-types → bun run lint → bun run build.

Effort: M.

Phase 3 — Gate validate-content into the build; make it testable

Goal: invalid frontmatter can no longer ship (audit P2: validator is manual-only today, wired only into setup).

Tasks

  1. Split apps/web/scripts/validate-content.js (behavior-preserving): extract the pure predicates/collectors — hasValue, readString, isDraft, isValidDate, isStringArray, isCategoryIndex, normalizeTranslationCandidate, hasFrenchSignals, likelyTranslatedContent, getTranslationCandidate, buildTranslationCandidateCounts, validatePost — into apps/web/scripts/lib/content-rules.js (ESM static exports; no require, no await import). validate-content.js keeps the fs walk, console output, and process.exitCode semantics byte-identical (the build gate depends on the exit code).
  2. Wire the build: apps/web/package.json "build": "node scripts/validate-content.js && node scripts/generate-rss.js && next build" — validate first, so bad frontmatter fails before RSS is generated from it.
  3. Create apps/web/scripts/lib/content-rules.test.js (bun:test, plain JS): draft skip, category _index warnings-vs-errors, invalid date, tags array rule, empty body, French-heuristic detection, duplicate-translation-candidate ⇒ translationKey warning, ogImageAlt warning — table-driven against synthetic frontmatter objects (no fs).
  4. Contingency: the live corpus has uncommitted edits; if validate-content fails on it during implementation, the implementer must stop and report — never weaken the validator or "fix" content silently. That's a real finding for the owner.
  5. Add bun run validate-content to the AGENTS.md web-commands list (Phase 5 reconciles fully).

Orchestration: implementer → validator. Validator diffs old vs new script output on the real corpus (must be identical) and reads the new tests for tautologies (DoD item 9).

Validation gate: bun run validate-content exits 0 on the current corpus → bun test green → bun run build (now content-gated) → bun run check-types.

Effort: S.

Phase 4 — Local gate composition: bun run verify

Goal: DoD 2 under D5 (no CI by design): typecheck + lint + test + build become one headless root command the owner and agents run before any phase is declared done.

Tasks

  1. Root package.json: add "verify": "bun run lint && bun run check-types && bun run test && bun run build" — the headless verification entrypoint (D5). Phases 0–3 already landed each ingredient; this composes them.
  2. AGENTS.md: document bun run verify as the pre-deploy and pre-phase-done gate.
  3. No .github/ directory is created and no workflow file is written anywhere (D5 — owner decision 2026-09-05).

Orchestration: implementer → validator. Validator reads the root package.json, confirms the chain is exactly lint → check-types → test → build, then runs bun run verify from a clean-install state; fail-fast proven once (deliberate failing test in a scratch copy → non-zero exit at the test step).

Validation gate: bun run verify exits 0 from repo root; every command in the chain exists in package.json files.

Effort: S.

Phase 5 — Dependency hygiene, quality report, docs truth

Goal: DoD items 5, 7, 8 closed; documentation stops contradicting reality.

Tasks

  1. renovate.json (repo root): {"$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["local>DimitriGilbert"]} (deviation D5-5 ordering note applies). dbuild has no "latest" pins today — Renovate keeps it that way and watches the next 15→16 upgrade path deliberately instead of by lockfile accident.
  2. Quality report (report-only, on demand — D4): bun add -d -w knip jscpd; add .jscpd.json with the launch-mommy canonical config (minLines: 8, minTokens: 80, exitCode: 0, exclude tests/generated — here: .next, out, content); minimal knip.json for the Next app. Root scripts "quality:knip" / "quality:jscpd" write reports to a git-ignored local directory; run on demand by the owner or during a periodic agent pass — no workflow, no schedule, no artifacts (D5).
  3. Coverage baseline: run bun run test:coverage, record measured lines/branches in AGENTS.md's Testing section as the ratchet baseline (ratchet +5 whenever Bun's tooling becomes threshold-grade; never lower).
  4. Docs reconciliation (audit P3, DoD item 5):
    • AGENTS.md: [email protected] (says 1.2.15); Testing section = runner (bun test), locations (src/lib/*.test.ts, scripts/lib/*.test.js), commands (incl. bun run verify), coverage baseline + report-only status, the D7 sentence ("the headless local verification command (bun run verify) is the quality gate, run by the owner/agents; hooks are local convenience"); Package Management section consistent with the new scripts.
    • CLAUDE.md: fix "No linting or type checking commands defined at root level" (false — root check-types/lint exist via turbo), drop the stale bun run lint implication, or better: reduce CLAUDE.md to a pointer at AGENTS.md to end the two-file drift permanently (owner's preference wins if they want both files).
  5. Optional (only if frictionless): adopt @dg/config tsconfig/vitest presets per D6 — explicitly skippable; never a churn PR for its own sake.

Orchestration: implementer → validator. Validator greps both docs for every claim and verifies each against the repo (the exact failure mode this phase exists to kill: phantom docs).

Validation gate: full chain from root — bun install --frozen-lockfile && bun run verify && bun run validate-content; knip and jscpd run exit 0 (report-only) and produce their local reports.

Effort: M.


4. Alignment Definition of Done — per-item status for dbuild

# DoD item (synthesis §3) Current status Closed by
1 Root-level headless test command, documented in AGENTS.md Missing — no test script anywhere Phase 2 + 5
2 Headless verification entrypoint runs typecheck + test + lint in one command; agent records green before a phase is done Missing — no root aggregate command Phase 4 (bun run verify)
3 Coverage measured & reported; baseline recorded; no threshold ever lowered Missing — no runner (Bun exception: report-only, no thresholds) Phase 2 + 5
4 Lint installed, zero errors, wired into the headless entrypoint; dead turbo lint task implemented or deleted Dead — next lint with no ESLint dep/config; turbo lint dangling; ignoreDuringBuilds: true Phase 1 + 4
5 AGENTS.md "Testing" section matches reality; no phantom docs Partial — honest about absence, but stale ([email protected], npm run in setup, CLAUDE.md false claims) Phase 5
6 Dead scaffold test deps removed or used Met (vacuously) — no RTL/jsdom scaffold deps present; nothing to remove n/a (Phase 2 keeps it true: no DOM deps added)
7 Renovate one-liner; no "latest" deps Half — no "latest" pins exist; no Renovate config Phase 5
8 Quality-report script (knip + jscpd) runnable locally, report-only Missing Phase 5
9 Nothing satisfied by a fake pass (no passWithNoTests, no echo-tests, no tautologies) Met today (nothing exists to fake); enforced going forward by validators reading every test All phases

5. Risks & repo-specific notes

  • Static-site scope discipline. No e2e, no component tests, no jsdom/RTL in v1 — value is pure-logic tests + content gating + the local build gate. Resist scope creep toward Playwright; the site has no backend to integration-test.
  • GH Pages deploy coupling. Deploys are manual gh-pages pushes from the owner's machine — that does not change under D5. The contract becomes: a green bun run verify immediately before deploy ⇒ the deploy is safe. Risk: the deployed site drifts from main if deploys lag — acceptable for a personal site; keep the pre-deploy verify habit documented in AGENTS.md.
  • Content corpus is live data. 55 markdown files, edited constantly (uncommitted edits in the tree right now). Corpus-integration tests assert structure, never counts; the Phase 3 build gate makes the validator an owner-facing contract — if it fails on real content, that's reported, not papered over.
  • Bun coverage is experimental — report-only forever until Bun's reporter is threshold-grade (synthesis §5); do not let a later PR add thresholds on top of misreportable numbers.
  • Export-refactor risk (blog.ts, Phase 2) is mechanical but touches a 598-line file with uncommitted edits — implementer must make the minimal diff (add export to existing pure functions, change nothing else) and the validator must diff behavior.
  • validate-content.js exit-code semantics are load-bearing once Phase 3 wires it into build — the refactor must not change output format or exit codes.
  • AGENTS.md hard bans (await import, require, any) bind all test code too; bun:test + static imports comply naturally.
  • Uncommitted work in the tree: all phases proceed on top of it; no stashing/resetting (fleet rule). Suggest the owner land or set aside current edits before Phase 0 touches the lockfile — bun install will rewrite bun.lock, which already has uncommitted modifications.

6. Effort summary

Phase Goal Effort
0 Next-drift resolution + workspace hygiene S
1 ESLint 9 flat config; kill dead next lint M
2 Seed bun:test over src/lib (2 sub-phases + phase-wide validation) M
3 validate-content build-gated + unit-tested S
4 Local gate composition (bun run verify) S
5 Renovate + quality report + docs truth M

Total: ~2 focused days of implementer/validator cycles. Sequencing rule: no phase starts before the previous gate is green; every gate is runnable from the repo root with the commands listed above.

Vorherrschende Sprache
TypeScript
Sterne
0
Forks
0
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.