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.tsdefineseffect-no-barrel-imports.apps/cli/src/content/lint.tscarries selected lint assets into scaffold summaries.apps/cli/src/scaffold/output.tswrites nearest package/appoxlint.config.tsfiles.apps/cli/src/scaffold/run.test.tsalready has public-seam scaffold lint tests throughrunScaffold.
Grilling Ledger
Locked decisions:
- Preserve nested package/app Oxlint configs. Do not move this behavior back to root-only config.
- Treat
runScaffoldas 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.0already supports the needed typed rule shape. - Keep implementation under
apps/cliunless 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
secretscheckout.
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--configdisables nested lookup. apps/cli/package.jsondoes not currently own every dev dependency needed by its ownoxlint.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 ── T5Parallel Execution Waves
| Wave | Tasks | Can Start When |
|---|---|---|
| 1 | T1, T2 | Immediately |
| 2 | T3 | T1 and T2 complete |
| 3 | T4 | T3 complete |
| 4 | T5 | T4 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.tstypechecks, 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-packagewith{ packageNames: ["effect"] }and the generated config passes a TypeScript check in the test fixture. - status: Complete
- log:
- 2026-07-09: Added public-seam
runScaffoldregression test for generated Effect workspaceoxlint.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 OxlintdefineConfig. - 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_modulesinstead of runningbun installin the temp workspace. - files edited/created:
apps/cli/src/scaffold/run.test.tsapps/cli/src/scaffold/output.tsapps/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:
runScaffoldemits an Effect workspaceoxlint.config.tsthat 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 bydefineConfig. - 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 reachedtsc: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 importsdefineConfigwithoutOxlintConfig. - 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-typesexited 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 runsbun installand resolvesoxlint,ultracite, and@effect/eslint-pluginfrom the repo install. - codebase_design_notes: Test through the
runScaffoldmodule 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/cliowns the lint/config packages needed by its own localoxlint.config.tsin isolated package installs. Use current repo policy versions unless implementation evidence shows a latest-version bump is required. - validation:
apps/cli/package.jsondeclares the needed dev dependencies and lockfile stays consistent. - status: Complete
- log: Added local
@punks/clidevDependency ownership for the packages itsoxlint.config.tsimports or asks Oxlint to load:@effect/eslint-plugin@0.3.2,oxlint@1.72.0, andultracite@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-onlyfirst failed because existing dirty root catalog TypeScript aliases were blocked by/Users/stefan/.bunfig.tomlminimumReleaseAge = 604800;/Users/stefan/.bun/bin/bun install --lockfile-only --minimum-release-age=0then succeeded withSaved bun.lock (1218 packages)./Users/stefan/.bun/bin/bun -e 'await import("./oxlint.config.ts"); console.log("apps/cli oxlint config loaded")'fromapps/cliprintedapps/cli oxlint config loaded./Users/stefan/.bun/bin/bun run --cwd apps/cli checkloaded the config and failed on pre-existing lint findings such assrc/data/subagents/manifest.mjssort-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/clitypecheck, 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/cliexited 0: Turbo rancheck-typesfor@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.tsexited 0:src/scaffold/run.test.tspassed 15 tests, includinggenerates 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.mdexited 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/clilocal 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.mdapps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.mdapps/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.mdexited 0 with no output. Note: the two spec files are currently untracked, so plaingit diffdoes 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.mdemitted 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.mdemitted 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/autoreviewfindings are classified and either fixed or explicitly deferred. - status: Complete
- log:
- 2026-07-09: Accepted P2 review finding that the new
typecheckable Effect Oxlint configtest used livebun install; fixed by linking temp fixture dependencies to repo-installed packages while preserving therunScaffoldseam and generated-configtscproof. - 2026-07-09: Classified P2 lockfile dependency churn finding as boundary/deferred:
bun.lockalready reflected pre-existing root/wiki TypeScript/Oxlint package changes from dirtypackage.jsonandapps/wiki/package.jsonedits. Issue #68 owns only the addedapps/clilocal lint dependency declarations on top of that dirty lockfile state. - files edited/created:
apps/cli/src/scaffold/run.test.tsapps/wiki/content/docs/project/specs/cli/issue-68-effect-oxlint-rule-typing/PLAN.mdapps/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-typesexited 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.mdexited 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
runScaffoldseam and nested-config invariant. - review_mode: cli
Testing Strategy
- First RED/GREEN target: the new
runScaffoldregression test for typecheckable generated Effect Oxlint config. - Focused CLI validation: targeted scaffold test,
@punks/clitypecheck, then broaderapps/cliscaffold 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
--configuse. 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.