Harness Intelligence Wiki
SpecsCLIScaffold Lint Config Baseline

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

DecisionStatus
React pack owns Ultracite React plus unnecessary-effect lint rulesLocked
Scaffold must create or patch configs, not only emit specsLocked
Closest package/app config owns scoped rulesLocked
Missing dev dependencies are added to nearest owning package.jsonLocked
Hook config lookup change ships with config applicationLocked
Ruff gets compatible model shape later, no Ruff rules nowLocked

Codebase Findings

  • apps/cli/src/scaffold/output.ts owns generated output and lint spec writing.
  • apps/cli/src/data/catalog/lint.ts owns lint asset metadata.
  • apps/cli/src/data/hooks/format-edited-file.mjs owns post-edit format/lint commands.
  • apps/cli/src/scaffold/run.test.ts already covers scaffold output files and lint specs.
  • apps/cli/src/data/hooks.test.ts already 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.2 exposes 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.ts for 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.ts creation 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 ultracite and the unnecessary-effect plugin gets them in devDependencies; 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.json from 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.ts
  • bun run check-types --filter=@punks/cli
  • bun run check --filter=@punks/cli
  • git 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.json only; leave unsupported existing config formats as spec metadata unless they are the closest supported JSON config.

Unresolved Questions

None.

On this page