Skip to content

refactor: resolve all deferred tech debt from PRs #106 and #107#108

Merged
dean0x merged 25 commits intomainfrom
chore/resolve-tech-debt-106-107
Mar 29, 2026
Merged

refactor: resolve all deferred tech debt from PRs #106 and #107#108
dean0x merged 25 commits intomainfrom
chore/resolve-tech-debt-106-107

Conversation

@dean0x
Copy link
Copy Markdown
Owner

@dean0x dean0x commented Mar 29, 2026

Summary

Net reduction: ~150 lines of duplicated infrastructure eliminated.

Test plan

  • cargo test — all tests pass (913+ unit, 45+ integration, 11 doc tests)
  • cargo clippy -- -D warnings — clean
  • cargo fmt -- --check — clean
  • Quality gates passed: Validator, Simplifier, Scrutinizer, Shepherd (both PRs)

Dean Sharon and others added 25 commits March 28, 2026 19:02
…int)

Add `skim lint` subcommand with four linter parsers following the
three-tier degradation pattern (Full JSON, Degraded regex, Passthrough).

- LintResult/LintIssue/LintGroup canonical types in output/canonical.rs
- CommandType::Lint variant in analytics
- eslint parser: --format json tier 1, default formatter regex tier 2
- ruff parser: --output-format json tier 1, text regex tier 2
- mypy parser: --output json NDJSON tier 1, text regex tier 2
- golangci-lint parser: --out-format json tier 1, text regex tier 2
- --json flag for structured JSON output on all linters
- 9 rewrite rules (eslint, npx eslint, ruff, ruff check, mypy,
  python -m mypy, python3 -m mypy, golangci-lint, golangci-lint run)
- E2E tests for all tiers, --json flag, help, unknown linter
- Rewrite E2E tests for all 9 lint rules

Co-Authored-By: Claude <noreply@anthropic.com>
…audit)

Add `skim pkg` subcommand with four package manager parsers following the
three-tier degradation pattern (JSON -> regex -> passthrough):

- npm: install, audit, outdated, ls (JSON + regex tiers)
- pnpm: install (regex), audit (JSON), outdated (JSON)
- pip: install (regex), check (regex), list --outdated (JSON)
- cargo: audit (JSON + regex tiers)

Also adds:
- PkgResult/PkgOperation canonical types in output/canonical.rs
- CommandType::Pkg variant in analytics
- 17 rewrite rules for npm/pnpm/pip/pip3/cargo audit
- 22 E2E pkg parser tests + 18 E2E rewrite tests
- 41 unit tests across all four parsers
- 15 fixture files with realistic tool output

Co-Authored-By: Claude <noreply@anthropic.com>
…loops, tighten assertions

- Extract `run_lint_json_mode` in lint/mod.rs to replace 4 duplicated
  `run_json_mode` functions (~320 lines -> single shared helper)
- Add 64 MiB stdin limit via `.take()` in shared helper, consistent
  with `run_parsed_command_with_mode`
- Preserve child process exit code instead of always returning SUCCESS
- Replace `?` operators in try_parse_json loops (eslint, ruff, golangci)
  with `let-else { continue }` to avoid discarding previously parsed issues
- Fix rule count comment in rewrite.rs (26 -> 24)

Co-Authored-By: Claude <noreply@anthropic.com>
- eslint Tier 2 test: replace weak > 0 check with exact assert_eq counts
- golangci Tier 1 test: replace sum assertion with individual error/warning counts
- golangci E2E test: add count assertions for 1 error and 3 warnings
- Add unit tests for group_issues (Info severity, empty input)
- Add unit tests for extract_json_flag (present and absent)
- Add E2E test for --show-stats with lint subcommand

Co-Authored-By: Claude <noreply@anthropic.com>
- Add 34 unit tests for all 18 Pkg rewrite rules (cargo audit, npm
  audit/install/i/ci/outdated/list/ls, pnpm audit/install/i/outdated,
  pip install/check/list, pip3 install/check/list) including skip-flag
  and category assertions
- Add two missing rewrite aliases: npm list -> skim pkg npm ls (skip:
  --json) and pnpm i -> skim pkg pnpm install (skip: none)
- Remove unnecessary .cloned() deep copy in cargo audit JSON parser;
  use borrowed reference with empty vec fallback instead
- Refactor combine_output into shared Cow-based helper in pkg/mod.rs
  to eliminate duplication across cargo/npm/pip/pnpm parsers

Co-Authored-By: Claude <noreply@anthropic.com>
…ip args, fix vuln counts

- Remove dead-code guards in pip and pnpm run() — replace unreachable
  let-else with .expect() since args.is_empty() is already checked
- Apply cargo fmt to npm.rs via-array handling block

Co-Authored-By: Claude <noreply@anthropic.com>
)

Split npm.rs (787 lines) into npm/ directory with 5 files:
- mod.rs (67 lines): dispatcher + re-exports
- install.rs (249 lines): npm install parser + tests
- audit.rs (270 lines): npm audit parser + tests
- outdated.rs (165 lines): npm outdated parser + tests
- ls.rs (156 lines): npm ls parser + tests

Extract extract_vuln_detail() helper from cargo.rs try_parse_audit_json,
reducing it from 91 to ~69 lines.

Pure structural refactor — zero behavioral changes. All existing tests pass.
Filenames already communicate purpose after the split — section headers
like "// npm install" are noise in dedicated files.
The function always returns Some since all fields have unwrap_or
fallbacks. Updated doc to accurately reflect this behavior.
Replace truncating `as u32` casts with `u32::try_from(x).unwrap_or(u32::MAX)`
in all four lint parsers (eslint, golangci, mypy, ruff) to prevent silent
data loss on line numbers exceeding u32::MAX.

Co-Authored-By: Claude <noreply@anthropic.com>
Add tests for extract_json_flag (flag present/absent) and
combine_output (borrowed/owned paths) in pkg/mod.rs. Add
three-tier integration tests (json->Full, garbage->Passthrough)
for npm outdated and npm ls parsers, matching install.rs pattern.

Co-Authored-By: Claude <noreply@anthropic.com>
- Change extract_vuln_detail return from Option<(String, &str)> to
  plain (String, &str) since all fields have unwrap_or fallbacks and
  the function never returns None
- Replace `as usize` casts in npm install parser with
  usize::try_from().ok() to avoid silent truncation on 32-bit targets
- Include co-located batch fixes: sanitize user input in error messages,
  use CARGO_TERM_COLOR env var, add three-tier integration tests

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove unnecessary String allocation in LintResult::render by using
  direct write! calls with inline pluralization instead of format!()
- Add test_parse_impl_text_produces_degraded to ruff, mypy, and
  golangci modules, matching the existing eslint pattern
- Add E2E test for `skim lint eslint --json` with degraded tier input
- Document golangci Tier 2 regex severity-defaults-to-Warning as a
  known limitation (text format lacks severity information)
- Fix Cow<str> type mismatch in parse_impl Passthrough arms after
  combine_stdout_stderr was refactored to return Cow
- Add stderr tier markers to run_lint_json_mode for observability

Co-Authored-By: Claude <noreply@anthropic.com>
Collapse stderr lock/emit/drop, inline single-use variables,
deduplicate render write calls, optimize group_issues ownership.
Deduplicate three identical u64-to-usize conversion chains
into a single helper function.
…n_linter helper

- Add OutputFormat enum (Text/Json) and output_format field to ParsedCommandConfig
- Add to_json_envelope() on ParseResult<T: Serialize> for JSON serialization
- Widen T bound to AsRef<str> + Serialize in run_parsed_command_with_mode
- Add JSON output branch in run_parsed_command_with_mode
- Extract LinterConfig + run_linter helper in lint/mod.rs
- Migrate all 4 linters (eslint, ruff, mypy, golangci) to use run_linter
- Delete run_lint_json_mode + LintJsonConfig (dead code)

Resolves tech debt items 1-3 from PR #106 review.

Co-Authored-By: Claude <noreply@anthropic.com>
…parser

- Add PkgSubcommandConfig + run_pkg_subcommand helper in pkg/mod.rs
- Migrate all 10 run_* functions to use the shared helper
- Rewrite try_parse_audit_regex from triple-regex to block-based parsing
  (handles missing fields and reordered fields correctly)
- Remove dead regex statics (RE_CRATE, RE_TITLE, RE_ADVISORY_ID)
- Add failing tests for missing-field and reordered-field cases (TDD)

Resolves tech debt items 5-6 from PR #107 review.

Co-Authored-By: Claude <noreply@anthropic.com>
- De-duplicate stats/analytics logic in run_parsed_command_with_mode by
  extracting compressed content from the output_format match arms
- Replace fully-qualified crate::cmd:: paths with proper use imports in
  lint/mod.rs and test/cargo.rs for consistency
…ith tech debt fixes

Merges feat/104-lint-parsers and feat/105-pkg-parsers into a single
consolidation branch. Resolves merge conflicts (additive — both PRs
add independent modules, types, and tests to shared files).

Post-merge fixes:
- Add output_format field to pkg's ParsedCommandConfig construction
- Add Serialize bound to run_pkg_subcommand generic parameter
- Reconstruct mangled struct/impl/test boundaries in canonical.rs

Tech debt resolved (items 1-3 from PR #106):
- Unified lint JSON mode into shared run_parsed_command_with_mode
- Extracted run_linter helper, migrated all 4 linters
- Deleted run_lint_json_mode + LintJsonConfig

Tech debt resolved (items 5-6 from PR #107):
- Extracted run_pkg_subcommand helper, migrated all 10 functions
- Block-based cargo audit parser replaces fragile triple-regex
- Removed dead regex statics
@dean0x dean0x merged commit 8b43039 into main Mar 29, 2026
4 of 5 checks passed
@dean0x dean0x deleted the chore/resolve-tech-debt-106-107 branch March 29, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant