@davesheffer/hunch 1.4.0 β 1.4.2
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.
- package/README.md +26 -308
- package/dist/core/pipeline.js +14 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,326 +1,44 @@
|
|
|
1
1
|
# π§ Hunch β Architectural Conformance for AI code
|
|
2
2
|
|
|
3
|
-
[](https://github.com/davesheffer/hunch)
|
|
4
3
|
[](https://www.npmjs.com/package/@davesheffer/hunch)
|
|
5
|
-
[](https://github.com/davesheffer/hunch)
|
|
6
5
|
[](LICENSE)
|
|
7
|
-
[](https://nodejs.org)
|
|
8
|
-
[](https://modelcontextprotocol.io)
|
|
9
|
-
|
|
10
|
-
> **Your repo remembers *what* changed. Hunch makes it remember *why*** β the decisions, the
|
|
11
|
-
> trade-offs, the bugs you already paid for β and keeps every AI coding session consistent with them.
|
|
12
|
-
> When a change would quietly undo something you decided on purpose, Hunch notices and shows the
|
|
13
|
-
> receipt: which decision, and which past bug it protects you from. A linter checks *patterns*;
|
|
14
|
-
> Hunch understands your *architecture* (layering, must-reach, dependency direction) β deterministically,
|
|
15
|
-
> from a **git-native** graph, across any MCP assistant.
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm i -g @davesheffer/hunch
|
|
19
|
-
cd your-repo && hunch init # 2 minutes; advisory by default β nothing blocks until you say so
|
|
20
|
-
|
|
21
|
-
# teach it one architectural rule, in plain words β with the why
|
|
22
|
-
hunch conform --add "controllers never reach the DB directly β go through the service layer" \
|
|
23
|
-
--assert not-calls --subject listOrders --object dbQuery --why "the Mar-2025 N+1 incident"
|
|
24
|
-
|
|
25
|
-
hunch conform # β
deterministic check β and when you're ready, --strict wires it into CI
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
> Here's the moment it earns its keep: an AI "optimizes" your controller to query the DB directly.
|
|
29
|
-
> Pattern tools stay **green** β it's a legitimate internal import, no bad pattern to match.
|
|
30
|
-
> Hunch quietly flags it: *"listOrders now reaches dbQuery Β· why this matters: the Mar-2025 N+1
|
|
31
|
-
> incident Β· protects against a repeat of bug_0317."* You decide what happens next β advisory
|
|
32
|
-
> shows the note, **strict** (opt-in) holds the change. Watch the whole loop in 15 seconds:
|
|
33
|
-
> [`demo/architectural-conformance.sh`](demo/architectural-conformance.sh).
|
|
34
|
-
|
|
35
|
-
**It helps twice β before the change, and after:**
|
|
36
|
-
- **Before** β the recorded rule rides into the AI's context. In a reproducible benchmark ([`bench/`](bench/architectural-conformance.md): n=90, three models, 3 invariant classes), that alone cut architectural drift **58% β 16%** (one model: **67% β 0%**).
|
|
37
|
-
- **After** β reminders help, but models still drift even when told (the same benchmark measured it). So a deterministic check β [`hunch check`](https://hunch-pi.vercel.app/docs#ci) on commit or in your PR gate β catches what reminders miss, always with the receipt, **no model in the loop**. Advisory first; you choose the [firmness](https://hunch-pi.vercel.app/docs#firmness).
|
|
38
|
-
|
|
39
|
-
<sub>Works with **Claude Code, Cursor, Copilot, Windsurf & Google Antigravity** from one shared, git-native graph.</sub>
|
|
40
|
-
|
|
41
|
-
### π **[Read the full documentation β hunch-pi.vercel.app/docs](https://hunch-pi.vercel.app/docs)**
|
|
42
|
-
|
|
43
|
-
The docs site is the complete reference β setup, every CLI command and MCP tool, the
|
|
44
|
-
guards, troubleshooting. This README is the tour. Jump to:
|
|
45
|
-
[Install](https://hunch-pi.vercel.app/docs#install) Β·
|
|
46
|
-
[MCP setup](https://hunch-pi.vercel.app/docs#mcp) Β·
|
|
47
|
-
[Firmness](https://hunch-pi.vercel.app/docs#firmness) Β·
|
|
48
|
-
[CLI reference](https://hunch-pi.vercel.app/docs#cli) Β·
|
|
49
|
-
[Troubleshooting](https://hunch-pi.vercel.app/docs#doctor)
|
|
50
|
-
|
|
51
|
-
> π **v1.3.0** β retrieval that follows the graph: live decisions outrank superseded ones, human-vouched outrank drafts, and a query that hits history surfaces the topic's *current* decision (Recall@10 90β100% on the committed golden set). Plus `hunch now` + the roadmap-as-proposed-decisions, session-deduped hook grounding (~100Γ smaller on repeats), content-matched blocking gates, and duplicate auto-drafts skipped before the LLM is called. [Full changelog β](https://hunch-pi.vercel.app/changelog)
|
|
52
|
-
|
|
53
|
-
## The problem
|
|
54
|
-
|
|
55
|
-
Every AI coding session starts from zero. The model re-reads your code, re-guesses the
|
|
56
|
-
intent, and happily "fixes" the thing you deliberately did last month β because the
|
|
57
|
-
*reasoning* behind the code lives in PRs, Slack, and people's heads, not in the repo.
|
|
58
|
-
|
|
59
|
-
**Hunch** captures that reasoning as a **byproduct of normal work** β commits and test
|
|
60
|
-
failures β stores it as a git-tracked graph next to your code, and feeds it back to
|
|
61
|
-
Claude Code so every session is grounded in the decisions, bugs, and invariants that
|
|
62
|
-
came before. Local-first, no documentation toil, no SaaS.
|
|
63
6
|
|
|
64
|
-
|
|
7
|
+
> **Your repo remembers *what* changed. Hunch makes it remember *why*** β and keeps every
|
|
8
|
+
> AI coding session consistent with the decisions, trade-offs, and bugs you already paid for.
|
|
9
|
+
> Local-first, git-native, works with Claude Code, Cursor, Copilot, Windsurf & Codex.
|
|
65
10
|
|
|
66
|
-
|
|
67
|
-
commit / test failure .hunch/ (git-tracked JSON) Claude Code
|
|
68
|
-
βββββββββββββββββββββββββ ββββββββββββββββββββββββββββ ββββββββββββββββ
|
|
69
|
-
β post-commit hook ββββΌβββββββββΆβ Decisions (why a change) ββββββββββΆβ MCP tools β
|
|
70
|
-
β record-bug ββββΌβββββββββΆβ Bugs (root causes) β read β /hunch-* cmds β
|
|
71
|
-
β structured diff + β write β Constraints(invariants) βββββββββββ CLAUDE.md β
|
|
72
|
-
β Claude (or heuristic) β β Components / Symbols/Edges β β CLI β
|
|
73
|
-
βββββββββββββββββββββββββ ββββββββββββββββββββββββββββ ββββββββββββββββ
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
- **Index** (no LLM): Hunch maps your repo β how functions, files, and components
|
|
77
|
-
connect β so it can see the ripple effect of any change.
|
|
78
|
-
- **Learn**: each commit becomes a structured **Decision** (an ADR); a failing test
|
|
79
|
-
becomes a **Bug** with its likely cause; recurring or severe bugs are promoted
|
|
80
|
-
into **Constraints** (do-not-break rules) and flag the riskiest parts of the code.
|
|
81
|
-
- **Ground**: any MCP assistant reads it through an **MCP server**, an auto-maintained
|
|
82
|
-
**`CLAUDE.md`**, and **slash commands** β every answer cites `provenance`
|
|
83
|
-
(source + confidence + evidence), so nothing is a blind assertion.
|
|
84
|
-
|
|
85
|
-
β Concepts in depth: [the reasoning graph](https://hunch-pi.vercel.app/docs#graph) Β·
|
|
86
|
-
[provenance](https://hunch-pi.vercel.app/docs#provenance) Β·
|
|
87
|
-
[time-travel](https://hunch-pi.vercel.app/docs#time-travel)
|
|
88
|
-
|
|
89
|
-
## Why Hunch is different
|
|
90
|
-
|
|
91
|
-
"Memory for coding agents" is getting crowded, but most of it is a *server-side, ephemeral,
|
|
92
|
-
single-vendor* RAG cache over your current code. Hunch is the opposite on every axis β and that
|
|
93
|
-
combination is the moat:
|
|
94
|
-
|
|
95
|
-
| | Typical agent memory | **Hunch** |
|
|
96
|
-
|---|---|---|
|
|
97
|
-
| **Storage** | server-side / a vendor's cloud | **git-tracked JSON in your repo** β diff it, review it in PRs, sync it over `git push` |
|
|
98
|
-
| **Lifetime** | the session; often auto-expiring | the **lifetime of the codebase** β non-destructive supersede/veto keeps the *why-it-changed* trail |
|
|
99
|
-
| **Clients** | one vendor's agent | **client-agnostic** β one `.hunch/` graph serves Claude Code, Cursor, Copilot & Windsurf via MCP |
|
|
100
|
-
| **What's stored** | opaque extracted "facts" | **structured ADRs** β decisions with rejected-alternatives, bug lineage, and invariants |
|
|
101
|
-
| **Enforcement** | advisory / just-in-time hints | **fail-closed guards** β no model in the block path; a commit fails only on a rule you've vouched for |
|
|
102
|
-
| **Trust** | take it on faith | **provenance on every record** (source + confidence + evidence) and a measurable retrieval signal (`hunch eval`) |
|
|
103
|
-
|
|
104
|
-
The short version: **git tracks *what* changed; Hunch tracks *why*** β locally, durably, and under
|
|
105
|
-
your control, with guards that actually hold the line instead of just suggesting.
|
|
106
|
-
|
|
107
|
-
## Decision-grounding: memory that stays true to the doc
|
|
108
|
-
|
|
109
|
-
Architectural Conformance keeps the *code* honest to the graph (**graph β code**). Decision-grounding
|
|
110
|
-
is its complement β it keeps your *docs* honest to the graph (**doc β graph**). A comment or a README
|
|
111
|
-
says one thing; the decision that actually governs the file says another. Both are "memory that stays
|
|
112
|
-
true"; you want both.
|
|
113
|
-
|
|
114
|
-
A decision can be anchored to a **topic** (e.g. `"auth.session"`), and a topic always has one live
|
|
115
|
-
answer: the **current** decision, its **history**, and what was **rejected** along the way. Existing
|
|
116
|
-
graphs are unaffected until you opt in.
|
|
117
|
-
|
|
118
|
-
- **Read-time grounding.** Before the AI edits a file β or a markdown doc like `AGENTS.md` β it's told
|
|
119
|
-
which decision is *current* (follow the graph, not a stale doc) and what was **rejected**, so it
|
|
120
|
-
doesn't re-add the approach you already ruled out.
|
|
121
|
-
- **Drift, caught deterministically.** Prose or a file still describing a **superseded** decision is
|
|
122
|
-
flagged in `hunch doctor`, and `hunch drift` exits non-zero so CI can gate on it. It only fires on
|
|
123
|
-
explicit anchors β never a semantic guess.
|
|
124
|
-
- **Capture, interviewed.** `/capture` walks a decision to a resolved state β topic, rationale, and
|
|
125
|
-
rejected alternatives β before it's written, and the graph refuses to hold **two live decisions on
|
|
126
|
-
one topic**. `hunch reconcile-topics` catches the one case a git merge can create, for human resolution.
|
|
127
|
-
- **`hunch heal`** + the **`/heal`** slash command do **read-only** docβgraph reconciliation β they show
|
|
128
|
-
exactly what disagrees and never rewrite your prose silently.
|
|
129
|
-
- **`hunch wiki`** β a generated component wiki + **specs ledger** rendered *from* the graph. Every repo
|
|
130
|
-
doc is graded deterministically (β
grounded / β stale / β» unverified); a stale doc is **adopted** β a
|
|
131
|
-
wiki-managed copy re-pinned to the current decision with the correction inline, while your original
|
|
132
|
-
file is never touched (and the copy retires once you heal the original). Freshness is hash-gated:
|
|
133
|
-
`hunch drift` names exactly which pages went stale, `hunch wiki --heal` regenerates only those, and
|
|
134
|
-
`hunch wiki --check` is the CI gate. With a private overlay, `hunch wiki --private` renders the FULL
|
|
135
|
-
graph into the overlay repo β nothing private ever lands in the committed wiki.
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
npm run build && bash demo/wiki.sh # watch a spec go stale, get adopted + healed, then released
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
β [docs](https://hunch-pi.vercel.app/docs#grounding)
|
|
142
|
-
|
|
143
|
-
## Getting started
|
|
11
|
+
## Install
|
|
144
12
|
|
|
145
13
|
```bash
|
|
146
|
-
npm
|
|
147
|
-
cd your-repo
|
|
148
|
-
hunch
|
|
149
|
-
hunch backfill --since 90d # cold start: seed decisions from recent git history
|
|
150
|
-
hunch why src/auth/session.ts # β¦then ask your assistant: "why is X built this way?"
|
|
151
|
-
hunch structure src/auth # the map, from the graph β no grep rounds
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**Claude Code users β one-step plugin install** (MCP tools + `/hunch:capture`, `/hunch:heal`, `/hunch:why`, `/hunch:fix`, `/hunch:fragile`):
|
|
155
|
-
|
|
156
|
-
```text
|
|
157
|
-
/plugin marketplace add davesheffer/hunch
|
|
158
|
-
/plugin install hunch@hunch
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Then `hunch init` in each repo you want remembered (the plugin brings the tools; init builds the graph + hooks).
|
|
162
|
-
|
|
163
|
-
`hunch init` scaffolds `.hunch/`, indexes the repo, installs the git hooks,
|
|
164
|
-
writes `.mcp.json` + slash commands + an auto-maintained `CLAUDE.md`, and wires up **every
|
|
165
|
-
detected assistant** (Claude Code, Cursor, VS Code/Copilot, Windsurf, Codex, Google Antigravity) to the same
|
|
166
|
-
graph β merging idempotently into existing files. **Reload your assistant in the repo**
|
|
167
|
-
afterward to pick up the `hunch_*` tools. Each teammate runs `hunch init` once; the
|
|
168
|
-
`.hunch/` content is shared via git.
|
|
169
|
-
|
|
170
|
-
> Synthesis is billed to **your coding-assistant subscription** (Claude/Codex/Cursor CLI),
|
|
171
|
-
> **never** a pay-per-token API key β and falls back to a deterministic heuristic if no CLI
|
|
172
|
-
> is present. Details: [Synthesis & billing](https://hunch-pi.vercel.app/docs#synthesis).
|
|
173
|
-
>
|
|
174
|
-
> **Deep Synthesis** (`backfill --deep` / `sync --deep`): gathers several independent takes on a
|
|
175
|
-
> change and reconciles them into one more-trustworthy note β trusting it more when they agree.
|
|
176
|
-
> Add `--verify` to fact-check the note against the commit and drop anything it doesn't support.
|
|
177
|
-
> It always stays *advisory* until you confirm it. Subscription-only; falls back to a single
|
|
178
|
-
> draft when only one assistant is available.
|
|
179
|
-
> On Windows, prefer `hunch init` over a global `claude mcp add`; if tools don't appear,
|
|
180
|
-
> `hunch doctor` heals it ([why](https://hunch-pi.vercel.app/docs#windows)).
|
|
181
|
-
|
|
182
|
-
**Full walkthrough β** [Getting started](https://hunch-pi.vercel.app/docs#install) Β·
|
|
183
|
-
[MCP & assistants](https://hunch-pi.vercel.app/docs#mcp) Β·
|
|
184
|
-
[MCP tools](https://hunch-pi.vercel.app/docs#mcp-tools) Β·
|
|
185
|
-
[slash commands](https://hunch-pi.vercel.app/docs#slash) Β·
|
|
186
|
-
[the full CLI reference](https://hunch-pi.vercel.app/docs#cli)
|
|
187
|
-
|
|
188
|
-
## Enforcement: memory that holds the line
|
|
189
|
-
|
|
190
|
-
Hunch isn't just recall β it's a set of **guards** that stop the AI (and you) from undoing
|
|
191
|
-
intentional design. All ride the same rails: the pre-edit hook, `hunch check`, the
|
|
192
|
-
`hunch_merge_verdict` MCP tool, and the CI Constraint Guard. How hard they push is one
|
|
193
|
-
committed knob β [**firmness**](https://hunch-pi.vercel.app/docs#firmness)
|
|
194
|
-
(`off` β `advisory` β `firm` β `strict`).
|
|
195
|
-
|
|
196
|
-
### Never Twice β corrections become enforced invariants
|
|
197
|
-
|
|
198
|
-
You tell the agent "no, never call the pay-per-token API here," it complies once, and next
|
|
199
|
-
session it does it again β because the feedback was stored as advisory text. Hunch closes
|
|
200
|
-
that loop: a correction is captured as a first-class **Constraint** (`human_confirmed`) via
|
|
201
|
-
`hunch_record_correction`, and from then on the **same hook + CI guard** hold *every*
|
|
202
|
-
assistant to it. β [docs](https://hunch-pi.vercel.app/docs#never-twice)
|
|
203
|
-
|
|
204
|
-
### Causal Merge Verdict β does this change re-open a closed bug?
|
|
205
|
-
|
|
206
|
-
A diff-only reviewer sees *what* changed; it can't see that the line you're deleting is the
|
|
207
|
-
fix for an incident. Hunch can β `hunch_merge_verdict` replays a diff against the graph and
|
|
208
|
-
returns a cited **BLOCK / WARN / PASS**:
|
|
209
|
-
|
|
210
|
-
```text
|
|
211
|
-
VERDICT: β BLOCK β this change breaks a recorded invariant or re-opens a known bug.
|
|
212
|
-
|
|
213
|
-
β pay() must verify the session before charging β con_pay
|
|
214
|
-
π§ why: "Charge must verify the session first" (dec_pay)
|
|
215
|
-
π guards against: Double-charge on unverified session (bug_β¦)
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
No model in the loop, so it's safe as a merge gate β it blocks only on a high-confidence rule
|
|
219
|
-
you've confirmed, and warns on everything softer. β [docs](https://hunch-pi.vercel.app/docs#merge-verdict)
|
|
220
|
-
|
|
221
|
-
### Decision Guard (Veto) β re-introducing a *rejected* approach is blocked
|
|
222
|
-
|
|
223
|
-
The most expensive reversal is re-adding an approach a decision **rejected** (latency, a
|
|
224
|
-
forbidden dependency) β code that never existed, so a diff reviewer is blind to it. A
|
|
225
|
-
decision remembers what it rejected; re-introduce that approach and Hunch blocks it with
|
|
226
|
-
the receipt of what you rejected and why. β [docs](https://hunch-pi.vercel.app/docs#veto)
|
|
227
|
-
|
|
228
|
-
### Redundancy Guard β "this already exists"
|
|
229
|
-
|
|
230
|
-
An agent works from a *local* context window, so it re-implements a helper that already
|
|
231
|
-
lives three modules over, or re-adds a dependency the codebase already has β sprawl a
|
|
232
|
-
diff-only reviewer can't see, but Hunch's symbol graph can. Add a function or class already
|
|
233
|
-
defined elsewhere and `hunch check` / the CI guard / `hunch_merge_verdict` flag it with the
|
|
234
|
-
existing location. **Advisory** β it never blocks, and it's tuned to stay quiet so a refactor
|
|
235
|
-
that just moves code isn't mistaken for a duplicate. β [docs](https://hunch-pi.vercel.app/docs#redundancy)
|
|
236
|
-
|
|
237
|
-
See also **[Decision-grounding](#decision-grounding-memory-that-stays-true-to-the-doc)** β the doc β graph
|
|
238
|
-
complement: topic anchors, read-time grounding in the pre-edit hook, and a deterministic `anchor-stale`
|
|
239
|
-
drift check (`hunch drift`) that fails CI when a file still points at a superseded decision.
|
|
240
|
-
|
|
241
|
-
Plus the **Regression Guard** (re-adding deliberately-retired code) and the
|
|
242
|
-
**[CI Constraint Guard](https://hunch-pi.vercel.app/docs#ci)** (`hunch ci` β a PR gate that
|
|
243
|
-
comments the affected `con_`/`dec_` ids and fails on a blocking one).
|
|
244
|
-
|
|
245
|
-
Name the actual violation β `record-constraint "β¦" --scope "src/**" --severity blocking
|
|
246
|
-
--forbid-dep "lodash"` β and it blocks the *real* change for the file's whole life, while staying
|
|
247
|
-
quiet on edits that don't break the rule. A comment or string that merely mentions the module can't
|
|
248
|
-
false-positive. None of these are a bypass-proof boundary β deliberate indirection can still route
|
|
249
|
-
around any rule.
|
|
250
|
-
|
|
251
|
-
## Working as a team
|
|
252
|
-
|
|
253
|
-
The `.hunch/` JSON is the **source of truth** β diffable, reviewable in PRs, synced for free
|
|
254
|
-
over `git push` / `pull`. `hunch init` sets things up so concurrent edits from different
|
|
255
|
-
teammates merge cleanly instead of throwing conflict markers, and it's **OS-agnostic** β
|
|
256
|
-
Windows / macOS / Linux teammates share one memory with no per-machine fixups.
|
|
257
|
-
β [docs](https://hunch-pi.vercel.app/docs#team)
|
|
258
|
-
|
|
259
|
-
### Branches & worktrees
|
|
260
|
-
|
|
261
|
-
Memory follows you across every branch and **git worktree**, with no per-worktree setup β a
|
|
262
|
-
fresh `git worktree add` on any branch sees the same decisions, bugs, and invariants. Create one
|
|
263
|
-
already wired in with **`hunch worktree <path> [-b <branch>]`**, or just run `hunch init` / `hunch
|
|
264
|
-
shared` (or `hunch private`) once and every worktree picks it up. Parallel worktrees never corrupt or lose memory, and
|
|
265
|
-
`hunch doctor` confirms a worktree is sharing.
|
|
266
|
-
|
|
267
|
-
Need one **single source of truth** for memory in any repo (private or public)?
|
|
268
|
-
Use **`hunch shared --repo <url>`**. Every capture β decisions, bugs, constraints, runbooks β
|
|
269
|
-
routes to one shared overlay repo and, by default, auto-commits + pushes so teammates/other
|
|
270
|
-
worktrees stay in sync automatically. It also publishes a committed **`.hunch/team.json`**
|
|
271
|
-
pointing at the store, so a fresh clone auto-connects on `hunch init` (agents and CI wire up
|
|
272
|
-
the same way via the MCP server) β everyone, on every branch, resolves the same memory.
|
|
273
|
-
|
|
274
|
-
## Private memory (public repo, private context)
|
|
275
|
-
|
|
276
|
-
Open-source your code without open-sourcing your *reasoning*. **`hunch private`** sets up a
|
|
277
|
-
separate private store in one command: your local queries, guards, and assistants see the
|
|
278
|
-
sensitive decisions β but they're never committed to the public repo, and public outputs (like
|
|
279
|
-
the CI PR comment) **can never contain them, by construction**. Opt-in, default-off; captures are
|
|
280
|
-
auto-committed to the store they land in (opt out with `--no-auto-commit`), and Hunch never
|
|
281
|
-
touches your code branch.
|
|
282
|
-
|
|
283
|
-
Already published a repo *with* its `.hunch/` memory and want it private after the fact?
|
|
284
|
-
**`hunch private --repo <url> --migrate`** moves the existing memory into the private store β
|
|
285
|
-
nothing lost β and leaves the public repo code-only, telling you the one `git` command left to run.
|
|
286
|
-
β [docs](https://hunch-pi.vercel.app/docs#private)
|
|
287
|
-
|
|
288
|
-
## Continuous learning (CI)
|
|
289
|
-
|
|
290
|
-
The decision half of the loop is automatic (the post-commit hook). Light up the bug/constraint
|
|
291
|
-
half by wrapping your test run β it captures failures as **Bugs** (recurrences auto-promote
|
|
292
|
-
**Constraints**) and resolves fixed ones, preserving the runner's exit code:
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
hunch test # runs `npm test`; any runner: hunch test -- pytest -q
|
|
14
|
+
npm i -g @davesheffer/hunch
|
|
15
|
+
cd your-repo && hunch init # 2 minutes; advisory by default β nothing blocks until you say so
|
|
16
|
+
hunch backfill --since 90d # optional: seed memory from recent git history
|
|
296
17
|
```
|
|
297
18
|
|
|
298
|
-
|
|
299
|
-
β [docs](https://hunch-pi.vercel.app/docs#ci)
|
|
19
|
+
Reload your assistant and ask: *"why is X built this way?"* β it answers from the graph, with receipts.
|
|
300
20
|
|
|
301
|
-
##
|
|
21
|
+
## The moment it earns its keep
|
|
302
22
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
23
|
+
An AI "optimizes" your controller to query the DB directly. Linters stay green β no bad
|
|
24
|
+
pattern to match. Hunch flags it: *"listOrders now reaches dbQuery Β· why: the Mar-2025 N+1
|
|
25
|
+
incident Β· protects against bug_0317."* You decide what happens next β advisory shows the
|
|
26
|
+
note; **strict** (opt-in) holds the change.
|
|
306
27
|
|
|
307
|
-
|
|
28
|
+
Measured ([`bench/`](bench/architectural-conformance.md), n=90, three models): recorded rules
|
|
29
|
+
in context cut architectural drift **58% β 16%**. The deterministic check catches the rest β
|
|
30
|
+
no model in the loop.
|
|
308
31
|
|
|
309
|
-
|
|
310
|
-
[Open VSX](https://open-vsx.org/extension/davesheffer/hunch-vscode) β VS Code / Cursor /
|
|
311
|
-
Windsurf / VSCodium) brings the graph into the editor: a tree of decisions / invariants /
|
|
312
|
-
bugs / bug-lineage / fragility / stale records, CodeLens summaries, hover with bug history,
|
|
313
|
-
invariants in the Problems panel, an interactive component graph, and a status-bar invariant
|
|
314
|
-
counter. It reads the committed `.hunch/` JSON directly; writes delegate to the `hunch` CLI.
|
|
32
|
+
## What you get
|
|
315
33
|
|
|
316
|
-
|
|
34
|
+
- **Memory as a byproduct of work** β every commit becomes a decision, failing tests become bug lineage; no documentation chore
|
|
35
|
+
- **Every answer with receipts** β decisions cite the why, the rejected alternatives, and the bug they protect against
|
|
36
|
+
- **Guards that hold the line** β corrections become permanent rules; drift and re-opened bugs get caught deterministically
|
|
37
|
+
- **Verification pipeline** (v1.4) β the agent can't end a turn claiming success on unverified edits
|
|
38
|
+
- **One graph, every assistant** β plain git-tracked JSON in `.hunch/`, served over MCP; no SaaS, $0, works offline
|
|
317
39
|
|
|
318
|
-
|
|
319
|
-
index is built from it and is throwaway. Subscription-billed synthesis (never a pay-per-token
|
|
320
|
-
API key) with a no-LLM fallback, and atomic writes so an interrupted write can't corrupt your
|
|
321
|
-
memory. β [the docs](https://hunch-pi.vercel.app/docs) for the conceptual model.
|
|
40
|
+
## Learn more
|
|
322
41
|
|
|
323
|
-
|
|
42
|
+
**[Documentation](https://hunch-pi.vercel.app/docs)** Β· **[Cookbook](https://hunch-pi.vercel.app/cookbook)** Β· **[Changelog](https://hunch-pi.vercel.app/changelog)** Β· **[15-second demo](demo/architectural-conformance.sh)**
|
|
324
43
|
|
|
325
|
-
|
|
326
|
-
welcome β see [CONTRIBUTING.md](CONTRIBUTING.md) and the [repo](https://github.com/davesheffer/hunch).
|
|
44
|
+
Apache-2.0
|
package/dist/core/pipeline.js
CHANGED
|
@@ -91,11 +91,22 @@ export function onEdit(state, path, profiles = DEFAULT_PROFILES) {
|
|
|
91
91
|
editedFiles: state.editedFiles.includes(path) ? state.editedFiles : [...state.editedFiles, path],
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
|
-
/** A shell command ran.
|
|
94
|
+
/** A shell command ran. After an edit, it counts as verification when it is
|
|
95
|
+
* verify-shaped for an active domain, a generic runner (`node --test`,
|
|
96
|
+
* `node -e` assertions), or names an edited file β a bespoke check on the
|
|
97
|
+
* thing you changed is verification, and uncredited real checks are how a
|
|
98
|
+
* gate gets disabled out of annoyance (first live false-negative: an HTML
|
|
99
|
+
* structure assertion via `node -e` was blocked on 2026-07-08). */
|
|
95
100
|
export function onCommand(state, command, profiles = DEFAULT_PROFILES) {
|
|
96
|
-
if (state.editedFiles.length
|
|
101
|
+
if (!state.editedFiles.length)
|
|
102
|
+
return state;
|
|
103
|
+
const editedFileNamed = state.editedFiles.some((f) => {
|
|
104
|
+
const base = f.replace(/\\/g, "/").split("/").pop();
|
|
105
|
+
return !!base && command.includes(base);
|
|
106
|
+
});
|
|
107
|
+
const verifyShaped = verifyPattern(state, profiles).test(command) || /node (--test|-e\b)/.test(command);
|
|
108
|
+
if (verifyShaped || editedFileNamed)
|
|
97
109
|
return { ...state, verifyAfterEdit: true };
|
|
98
|
-
}
|
|
99
110
|
return state;
|
|
100
111
|
}
|
|
101
112
|
/** A verification-class skill ran (/verify, /code-review) β counts as coverage. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davesheffer/hunch",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Dave Sheffer <dave.sheffer1@gmail.com>",
|
|
6
6
|
"description": "Architectural Conformance for AI-generated code: a git-native graph that deterministically blocks AI changes which break your architecture β the semantic invariants (layering, must-reach, dependency direction) pattern-SAST can't express β grounded in the decisions and bugs behind each rule, across any MCP assistant (Claude Code, Cursor, Copilot, Windsurf, Codex).",
|