@davesheffer/hunch 1.2.2 โ†’ 1.2.3

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 CHANGED
@@ -44,6 +44,8 @@ guards, troubleshooting. This README is the tour. Jump to:
44
44
  [CLI reference](https://hunch-pi.vercel.app/docs#cli) ยท
45
45
  [Troubleshooting](https://hunch-pi.vercel.app/docs#doctor)
46
46
 
47
+ > ๐Ÿ†• **v1.2.2** โ€” the [component wiki + specs ledger](https://hunch-pi.vercel.app/docs#wiki): Hunch takes over your stale docs โ€” graded deterministically, adopted into a graph-healed wiki copy, never rewriting your originals โ€” with staleness drift-gated in CI. Plus honest auto-commit reporting, a friendly Node < 22.13 gate, and churn-free reindexing. [Full changelog โ†’](https://hunch-pi.vercel.app/changelog)
48
+
47
49
  ## The problem
48
50
 
49
51
  Every AI coding session starts from zero. The model re-reads your code, re-guesses the
package/dist/cli/index.js CHANGED
@@ -150,11 +150,17 @@ program
150
150
  else {
151
151
  console.log(" โš  not a git repo โ€” skipped hooks (run `git init` to enable the learning loop)");
152
152
  }
153
- const mcp = writeMcpJson(root, inv.mcp);
154
153
  // .mcp.json is the CANONICAL registration: Claude Code resolves it by file path,
155
154
  // so it's immune to the Windows ~/.claude.json drive-letter case-split that a
156
- // global `claude mcp add` is prone to (see `hunch doctor`).
157
- console.log(` โœ“ wrote ${rel(root, mcp)} (registers the Hunch MCP server โ€” canonical, path-keyed; prefer over a global \`claude mcp add\`)`);
155
+ // global `claude mcp add` is prone to (see `hunch doctor`). An unparseable
156
+ // existing file is refused (con_8460b6770f) โ€” warn and continue, never clobber.
157
+ try {
158
+ const mcp = writeMcpJson(root, inv.mcp);
159
+ console.log(` โœ“ wrote ${rel(root, mcp)} (registers the Hunch MCP server โ€” canonical, path-keyed; prefer over a global \`claude mcp add\`)`);
160
+ }
161
+ catch (e) {
162
+ console.log(` โš  skipped .mcp.json: ${e.message}`);
163
+ }
158
164
  const cmds = writeSlashCommands(root);
159
165
  console.log(` โœ“ wrote ${cmds.length} slash commands (/hunch-why, /hunch-fix, /hunch-fragile)`);
160
166
  const cmd = updateClaudeMd(root, store);
@@ -191,7 +191,11 @@ export function indexRepo(store, root, opts = {}) {
191
191
  // ---- helpers --------------------------------------------------------------
192
192
  function listCodeFiles(root) {
193
193
  if (isGitRepo(root)) {
194
- const tracked = trackedFiles(root, CODE_EXTS).map((f) => join(root, f));
194
+ // Apply SKIP_DIRS to the git-tracked list too: a repo that (accidentally)
195
+ // tracks node_modules/ or dist/ must not flood the graph with vendored symbols.
196
+ const tracked = trackedFiles(root, CODE_EXTS)
197
+ .filter((f) => !f.split(/[\\/]/).some((seg) => SKIP_DIRS.has(seg)))
198
+ .map((f) => join(root, f));
195
199
  if (tracked.length > 0)
196
200
  return tracked; // else fall through (nothing committed yet)
197
201
  }
@@ -5,16 +5,25 @@
5
5
  */
6
6
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
7
7
  import { join, dirname } from "node:path";
8
- /** Merge a `hunch` server entry into .mcp.json, preserving other servers. */
8
+ /** Merge a `hunch` server entry into .mcp.json, preserving other servers.
9
+ * A non-empty file we cannot parse THROWS instead of being silently replaced
10
+ * (con_8460b6770f โ€” it may hold the user's other MCP servers); the caller
11
+ * degrades that to a warning. */
9
12
  export function writeMcpJson(root, inv) {
10
13
  const file = join(root, ".mcp.json");
11
14
  let json = {};
12
15
  if (existsSync(file)) {
13
- try {
14
- json = JSON.parse(readFileSync(file, "utf8"));
15
- }
16
- catch {
17
- json = {};
16
+ const raw = readFileSync(file, "utf8");
17
+ if (raw.trim()) {
18
+ try {
19
+ const v = JSON.parse(raw);
20
+ if (!v || typeof v !== "object" || Array.isArray(v))
21
+ throw new Error("not a JSON object");
22
+ json = v;
23
+ }
24
+ catch (e) {
25
+ throw new Error(`refusing to overwrite ${file}: could not parse it (${e.message}). Fix or remove it, then re-run.`);
26
+ }
18
27
  }
19
28
  }
20
29
  json.mcpServers = json.mcpServers ?? {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@davesheffer/hunch",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
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).",