Harness Intelligence Wiki
SpecsCLIIssue 68 Effect Oxlint Rule Typing

Plan: Issue 68 Effect Oxlint Rule Typing

Plan: Issue 68 Effect Oxlint Rule Typing

Generated: 2026-07-09 Spec: SPEC.md Backlog item: https://github.com/wearedevpunks/harness-intelligence/issues/68 Mode: parallel: true

Initial Situation

Issue #68 reports that hi scaffold setup --yes can generate a nested package/app oxlint.config.ts for an Effect workspace that fails TypeScript checking. The failing rule is effect-js/no-import-from-barrel-package.

Current generator path:

  • apps/cli/src/data/catalog/lint.ts defines effect-no-barrel-imports.
  • apps/cli/src/content/lint.ts carries selected lint assets into scaffold summaries.
  • apps/cli/src/scaffold/output.ts writes nearest package/app oxlint.config.ts files.
  • apps/cli/src/scaffold/run.test.ts already has public-seam scaffold lint tests through runScaffold.

Grilling Ledger

Locked decisions:

  • Preserve nested package/app Oxlint configs. Do not move this behavior back to root-only config.
  • Treat runScaffold as the RED/GREEN public seam.
  • Do not update Oxlint/Ultracite only for churn. Registry check shows latest packages are newer, but readonly Oxlint research found oxlint@1.72.0 already supports the needed typed rule shape.
  • Keep implementation under apps/cli unless a shared scaffold model contract proves necessary.

Assumptions:

  • The GitHub issue is the product backlog item; no new backlog item is required.
  • Consumer proof can use a generated temp workspace fixture rather than the dirty secrets checkout.

Open decisions:

  • None blocking.

Research Notes

Readonly workers found:

  • Oxlint accepts JS plugin rule config as severity or tuple: AllowWarnDeny | [AllowWarnDeny, ...unknown[]].
  • The reported rule shape is semantically right when emitted as ["error", { packageNames: ["effect"] }].
  • The generator currently emits const localConfig = { ... }; TypeScript can infer the rule array as a widened array instead of the tuple type required by Oxlint.
  • Nested Oxlint config lookup is supported when callers do not pass --config; passing --config disables nested lookup.
  • apps/cli/package.json does not currently own every dev dependency needed by its own oxlint.config.ts, which may affect isolated package checks.

Codebase Design Notes

The deep module seam is runScaffold: it hides detection, pack resolution, lint asset selection, config generation, and package dependency writes behind one observable scaffold operation. The plan tests there rather than testing private encoder helpers.

The likely implementation seam is encodeOxlintConfigTs: it should emit generated TypeScript that lets Oxlint's own exported types contextualize local rule config without changing catalog data semantics.

Dependency Graph

T1 ─┐
T2 ─┼─ T3 ── T4 ── T5

Parallel Execution Waves

WaveTasksCan Start When
1T1, T2Immediately
2T3T1 and T2 complete
3T4T3 complete
4T5T4 complete

Tasks

T1: RED Test And Generator Fix

  • depends_on: []
  • location: apps/cli/src/scaffold/run.test.ts, apps/cli/src/scaffold/output.ts
  • description: Add a failing public-seam regression test that scaffolds an Effect workspace and proves the generated nested oxlint.config.ts typechecks, then update the config encoder so generated local rule config is typed against Oxlint without losing nearest-config behavior.
  • validation: Generated Effect workspace config includes effect-js/no-import-from-barrel-package with { packageNames: ["effect"] } and the generated config passes a TypeScript check in the test fixture.
  • status: Complete
  • log:
  • 2026-07-09: Added public-seam runScaffold regression test for generated Effect workspace oxlint.config.ts; exact plan command accepted by Vitest as-is.
  • 2026-07-09: RED captured with generated localConfig.rules["effect-js/no-import-from-barrel-package"] inferred as a widened array and rejected by Oxlint defineConfig.
  • 2026-07-09: Fixed generator by emitting localRules satisfies OxlintConfig["rules"] and then composing normal local config, preserving nearest package/app config generation and existing merge behavior.
  • 2026-07-09: Review follow-up fixed no-rules generated configs to avoid importing unused OxlintConfig; added Vitest-only scaffold assertion.
  • 2026-07-09: Accepted P2 review follow-up made the typecheck regression hermetic by linking fixture dependencies from repo node_modules instead of running bun install in the temp workspace.
  • files edited/created:
  • apps/cli/src/scaffold/run.test.ts
  • apps/cli/src/scaffold/output.ts
  • apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md
  • backlog_item_id: issue-68
  • backlog_item_url: https://github.com/wearedevpunks/harness-intelligence/issues/68
  • relation_mode: body-links
  • assigned_skills: tdd, quality-types, codebase-design, simplify, turborepo
  • tdd_status: required
  • tdd_target: runScaffold emits an Effect workspace oxlint.config.ts that TypeScript accepts.
  • red_command: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config"
  • expected_red_failure: The new test fails because generated localConfig.rules["effect-js/no-import-from-barrel-package"] is inferred as a widened array and rejected by defineConfig.
  • green_command: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config"
  • reason_not_testable:
  • red_evidence:
  • /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config" exited 1 after the test reached tsc: packages/effect-service/oxlint.config.ts(24,29): error TS2345: Argument of type '{ jsPlugins: { name: string; specifier: string; }[]; rules: { "effect-js/no-import-from-barrel-package": (string | { packageNames: string[]; })[]; }; extends: OxlintConfig[]; ignorePatterns: string[] | undefined; }' is not assignable to parameter of type 'OxlintConfig'. The diagnostic continued: Type '(string | { packageNames: string[]; })[]' is not assignable to type '[AllowWarnDeny, ...unknown[]]'. Source provides no match for required element at position 0 in target.
  • green_evidence:
  • /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config" exited 0: 1 passed | 22 skipped; runScaffold > generates a typecheckable Effect Oxlint config.
  • Additional nested-config guard: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "Oxlint config" exited 0: 3 passed | 195 skipped, covering create, merge, and the new Effect typecheck regression.
  • Review follow-up guard: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "no local rules" exited 0: 1 passed | 198 skipped; generated Vitest-only config imports defineConfig without OxlintConfig.
  • Final review follow-up validation: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "Oxlint config" exited 0: 3 passed | 196 skipped; /Users/stefan/.bun/bin/bun run --cwd apps/cli check-types exited 0.
  • P2 hermetic-test follow-up: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config" exited 0: 1 passed | 198 skipped; the temp workspace no longer runs bun install and resolves oxlint, ultracite, and @effect/eslint-plugin from the repo install.
  • codebase_design_notes: Test through the runScaffold module seam; keep encoder changes local to generated config typing.
  • review_mode: cli

T2: CLI Lint Dependency Ownership

  • depends_on: []
  • location: apps/cli/package.json, bun.lock
  • description: Ensure @punks/cli owns the lint/config packages needed by its own local oxlint.config.ts in isolated package installs. Use current repo policy versions unless implementation evidence shows a latest-version bump is required.
  • validation: apps/cli/package.json declares the needed dev dependencies and lockfile stays consistent.
  • status: Complete
  • log: Added local @punks/cli devDependency ownership for the packages its oxlint.config.ts imports or asks Oxlint to load: @effect/eslint-plugin@0.3.2, oxlint@1.72.0, and ultracite@7.8.3. Used the repo's existing Oxlint/Ultracite policy versions and the current published Effect plugin version; no latest-version bump was needed.
  • files edited/created: apps/cli/package.json, bun.lock
  • backlog_item_id: issue-68
  • backlog_item_url: https://github.com/wearedevpunks/harness-intelligence/issues/68
  • relation_mode: body-links
  • assigned_skills: quality-types, turborepo, simplify
  • tdd_status: not_applicable
  • tdd_target: Package metadata consistency for local lint config ownership.
  • red_command:
  • expected_red_failure:
  • green_command: /Users/stefan/.bun/bin/bun install --lockfile-only
  • reason_not_testable: Package metadata/lockfile ownership change; validated by install consistency and package checks.
  • red_evidence:
  • green_evidence: /Users/stefan/.bun/bin/bun install --lockfile-only first failed because existing dirty root catalog TypeScript aliases were blocked by /Users/stefan/.bunfig.toml minimumReleaseAge = 604800; /Users/stefan/.bun/bin/bun install --lockfile-only --minimum-release-age=0 then succeeded with Saved bun.lock (1218 packages). /Users/stefan/.bun/bin/bun -e 'await import("./oxlint.config.ts"); console.log("apps/cli oxlint config loaded")' from apps/cli printed apps/cli oxlint config loaded. /Users/stefan/.bun/bin/bun run --cwd apps/cli check loaded the config and failed on pre-existing lint findings such as src/data/subagents/manifest.mjs sort-keys and many existing Ultracite rule violations, not on missing config dependencies.
  • codebase_design_notes: Keep dependency ownership local to the package that owns the config.
  • review_mode: cli

T3: Focused Validation

  • depends_on: [T1, T2]
  • location: apps/cli
  • description: Run focused CLI tests and type checks for the changed scaffold path.
  • validation: Targeted scaffold test, @punks/cli typecheck, and relevant lint/package checks pass or blockers are recorded with exact output.
  • status: Complete
  • log:
  • 2026-07-09: Parent validation passed for the focused CLI typecheck and full scaffold run test file after T1/T2.
  • files edited/created:
  • apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md
  • backlog_item_id: issue-68
  • backlog_item_url: https://github.com/wearedevpunks/harness-intelligence/issues/68
  • relation_mode: body-links
  • assigned_skills: tdd, quality-types, turborepo
  • tdd_status: not_applicable
  • tdd_target: Verification gate for completed behavior slices.
  • red_command:
  • expected_red_failure:
  • green_command: /Users/stefan/.bun/bin/bun run check-types --filter=@punks/cli && /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- src/scaffold/run.test.ts
  • reason_not_testable: Validation task consumes tests from T1 rather than adding behavior.
  • red_evidence:
  • green_evidence:
  • /Users/stefan/.bun/bin/bun run check-types --filter=@punks/cli exited 0: Turbo ran check-types for @punks/scaffold, @punks/contract, and @punks/cli; 3 successful, 3 total.
  • /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- src/scaffold/run.test.ts exited 0: src/scaffold/run.test.ts passed 15 tests, including generates a typecheckable Effect Oxlint config.
  • git diff --check -- apps/cli/src/scaffold/output.ts apps/cli/src/scaffold/run.test.ts apps/cli/package.json apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md exited 0.
  • codebase_design_notes: Validate from narrow CLI surface outward.
  • review_mode: cli

T4: Docs And Notes

  • depends_on: [T3]
  • location: .agents/notes/2026-07-09-cli-check-ultracite-dependency.md, apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md, apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md
  • description: Update only the durable note and issue #68 planning artifacts with the tuple-inference resolution, local dependency ownership, and docs/notes evidence. Leave GitHub/tracker closeout for after mandatory review.
  • validation: Docs/notes match implemented reality; scoped whitespace check passes.
  • status: Complete
  • log:
  • 2026-07-09: Added concise note resolution for TS tuple inference and apps/cli local lint dependency ownership.
  • 2026-07-09: Corrected T4/T5 dependency/status flow so docs/notes complete before mandatory review; GitHub/tracker closeout stays after review.
  • files edited/created:
  • .agents/notes/2026-07-09-cli-check-ultracite-dependency.md
  • apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md
  • apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md
  • backlog_item_id: issue-68
  • backlog_item_url: https://github.com/wearedevpunks/harness-intelligence/issues/68
  • relation_mode: body-links
  • assigned_skills: docs-ingest-phase, docs-onboarding, simplify, writing-shape
  • tdd_status: not_applicable
  • tdd_target: Durable closeout artifacts, not runtime behavior.
  • red_command:
  • expected_red_failure:
  • green_command: git diff --check -- .agents/notes/2026-07-09-cli-check-ultracite-dependency.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md
  • reason_not_testable: Documentation/closeout artifact task.
  • red_evidence:
  • green_evidence:
  • git diff --check -- .agents/notes/2026-07-09-cli-check-ultracite-dependency.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md exited 0 with no output. Note: the two spec files are currently untracked, so plain git diff does not inspect their content.
  • git diff --check --no-index -- /dev/null apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md emitted no whitespace diagnostics; exit 1 is expected because the file differs from /dev/null.
  • git diff --check --no-index -- /dev/null apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md emitted no whitespace diagnostics; exit 1 is expected because the file differs from /dev/null.
  • codebase_design_notes: Keep docs scoped to generated nested Oxlint config behavior and dependency ownership.
  • review_mode: cli

T5: Review Follow-up

  • depends_on: [T4]
  • location: changed files
  • description: Run a readonly review of the planned/implemented changes for missing edge cases, over-broad edits, dependency ownership mistakes, and validation gaps.
  • validation: review-phase/autoreview findings are classified and either fixed or explicitly deferred.
  • status: Complete
  • log:
  • 2026-07-09: Accepted P2 review finding that the new typecheckable Effect Oxlint config test used live bun install; fixed by linking temp fixture dependencies to repo-installed packages while preserving the runScaffold seam and generated-config tsc proof.
  • 2026-07-09: Classified P2 lockfile dependency churn finding as boundary/deferred: bun.lock already reflected pre-existing root/wiki TypeScript/Oxlint package changes from dirty package.json and apps/wiki/package.json edits. Issue #68 owns only the added apps/cli local lint dependency declarations on top of that dirty lockfile state.
  • files edited/created:
  • apps/cli/src/scaffold/run.test.ts
  • apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md
  • apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md
  • backlog_item_id: issue-68
  • backlog_item_url: https://github.com/wearedevpunks/harness-intelligence/issues/68
  • relation_mode: body-links
  • assigned_skills: review-phase, autoreview, simplify, quality-types, tdd
  • tdd_status: not_applicable
  • tdd_target: Review artifact.
  • red_command:
  • expected_red_failure:
  • green_command: /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config" && /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "Oxlint config" && /Users/stefan/.bun/bin/bun run --cwd apps/cli check-types && git diff --check -- apps/cli/src/scaffold/run.test.ts apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md
  • reason_not_testable: Readonly review task.
  • red_evidence:
  • green_evidence:
  • /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "typecheckable Effect Oxlint config" exited 0: 1 passed | 198 skipped.
  • /Users/stefan/.bun/bin/bun run --cwd apps/cli test -- --testNamePattern "Oxlint config" exited 0: 3 passed | 196 skipped.
  • /Users/stefan/.bun/bin/bun run --cwd apps/cli check-types exited 0.
  • git diff --check -- apps/cli/src/scaffold/run.test.ts apps/cli/src/scaffold/output.ts apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.md apps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/IMPLEMENTATION-NOTES.md exited 0.
  • Review classification: hermetic-test P2 accepted/fixed; dirty-lockfile P2 boundary/deferred to preserve unrelated pre-existing root/wiki dependency work.
  • codebase_design_notes: Review should protect the runScaffold seam and nested-config invariant.
  • review_mode: cli

Testing Strategy

  • First RED/GREEN target: the new runScaffold regression test for typecheckable generated Effect Oxlint config.
  • Focused CLI validation: targeted scaffold test, @punks/cli typecheck, then broader apps/cli scaffold tests if time or risk indicates.
  • Final validation: git diff --check; docs/wiki build only if docs changes include routed syntax risk.

Risks And Mitigations

  • Risk: Typing the generated config too strictly rejects preserved user JSONC config fields. Mitigation: test an existing-config merge case remains green and prefer Oxlint's public config type only where it protects rule values.
  • Risk: Updating lint packages introduces unrelated lockfile churn. Mitigation: do not bump package versions unless a command proves it is required.
  • Risk: Nested configs regress through root --config use. Mitigation: preserve existing hook/root check behavior and avoid root-only fixes.

Backlog Sync

No backlog mutation during T4. GitHub issue #68 is the owning product-facing item and already links the bug report; comment/closeout waits until after mandatory review.

Review And Docs Ingest

T4 completed the private/internal docs/notes update. T5 accepted and resolved the P2 hermetic-test review finding, and classified the dirty-lockfile P2 as boundary/deferred. GitHub/tracker closeout should state that issue #68 adds only apps/cli dependency ownership while preserving unrelated pre-existing root/wiki dependency churn.

On this page