Skip to content

Commit b8af2a8

Browse files
committed
feat(cli): improve first-run activation
1 parent 59a4cf7 commit b8af2a8

8 files changed

Lines changed: 201 additions & 107 deletions

File tree

README.md

Lines changed: 74 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<h1 align="center">Reforge</h1>
66

77
<p align="center">
8-
Evidence-backed structural analysis for codebases changing faster than they can be reviewed.
8+
Find structural drift before it becomes the next refactor.
99
</p>
1010

1111
<p align="center">
@@ -15,156 +15,129 @@
1515
<a href="https://lylemi.github.io/Reforge/"><img alt="Documentation" src="https://img.shields.io/badge/docs-read-1556ad"></a>
1616
</p>
1717

18-
Reforge is a local CLI that shows maintainers where a codebase is becoming
19-
harder to change. It finds duplicated implementations, oversized
20-
responsibilities, dependency tangles, and architecture drift across the whole
21-
repository—including patterns introduced gradually by coding agents.
18+
Reforge is a local CLI for repository-level code review. It finds duplicated
19+
implementations, oversized responsibilities, dependency tangles, and
20+
architecture drift—including patterns introduced gradually by coding agents.
2221

23-
It does not assign an opaque health score or ask you to trust a generated
24-
summary. Every finding includes the source locations, measurements, and rule
25-
that produced it. Every report also records what Reforge could and could not
26-
analyze.
22+
Every finding identifies its rule and relevant source locations, with
23+
measurements or a value-flow witness when the rule produces them. Coverage
24+
records what Reforge could and could not analyze. Reforge does not upload source
25+
code, assign a health score, or claim that a finding is a bug.
2726

2827
<p align="center">
29-
<a href="https://lylemi.github.io/Reforge/playground/"><strong>See the agent-code Playground →</strong></a>
28+
<a href="https://lylemi.github.io/Reforge/playground/"><strong>Try the agent-code Playground →</strong></a>
3029
&nbsp;·&nbsp;
31-
<a href="https://lylemi.github.io/Reforge/sample/"><strong>Explore Reforge's self-analysis report →</strong></a>
30+
<a href="https://lylemi.github.io/Reforge/sample/"><strong>Open an example report →</strong></a>
3231
</p>
3332

34-
## See the evidence behind a finding
35-
36-
This finding came from Reforge analyzing its own report application:
37-
38-
```text
39-
Function readability: ReportView in web/report-app/src/reportApp.tsx
40-
41-
Rule: reforge.codebase.complex_function
42-
Location: web/report-app/src/reportApp.tsx:33
43-
Measurement: estimated complexity 15 (threshold 14)
44-
Guidance: Reduce the function to a clear sequence of named responsibilities.
45-
```
46-
47-
The location makes the finding inspectable. The measurement explains why it
48-
was reported. The threshold can be tuned, and a legitimate exception can be
49-
suppressed with its reason preserved. Reforge makes the case for review; it
50-
does not pretend that a measurement can decide the refactor for you.
51-
52-
## Get started
33+
## Quick start
5334

5435
Install the latest release on Linux or macOS:
5536

5637
```sh
5738
curl -fsSL https://raw.githubusercontent.com/LyleMi/Reforge/main/scripts/install.sh | sh
5839
```
5940

60-
On Windows PowerShell:
61-
62-
```powershell
63-
$installer = Join-Path $env:TEMP "install-reforge.ps1"
64-
irm https://raw.githubusercontent.com/LyleMi/Reforge/main/scripts/install.ps1 -OutFile $installer
65-
& $installer
66-
```
67-
68-
Rust users can alternatively build and install the command from crates.io:
41+
Or install only the CLI from crates.io:
6942

7043
```sh
7144
cargo install reforge-cli --locked
7245
```
7346

74-
The crates.io package installs the `reforge` binary only. Use the verified
75-
release installer above when you also want the bundled `reforge-analyze` Codex
76-
skill.
77-
78-
Reforge runs Codebase analysis by default. Its rules begin as opt-in previews,
79-
so adopting Reforge does not immediately impose someone else's definition of
80-
maintainability. Initialize a configuration, then enable a small starter set:
47+
Then analyze a repository:
8148

8249
```sh
83-
reforge init
84-
```
85-
86-
In the generated `reforge.toml`, start with:
87-
88-
```toml
89-
[rules]
90-
enable = [
91-
"reforge.codebase.large_file",
92-
"reforge.codebase.long_function",
93-
"reforge.codebase.dependency_cycle",
94-
"reforge.codebase.similar_functions",
95-
]
50+
reforge analyze .
9651
```
9752

98-
Run the review in your repository or generate a standalone HTML report:
53+
With no configuration, the CLI runs Codebase analysis with four preview
54+
advisories: large files, long functions, dependency cycles, and similar
55+
functions. They are review prompts, not CI failures. Create a versioned starter
56+
configuration to tune or disable them:
9957

10058
```sh
101-
reforge analyze .
59+
reforge init
10260
reforge analyze . --output html --output-file reforge-report.html
10361
```
10462

105-
## Built for repository-level review
63+
Windows PowerShell and pinned-version installation are covered in the
64+
[installation guide](https://lylemi.github.io/Reforge/user-guide.html#install).
10665

107-
| Need | What Reforge provides |
108-
| --- | --- |
109-
| Find change pressure beyond style errors | Project-wide signals for responsibilities, duplication, dependencies, and drift |
110-
| Verify why something was flagged | Source locations, measurements, thresholds, and rule provenance |
111-
| Trust an empty report appropriately | Coverage receipts and explicit analysis limitations |
112-
| Keep an accepted refactor from regressing | Reproducible baselines and CI gates for new or changed findings |
113-
| Keep source code private | Local analysis with no uploads or telemetry |
114-
115-
Reforge complements compilers, linters, and security scanners. Its job is not
116-
to prove correctness or find vulnerabilities; it identifies structural
117-
pressure that deserves a maintainer's judgment before the next refactor.
118-
119-
## What Codebase finds
66+
## What it finds
12067

12168
| Area | Examples |
12269
| --- | --- |
123-
| **Responsibilities** | Large files, long or complex functions, deep nesting, broad public surfaces |
124-
| **Duplication** | Similar functions, repeated literals, repeated test setup, overlapping type shapes |
125-
| **Architecture drift** | Dependency cycles, generic buckets, parallel implementations, boundary bypasses |
126-
| **Repository consistency** | Naming drift, stale compatibility paths, TODO/FIXME clusters |
70+
| Responsibilities | Large files, long or complex functions, deep nesting, broad public surfaces |
71+
| Duplication | Similar functions, repeated literals, repeated test setup, overlapping type shapes |
72+
| Architecture drift | Dependency cycles, generic buckets, parallel implementations, boundary bypasses |
73+
| Repository consistency | Naming drift, stale compatibility paths, TODO/FIXME clusters |
74+
75+
Codebase analysis supports Rust, JavaScript, TypeScript/TSX, Vue, Python, Go,
76+
Java, C#, Kotlin, PHP, Ruby, Bash, and PowerShell. Dependency rules also
77+
recognize C and C++.
12778

128-
Each finding points to a concrete subject and includes the rule, source locations, and measurements that produced it. Coverage shows which languages and capabilities were actually observed. Reforge does not turn these signals into a health score, severity, or defect prediction—the decision stays with the reviewer.
79+
## What a finding contains
12980

130-
Codebase supports Rust, JavaScript, TypeScript/TSX, Vue, Python, Go, Java, C#, Kotlin, PHP, Ruby, Bash, and PowerShell. Dependency rules also recognize C and C++.
81+
```text
82+
Implementation duplication: 3 related items
83+
84+
Rule: reforge.codebase.shadowed_abstraction
85+
Locations: forms/legacy_email_validator.py:1
86+
forms/signup_email_validator.py:1
87+
shared/email_validator.py:1
88+
Measurement: group size 3 (threshold 3)
89+
Guidance: Consolidate shared behavior or make separate variants explicit.
90+
```
13191

132-
Analysis runs locally. Reforge does not upload source code or collect telemetry.
92+
The evidence makes a finding inspectable; it does not decide the refactor for
93+
you. An empty report is meaningful only for the languages, capabilities, and
94+
rules marked as observed in Coverage.
13395

134-
## Use it in CI
96+
## Automate review
13597

136-
Keep configuration in `reforge.toml`, review a JSON report as a baseline, then gate new or changed policy findings:
98+
Export JSON or SARIF for CI and code-scanning integrations:
13799

138100
```sh
139-
reforge analyze . --output json --output-file current.json \
140-
--baseline reforge-baseline.json --gate new --reproducible
101+
reforge analyze . --output sarif --output-file reforge.sarif --reproducible
141102
```
142103

143-
Rules begin as opt-in previews. This keeps adoption deliberate: enable the signals that fit your codebase, review their evidence, and enforce only the policies your team has accepted.
104+
All current core rules are preview and advisory-only. The `--gate` options apply
105+
only to rules that later satisfy Reforge's calibration contract, become stable,
106+
and are explicitly enforced; preview findings do not fail CI.
107+
108+
## Advanced Dataflow analysis
109+
110+
Dataflow is opt-in and intended for exact value-path and declared-boundary
111+
inspection:
112+
113+
```sh
114+
reforge analyze . --analysis dataflow --output json --reproducible
115+
reforge analyze . --analysis codebase --analysis dataflow --reproducible
116+
```
144117

145-
## Learn more
118+
See the [Dataflow guide](docs/dataflow.md) for its configuration and coverage
119+
limits.
146120

147-
- [Documentation](https://lylemi.github.io/Reforge/) — start here for installation, configuration, and report interpretation
148-
- [Codebase guide](docs/analyses.md) — understand what is analyzed and how to review findings
149-
- [Rule reference](docs/rule-cards.md) — see every available signal and its intended limits
150-
- [Configuration reference](docs/configuration.md) — tune scope, thresholds, policies, and suppressions
151-
- [Contributing](docs/contributing.md) — build and test Reforge locally
121+
## Documentation
152122

153-
Reforge also includes an advanced, opt-in [Dataflow analysis](docs/dataflow.md) for exact value-path and boundary-policy inspection.
123+
- [User guide](https://lylemi.github.io/Reforge/user-guide.html)
124+
- [Codebase analysis](docs/analyses.md)
125+
- [Rule reference](docs/rule-cards.md)
126+
- [Configuration reference](docs/configuration.md)
127+
- [Contributing](docs/contributing.md)
154128

155129
## Development
156130

157-
Reforge is a Rust 2024 workspace. Run the full validation suite with:
131+
Reforge is a Rust 2024 workspace. Run the complete validation gate with:
158132

159133
```sh
160-
cargo fmt --all -- --check
161-
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
162-
cargo test --locked --workspace --all-targets --all-features
134+
scripts/check-ci.sh
163135
```
164136

165-
Run the complete Linux CI gate locally, or install it as a pre-push hook:
137+
Or run the core checks directly:
166138

167139
```sh
168-
scripts/check-ci.sh
169-
scripts/install-git-hooks.sh
140+
cargo fmt --all -- --check
141+
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
142+
cargo test --locked --workspace --all-targets --all-features
170143
```

crates/reforge-output/src/human.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,31 @@ fn write_human_coverage(
102102
}
103103
}
104104
}
105+
write_human_rules(writer, coverage)?;
106+
Ok(())
107+
}
108+
109+
fn write_human_rules(
110+
writer: &mut impl Write,
111+
coverage: &reforge_schema::AnalysisCoverage,
112+
) -> Result<()> {
105113
for (rule, execution) in &coverage.rules {
106-
write_human_rule(writer, rule, execution)?;
114+
if execution.enabled_source != reforge_schema::RuleActivation::Disabled {
115+
write_human_rule(writer, rule, execution)?;
116+
}
117+
}
118+
let disabled = coverage
119+
.rules
120+
.values()
121+
.filter(|execution| {
122+
execution.enabled_source == reforge_schema::RuleActivation::Disabled
123+
})
124+
.count();
125+
if disabled > 0 {
126+
writeln!(
127+
writer,
128+
" {disabled} disabled rule(s) omitted; JSON and YAML retain full coverage"
129+
)?;
107130
}
108131
Ok(())
109132
}

crates/reforge-output/src/tests.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,42 @@ fn human_output_includes_language_capability_receipts() {
151151
assert!(output.contains("capability direct_calls: Partial"));
152152
assert!(output.contains("unresolved_direct_call (1): one call could not be resolved"));
153153
}
154+
155+
#[test]
156+
fn human_output_summarizes_disabled_rules_without_losing_machine_coverage() {
157+
let mut report = report_with_issue();
158+
report.coverage.get_mut("codebase").unwrap().rules = BTreeMap::from([
159+
(
160+
"reforge.codebase.large_file".into(),
161+
reforge_schema::RuleExecution {
162+
maturity: "preview".into(),
163+
enabled_source: reforge_schema::RuleActivation::Enable,
164+
status: CoverageStatus::Observed,
165+
observations: Vec::new(),
166+
limitations: Vec::new(),
167+
},
168+
),
169+
(
170+
"reforge.codebase.long_function".into(),
171+
reforge_schema::RuleExecution {
172+
maturity: "preview".into(),
173+
enabled_source: reforge_schema::RuleActivation::Disabled,
174+
status: CoverageStatus::Observed,
175+
observations: Vec::new(),
176+
limitations: Vec::new(),
177+
},
178+
),
179+
]);
180+
report.provenance = default_provenance(&report.coverage, &report.issues);
181+
182+
let mut output = Vec::new();
183+
write_report(&mut output, &report, OutputFormat::Human).unwrap();
184+
let output = String::from_utf8(output).unwrap();
185+
186+
assert!(output.contains("rule reforge.codebase.large_file"));
187+
assert!(!output.contains("rule reforge.codebase.long_function"));
188+
assert!(output.contains("1 disabled rule(s) omitted"));
189+
190+
let json = serde_json::to_value(&report).unwrap();
191+
assert!(json["coverage"]["codebase"]["rules"]["reforge.codebase.long_function"].is_object());
192+
}

docs/configuration.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ exclude-tests = false
1616
ignore-paths = []
1717

1818
[rules]
19-
enable = []
19+
enable = [
20+
"reforge.codebase.large_file",
21+
"reforge.codebase.long_function",
22+
"reforge.codebase.dependency_cycle",
23+
"reforge.codebase.similar_functions",
24+
]
2025
disable = []
2126
enforce = []
2227

@@ -46,8 +51,9 @@ min-modules = 3
4651
Rule arrays require complete IDs. Duplicate, conflicting, and unknown IDs are
4752
errors. `enforce` implies enable and accepts only stable rules. Experimental
4853
rules remain internal observations; preview rules are off unless enabled and
49-
can only produce advisory Issues. Only explicitly enforced stable rules produce
50-
policy Issues or participate in a gate.
54+
can only produce advisory Issues. The CLI starter configuration enables four
55+
preview rules explicitly. Only enforced stable rules produce policy Issues or
56+
participate in a gate.
5157

5258
Each Dataflow policy is single-language and names exact sink declarations:
5359

docs/rule-cards.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ All rules below are currently `preview`, `default_enabled = false`,
1111
`validation_basis = fixture`, semantic version `1.0.0`, and ineligible for
1212
enforcement. A language can become stable only through the audited calibration
1313
protocol in `calibration/README.md`; other languages remain preview.
14+
The CLI's starter configuration explicitly enables four of these rules as
15+
advisories; this does not change their manifest maturity or default-enabled
16+
state.
1417

1518
| Rule | Claim / inspection question | Capability | Positive and negative fixtures | Legitimate exceptions |
1619
| --- | --- | --- | --- | --- |

docs/user-guide.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ Run the default Codebase analysis:
3737
reforge analyze . --reproducible
3838
```
3939

40+
Without a configuration file, the CLI enables a small starter set of preview
41+
advisories for large files, long functions, dependency cycles, and similar
42+
functions. They produce review prompts but cannot fail a policy gate. Run
43+
`reforge init` to write the same starter selection to `reforge.toml`, then tune
44+
or disable it for the repository.
45+
4046
Dataflow is explicit. Run it alone or combine both core analyses over one workspace index:
4147

4248
```sh
@@ -70,7 +76,9 @@ reforge analyze . --output json --output-file current.json \
7076
--baseline reforge-baseline.json --gate new --reproducible
7177
```
7278

73-
`--gate all` fails on every current policy Issue. Rules are preview/off by default; enable and enforce the selected rule IDs in versioned `reforge.toml`.
79+
`--gate all` fails on every current policy Issue. Most rules remain preview/off;
80+
enable selected preview rules as advisories in versioned `reforge.toml`. Only
81+
stable rules can be enforced as policy.
7482

7583
## Configuration and rules
7684

0 commit comments

Comments
 (0)