@davesheffer/hunch 1.23.3 → 1.25.0
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 +123 -121
- package/dist/cli/index.js +2 -0
- package/dist/cli/update.js +72 -0
- package/dist/core/provenance.js +43 -0
- package/dist/core/stateContract.js +250 -0
- package/dist/core/stateRecords.js +150 -0
- package/dist/core/types.js +16 -29
- package/dist/integrations/claudemd.js +1 -0
- package/dist/integrations/gitignore.js +8 -0
- package/dist/mcp/server.js +75 -0
- package/dist/store/changeLedger.js +96 -0
- package/dist/store/jsonStore.js +5 -0
- package/dist/store/stateBinding.js +385 -0
- package/package.json +2 -2
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -6,28 +6,20 @@
|
|
|
6
6
|
[](https://github.com/davesheffer/hunch)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
-
Every new AI coding session can read your code. It cannot automatically see why your team chose
|
|
10
|
-
this design, which alternative already failed, what an odd-looking line protects, or how this
|
|
11
|
-
repository expects work to be explained and reviewed.
|
|
9
|
+
Every new AI coding session can read your code. It cannot automatically see why your team chose this design, which alternative already failed, what an odd-looking line protects, or how this repository expects work to be explained and reviewed.
|
|
12
10
|
|
|
13
|
-
That is how settled decisions get reopened, fixed bugs return, and technically plausible changes
|
|
14
|
-
arrive feeling foreign to the project.
|
|
11
|
+
That is how settled decisions get reopened, fixed bugs return, and technically plausible changes arrive feeling foreign to the project.
|
|
15
12
|
|
|
16
|
-
**Hunch is evidence-backed project intelligence for the AI coding tools you already use.** It gives
|
|
17
|
-
Claude, Codex, Cursor, Copilot, Windsurf, Antigravity, and other MCP clients the same durable
|
|
18
|
-
understanding of your codebase:
|
|
13
|
+
**Hunch is evidence-backed deterministic project intelligence for the AI coding tools you already use.** It gives Claude, Codex, Cursor, Copilot, Windsurf, Antigravity and other MCP clients the same durable understanding of your codebase:
|
|
19
14
|
|
|
20
15
|
- why the code is shaped this way;
|
|
21
|
-
- how the repository communicates, reviews
|
|
16
|
+
- how the repository communicates, reviews and builds;
|
|
22
17
|
- what depends on the code about to change; and
|
|
23
|
-
- which trusted decisions, fixes
|
|
18
|
+
- which trusted decisions, fixes and architectural boundaries the result must preserve.
|
|
24
19
|
|
|
25
|
-
For precise rules your team has explicitly trusted, the promise is **Never Twice**: an agent may
|
|
26
|
-
propose a different direction, but it cannot quietly re-make a decided decision or re-introduce a
|
|
27
|
-
fixed failure without Hunch surfacing the conflict and its evidence.
|
|
20
|
+
For precise rules your team has explicitly trusted, the promise is **Never Twice**: an agent may propose a different direction, but it cannot quietly re-make a decided decision or re-introduce a fixed failure without Hunch surfacing the conflict and its evidence.
|
|
28
21
|
|
|
29
|
-
Memory starts advisory. Nothing blocks until a human deliberately trusts a precise rule and opts
|
|
30
|
-
into strict enforcement.
|
|
22
|
+
Memory starts advisory. Nothing blocks until a human deliberately trusts a precise rule and opts into strict enforcement.
|
|
31
23
|
|
|
32
24
|
## Start in five minutes
|
|
33
25
|
|
|
@@ -44,12 +36,19 @@ Reload your coding assistant, then ask a normal question:
|
|
|
44
36
|
|
|
45
37
|
> Why is this built this way?
|
|
46
38
|
|
|
47
|
-
`hunch init` indexes the repository, installs local lifecycle hooks
|
|
48
|
-
assistants without replacing their existing configuration. The next session receives the relevant
|
|
49
|
-
story with its sources, not a giant transcript or a generic prompt wall. Lifecycle coverage
|
|
50
|
-
depends on the harness; MCP connectivity alone does not establish automatic grounding or enforcement.
|
|
39
|
+
`hunch init` indexes the repository, installs local lifecycle hooks and connects supported assistants without replacing their existing configuration. The next session receives the relevant story with its sources, not a giant transcript or generic prompt wall.
|
|
51
40
|
|
|
52
|
-
|
|
41
|
+
Lifecycle coverage depends on the harness; MCP connectivity alone does not establish automatic grounding or enforcement.
|
|
42
|
+
|
|
43
|
+
To update Hunch and configured harness pins for the current repository:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
hunch update
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Agents receive an instruction to run this when you ask **“update Hunch”** in generated Hunch guidance. Restart active harnesses afterward.
|
|
50
|
+
|
|
51
|
+
Check integrations after upgrading Hunch or switching assistants:
|
|
53
52
|
|
|
54
53
|
```sh
|
|
55
54
|
hunch integrations check
|
|
@@ -58,25 +57,11 @@ hunch integrations check --harness claude --probe --require mcp
|
|
|
58
57
|
hunch integrations check --harness codex --require context,edit-blocking
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Capabilities are reported as **verified**, **advisory-only**, **unsupported**, or **untested**.
|
|
68
|
-
`--require` fails unless every named capability is verified. The Codex example currently fails:
|
|
69
|
-
Hunch's Codex integration supplies MCP and instructions, with no native lifecycle adapter.
|
|
70
|
-
The opt-in `--probe` starts the selected generated npm launcher, checks the server version,
|
|
71
|
-
and reads memory; it may download the pinned package. It verifies a fresh MCP process only,
|
|
72
|
-
not the existing host session, hook delivery, or whether a model follows the memory.
|
|
73
|
-
Custom launchers and environment overrides require host-side verification.
|
|
74
|
-
|
|
75
|
-
`doctor` includes this report, and session hooks with a context channel surface configuration
|
|
76
|
-
problems. Checks cover repository-local configurations; global/managed overrides remain
|
|
77
|
-
outside this inspection. Use `hunch integrations check` in CI to prevent pin drift; add
|
|
78
|
-
`--require` for capabilities your workflow cannot operate without. Hook failure remains
|
|
79
|
-
non-blocking; this explicit CI/preflight gate fails closed on unmet requirements.
|
|
60
|
+
Capabilities are reported as **verified**, **advisory-only**, **unsupported** or **untested**. `--require` fails unless every named capability is verified.
|
|
61
|
+
|
|
62
|
+
The Codex integration currently supplies MCP and instructions, with no native lifecycle adapter. The opt-in `--probe` verifies a fresh MCP process, not whether an existing host session or model actually followed the memory.
|
|
63
|
+
|
|
64
|
+
Use `hunch integrations check` in CI to prevent pin drift; add `--require` for capabilities your workflow cannot operate without.
|
|
80
65
|
|
|
81
66
|
## One evidence loop, not another model
|
|
82
67
|
|
|
@@ -98,37 +83,29 @@ Git history + ADRs + corrections + tests + repository conventions
|
|
|
98
83
|
deterministic change receipt
|
|
99
84
|
```
|
|
100
85
|
|
|
101
|
-
Hunch is not
|
|
102
|
-
validation layer behind the tools that write the code.
|
|
86
|
+
Hunch is not the agent and is not the workflow engine. The model thinks; Hunch holds deterministic, evidence-backed state about the project and validates what must remain true.
|
|
103
87
|
|
|
104
88
|
## What Hunch understands
|
|
105
89
|
|
|
106
90
|
| Layer | What it adds |
|
|
107
91
|
| --- | --- |
|
|
108
|
-
| **Engineering Memory** | Decisions, rejected alternatives, corrections, bug lineage, findings
|
|
109
|
-
| **Code Graph** | Symbols, calls, imports, dependencies, components, blast radius
|
|
110
|
-
| **Project DNA** | Revision-specific, evidence-backed observations about how a repository communicates and works: vocabulary, contribution habits, review expectations, engineering conventions
|
|
111
|
-
| **Engineering Landscape** |
|
|
112
|
-
| **Validated Delivery** | The smallest relevant evidence for the current builder
|
|
113
|
-
| **Native Change Proof** | A sealed exact-change artifact binding revisions, DNA, base/result graphs, memory, blast radius, conformance, guard verdict
|
|
114
|
-
| **Change Gate + Constitution** | Deterministic checks for trusted constraints and architectural intent. Policies are compiled, proved, inspected
|
|
92
|
+
| **Engineering Memory** | Decisions, rejected alternatives, corrections, bug lineage, findings and rationale a future session would otherwise miss. |
|
|
93
|
+
| **Code Graph** | Symbols, calls, imports, dependencies, components, blast radius and architectural reachability across supported languages/configuration. Memory itself works with any language. |
|
|
94
|
+
| **Project DNA** | Revision-specific, evidence-backed observations about how a repository communicates and works: vocabulary, contribution habits, review expectations, engineering conventions and culture. |
|
|
95
|
+
| **Engineering Landscape** | Durable links from product/capability to system, repository, service, interface, data, delivery resources, runbooks, ownership, dashboards and SLOs. |
|
|
96
|
+
| **Validated Delivery** | The smallest relevant evidence for the current builder/reviewer/architect, with provenance, currentness, omissions, authority and a content-addressed receipt. |
|
|
97
|
+
| **Native Change Proof** | A sealed exact-change artifact binding revisions, DNA, base/result graphs, memory, blast radius, conformance, guard verdict and explicit gaps without granting workflow authority. |
|
|
98
|
+
| **Change Gate + Constitution** | Deterministic checks for trusted constraints and architectural intent. Policies are compiled, proved, inspected and explicitly activated by a human. |
|
|
115
99
|
|
|
116
|
-
Readable JSON in `.hunch/` is the source of truth. SQLite is a fast, rebuildable projection. Git
|
|
117
|
-
keeps the memory portable, reviewable, and reversible.
|
|
100
|
+
Readable JSON in `.hunch/` is the repository-scoped source of truth. SQLite is a fast, rebuildable projection. Git keeps the state portable, reviewable and reversible.
|
|
118
101
|
|
|
119
102
|
## Project DNA: help the agent work like it belongs here
|
|
120
103
|
|
|
121
|
-
Project DNA is Hunch's evidence-bound model of **how a repository communicates and works**. It is
|
|
122
|
-
not a persona, does not impersonate a maintainer, and does not turn frequent behavior into policy.
|
|
104
|
+
Project DNA is Hunch's evidence-bound model of **how a repository communicates and works**. It is not a persona, does not impersonate a maintainer and does not turn frequent behavior into policy.
|
|
123
105
|
|
|
124
|
-
The deterministic baseline reads an exact Git revision, bounded commit history, and
|
|
125
|
-
convention files. The current release can also accept bounded, caller-authorized pull-request and
|
|
126
|
-
review evidence. Every evidence batch is validated and sealed; raw collaboration text does not
|
|
127
|
-
enter the profile.
|
|
106
|
+
The deterministic baseline reads an exact Git revision, bounded commit history and committed convention files. The current release can also accept bounded, caller-authorized pull-request/review evidence. Every evidence batch is validated and sealed; raw collaboration text does not enter the profile.
|
|
128
107
|
|
|
129
|
-
Each trait keeps its category, confidence, freshness, repository revision
|
|
130
|
-
can then include only the relevant DNA in normal context, explain how well a commit, PR, issue, or
|
|
131
|
-
message matches repository conventions, and show how the profile changed between two revisions.
|
|
108
|
+
Each trait keeps its category, confidence, freshness, repository revision and evidence hash. Hunch can include only the relevant DNA in normal context, explain how an artifact matches repository conventions and show profile change between revisions.
|
|
132
109
|
|
|
133
110
|
```bash
|
|
134
111
|
hunch dna inspect
|
|
@@ -136,32 +113,27 @@ hunch dna context
|
|
|
136
113
|
hunch dna diff <older-ref> <newer-ref>
|
|
137
114
|
```
|
|
138
115
|
|
|
139
|
-
DNA may shape orientation, terminology
|
|
140
|
-
override a decision, constraint, finding, conformance rule, policy, or permission.
|
|
116
|
+
DNA may shape orientation, terminology and advisory Project Match checks. It cannot create or override a decision, constraint, finding, conformance rule, policy or permission.
|
|
141
117
|
|
|
142
|
-
Read the [Project DNA contract](docs/project-dna.md) and
|
|
143
|
-
[Project DNA vision](docs/project-dna-engine.md).
|
|
118
|
+
Read the [Project DNA contract](docs/project-dna.md) and broader [Project DNA vision](docs/project-dna-engine.md).
|
|
144
119
|
|
|
145
120
|
## Day-to-day
|
|
146
121
|
|
|
147
|
-
Most capture happens around normal commits and test failures. These commands cover the common
|
|
148
|
-
manual paths:
|
|
149
|
-
|
|
150
122
|
| Command | Use it for |
|
|
151
123
|
| --- | --- |
|
|
152
|
-
| `hunch context "<task>" --profile builder` | Get a bounded builder
|
|
153
|
-
| `hunch why <file-or-symbol>` | See
|
|
154
|
-
| `hunch structure [target]` | Inspect
|
|
124
|
+
| `hunch context "<task>" --profile builder` | Get a bounded builder/reviewer/architect brief before work starts |
|
|
125
|
+
| `hunch why <file-or-symbol>` | See decisions, bugs, constraints and blast radius behind code |
|
|
126
|
+
| `hunch structure [target]` | Inspect indexed repository shape without repeated search rounds |
|
|
155
127
|
| `hunch findings [scope]` | Inherit known-but-unfixed gaps instead of rediscovering them |
|
|
156
128
|
| `hunch check --working` | Review the current tree against trusted project rules |
|
|
157
129
|
| `hunch conform` | Prove the code still satisfies recorded architectural intent |
|
|
158
130
|
| `hunch impact origin/main` | See the dependency and memory surface of a branch |
|
|
159
|
-
| `hunch compare branch-a branch-b` | Rank candidate changes by
|
|
131
|
+
| `hunch compare branch-a branch-b` | Rank candidate changes by invariant/decision conflicts |
|
|
160
132
|
| `hunch prove origin/main --public-only` | Produce a publication-safe `hunch.change-proof/1` artifact for an exact committed change |
|
|
161
133
|
| `hunch landscape review` | Inspect a hash-bound repository landscape without writing authority |
|
|
162
|
-
| `hunch now` | See recent memory and
|
|
163
|
-
| `hunch escalations` | See
|
|
164
|
-
| `hunch doctor` | Diagnose setup, provider, index
|
|
134
|
+
| `hunch now` | See recent memory and live decision-backed roadmap |
|
|
135
|
+
| `hunch escalations` | See questions that genuinely require a human answer |
|
|
136
|
+
| `hunch doctor` | Diagnose setup, provider, index or overlay problems |
|
|
165
137
|
|
|
166
138
|
When you are ready for deterministic enforcement:
|
|
167
139
|
|
|
@@ -170,45 +142,70 @@ hunch firmness strict
|
|
|
170
142
|
hunch check --staged --strict
|
|
171
143
|
```
|
|
172
144
|
|
|
173
|
-
|
|
145
|
+
Captured memory cannot silently hard-block on its own.
|
|
174
146
|
|
|
175
|
-
##
|
|
147
|
+
## Deterministic organizational state — next product direction
|
|
148
|
+
|
|
149
|
+
Repository memory solves one version of a larger problem.
|
|
150
|
+
|
|
151
|
+
As organizations give every employee an agent that can work across CRM, email, messaging, repositories and other tools, the agents become probabilistic writers/readers of the same organization. If each one independently reconstructs what was decided, what was already done or what is still owed, the organization gets multiple conflicting realities.
|
|
152
|
+
|
|
153
|
+
The active roadmap asks whether Hunch can become the deterministic state layer between those agents and the organization:
|
|
154
|
+
|
|
155
|
+
> **Agents are probabilistic. Organizations need deterministic state. Hunch is the state layer between them.**
|
|
156
|
+
|
|
157
|
+
The target is **one product, one authorized state graph and one versioned state contract** across repository, user, team and organization scopes.
|
|
176
158
|
|
|
177
|
-
|
|
178
|
-
whole product.
|
|
159
|
+
Planned state includes:
|
|
179
160
|
|
|
180
|
-
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
-
|
|
184
|
-
|
|
185
|
-
-
|
|
186
|
-
|
|
187
|
-
or changing policy authority.
|
|
161
|
+
- decisions currently in force;
|
|
162
|
+
- verified action receipts / what was done;
|
|
163
|
+
- commitments and due-state;
|
|
164
|
+
- entities and relationships;
|
|
165
|
+
- code/system changes with proof;
|
|
166
|
+
- repository/user/team/org DNA;
|
|
167
|
+
- derived current state with exact dependencies/invalidation.
|
|
188
168
|
|
|
189
|
-
|
|
190
|
-
[roadmap](ROADMAP.md) for what is next and deliberately out of scope.
|
|
169
|
+
Agents continue to own live connector mechanics. Hunch must **not** become a managed proxy that fetches Gmail, CRM, WhatsApp or GitHub on an agent's behalf.
|
|
191
170
|
|
|
192
|
-
|
|
193
|
-
<summary><strong>The scoped v1.19 benchmark</strong></summary>
|
|
171
|
+
Instead:
|
|
194
172
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
173
|
+
```text
|
|
174
|
+
Hunch deterministic state
|
|
175
|
+
↑ ↓
|
|
176
|
+
agent -> deterministic action gate -> connector -> source system
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Hunch may hold durable state **about** external work with credential-free provenance pointers, but should not mirror raw source-system contents into a universal cache.
|
|
180
|
+
|
|
181
|
+
The first real-world pilot is **Sofia**, a working operations agent over CRM, Gmail and WhatsApp. Sofia's approved actions, follow-ups, customer/source relationships and cited summaries map naturally to action receipts, commitments, entities/relationships and dependency-bound state.
|
|
182
|
+
|
|
183
|
+
The pilot measures whether Sofia and a second, different agent stop re-deriving contradictory state when the deterministic state is delivered before they answer or act.
|
|
184
|
+
|
|
185
|
+
### The state contract, shipped
|
|
186
|
+
|
|
187
|
+
As of 1.25.0 the contract exists as code: `nuryel.state/1` — three verbs (`read` under the
|
|
188
|
+
delivery envelope's receipt, `write` with provenance and an idempotency key, `subscribe` to a
|
|
189
|
+
strictly ordered change stream) over five new record facets: action receipts, commitments,
|
|
190
|
+
derived state that names what it rests on, external entities and their relationships. Ids are
|
|
191
|
+
derived from a record's facts, a replay returns the original, a second live decision on a topic is
|
|
192
|
+
refused with the incumbent named, and derived state without dependencies is not state. Each scope
|
|
193
|
+
keeps a git-native change ledger under `.hunch/changes/`; organization, team and user partitions
|
|
194
|
+
are homed in an overlay, never in a repository. The MCP server binds it as `nuryel_capabilities`,
|
|
195
|
+
`nuryel_read`, `nuryel_write` and `nuryel_subscribe`; every other transport will call the same
|
|
196
|
+
store binding. Contract and evidence: [docs/nuryel-state-contract.md](docs/nuryel-state-contract.md).
|
|
197
|
+
|
|
198
|
+
Read [Deterministic organizational state](docs/deterministic-state.md) and the [roadmap](ROADMAP.md).
|
|
199
199
|
|
|
200
|
-
|
|
201
|
-
Failed evidence and causal rerankers remain disabled; evidence can annotate the shortlist but does
|
|
202
|
-
not reorder it or claim an exact correction owner. The detailed receipts live in
|
|
203
|
-
[`bench/external/results`](bench/external/results).
|
|
200
|
+
### Naming
|
|
204
201
|
|
|
205
|
-
|
|
202
|
+
The product is still **Hunch**. A possible hosted-platform name, **Nuryel**, is intentionally deferred until the state contract and Sofia pilot have evidence. Rename work is not the deliverable.
|
|
206
203
|
|
|
207
|
-
## Share one living memory with your team
|
|
204
|
+
## Share one living repository memory with your team
|
|
208
205
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
206
|
+
The current release can keep a team's **repository-scoped** memory in a dedicated private Git repository, separate from the code.
|
|
207
|
+
|
|
208
|
+
Today Hunch does not host that shared Git repository; teammates/CI use normal Git access and one maintainer connects it:
|
|
212
209
|
|
|
213
210
|
```bash
|
|
214
211
|
npm i -g @davesheffer/hunch@1.23.3
|
|
@@ -227,34 +224,39 @@ hunch init
|
|
|
227
224
|
hunch doctor
|
|
228
225
|
```
|
|
229
226
|
|
|
230
|
-
The committed pointer contains a credential-free repository locator and branch.
|
|
231
|
-
|
|
232
|
-
|
|
227
|
+
The committed pointer contains a credential-free repository locator and branch. Local clone paths, preferences and private overlays stay ignored. MCP sessions refresh shared memory at tool boundaries; failed pushes can be retried by later capture or `hunch shared --sync`.
|
|
228
|
+
|
|
229
|
+
Use `hunch firmness off` to pause hook enforcement without deleting history. Use `hunch shared --repo <url> --no-auto-commit` when captures should remain local until explicit `hunch shared --sync`.
|
|
233
230
|
|
|
234
|
-
|
|
235
|
-
`hunch shared --repo <url> --no-auto-commit` when captures should remain local until an explicit
|
|
236
|
-
`hunch shared --sync`.
|
|
231
|
+
This existing Git-sharing feature is not the same thing as the planned organization/team/user state service. The roadmap extends the git-native model rather than declaring today's shared-memory repository to be an organization control plane.
|
|
237
232
|
|
|
238
233
|
## Trust boundaries that stay visible
|
|
239
234
|
|
|
240
|
-
- **Local-first.** Hunch
|
|
241
|
-
|
|
242
|
-
- **Private when needed.** `hunch private --repo <url>` keeps sensitive reasoning in a separate
|
|
243
|
-
|
|
244
|
-
- **
|
|
245
|
-
|
|
246
|
-
- **
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
-
|
|
252
|
-
|
|
235
|
+
- **Local-first today.** Repository Hunch works without a hosted service or telemetry. Git remains the repository-scoped authority.
|
|
236
|
+
- **Hosted state is a roadmap extension, not a shipped claim.** Organization/team/user state will require authenticated scope/visibility, idempotency and durability while preserving git-native truth.
|
|
237
|
+
- **Private when needed.** `hunch private --repo <url>` keeps sensitive repository reasoning in a separate overlay; public CI/documentation remain public-only.
|
|
238
|
+
- **Human authority.** Observations, generated drafts, imported ADRs, discovered landscape records and proved policy candidates do not silently become trusted truth.
|
|
239
|
+
- **Deterministic core.** Indexing, retrieval receipts, currentness, conformance, Project DNA discovery and policy evaluation do not require a model.
|
|
240
|
+
- **Agents own execution.** Hunch state does not silently grant connector permissions, send messages or become a source-system proxy.
|
|
241
|
+
- **No surprise synthesis bill.** Optional drafting can use a selected Claude Code, Codex or Cursor subscription CLI, a local OpenAI-compatible endpoint or deterministic fallback. Public remote endpoints require explicit opt-in.
|
|
242
|
+
- **Traceable releases.** npm packages and the VS Code extension are content-addressed, verified against public registries and tied back to exact source tags.
|
|
243
|
+
|
|
244
|
+
## What changed after v1.19
|
|
245
|
+
|
|
246
|
+
The v1.19 correction-search benchmark remains scoped evidence, but it no longer describes the whole product.
|
|
247
|
+
|
|
248
|
+
- **v1.20 — one validated path from reason to result.** Role-shaped context, reviewed Engineering Landscape fragments, exact change identity, PHP graph support and hash-bound ADR review moved source, provenance, currentness, omissions and human authority through one delivery contract.
|
|
249
|
+
- **v1.21 — Project DNA.** Hunch gained deterministic, revision-specific repository profiles, bounded DNA context delivery, explainable Project Match checks and auditable profile deltas.
|
|
250
|
+
- **v1.22 — authorized collaboration evidence.** Hosts can contribute bounded PR/review evidence to Project DNA through a typed, sealed contract without raw collaboration persistence or policy-authority change.
|
|
251
|
+
- **v1.23 — native change proof and proof-carrying evidence work.** Exact Git change identity, graph before/after, decisions/constraints, blast radius and Change Gate result can be bound into a sealed evidence artifact without granting authority.
|
|
252
|
+
|
|
253
|
+
See the [changelog](CHANGELOG.md) for release detail and the [roadmap](ROADMAP.md) for active work.
|
|
253
254
|
|
|
254
255
|
## Learn more
|
|
255
256
|
|
|
256
257
|
- [Full documentation](https://www.hunchmemory.com/docs)
|
|
257
258
|
- [Copy-paste cookbook](https://www.hunchmemory.com/cookbook)
|
|
259
|
+
- [Deterministic organizational state](docs/deterministic-state.md)
|
|
258
260
|
- [Project DNA](docs/project-dna.md)
|
|
259
261
|
- [Native change proof](docs/change-proof.md)
|
|
260
262
|
- [Engineering Landscape Graph](docs/engineering-landscape.md)
|
package/dist/cli/index.js
CHANGED
|
@@ -25,6 +25,7 @@ import { writeFileAtomic } from "../core/io.js";
|
|
|
25
25
|
import { looksLikeCorrection, CORRECTION_NUDGE } from "../core/correction.js";
|
|
26
26
|
import { HUNCH_VERSION } from "../core/version.js";
|
|
27
27
|
import { registerIntegrationCommands } from "./integrations.js";
|
|
28
|
+
import { registerUpdateCommand } from "./update.js";
|
|
28
29
|
import { inspectIntegrations, formatIntegrationHealth, integrationHealthFails, integrationSessionWarning } from "../integrations/health.js";
|
|
29
30
|
import { HunchStore } from "../store/hunchStore.js";
|
|
30
31
|
import { JsonStore } from "../store/jsonStore.js";
|
|
@@ -112,6 +113,7 @@ import { resolveInvocation, dim, synthesisStatusLines, maybeWarnOllamaContext }
|
|
|
112
113
|
const program = new Command();
|
|
113
114
|
program.name("hunch").description("Hunch — engineering memory and a deterministic Change Gate for AI-assisted codebases.").version(HUNCH_VERSION);
|
|
114
115
|
registerIntegrationCommands(program);
|
|
116
|
+
registerUpdateCommand(program);
|
|
115
117
|
let openStore = null;
|
|
116
118
|
function openTeamStore(root, opts = {}) {
|
|
117
119
|
// A committed team.json is an explicit declaration that this checkout belongs
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { findRoot } from "../core/paths.js";
|
|
5
|
+
const PACKAGE = "@davesheffer/hunch";
|
|
6
|
+
/** Arguments come only from fixed commands and a validated registry version.
|
|
7
|
+
* Windows needs the shell to resolve npm.cmd; cwd is never interpolated. */
|
|
8
|
+
export function runNpm(root, args, capture = false) {
|
|
9
|
+
if (args.some(arg => !/^[a-zA-Z0-9@/_.=+:-]+$/.test(arg)))
|
|
10
|
+
throw new Error("unsafe npm argument");
|
|
11
|
+
const windows = process.platform === "win32";
|
|
12
|
+
const result = spawnSync(windows ? `npm ${args.join(" ")}` : "npm", windows ? [] : args, {
|
|
13
|
+
cwd: root, shell: windows, windowsHide: true,
|
|
14
|
+
encoding: "utf8", stdio: capture ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
15
|
+
});
|
|
16
|
+
if (result.error)
|
|
17
|
+
throw result.error;
|
|
18
|
+
if (result.status !== 0)
|
|
19
|
+
throw new Error(`npm ${args.join(" ")} failed (${result.status ?? result.signal})${result.stderr ? `: ${result.stderr.trim()}` : ""}`);
|
|
20
|
+
return result.stdout ?? "";
|
|
21
|
+
}
|
|
22
|
+
/** Fresh child execution is essential: the currently running CLI still has the
|
|
23
|
+
* old modules loaded after npm replaces its installation. */
|
|
24
|
+
export function updateHunch(root, opts = {}, run = (args, capture) => runNpm(root, args, capture), log = console.log) {
|
|
25
|
+
const file = join(root, "package.json");
|
|
26
|
+
const manifest = existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : {};
|
|
27
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest))
|
|
28
|
+
throw new Error("package.json must contain an object");
|
|
29
|
+
if (manifest.name === PACKAGE)
|
|
30
|
+
throw new Error("Run hunch update in a consumer repository, not Hunch's own source checkout.");
|
|
31
|
+
const sections = ["dependencies", "devDependencies", "optionalDependencies"];
|
|
32
|
+
const declared = sections.filter(section => {
|
|
33
|
+
const deps = manifest[section];
|
|
34
|
+
if (deps !== undefined && (!deps || typeof deps !== "object" || Array.isArray(deps)))
|
|
35
|
+
throw new Error(`invalid ${section} in package.json`);
|
|
36
|
+
return deps && Object.hasOwn(deps, PACKAGE);
|
|
37
|
+
});
|
|
38
|
+
if (declared.length > 1)
|
|
39
|
+
throw new Error("Hunch is declared in multiple dependency sections; resolve the duplicate before updating.");
|
|
40
|
+
if (declared.length && (manifest.workspaces || (manifest.packageManager && !/^npm@/.test(manifest.packageManager)) || ["pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb"].some(name => existsSync(join(root, name))))) {
|
|
41
|
+
throw new Error("Automatic dependency updates currently support standalone npm projects. Update Hunch to an exact version with your package manager, then run hunch integrations repair-pins.");
|
|
42
|
+
}
|
|
43
|
+
const version = JSON.parse(run(["view", `${PACKAGE}@latest`, "version", "--json"], true));
|
|
44
|
+
if (typeof version !== "string" || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(version))
|
|
45
|
+
throw new Error("npm returned an invalid Hunch version");
|
|
46
|
+
const spec = `${PACKAGE}@${version}`;
|
|
47
|
+
const commands = [];
|
|
48
|
+
if (declared.length) {
|
|
49
|
+
const flag = { dependencies: "--save-prod", devDependencies: "--save-dev", optionalDependencies: "--save-optional" }[declared[0]];
|
|
50
|
+
commands.push(["install", flag, "--save-exact", spec]);
|
|
51
|
+
}
|
|
52
|
+
if (!declared.length || opts.global)
|
|
53
|
+
commands.push(["install", "--global", spec]);
|
|
54
|
+
// The alias prevents npm exec from substituting a stale local hunch binary.
|
|
55
|
+
commands.push(["exec", "--yes", `--package=hunch-exact@npm:${spec}`, "--", "hunch", "integrations", "repair-pins"]);
|
|
56
|
+
log(`${opts.dryRun ? "Preview" : "Updating"}: Hunch ${version} for ${root}`);
|
|
57
|
+
for (const args of commands) {
|
|
58
|
+
log(`npm ${args.join(" ")}`);
|
|
59
|
+
if (!opts.dryRun)
|
|
60
|
+
run(args);
|
|
61
|
+
}
|
|
62
|
+
if (!opts.dryRun)
|
|
63
|
+
log("Hunch updated; repository integration check passed. Restart or reconnect active harnesses to load the new MCP version.");
|
|
64
|
+
}
|
|
65
|
+
export function registerUpdateCommand(program) {
|
|
66
|
+
program.command("update")
|
|
67
|
+
.description("Update Hunch to latest and repair all configured harness pins in this repository")
|
|
68
|
+
.option("--global", "also update the global CLI when a repository dependency exists")
|
|
69
|
+
.option("--dry-run", "resolve latest and print commands without changing files")
|
|
70
|
+
.action((opts) => updateHunch(findRoot(), opts));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance and credential-free text — a LEAF module (zod only) so that record
|
|
3
|
+
* schemas registered in the store can import it without pulling in types.ts,
|
|
4
|
+
* which itself imports the store's kind registry. types.ts re-exports everything
|
|
5
|
+
* here, so existing imports keep working unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
/** Where a fact came from and how much to trust it. Confidence tiers (DESIGN §4):
|
|
9
|
+
* inferred < extracted < llm_draft < llm_draft+human_confirmed/derived. */
|
|
10
|
+
export const ProvenanceSchema = z.object({
|
|
11
|
+
source: z.string().describe("e.g. extracted | inferred | llm_draft | human_confirmed | test_failure+llm | derived"),
|
|
12
|
+
confidence: z.number().min(0).max(1),
|
|
13
|
+
evidence: z.array(z.string()).default([]).describe("file paths, commit ids, test ids backing the claim"),
|
|
14
|
+
last_verified: z.string().optional().describe("ISO timestamp of last re-validation"),
|
|
15
|
+
});
|
|
16
|
+
export const SENSITIVE_METADATA_KEY = /(^|[_-])(authorization|bearer|credential|password|passwd|private[_-]?key|secret|token|api[_-]?key)($|[_-])/i;
|
|
17
|
+
const SENSITIVE_ASSIGNMENT = /\b(authorization|password|passwd|private[_-]?key|secret|access[_-]?token|refresh[_-]?token|api[_-]?key)\s*[:=]\s*[^\s,;]{4,}/i;
|
|
18
|
+
const PRIVATE_KEY_BLOCK = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/i;
|
|
19
|
+
const BEARER_VALUE = /\bBearer\s+[A-Za-z0-9._~+\/-]{12,}/i;
|
|
20
|
+
/** Reject credential material while allowing ordinary architecture prose such as
|
|
21
|
+
* "authentication service" or "secrets are managed externally". */
|
|
22
|
+
export function isCredentialFreeText(value) {
|
|
23
|
+
if (PRIVATE_KEY_BLOCK.test(value) || BEARER_VALUE.test(value) || SENSITIVE_ASSIGNMENT.test(value))
|
|
24
|
+
return false;
|
|
25
|
+
try {
|
|
26
|
+
const url = new URL(value);
|
|
27
|
+
if (url.username || url.password)
|
|
28
|
+
return false;
|
|
29
|
+
for (const [key] of url.searchParams)
|
|
30
|
+
if (SENSITIVE_METADATA_KEY.test(key))
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
catch { /* credential-free canonical locators need not be absolute URLs */ }
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/** Bare secret shapes the general detector does not cover: it looks for assignments, bearer
|
|
37
|
+
* values, private-key blocks and URL userinfo; a token pasted on its own into an object key or
|
|
38
|
+
* locator would pass. These prefixes are the common ones. */
|
|
39
|
+
const BARE_SECRET = /(?:^|[^A-Za-z0-9])(?:ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|sk-[A-Za-z0-9_-]{16,}|xox[abpr]-[A-Za-z0-9-]{10,}|AKIA[0-9A-Z]{16}|eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})/;
|
|
40
|
+
export function isCredentialFreeValue(value) {
|
|
41
|
+
return isCredentialFreeText(value) && !BARE_SECRET.test(value);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=provenance.js.map
|