Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
861c365
chore: add tooling config, ci workflow, and dependency updates
aspala Mar 19, 2026
dad7ca1
refactor(engine): extract engine layer and reorganize metrics namespaces
aspala Mar 19, 2026
653e830
feat(ast): add AST parsing system with lexing, signals, and node clas…
aspala Mar 19, 2026
62ed12d
feat(languages): add multi-language definitions and test fixtures
aspala Mar 19, 2026
fb4135e
feat(analysis): add OTP-based analysis run context and servers
aspala Mar 19, 2026
110ffd2
feat(combined-metrics): add combined metrics scoring framework
aspala Mar 19, 2026
5d67df7
feat(near-duplicate-blocks): add near-duplicate block detection and i…
aspala Mar 19, 2026
ef91d6b
feat(diagnostics): add config and diagnostics modules
aspala Mar 19, 2026
3a465c9
feat(health-report): update health report with new categories and gra…
aspala Mar 19, 2026
13f8b3c
feat(cli): add diagnose command and update existing commands
aspala Mar 19, 2026
397fd8f
feat(scalar-tuner): add scalar tuner UI tool
aspala Mar 19, 2026
5250d22
docs: update README and action configuration
aspala Mar 19, 2026
d49f463
test(analysis): add tests for OTP analysis servers
aspala Mar 19, 2026
6678ca7
test(ast): add tests for AST parsing, signals, nodes, and enrichment
aspala Mar 19, 2026
45ae2b2
chore(gitignore): ignore scripts/*.exs and docs plan directories
aspala Mar 19, 2026
b58c8bf
feat(combined-metrics): detect and persist language coverage per beha…
aspala Mar 20, 2026
a8267d3
feat(combined-metrics): filter diagnose_aggregate by language
aspala Mar 20, 2026
4e12620
fix(combined-metrics): improve behavior_language_applies? guards and …
aspala Mar 20, 2026
bca01a2
feat(combined-metrics): filter score_aggregate by project languages
aspala Mar 20, 2026
a9f017b
feat(file-scorer): detect file language and filter behaviors accordingly
aspala Mar 20, 2026
5556a30
feat: thread project languages through all codebase-level scoring cal…
aspala Mar 20, 2026
d8d448a
fix(block-impact-analyzer): avoid redundant language detection, clari…
aspala Mar 20, 2026
1e57187
feat(cli): add --apply-languages flag to sample_report mix task
aspala Mar 20, 2026
76fc86c
chore(combined-metrics): populate _languages coverage from samples
aspala Mar 20, 2026
db764fc
feat(ci): add workflow to auto-sync behavior language coverage and sc…
aspala Mar 20, 2026
1d10f53
chore(combined-metrics): sync language coverage and scalar vectors [s…
github-actions[bot] Mar 20, 2026
f6d1b97
docs(spec): health report block impact section, PR delta, and compare…
aspala Mar 20, 2026
3af09e9
docs(spec): address review findings — fix changed_files interface, en…
aspala Mar 20, 2026
6d1042f
docs(plan): health report block impact, PR delta, and compare consoli…
aspala Mar 21, 2026
34a118f
feat(block-impact): serialize end_line in node output
aspala Mar 21, 2026
5b46e98
feat(health-report): add Delta module for aggregate metric comparison
aspala Mar 21, 2026
fa96b53
fix(health-report/delta): coerce Float.round operand; document asymme…
aspala Mar 21, 2026
3211439
feat(health-report): add TopBlocks module for severity-classified blo…
aspala Mar 21, 2026
10dba09
fix(top-blocks): guard non-map YAML entries in build_fix_hint_lookup
aspala Mar 21, 2026
7d47f69
feat(health-report): add top_blocks, pr_summary, codebase_delta; drop…
aspala Mar 21, 2026
d563d62
fix(health-report): remove dead _detail binding; tag slow test
aspala Mar 21, 2026
b9f1bd7
feat(formatter): add block, delta, PR summary sections; remove worst_…
aspala Mar 21, 2026
248bd30
feat(formatter): remove worst_offenders rendering and tests from plai…
aspala Mar 21, 2026
86a9014
feat(formatter): add block, delta, PR summary sections; remove worst_…
aspala Mar 21, 2026
ec2bc51
fix(formatter): add fallback clause to severity_icon/1
aspala Mar 21, 2026
980860c
feat(cli): add --base-ref/--head-ref to health-report for PR delta an…
aspala Mar 21, 2026
110f439
feat(cli): delete compare command — absorbed into health-report
aspala Mar 21, 2026
1deed5a
chore(quality): fix all credo and dialyzer issues
aspala Mar 21, 2026
1876aeb
chore(combined-metrics): sync language coverage and scalar vectors [s…
github-actions[bot] Mar 21, 2026
05019e8
refactor(codebase): structural cleanup from health report analysis
aspala Mar 21, 2026
97cb5d0
chore(combined-metrics): sync language coverage and scalar vectors [s…
github-actions[bot] Mar 21, 2026
579f191
chore(ci): upgrade checkout to v6, add caching, remove dead blocks co…
aspala Mar 21, 2026
0787134
fix(near-duplicate-blocks): return zeroed map when blocks is nil
aspala Mar 22, 2026
20d1773
chore(combined-metrics): annotate language coverage for all behaviors
aspala Mar 22, 2026
e68cbd3
perf(block-impact): precompute log metrics and cache behaviors for co…
aspala Mar 22, 2026
70302cf
refactor(health-report): pre-compute cosines outside Grader
aspala Mar 22, 2026
71c8f0a
refactor(engine): integrate block impact computation into the analyze…
aspala Mar 22, 2026
3abbc0a
test: update tests for refactored grader and near-duplicate-blocks in…
aspala Mar 22, 2026
3b67dbb
refactor: fix dialyzer, credo nesting, and compiler warnings
aspala Mar 22, 2026
03cce19
fix(test): pass path to build_file_context in NearDuplicateBlocksFile…
aspala Mar 22, 2026
ddff5c1
chore(combined-metrics): sync language coverage and scalar vectors [s…
github-actions[bot] Mar 22, 2026
4e2eeb0
docs: add multi-part PR comment design spec
aspala Mar 22, 2026
9a220dd
docs: address spec review issues in multi-part PR comments design
aspala Mar 22, 2026
d2438f5
docs: fix sentinel and part-count clarifications in multi-part spec
aspala Mar 22, 2026
757114e
docs: final spec clarifications — part-count loop and placeholder own…
aspala Mar 22, 2026
ffa7400
feat(multi-part-comments): split health report into multiple PR comments
aspala Mar 26, 2026
d198001
fix(action): pass GITHUB_TOKEN to run.sh for PR comment posting
aspala Mar 26, 2026
570812a
chore: remove docs/ and ignore test/ in codeqa analysis
aspala Mar 26, 2026
4b43621
chore: ignore README.md and action.yml in codeqa analysis
aspala Mar 26, 2026
fe643c3
feat(blocks): show top 10 blocks by impact with source code
aspala Mar 26, 2026
228aef2
chore: trigger CI
aspala Mar 26, 2026
9b2d184
feat(blocks): filter blocks by line count (3-20 lines default)
aspala Mar 26, 2026
bfa9e3e
feat(blocks): filter blocks by diff line overlap when --base-ref prov…
aspala Mar 26, 2026
c9704ed
feat(report): show worst offending block per cosine category
aspala Mar 26, 2026
09c0901
chore(combined-metrics): sync language coverage and scalar vectors [s…
github-actions[bot] Mar 26, 2026
8925e76
fix(report): display blocks from 1-15 lines instead of 4-10
aspala Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
30 changes: 29 additions & 1 deletion .codeqa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,32 @@
# Patterns here are merged with any --ignore-paths passed on the command line.

ignore_paths:
- priv/combined_metrics/samples/**
- priv/**
- tools/**
- scripts/**
- docs/**
- plans/**
- test/**
- devenv*
- direnv*
- README.md
- action.yml

# Impact weights for overall score calculation.
# Combined metric categories default to 1 (can be overridden here).
impact:
complexity: 5
file_structure: 4
function_design: 4
code_smells: 3
naming_conventions: 2
error_handling: 2
consistency: 2
documentation: 1
testing: 1
# combined categories override example:
# variable_naming: 2

combined_top: 5 # worst offender files per combined-metric behavior

cosine_significance_threshold: 0.25 # threshold for cosine similarity calculation in behavior categories
14 changes: 14 additions & 0 deletions .dialyzer_ignore.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
# Dialyzer specializes analyze/2 for the codebase call-site where include_pairs
# is always true, making the false branch appear unreachable. Both branches are
# valid and reachable at runtime from the file-level and codebase callers.
{"lib/codeqa/metrics/file/near_duplicate_blocks.ex", :pattern_match},
# Mix module type information is not available in the PLT; these are valid
# Mix.Task callbacks and standard Mix module calls.
{"lib/mix/tasks/codeqa/sample_report.ex", :callback_info_missing},
{"lib/mix/tasks/codeqa/signal_debug.ex", :callback_info_missing},
{"lib/mix/tasks/codeqa/sample_report.ex", :unknown_function},
{"lib/mix/tasks/codeqa/signal_debug.ex", :unknown_function},
# CodeQA.Engine.Registry.t/0 is defined via a macro; type is available at runtime.
{"lib/codeqa/analysis/file_metrics_server.ex", :unknown_type}
]
2 changes: 1 addition & 1 deletion .github/workflows/bootstrap-labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
bootstrap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Bootstrap labels
uses: actions/github-script@v7
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/compare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,19 @@ jobs:
compare:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Cache Mix deps and build
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-1.19-27.3-${{ hashFiles('mix.lock', 'mix.exs') }}
restore-keys: ${{ runner.os }}-mix-1.19-27.3-

- name: Get fork point
id: fork-point
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/dialyzer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:

steps:
- name: Checkout PR
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up Elixir
uses: erlef/setup-beam@v1
Expand All @@ -45,9 +45,9 @@ jobs:
uses: actions/cache@v4
with:
path: _build
key: build-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('mix.lock') }}
key: build-${{ env.MIX_ENV }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('mix.lock') }}
restore-keys: |
build-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-
build-${{ env.MIX_ENV }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-

- name: Cache PLT
uses: actions/cache@v4
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/health-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@ jobs:
health-report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Cache Mix deps and build
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-1.19-27.3-${{ hashFiles('mix.lock', 'mix.exs') }}
restore-keys: ${{ runner.os }}-mix-1.19-27.3-

- uses: ./
with:
command: health-report
Expand Down
24 changes: 21 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,33 @@ jobs:
build:
runs-on: ubuntu-latest

env:
ELIXIR_VERSION: "1.19"
OTP_VERSION: "27.3"

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
otp-version: "27.3"
elixir-version: "1.19"
otp-version: ${{ env.OTP_VERSION }}
elixir-version: ${{ env.ELIXIR_VERSION }}

- name: Cache deps
uses: actions/cache@v4
with:
path: deps
key: deps-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('mix.lock', 'mix.exs') }}
restore-keys: deps-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-

- name: Cache build
uses: actions/cache@v4
with:
path: _build
key: build-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('mix.lock', 'mix.exs') }}
restore-keys: build-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-

- name: Build escript
run: |
Expand Down
65 changes: 65 additions & 0 deletions .github/workflows/sync-behavior-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Sync Behavior Coverage

on:
pull_request:
branches: [main]

permissions:
contents: write

jobs:
sync:
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository

steps:
- name: Checkout PR branch
uses: actions/checkout@v6
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
otp-version: "27.3"
elixir-version: "1.19"

- name: Cache deps
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-dev-otp27.3-elixir1.19-${{ hashFiles('mix.lock', 'mix.exs') }}
restore-keys: ${{ runner.os }}-mix-dev-otp27.3-elixir1.19-

- name: Install dependencies
run: mix deps.get

- name: Compile
run: mix compile --warnings-as-errors

- name: Regenerate language coverage
run: mix codeqa.sample_report --apply-languages

- name: Regenerate scalar vectors
run: mix codeqa.sample_report --apply-scalars

- name: Check for YAML drift
id: diff
run: |
if git diff --quiet priv/combined_metrics/; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi

- name: Commit and push updated YAMLs
if: steps.diff.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add priv/combined_metrics/*.yml
git commit -m "chore(combined-metrics): sync language coverage and scalar vectors [skip ci]"
git push
9 changes: 6 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,27 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up Elixir
id: beam
uses: erlef/setup-beam@v1
with:
otp-version: "27.3"
elixir-version: "1.19"

- name: Cache deps
id: mix-cache
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-${{ hashFiles('mix.lock') }}
restore-keys: ${{ runner.os }}-mix-
key: ${{ runner.os }}-mix-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('mix.lock', 'mix.exs') }}
restore-keys: ${{ runner.os }}-mix-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-

- name: Install dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: mix deps.get

- name: Compile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate-issue-links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Validate issue template links
run: |
Expand Down
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@ devenv.lock

# Git worktrees
.worktrees/
docs/plans/
docs/superpowers/
plans/
scripts/*.exs

# Claude Code
.claude/

# Node
node_modules/
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
repos:
- repo: local
hooks:
- id: mix-precommit
name: Mix precommit
entry: devenv shell precommit
language: system
pass_filenames: false
Loading
Loading