Background
PR #1396 ("refactor: address review findings from Rovodev PR #1377") was reviewed and all critical/high/mid findings were addressed before merge. The remaining low and mid findings are maintainability improvements that can be tackled in follow-up work. This issue consolidates them for future reference.
Details
Mid severity
1. Repeated union narrowing pattern in RovodevRule — extract a type guard function
- File:
src/features/rules/rovodev-rule.ts (lines 104-108, 177, 189, 253)
- The pattern
"nonRoot" in paths && paths.nonRoot and "alternativeRoots" in paths appears in multiple places to narrow the RovodevRuleSettablePaths | ToolRuleSettablePathsGlobal union.
- A dedicated type guard (e.g.
isProjectPaths(paths): paths is RovodevRuleSettablePaths) would reduce duplication and make the two-mode design explicit.
2. buildDeletionRulesFromPaths is a closure that cannot be unit-tested independently
- File:
src/features/rules/rules-processor.ts (lines 937-963)
- The helper captures
this.baseDir, this.global, factory, and resolveRelativeDirPath from outer scope.
- If it grows or is needed elsewhere, consider promoting it to a private method with explicit parameters for independent testability.
Low severity
3. isAllowedModularRulesRelativePath checks all path segments, not just the final basename
- File:
src/features/rules/rovodev-rule.ts (lines 52-59)
- A directory named
agents.md (e.g. agents.md/foo.md) would also be rejected. If this is intentional, the JSDoc and constant name (DISALLOWED_ROVODEV_MODULAR_RULE_BASENAMES) should clarify that it applies to all segments.
4. **/.rovodev/.rulesync/ gitignore entry uses general feature tag
- File:
src/cli/commands/gitignore-entries.ts (lines 197-201)
- Sibling entries use specific feature tags (
subagents, skills), but this one uses general. If intentional (implementation detail that should always be ignored), an inline comment would help.
5. fromRootFile parameter name overrideDirPath is slightly misleading
- File:
src/features/rules/rovodev-rule.ts (lines 159-173)
- It falls back to
paths.root.relativeDirPath when undefined, so "override" implies it always overrides something. Consider relativeDirPath or explicitDirPath.
6. Test coverage: add positive cases with similar-but-allowed names
- File:
src/features/rules/rovodev-rule.test.ts
- Current tests verify that mixed-case reserved names are rejected. Adding tests for names containing the substring "agents" but not matching (e.g.
agents-custom.md, my-agents.md) would confirm the check is not overly broad.
7. Granular .rovodev/ gitignore entries risk drift
- File:
.gitignore (lines 307-313)
- New files under
.rovodev/ will need corresponding gitignore entries. Already covered by feature-change-guidelines.md, but worth keeping in mind.
8. JSDoc markdown bold in buildDeletionRulesFromPaths — already fixed in latest commit
- Replaced
**Root mode** / **Non-root mode** with plain text labels.
Solution / Next Steps
- Type guard extraction (item 1): Create
isProjectPaths type guard in rovodev-rule.ts and replace all manual narrowing checks.
- Closure testability (item 2): Monitor growth of
buildDeletionRulesFromPaths. If it gains complexity, extract to a private method with explicit parameters.
- Documentation / comments (items 3, 4, 5): Add clarifying JSDoc/comments for the path-segment check scope,
general feature tag choice, and parameter naming.
- Test coverage (item 6): Add positive test cases for similar-but-allowed names.
- Items 7-8 are informational / already resolved.
Background
PR #1396 ("refactor: address review findings from Rovodev PR #1377") was reviewed and all critical/high/mid findings were addressed before merge. The remaining low and mid findings are maintainability improvements that can be tackled in follow-up work. This issue consolidates them for future reference.
Details
Mid severity
1. Repeated union narrowing pattern in
RovodevRule— extract a type guard functionsrc/features/rules/rovodev-rule.ts(lines 104-108, 177, 189, 253)"nonRoot" in paths && paths.nonRootand"alternativeRoots" in pathsappears in multiple places to narrow theRovodevRuleSettablePaths | ToolRuleSettablePathsGlobalunion.isProjectPaths(paths): paths is RovodevRuleSettablePaths) would reduce duplication and make the two-mode design explicit.2.
buildDeletionRulesFromPathsis a closure that cannot be unit-tested independentlysrc/features/rules/rules-processor.ts(lines 937-963)this.baseDir,this.global,factory, andresolveRelativeDirPathfrom outer scope.Low severity
3.
isAllowedModularRulesRelativePathchecks all path segments, not just the final basenamesrc/features/rules/rovodev-rule.ts(lines 52-59)agents.md(e.g.agents.md/foo.md) would also be rejected. If this is intentional, the JSDoc and constant name (DISALLOWED_ROVODEV_MODULAR_RULE_BASENAMES) should clarify that it applies to all segments.4.
**/.rovodev/.rulesync/gitignore entry usesgeneralfeature tagsrc/cli/commands/gitignore-entries.ts(lines 197-201)subagents,skills), but this one usesgeneral. If intentional (implementation detail that should always be ignored), an inline comment would help.5.
fromRootFileparameter nameoverrideDirPathis slightly misleadingsrc/features/rules/rovodev-rule.ts(lines 159-173)paths.root.relativeDirPathwhenundefined, so "override" implies it always overrides something. ConsiderrelativeDirPathorexplicitDirPath.6. Test coverage: add positive cases with similar-but-allowed names
src/features/rules/rovodev-rule.test.tsagents-custom.md,my-agents.md) would confirm the check is not overly broad.7. Granular
.rovodev/gitignore entries risk drift.gitignore(lines 307-313).rovodev/will need corresponding gitignore entries. Already covered byfeature-change-guidelines.md, but worth keeping in mind.8. JSDoc markdown bold in
buildDeletionRulesFromPaths— already fixed in latest commit**Root mode**/**Non-root mode**with plain text labels.Solution / Next Steps
isProjectPathstype guard inrovodev-rule.tsand replace all manual narrowing checks.buildDeletionRulesFromPaths. If it gains complexity, extract to a private method with explicit parameters.generalfeature tag choice, and parameter naming.