Plan: Scaffold Lint Config Baseline
Plan: Scaffold Lint Config Baseline
Status: Complete Mode: sequential
Initial Situation
The CLI has a pack-owned lint asset catalog at apps/cli/src/data/catalog/lint.ts. runScaffold resolves selected assets only when oxlint is detected, writes .devpunks/specs/lint/*, and optionally writes .devpunks/specs/lint/oxlint-starter.json. It does not mutate real Oxlint configs. The generated hook runs oxlint -c .oxlintrc.json <file>, which prevents nested config lookup.
Issue
Selected lint assets are advisory instead of executable. React pack rules may be missing from consumer configs, plugin dependencies may be missing from the owning workspace, and hooks do not respect closest-config scoping. The final strategy pivots to Ultracite presets as the maintained baseline, with optional individual lint overlays for gaps such as unnecessary React effects.
Solution Shape
Add an Oxlint config application step to scaffold output. The step derives lint placements from detected workspaces, writes the closest oxlint.config.ts in each owning package/app, extends Ultracite core/framework presets, carries forward existing JSON/JSONC local config where possible, and patches the closest package manifest with missing dev dependencies. Update the hook to call Oxlint without -c so nearest config lookup works. Keep .devpunks/specs/lint as trace metadata.
Resolved Decision Ledger
| Decision | Status |
|---|---|
| React pack owns Ultracite React plus unnecessary-effect lint rules | Locked |
| Scaffold must create or patch configs, not only emit specs | Locked |
| Closest package/app config owns scoped rules | Locked |
Missing dev dependencies are added to nearest owning package.json | Locked |
| Hook config lookup change ships with config application | Locked |
| Ruff gets compatible model shape later, no Ruff rules now | Locked |
Codebase Findings
apps/cli/src/scaffold/output.tsowns generated output and lint spec writing.apps/cli/src/data/catalog/lint.tsowns lint asset metadata.apps/cli/src/data/hooks/format-edited-file.mjsowns post-edit format/lint commands.apps/cli/src/scaffold/run.test.tsalready covers scaffold output files and lint specs.apps/cli/src/data/hooks.test.tsalready covers hook command construction.
External Research
- React Hooks lint rules are from
https://react.dev/reference/eslint-plugin-react-hooks. eslint-plugin-react-you-might-not-need-an-effect@0.10.2exposes eight rules in upstream source.- Oxlint nested config lookup should be allowed by omitting explicit
--config. - Ruff model compatibility matters because Ruff config lookup also follows nearest project config.
Dependency Graph
T1 -> T2 -> T3 -> T4 -> T5
T1: Normalize lint asset catalog
- depends_on: []
- location:
apps/cli/src/data/catalog/lint.ts,apps/cli/src/content/content.test.ts - description: Use Ultracite framework presets as the baseline and keep the React unnecessary-effect overlay valid.
- validation: Catalog tests pass and selected React assets list valid rule names.
- status: Complete
- log: Moved React/Next/TanStack/Vitest framework baselines to Ultracite presets, kept the React unnecessary-effect overlay, removed invalid
no-empty-effect, and kept catalog validation covered by focused tests. - files edited/created:
apps/cli/src/data/catalog/lint.ts,apps/cli/src/scaffold/run.test.ts - backlog_item_id: none
- backlog_item_url: none
- relation_mode: none
- assigned_skills: [
simplify,tdd] - tdd_target: A test/assertion fails if the removed invalid rule returns to the catalog.
- review_mode: cli
T2: Apply Oxlint configs during scaffold
- depends_on: [T1]
- location:
apps/cli/src/scaffold/output.ts,apps/cli/src/scaffold/run.test.ts - description: Create nearest
oxlint.config.tsfor selected lint assets and record applied config paths. - validation: Scaffold tests prove new config creation and existing config merge.
- status: Complete
- log: Added scaffold-time
oxlint.config.tscreation with Ultracite presets and JSON/JSONC local-rule carry-forward for selected package/app workspaces, plus applied-config trace metadata in lint selection output. - files edited/created:
apps/cli/src/scaffold/output.ts,apps/cli/src/scaffold/run.test.ts - backlog_item_id: none
- backlog_item_url: none
- relation_mode: none
- assigned_skills: [
effect-authoring,simplify,tdd] - tdd_target: A React workspace without config receives a runnable
oxlint.config.ts; a workspace with JSON/JSONC config gets missing overlays merged without deleting existing values. - review_mode: cli
T3: Patch nearest package dev dependencies
- depends_on: [T2]
- location:
apps/cli/src/scaffold/output.ts,apps/cli/src/scaffold/run.test.ts - description: Add missing required lint dev dependencies to the owning workspace
package.json. - validation: Scaffold tests prove dependencies are added once and existing versions remain untouched.
- status: Complete
- log: Added nearest manifest dev-dependency patching with existing dependency/version preservation, including workspace catalog support.
- files edited/created:
apps/cli/src/scaffold/output.ts,apps/cli/src/scaffold/run.test.ts - backlog_item_id: none
- backlog_item_url: none
- relation_mode: none
- assigned_skills: [
effect-authoring,simplify,tdd] - tdd_target: A React package missing
ultraciteand the unnecessary-effect plugin gets them indevDependencies; existing versions are preserved. - review_mode: cli
T4: Make hook respect nearest Oxlint config
- depends_on: [T2]
- location:
apps/cli/src/data/hooks/format-edited-file.mjs,apps/cli/src/data/hooks.test.ts - description: Remove forced root config from Oxlint hook command.
- validation: Hook tests expect
oxlint <file>through repo package-manager executor. - status: Complete
- log: Removed forced
-c .oxlintrc.jsonfrom the Oxlint hook command so Oxlint can resolve the nearest config. - files edited/created:
apps/cli/src/data/hooks/format-edited-file.mjs,apps/cli/src/data/hooks.test.ts - backlog_item_id: none
- backlog_item_url: none
- relation_mode: none
- assigned_skills: [
simplify,tdd] - tdd_target: Hook command construction fails while it still includes
-c .oxlintrc.json. - review_mode: cli
T5: Update docs and implementation notes
- depends_on: [T1, T2, T3, T4]
- location:
docs/README.md,docs/reference/dp-requirements.md,docs/runbooks/dp-cli-scaffolding.md,apps/wiki/content/docs/harness/validation-and-tools/hooks.mdx,apps/wiki/specs/cli/scaffold-lint-config-baseline/IMPLEMENTATION-NOTES.md - description: Align durable docs with new scaffold behavior and record implementation evidence.
- validation: Docs mention created/patched closest configs, dependency patching, and nearest hook lookup.
- status: Complete
- log: Updated root docs, routed project copies, hook concept page, scaffold handoff copy, and implementation notes.
- files edited/created:
docs/README.md,docs/reference/dp-requirements.md,docs/runbooks/dp-cli-scaffolding.md,apps/wiki/content/docs/harness/validation-and-tools/hooks.mdx,apps/wiki/content/docs/project/reference/dp-requirements.md,apps/wiki/content/docs/project/runbooks/dp-cli-scaffolding.md,apps/cli/src/content/scaffold-copy.ts,apps/wiki/specs/cli/scaffold-lint-config-baseline/IMPLEMENTATION-NOTES.md - backlog_item_id: none
- backlog_item_url: none
- relation_mode: none
- assigned_skills: [
parallel-research,simplify] - tdd_target: Documentation review catches stale “does not mutate final Oxlint config” claims.
- review_mode: cli
Testing Strategy
bun run --cwd apps/cli test data/hooks.test.ts content/content.test.ts scaffold/run.test.tsbun run check-types --filter=@punks/clibun run check --filter=@punks/cligit diff --check
Risks And Mitigations
- Risk: Config merge overwrites local lint policy. Mitigation: merge missing keys only and preserve existing rule/settings values.
- Risk: Rules are applied too broadly in monorepos. Mitigation: derive owning workspace paths from manifests and write package/app-local configs.
- Risk: Dependency patching touches root manifest unexpectedly. Mitigation: patch the nearest manifest for each targeted workspace.
- Risk: JSONC or TS configs require parsers. Mitigation: create/merge
.oxlintrc.jsononly; leave unsupported existing config formats as spec metadata unless they are the closest supported JSON config.
Unresolved Questions
None.