Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Before creating any release PR, verify ALL of the following are updated:

- [ ] `Cargo.toml` — version bump
- [ ] All target issues merged to `develop`
- [ ] `cargo test` — all 485+ tests pass
- [ ] `cargo test` — all 495+ tests pass
- [ ] `cargo clippy --all-targets -- -D warnings` — clean
- [ ] `cargo fmt --all -- --check` — clean
- [ ] `cargo build --release` — no errors
Expand Down
12 changes: 7 additions & 5 deletions AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ no managed API, no cloud service. Runs locally against diffs, scans, or branches
```bash
cargo build # Build (debug)
cargo build --release # Build (release)
cargo test # Run all 485 tests
cargo test # Run all 495 tests
cargo clippy --all-targets -- -D warnings # Lint (strict)
cargo fmt --all -- --check # Format check
```
Expand All @@ -33,6 +33,7 @@ src/
│ ├── mod.rs
│ ├── review.rs # cora review (diff-based review)
│ ├── scan.rs # cora scan (full-file scan)
│ ├── debt.rs # cora debt (tech debt report)
│ ├── config_cmd.rs # cora config (show/set/validate)
│ ├── auth.rs # cora auth (API key management)
│ ├── hook_cmd.rs # cora hook (pre-commit hook install/uninstall)
Expand All @@ -56,6 +57,7 @@ src/
│ ├── chunker.rs # Auto-chunking large diffs
│ ├── profiles.rs # Quality profiles (strict/balanced/lax)
│ ├── quality_gate.rs # Quality gate thresholds + pass/fail
│ ├── debt_tracker.rs # Tech debt metrics + trend tracking
│ ├── security_scanner.rs # Static security pattern matching
│ ├── language_analyzer.rs # Language-specific review guidance
│ ├── secrets_scanner.rs # Secret/credential detection
Expand Down Expand Up @@ -98,8 +100,8 @@ src/
## Testing

```bash
cargo test # 485 tests total
# 463 unit tests
cargo test # 495 tests total
# 473 unit tests
# 16 CLI integration tests
# 6 config tests
cargo test --no-verify # Skip pre-commit hooks (avoids timeout in hooks)
Expand Down Expand Up @@ -230,7 +232,7 @@ Missing any = release blocker.
### 1. Code

- [ ] All target issues merged to `develop`
- [ ] `cargo test` — all 453+ tests pass
- [ ] `cargo test` — all 495+ tests pass
- [ ] `cargo clippy --all-targets -- -D warnings` — clean
- [ ] `cargo fmt --all -- --check` — clean
- [ ] `cargo build --release` — no errors
Expand Down Expand Up @@ -300,7 +302,7 @@ When submitting cora to directories, aggregators, or showcases (Trendshift, etc.

### Key Metrics to Mention

- Test count (453+)
- Test count (495+)
- Lines of Rust code (16,800+)
- CI checks (10)
- GitHub Marketplace action published
Expand Down
7 changes: 7 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ Complete command reference for the cora CLI.
| `cora auth remove` | Remove stored API key |
| `cora providers` | List detected AI providers |
| `cora upload-sarif` `<file>` | Upload SARIF to GitHub Code Scanning |
| `cora debt` | Show tech debt report from review history |
| `cora debt --json` | Debt report as JSON (for CI/dashboards) |
| `cora debt --trend` | Quality score trend graph |
| `cora debt --badge` | Shields.io badge JSON endpoint |
| `cora debt --estimate` | Show estimated fix time |
| `cora debt --since v0.4.5` | Filter by git tag or date |
| `cora debt --branch main` | Filter by branch |
| `cora completion` `<shell>` | Generate shell completions (bash/zsh/fish) |
| `cora mcp` | Start MCP server for AI coding agents (Claude Code, Cursor, Windsurf) |
| `cora debt` | Show tech debt report from review history |
Expand Down
41 changes: 41 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,47 @@ quality_gate:

When `quality_gate.enabled` is `false` (default), quality gate is skipped. The existing `--ci` flag and `hook.on_violation` settings continue to work as before.

## Debt Tracking

cora tracks review findings over time and reports quality trends. After each review, a lightweight JSON snapshot is saved to `.cora/history/`. Use `cora debt` to view the aggregated report.

```yaml
debt:
enabled: true # enable auto-save of review snapshots
history_dir: .cora/history # directory for snapshot files
retention_days: 90 # auto-cleanup old snapshots
```

### CLI Usage

```bash
cora debt # show debt report table
cora debt --json # machine-readable JSON
cora debt --trend # quality score trend graph
cora debt --badge # shields.io badge JSON
cora debt --estimate # show estimated fix time
cora debt --since v0.4.5 # filter by git tag or date
```

### Quality Score

Ranges from 0–10 (10 = no issues). Penalties per finding:

| Severity | Penalty |
|----------|--------|
| Critical | -2.0 |
| Major | -1.0 |
| Minor | -0.3 |
| Info | -0.1 |

### Badge Integration

Use `cora debt --badge` output as a shields.io endpoint:

```markdown
[![Quality](https://img.shields.io/endpoint?url=https://example.com/cora-badge.json)]()
```

## Secrets Pre-Scan

cora runs a deterministic secrets scan before the AI review. 12 built-in patterns detect leaked credentials:
Expand Down
45 changes: 45 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,51 @@ cora mcp

See [Configuration → MCP Server](./configuration#mcp-server) for setup guides for Claude Code, Cursor, and other agents.

## Tech Debt Tracking

cora automatically tracks review findings over time, letting you answer "is our codebase getting better or worse?"

```bash
# Show debt report
$ cora debt

# Show trend graph over review history
$ cora debt --trend

# Machine-readable output for CI dashboards
$ cora debt --json

# Shields.io badge JSON (embed in README)
$ cora debt --badge

# Estimated fix time
$ cora debt --estimate

# Filter by date or git tag
$ cora debt --since 2026-06-01
$ cora debt --since v0.4.5

# Filter by branch
$ cora debt --branch develop
```

Snapshots are saved to `.cora/history/` after each review. Configure in `.cora.yaml`:

```yaml
debt:
enabled: true # default
history_dir: .cora/history
retention_days: 90
```

Quality score ranges from 0 (worst) to 10 (best). Each finding reduces the score:
- Critical: -2.0
- Major: -1.0
- Minor: -0.3
- Info: -0.1

Trend indicators: ▼ improving (fewer findings), ► stable, ▲ worsening (more findings).

## Tips

- Use `cora review` with no flags for the fastest pre-commit feedback
Expand Down
38 changes: 35 additions & 3 deletions src/commands/debt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ pub struct DebtOptions {
pub since: Option<String>,
/// Filter: only snapshots for this branch.
pub branch: Option<String>,
/// Generate shields.io badge JSON.
pub badge: bool,
/// Show estimated debt fix time.
pub estimate: bool,
}

/// Execute the `cora debt` subcommand.
Expand Down Expand Up @@ -68,8 +72,29 @@ pub fn execute_debt(opts: &DebtOptions) -> Result<i32> {

let report = debt_tracker::aggregate(&snapshots);

if opts.badge {
let badge = if opts.estimate {
debt_tracker::generate_badge_with_debt(&report)
} else {
debt_tracker::generate_badge(&report)
};
let json = serde_json::to_string(&badge)?;
println!("{json}");
return Ok(EXIT_OK);
}

if opts.json {
let json = serde_json::to_string_pretty(&report)?;
// Add debt estimation to report output
let hours = debt_tracker::estimate_debt_hours(&report.findings);
let mut json_report = serde_json::to_value(&report)?;
if let Some(obj) = json_report.as_object_mut() {
obj.insert("estimated_debt_hours".to_string(), serde_json::json!(hours));
obj.insert(
"estimated_debt_human".to_string(),
serde_json::json!(debt_tracker::format_debt_hours(hours)),
);
}
let json = serde_json::to_string_pretty(&json_report)?;
println!("{json}");
return Ok(EXIT_OK);
}
Expand All @@ -79,7 +104,7 @@ pub fn execute_debt(opts: &DebtOptions) -> Result<i32> {
println!();
}

print_debt_table(&report);
print_debt_table(&report, opts.estimate);

Ok(EXIT_OK)
}
Expand Down Expand Up @@ -148,7 +173,7 @@ fn resolve_tag_date(tag: &str) -> Option<chrono::DateTime<chrono::Utc>> {
}

/// Print the debt report as a terminal table.
fn print_debt_table(report: &debt_tracker::DebtReport) {
fn print_debt_table(report: &debt_tracker::DebtReport, show_estimate: bool) {
let mut out = Vec::new();

// Header
Expand Down Expand Up @@ -199,6 +224,13 @@ fn print_debt_table(report: &debt_tracker::DebtReport) {
)
.unwrap();

// Debt estimation
if show_estimate {
let hours = debt_tracker::estimate_debt_hours(&report.findings);
let human = debt_tracker::format_debt_hours(hours);
writeln!(out, " Est. Debt: {}", human.yellow()).unwrap();
}

// Severity breakdown
writeln!(out).unwrap();
writeln!(out, " {}", "Severity Breakdown:".white().bold()).unwrap();
Expand Down
Loading
Loading