refactor: dedupe read_dir loops; drive biome lint to clean#43
Merged
Conversation
Follow-up to PR #42's helper extraction. Replaces 8 pre-existing `read_dir + extension filter` loops with `super::files_with_ext` helper calls; behaviour-preserving mechanical refactor, 4 adapters touched: - claude.rs: rules/, commands/, output-styles/ (3 loops in global_rules_files / global_settings_files); inner memory/ loop in global_memory_files (outer projects/* iteration kept β multi-level pattern doesn't match the helper) - gemini.rs: commands/, policies/ in global_settings_files - copilot.rs: hooks/ in global_settings_files - codex.rs: memories/ in global_memory_files β adds explicit `.filter(|p| p.is_file())` to preserve prior `is_file()` check (cheap parity over a "siblings don't bother" argument) Net: -64 / +12 lines. 385 hk-core tests pass, clippy -D warnings clean. Plugin/marketplace recursive multi-level scans intentionally left untouched β they have a different shape than the helper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reduces biome diagnostics from 13 errors + 12 warnings + 1 info to fully
clean. Combines auto-fix and manual passes:
Auto-fix (Step 2 β `npm run lint:fix`, 8 files): import sorting,
formatter pass, blank-line cleanup. Pure cosmetic, zero behavior change.
Manual (Step 3, by category):
Category A β trivial mechanical (2 sites):
- transport.ts useLiteralKeys: `headers["Authorization"]` β `.Authorization`
- invoke.ts useOptionalChain: `!value || !value.trim()` β `!value?.trim()`
Category D β noExplicitAny (1 site, onboarding.tsx):
- Removed dead `roughness` field from rough-notation `annotate()` config
(library hardcodes its own roughness via getOptions(type) in render.js
and never reads user-supplied values), removed accompanying `as any`.
Category C β useExhaustiveDependencies (4 sites, 5 findings):
- Added single-line `biome-ignore` with rationale at each site where the
dep array intentionally omits a value or includes a trigger sentinel:
- section-anchor-rail revisionKey (documented re-discovery sentinel)
- extension-filters extensions (Zustand getter trigger)
- extension-table scope (cell-renderer getState() trigger)
- scope-switcher-menu handleSelect/handleAddProject (new closures
capturing only stable refs β adding them would only churn the
keydown listener)
- Replaced obsolete `eslint-disable-next-line` comment in
scope-switcher-menu (project uses biome, not eslint).
Category B β noNonNullAssertion (9 sites, 5 biome-ignore + 4 refactor):
- biome-ignore where the `!` reflects a TS narrowing limitation through
JSX/by-construction guarantees (main.tsx React entry, config-file-entry
JSX gates, detail-paths Map.get of own keys, test idiom).
- Refactor where a small rewrite removes the `!` cleanly:
- delete-dialog: redundant `&& filteredSkillLocations` lets TS narrow
- extension-detail: extracted `activePath` local var (kills 2 `!`)
- new-skills-dialog: explicit Map get-or-create binding
- agent-config-store: single `get()` + undefined check instead of
has()/get()! pair (cache stores strings only, so `cached !== undefined`
is exactly equivalent to `has`)
Final state: `npm run lint` clean; tsc clean; 148/148 frontend tests
pass; no behavior changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
read_dir + extension filterloops (claude rules/commands/output-styles/projects-memory, gemini commands/policies, copilot hooks, codex memories) replaced with calls to thefiles_with_exthelper extracted in PR feat: scan project-level subagents across 6 agentsΒ #42. Behaviour-preserving.13 errors + 12 warnings + 1 infoβ 0 / 0 / 0. Mix ofnpm run lint:fix(auto-fix), targeted refactors, and documentedbiome-ignorefor legitimate trigger-sentinel patterns.Commits
Each commit is independently bisect-able and tests-clean.
Commit 1 β Rust read_dir dedup
global_rules_files(rules/),global_settings_files(commands/, output-styles/),global_memory_files(projects/*/memory/ inner loop)global_settings_files(commands/, policies/)global_settings_files(hooks/)global_memory_files(memories/).filter(|p| p.is_file())to preserve prioris_file()defensive checkPlugin / marketplace recursive multi-level scans intentionally left untouched β they don't fit the
files_with_extshape.Closes the follow-up tracked in
project_adapter_readdir_helper_extract_roadmap.md.Commit 2 β Frontend lint cleanup
Auto-fix (Step 2 β
npm run lint:fix, 8 files)Pure cosmetic: import sorting, formatter pass, blank-line cleanup. Zero behaviour change.
Manual fixes by category
Category A β trivial mechanical (2 sites)
transport.tsuseLiteralKeys:headers["Authorization"]β.Authorizationinvoke.tsuseOptionalChain:!value || !value.trim()β!value?.trim()Category D β
noExplicitAny(1 site, onboarding.tsx)roughnessfield fromrough-notation'sannotate()config (library hardcodes its own roughness viagetOptions(type)inrender.jsand never reads user-supplied values), removed accompanyingas any.Category C β
useExhaustiveDependencies(4 files, 5 findings)Each is a deliberate trigger-sentinel pattern; auto-fix would have broken behaviour. Documented with single-line
biome-ignore:section-anchor-railrevisionKey(re-discovery sentinel β see component JSDoc)extension-filtersextensions(Zustand store closure trigger viagrouped())extension-tablescope(cell-renderergetState()trigger)scope-switcher-menuhandleSelect/handleAddProject(new closures capturing only stable refs β adding them only churns the keydown listener)Also replaced an obsolete
eslint-disable-next-linecomment (project uses biome, not eslint).Category B β
noNonNullAssertion(9 sites)Per-site judgment call:
!is a TS-narrowing limitation through JSX or by-construction guarantees (React entry pattern, JSX&&gates not propagating into callbacks,Map.getof own keys, test idiom).!cleanly:delete-dialog: redundant&& filteredSkillLocationslets TS narrow inside the ternary's true branchextension-detail: extractedactivePathlocal variable via IIFE wrapper (kills 2!)new-skills-dialog: explicit Map get-or-create binding instead ofhas()+get()!agent-config-store: singleget()+cached !== undefinedcheck (cache stores strings only, soundefinedβ‘!has); also reduces a redundant zustandget()callTest coverage
cargo build --workspace: cleancargo test --workspace: 402 tests pass (385 hk-core + 17 across other crates)cargo clippy --workspace --all-targets -- -D warnings: cleannpx tsc --noEmit: cleannpm run lint(biome): 0 errors / 0 warnings / 0 infonpx vitest run: 148 / 148 passTest plan
roughnessuser-config was dead, visuals should be identical)Roadmap follow-ups not in this PR
None new. The roadmap entry
project_adapter_readdir_helper_extract_roadmap.mdis now complete and can be retired.