whycode-cli 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- whycode_cli-0.2.0/LICENSE +21 -0
- whycode_cli-0.2.0/PKG-INFO +223 -0
- whycode_cli-0.2.0/README.md +195 -0
- whycode_cli-0.2.0/pyproject.toml +90 -0
- whycode_cli-0.2.0/setup.cfg +4 -0
- whycode_cli-0.2.0/src/whycode/__init__.py +3 -0
- whycode_cli-0.2.0/src/whycode/__main__.py +6 -0
- whycode_cli-0.2.0/src/whycode/cli.py +709 -0
- whycode_cli-0.2.0/src/whycode/git_facts.py +450 -0
- whycode_cli-0.2.0/src/whycode/mcp_server.py +204 -0
- whycode_cli-0.2.0/src/whycode/risk_card.py +192 -0
- whycode_cli-0.2.0/src/whycode/scorer.py +55 -0
- whycode_cli-0.2.0/src/whycode/signals.py +389 -0
- whycode_cli-0.2.0/src/whycode/templates/__init__.py +0 -0
- whycode_cli-0.2.0/src/whycode/templates/github-workflow.yml +42 -0
- whycode_cli-0.2.0/src/whycode/templates/pre-commit +7 -0
- whycode_cli-0.2.0/src/whycode_cli.egg-info/PKG-INFO +223 -0
- whycode_cli-0.2.0/src/whycode_cli.egg-info/SOURCES.txt +24 -0
- whycode_cli-0.2.0/src/whycode_cli.egg-info/dependency_links.txt +1 -0
- whycode_cli-0.2.0/src/whycode_cli.egg-info/entry_points.txt +2 -0
- whycode_cli-0.2.0/src/whycode_cli.egg-info/requires.txt +11 -0
- whycode_cli-0.2.0/src/whycode_cli.egg-info/top_level.txt +1 -0
- whycode_cli-0.2.0/tests/test_cli.py +414 -0
- whycode_cli-0.2.0/tests/test_git_facts.py +188 -0
- whycode_cli-0.2.0/tests/test_scorer.py +37 -0
- whycode_cli-0.2.0/tests/test_signals.py +271 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kevin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: whycode-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Tells you what to be afraid of before you touch a file.
|
|
5
|
+
Author: Kevin
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/fangshuor/WhyCode
|
|
8
|
+
Project-URL: Issues, https://github.com/fangshuor/WhyCode/issues
|
|
9
|
+
Keywords: git,code-review,mcp,developer-tools,ai
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: typer>=0.12
|
|
19
|
+
Requires-Dist: rich>=13.7
|
|
20
|
+
Provides-Extra: mcp
|
|
21
|
+
Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
25
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
26
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# WhyCode
|
|
30
|
+
|
|
31
|
+
> **Tells you what to be afraid of before touching a file.**
|
|
32
|
+
|
|
33
|
+
`git blame` answers "who". `git log` answers "what". WhyCode answers the
|
|
34
|
+
question your senior engineer asks before any change:
|
|
35
|
+
|
|
36
|
+
> *"Should I be careful here?"*
|
|
37
|
+
|
|
38
|
+
It mines what your repository already remembers — reverts, hotfixes,
|
|
39
|
+
incident-tagged commits, ghost authors, tightly coupled files, long silences,
|
|
40
|
+
verbatim warnings from past authors — and condenses them into a single **Risk
|
|
41
|
+
Card**. Then it hands that card to you, your CI, or the AI that's about to edit
|
|
42
|
+
the code.
|
|
43
|
+
|
|
44
|
+
## Who is this for?
|
|
45
|
+
|
|
46
|
+
WhyCode is most valuable in moments when *the wrong edit hurts.* If you
|
|
47
|
+
recognise yourself in any of these, it'll pay rent:
|
|
48
|
+
|
|
49
|
+
- **Solo dev returning to a 3-month-old side project** — `whycode why <file>`
|
|
50
|
+
to remember why the weird bit is weird before the AI "fixes" it.
|
|
51
|
+
- **Senior engineer joining an unfamiliar codebase** — `whycode scan` to map
|
|
52
|
+
the load-bearing walls; `whycode why` before each first edit.
|
|
53
|
+
- **AI-paired developer** — install the MCP server and your editor's
|
|
54
|
+
assistant can read invariants and incident history *before* it refactors.
|
|
55
|
+
- **Tech lead reviewing PRs** — `whycode diff` ranks the PR's files by risk
|
|
56
|
+
so attention goes to the scary changes first.
|
|
57
|
+
- **CI / pre-commit gating** — `whycode diff --fail-on history` blocks the
|
|
58
|
+
build when high-risk files change without explanation.
|
|
59
|
+
- **SRE doing a 3am hotfix** — `whycode why <file> --brief` for a one-line
|
|
60
|
+
"what should I be afraid of?" sanity check.
|
|
61
|
+
- **Junior dev wanting to ship without breaking things** — `whycode scan`
|
|
62
|
+
shows where to step lightly.
|
|
63
|
+
|
|
64
|
+
What WhyCode is **not** for: replacing `git blame`, telling you *what*
|
|
65
|
+
changed, or suggesting fixes. It tells you the *why* and the *risk*. You
|
|
66
|
+
decide what to do.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
Once published to PyPI:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install whycode
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
From source (current canonical path):
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install git+https://github.com/fangshuor/WhyCode.git
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Requires Python 3.11+.
|
|
83
|
+
|
|
84
|
+
## 60-second tour
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cd /path/to/your/repo
|
|
88
|
+
|
|
89
|
+
whycode init # one-command setup: CI workflow + pre-commit gate
|
|
90
|
+
whycode why src/some/file.py # the Risk Card for one file
|
|
91
|
+
whycode why src/some/file.py -b # one-line summary (for triage / scripts)
|
|
92
|
+
whycode why src/some/file.py --at <sha> # what did this file's risk look like as of <sha>?
|
|
93
|
+
whycode diff # rank everything you changed vs origin/main
|
|
94
|
+
whycode diff --staged # ditto, for files staged for commit
|
|
95
|
+
whycode diff --fail-on history # CI gate: exit 1 if any file is ≥ READ HISTORY FIRST
|
|
96
|
+
whycode show <sha> # classification + per-file risk for one commit
|
|
97
|
+
whycode timeline src/some/file.py # risk score evolution across the file's history
|
|
98
|
+
whycode honest src/some/file.py # every invariant line, verbatim, untruncated
|
|
99
|
+
whycode scan --top 10 # the riskiest files in the whole repo
|
|
100
|
+
whycode mcp -v # MCP server with tool-call logging
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That's it. No config file, no daemon, no account, no upload.
|
|
104
|
+
|
|
105
|
+
### What a Risk Card looks like
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
╭─ READ HISTORY FIRST score 57/100 ──────────────────────────────╮
|
|
109
|
+
│ src/payment/refund.py (24 commits) │
|
|
110
|
+
│ Latest: hotfix: idempotency token regression │
|
|
111
|
+
│ a3f4b2c1 Mei Chen 2025-09-14 │
|
|
112
|
+
╰──────────────────────────────────────────────────────────────────╯
|
|
113
|
+
HIGH 3 reverts touched this file
|
|
114
|
+
9d2e7a1 reverts c5b81fe; bbf441c reverts 4d29ab0; …
|
|
115
|
+
|
|
116
|
+
MED 2 incident-flagged changes in history
|
|
117
|
+
2 commits matched incident keywords (latest 12 days ago:
|
|
118
|
+
'hotfix: idempotency token regression').
|
|
119
|
+
evidence: a3f4b2c, 7e22a04
|
|
120
|
+
|
|
121
|
+
MED 2 invariants stated by past authors
|
|
122
|
+
> Do not switch to async — v1 clients break. (4d29ab0)
|
|
123
|
+
> Important: keep the legacy header in place. (c5b81fe)
|
|
124
|
+
|
|
125
|
+
→ git show 9d2e7a1 to read the most relevant commit in full
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Score interpretation:
|
|
129
|
+
|
|
130
|
+
| Score | Band | What to do |
|
|
131
|
+
| ------- | ------------------- | --------------------------------------- |
|
|
132
|
+
| 75–100 | HANDLE WITH CARE | Stop. Read the linked commits first. |
|
|
133
|
+
| 50–74 | READ HISTORY FIRST | At least skim the top signal. |
|
|
134
|
+
| 25–49 | WORTH A LOOK | One thing might bite you. Glance. |
|
|
135
|
+
| 0–24 | NO FLAGS | Quiet history — but read the diff anyway. |
|
|
136
|
+
|
|
137
|
+
## The killer use case: hand it to your AI editor
|
|
138
|
+
|
|
139
|
+
WhyCode is also an MCP server. Configure it in any MCP-aware editor or
|
|
140
|
+
assistant, and the host LLM can pull a Risk Card before it edits any file.
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"mcpServers": {
|
|
145
|
+
"whycode": { "command": "whycode", "args": ["mcp"] }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Drop that snippet into your editor's MCP configuration file (location varies
|
|
151
|
+
by editor — check your editor's MCP docs). Then in any chat:
|
|
152
|
+
|
|
153
|
+
> *"Refactor the refund flow."*
|
|
154
|
+
|
|
155
|
+
A well-configured assistant will call `get_risk_profile("src/payment/refund.py")`
|
|
156
|
+
first and read the warnings before it changes a line. Run `whycode mcp -v`
|
|
157
|
+
during development to log every tool call to stderr so you can verify the
|
|
158
|
+
integration is actually live.
|
|
159
|
+
|
|
160
|
+
Tools exposed:
|
|
161
|
+
|
|
162
|
+
- `get_risk_profile(path)` — full Risk Card.
|
|
163
|
+
- `get_file_decisions(path, limit=5)` — only the decision-flavoured signals
|
|
164
|
+
(reverts, incidents, ghost keepers, invariant quotes).
|
|
165
|
+
|
|
166
|
+
## Wire it into git, CI, and your editor
|
|
167
|
+
|
|
168
|
+
WhyCode is most useful when it shows up automatically in the moments you'd
|
|
169
|
+
otherwise forget to look. The fast path:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
whycode init
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
That installs two things:
|
|
176
|
+
|
|
177
|
+
- **`.git/hooks/pre-commit`** — runs `whycode diff --staged --fail-on handle`
|
|
178
|
+
before every commit. HANDLE WITH CARE files can't be touched without an
|
|
179
|
+
explicit `git commit --no-verify`.
|
|
180
|
+
- **`.github/workflows/whycode.yml`** — a GitHub Action that risk-ranks every
|
|
181
|
+
PR's files and fails the build at `--fail-on history` (≥ READ HISTORY FIRST).
|
|
182
|
+
|
|
183
|
+
Tune the `--fail-on` thresholds inside those two files for your repo. Re-run
|
|
184
|
+
with `whycode init --force` to overwrite.
|
|
185
|
+
|
|
186
|
+
**MCP server** — see the next section.
|
|
187
|
+
|
|
188
|
+
## Architecture (three layers, by design)
|
|
189
|
+
|
|
190
|
+
| Layer | What | Network? | API key? |
|
|
191
|
+
| ----- | ------------------------------------------------------------------------ | -------- | -------- |
|
|
192
|
+
| 1 | Deterministic git facts (log, diffstat, revert pairs, author activity) | no | no |
|
|
193
|
+
| 2 | Heuristic signals (reverts, incidents, silence, ghost keeper, coupling, invariants, churn, newborn) | no | no |
|
|
194
|
+
| 3 | LLM polish (optional, opt-in, never on by default) | yes | yes |
|
|
195
|
+
|
|
196
|
+
**Layer 1 + Layer 2 produce the Risk Card you saw above. No model calls, no
|
|
197
|
+
data leaving your machine.** Layer 3 is reserved for natural-language
|
|
198
|
+
summarisation of decisions and is strictly opt-in.
|
|
199
|
+
|
|
200
|
+
## What this is NOT
|
|
201
|
+
|
|
202
|
+
- ❌ Not a SaaS. No accounts, no cloud, no telemetry.
|
|
203
|
+
- ❌ Not a code review bot. WhyCode reports — never prescribes.
|
|
204
|
+
- ❌ Not a "what changed" tool. Plenty of those exist already.
|
|
205
|
+
- ❌ Not language-specific. We read git history, not your AST.
|
|
206
|
+
- ❌ Not a replacement for `git blame`. It's the briefing your senior would
|
|
207
|
+
give you *before* you opened blame.
|
|
208
|
+
|
|
209
|
+
## Developing
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
git clone https://github.com/fangshuor/WhyCode.git
|
|
213
|
+
cd WhyCode
|
|
214
|
+
pip install -e '.[dev,mcp]'
|
|
215
|
+
ruff check . && mypy src/whycode/ && pytest -q
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
See [`ENGINEERING.md`](./ENGINEERING.md) for the engineering charter — the
|
|
219
|
+
durable rules this repo is built under.
|
|
220
|
+
|
|
221
|
+
## License
|
|
222
|
+
|
|
223
|
+
MIT. © 2026 Kevin.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# WhyCode
|
|
2
|
+
|
|
3
|
+
> **Tells you what to be afraid of before touching a file.**
|
|
4
|
+
|
|
5
|
+
`git blame` answers "who". `git log` answers "what". WhyCode answers the
|
|
6
|
+
question your senior engineer asks before any change:
|
|
7
|
+
|
|
8
|
+
> *"Should I be careful here?"*
|
|
9
|
+
|
|
10
|
+
It mines what your repository already remembers — reverts, hotfixes,
|
|
11
|
+
incident-tagged commits, ghost authors, tightly coupled files, long silences,
|
|
12
|
+
verbatim warnings from past authors — and condenses them into a single **Risk
|
|
13
|
+
Card**. Then it hands that card to you, your CI, or the AI that's about to edit
|
|
14
|
+
the code.
|
|
15
|
+
|
|
16
|
+
## Who is this for?
|
|
17
|
+
|
|
18
|
+
WhyCode is most valuable in moments when *the wrong edit hurts.* If you
|
|
19
|
+
recognise yourself in any of these, it'll pay rent:
|
|
20
|
+
|
|
21
|
+
- **Solo dev returning to a 3-month-old side project** — `whycode why <file>`
|
|
22
|
+
to remember why the weird bit is weird before the AI "fixes" it.
|
|
23
|
+
- **Senior engineer joining an unfamiliar codebase** — `whycode scan` to map
|
|
24
|
+
the load-bearing walls; `whycode why` before each first edit.
|
|
25
|
+
- **AI-paired developer** — install the MCP server and your editor's
|
|
26
|
+
assistant can read invariants and incident history *before* it refactors.
|
|
27
|
+
- **Tech lead reviewing PRs** — `whycode diff` ranks the PR's files by risk
|
|
28
|
+
so attention goes to the scary changes first.
|
|
29
|
+
- **CI / pre-commit gating** — `whycode diff --fail-on history` blocks the
|
|
30
|
+
build when high-risk files change without explanation.
|
|
31
|
+
- **SRE doing a 3am hotfix** — `whycode why <file> --brief` for a one-line
|
|
32
|
+
"what should I be afraid of?" sanity check.
|
|
33
|
+
- **Junior dev wanting to ship without breaking things** — `whycode scan`
|
|
34
|
+
shows where to step lightly.
|
|
35
|
+
|
|
36
|
+
What WhyCode is **not** for: replacing `git blame`, telling you *what*
|
|
37
|
+
changed, or suggesting fixes. It tells you the *why* and the *risk*. You
|
|
38
|
+
decide what to do.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
Once published to PyPI:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install whycode
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
From source (current canonical path):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install git+https://github.com/fangshuor/WhyCode.git
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Requires Python 3.11+.
|
|
55
|
+
|
|
56
|
+
## 60-second tour
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd /path/to/your/repo
|
|
60
|
+
|
|
61
|
+
whycode init # one-command setup: CI workflow + pre-commit gate
|
|
62
|
+
whycode why src/some/file.py # the Risk Card for one file
|
|
63
|
+
whycode why src/some/file.py -b # one-line summary (for triage / scripts)
|
|
64
|
+
whycode why src/some/file.py --at <sha> # what did this file's risk look like as of <sha>?
|
|
65
|
+
whycode diff # rank everything you changed vs origin/main
|
|
66
|
+
whycode diff --staged # ditto, for files staged for commit
|
|
67
|
+
whycode diff --fail-on history # CI gate: exit 1 if any file is ≥ READ HISTORY FIRST
|
|
68
|
+
whycode show <sha> # classification + per-file risk for one commit
|
|
69
|
+
whycode timeline src/some/file.py # risk score evolution across the file's history
|
|
70
|
+
whycode honest src/some/file.py # every invariant line, verbatim, untruncated
|
|
71
|
+
whycode scan --top 10 # the riskiest files in the whole repo
|
|
72
|
+
whycode mcp -v # MCP server with tool-call logging
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
That's it. No config file, no daemon, no account, no upload.
|
|
76
|
+
|
|
77
|
+
### What a Risk Card looks like
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
╭─ READ HISTORY FIRST score 57/100 ──────────────────────────────╮
|
|
81
|
+
│ src/payment/refund.py (24 commits) │
|
|
82
|
+
│ Latest: hotfix: idempotency token regression │
|
|
83
|
+
│ a3f4b2c1 Mei Chen 2025-09-14 │
|
|
84
|
+
╰──────────────────────────────────────────────────────────────────╯
|
|
85
|
+
HIGH 3 reverts touched this file
|
|
86
|
+
9d2e7a1 reverts c5b81fe; bbf441c reverts 4d29ab0; …
|
|
87
|
+
|
|
88
|
+
MED 2 incident-flagged changes in history
|
|
89
|
+
2 commits matched incident keywords (latest 12 days ago:
|
|
90
|
+
'hotfix: idempotency token regression').
|
|
91
|
+
evidence: a3f4b2c, 7e22a04
|
|
92
|
+
|
|
93
|
+
MED 2 invariants stated by past authors
|
|
94
|
+
> Do not switch to async — v1 clients break. (4d29ab0)
|
|
95
|
+
> Important: keep the legacy header in place. (c5b81fe)
|
|
96
|
+
|
|
97
|
+
→ git show 9d2e7a1 to read the most relevant commit in full
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Score interpretation:
|
|
101
|
+
|
|
102
|
+
| Score | Band | What to do |
|
|
103
|
+
| ------- | ------------------- | --------------------------------------- |
|
|
104
|
+
| 75–100 | HANDLE WITH CARE | Stop. Read the linked commits first. |
|
|
105
|
+
| 50–74 | READ HISTORY FIRST | At least skim the top signal. |
|
|
106
|
+
| 25–49 | WORTH A LOOK | One thing might bite you. Glance. |
|
|
107
|
+
| 0–24 | NO FLAGS | Quiet history — but read the diff anyway. |
|
|
108
|
+
|
|
109
|
+
## The killer use case: hand it to your AI editor
|
|
110
|
+
|
|
111
|
+
WhyCode is also an MCP server. Configure it in any MCP-aware editor or
|
|
112
|
+
assistant, and the host LLM can pull a Risk Card before it edits any file.
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"mcpServers": {
|
|
117
|
+
"whycode": { "command": "whycode", "args": ["mcp"] }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Drop that snippet into your editor's MCP configuration file (location varies
|
|
123
|
+
by editor — check your editor's MCP docs). Then in any chat:
|
|
124
|
+
|
|
125
|
+
> *"Refactor the refund flow."*
|
|
126
|
+
|
|
127
|
+
A well-configured assistant will call `get_risk_profile("src/payment/refund.py")`
|
|
128
|
+
first and read the warnings before it changes a line. Run `whycode mcp -v`
|
|
129
|
+
during development to log every tool call to stderr so you can verify the
|
|
130
|
+
integration is actually live.
|
|
131
|
+
|
|
132
|
+
Tools exposed:
|
|
133
|
+
|
|
134
|
+
- `get_risk_profile(path)` — full Risk Card.
|
|
135
|
+
- `get_file_decisions(path, limit=5)` — only the decision-flavoured signals
|
|
136
|
+
(reverts, incidents, ghost keepers, invariant quotes).
|
|
137
|
+
|
|
138
|
+
## Wire it into git, CI, and your editor
|
|
139
|
+
|
|
140
|
+
WhyCode is most useful when it shows up automatically in the moments you'd
|
|
141
|
+
otherwise forget to look. The fast path:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
whycode init
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
That installs two things:
|
|
148
|
+
|
|
149
|
+
- **`.git/hooks/pre-commit`** — runs `whycode diff --staged --fail-on handle`
|
|
150
|
+
before every commit. HANDLE WITH CARE files can't be touched without an
|
|
151
|
+
explicit `git commit --no-verify`.
|
|
152
|
+
- **`.github/workflows/whycode.yml`** — a GitHub Action that risk-ranks every
|
|
153
|
+
PR's files and fails the build at `--fail-on history` (≥ READ HISTORY FIRST).
|
|
154
|
+
|
|
155
|
+
Tune the `--fail-on` thresholds inside those two files for your repo. Re-run
|
|
156
|
+
with `whycode init --force` to overwrite.
|
|
157
|
+
|
|
158
|
+
**MCP server** — see the next section.
|
|
159
|
+
|
|
160
|
+
## Architecture (three layers, by design)
|
|
161
|
+
|
|
162
|
+
| Layer | What | Network? | API key? |
|
|
163
|
+
| ----- | ------------------------------------------------------------------------ | -------- | -------- |
|
|
164
|
+
| 1 | Deterministic git facts (log, diffstat, revert pairs, author activity) | no | no |
|
|
165
|
+
| 2 | Heuristic signals (reverts, incidents, silence, ghost keeper, coupling, invariants, churn, newborn) | no | no |
|
|
166
|
+
| 3 | LLM polish (optional, opt-in, never on by default) | yes | yes |
|
|
167
|
+
|
|
168
|
+
**Layer 1 + Layer 2 produce the Risk Card you saw above. No model calls, no
|
|
169
|
+
data leaving your machine.** Layer 3 is reserved for natural-language
|
|
170
|
+
summarisation of decisions and is strictly opt-in.
|
|
171
|
+
|
|
172
|
+
## What this is NOT
|
|
173
|
+
|
|
174
|
+
- ❌ Not a SaaS. No accounts, no cloud, no telemetry.
|
|
175
|
+
- ❌ Not a code review bot. WhyCode reports — never prescribes.
|
|
176
|
+
- ❌ Not a "what changed" tool. Plenty of those exist already.
|
|
177
|
+
- ❌ Not language-specific. We read git history, not your AST.
|
|
178
|
+
- ❌ Not a replacement for `git blame`. It's the briefing your senior would
|
|
179
|
+
give you *before* you opened blame.
|
|
180
|
+
|
|
181
|
+
## Developing
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
git clone https://github.com/fangshuor/WhyCode.git
|
|
185
|
+
cd WhyCode
|
|
186
|
+
pip install -e '.[dev,mcp]'
|
|
187
|
+
ruff check . && mypy src/whycode/ && pytest -q
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
See [`ENGINEERING.md`](./ENGINEERING.md) for the engineering charter — the
|
|
191
|
+
durable rules this repo is built under.
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT. © 2026 Kevin.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "whycode-cli"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Tells you what to be afraid of before you touch a file."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
authors = [{ name = "Kevin" }]
|
|
14
|
+
keywords = ["git", "code-review", "mcp", "developer-tools", "ai"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Software Development :: Version Control :: Git",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"typer>=0.12",
|
|
24
|
+
"rich>=13.7",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
mcp = ["mcp>=1.0"]
|
|
29
|
+
dev = [
|
|
30
|
+
"pytest>=8",
|
|
31
|
+
"pytest-cov>=5",
|
|
32
|
+
"ruff>=0.6",
|
|
33
|
+
"mypy>=1.10",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
whycode = "whycode.cli:app"
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/fangshuor/WhyCode"
|
|
41
|
+
Issues = "https://github.com/fangshuor/WhyCode/issues"
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
where = ["src"]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.package-data]
|
|
47
|
+
whycode = ["templates/*"]
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
line-length = 100
|
|
51
|
+
target-version = "py311"
|
|
52
|
+
src = ["src", "tests"]
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = [
|
|
56
|
+
"E", "F", "W", # pycodestyle, pyflakes
|
|
57
|
+
"I", # isort
|
|
58
|
+
"B", # flake8-bugbear
|
|
59
|
+
"UP", # pyupgrade
|
|
60
|
+
"SIM", # flake8-simplify
|
|
61
|
+
"RUF", # ruff-specific
|
|
62
|
+
]
|
|
63
|
+
ignore = [
|
|
64
|
+
"E501", # line length handled by formatter
|
|
65
|
+
"B008", # typer.Option/Argument as defaults is the canonical pattern
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[tool.ruff.format]
|
|
69
|
+
quote-style = "double"
|
|
70
|
+
indent-style = "space"
|
|
71
|
+
|
|
72
|
+
[tool.mypy]
|
|
73
|
+
python_version = "3.11"
|
|
74
|
+
strict = true
|
|
75
|
+
warn_unused_ignores = true
|
|
76
|
+
warn_redundant_casts = true
|
|
77
|
+
files = ["src/whycode"]
|
|
78
|
+
|
|
79
|
+
[[tool.mypy.overrides]]
|
|
80
|
+
module = ["mcp.*"]
|
|
81
|
+
ignore_missing_imports = true
|
|
82
|
+
|
|
83
|
+
[tool.pytest.ini_options]
|
|
84
|
+
testpaths = ["tests"]
|
|
85
|
+
addopts = "-ra --strict-markers"
|
|
86
|
+
filterwarnings = ["error"]
|
|
87
|
+
|
|
88
|
+
[tool.coverage.run]
|
|
89
|
+
source = ["src/whycode"]
|
|
90
|
+
branch = true
|