@davesheffer/hunch 0.26.1 → 0.27.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/dist/cli/index.js +14 -6
- package/dist/integrations/providers.js +27 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -38,7 +38,7 @@ import { ensureGitignore, ignoreHunchMemory, HUNCH_MEMORY_DIRS } from "../integr
|
|
|
38
38
|
import { writeCiWorkflow } from "../integrations/ciAction.js";
|
|
39
39
|
import { updateClaudeMd } from "../integrations/claudemd.js";
|
|
40
40
|
import { writeMcpJson, writeSlashCommands, installClaudeHooks } from "../integrations/scaffold.js";
|
|
41
|
-
import { scaffoldProviders, regenerateGrounding } from "../integrations/providers.js";
|
|
41
|
+
import { scaffoldProviders, regenerateGrounding, refreshExistingGrounding } from "../integrations/providers.js";
|
|
42
42
|
import { healClaudeConfigCaseSplit } from "../integrations/claudeConfig.js";
|
|
43
43
|
import { formatContext } from "../core/format.js";
|
|
44
44
|
import { readConfig, writeConfig, FIRMNESS_LEVELS, isFirmness } from "../core/config.js";
|
|
@@ -165,9 +165,13 @@ program
|
|
|
165
165
|
ensureGitignore(root); // keep the derived SQLite index out of git (idempotent)
|
|
166
166
|
const res = indexRepo(store, root);
|
|
167
167
|
const { counts } = store.reindex();
|
|
168
|
-
|
|
168
|
+
// Self-heal grounding: pick up generator fixes (param names) + fresh counts in every
|
|
169
|
+
// assistant doc the project already has — no manual re-init. Refresh-only (no scaffold).
|
|
170
|
+
const healed = refreshExistingGrounding(root, store);
|
|
169
171
|
console.log(`Indexed ${res.files} files:`);
|
|
170
172
|
console.log(` ${counts.symbols} symbols, ${counts.edges} edges, ${counts.components} components`);
|
|
173
|
+
if (healed.length)
|
|
174
|
+
console.log(` grounding refreshed: ${healed.join(", ")}`);
|
|
171
175
|
if (res.skipped)
|
|
172
176
|
console.log(` ⚠ ${res.skipped} file(s) could not be parsed (skipped)`);
|
|
173
177
|
store.close();
|
|
@@ -262,10 +266,14 @@ program
|
|
|
262
266
|
const r = await syncCommit(store, root, sha ?? headSha(root), { force: opts.force, private: opts.private, deep: opts.deep, verify: opts.verify, samples: parseSamples(opts.samples) });
|
|
263
267
|
if (r.status === "written") {
|
|
264
268
|
store.reindex();
|
|
265
|
-
// Don't rewrite
|
|
266
|
-
//
|
|
267
|
-
|
|
268
|
-
|
|
269
|
+
// Don't rewrite grounding from the hook — it would dirty the working tree on
|
|
270
|
+
// every commit. Off the hook (manual `hunch sync`), self-heal ALL existing
|
|
271
|
+
// grounding docs (param-name fixes + fresh counts), not just CLAUDE.md.
|
|
272
|
+
if (!opts.fromHook) {
|
|
273
|
+
const healed = refreshExistingGrounding(root, store);
|
|
274
|
+
if (healed.length && !opts.quiet)
|
|
275
|
+
console.log(` ↳ grounding refreshed: ${healed.join(", ")}`);
|
|
276
|
+
}
|
|
269
277
|
// Opt-in: persist the captured decision in the repo it landed in (private store
|
|
270
278
|
// under --private, else this repo). Best-effort — a non-repo dir / offline push
|
|
271
279
|
// just no-ops. Stage ONLY the hunch dir (never sweep unrelated working-tree
|
|
@@ -241,6 +241,33 @@ export function regenerateGrounding(root, store) {
|
|
|
241
241
|
writeWindsurfRule(root, store),
|
|
242
242
|
];
|
|
243
243
|
}
|
|
244
|
+
/** Self-heal: refresh the Hunch section in each grounding doc that ALREADY exists,
|
|
245
|
+
* and report which ones actually changed. Unlike regenerateGrounding it NEVER creates
|
|
246
|
+
* a file (so it can't scaffold grounding into a project that opted out of an
|
|
247
|
+
* assistant). Run by `hunch index` and non-hook `hunch sync` so a project silently
|
|
248
|
+
* picks up generator fixes (e.g. corrected MCP tool param names) and fresh record
|
|
249
|
+
* counts on the next refresh — no manual `hunch init`. Not run from the commit hook,
|
|
250
|
+
* which deliberately avoids dirtying the working tree on every commit. */
|
|
251
|
+
export function refreshExistingGrounding(root, store) {
|
|
252
|
+
const targets = [
|
|
253
|
+
["CLAUDE.md", () => updateClaudeMd(root, store)],
|
|
254
|
+
["AGENTS.md", () => writeAgentsMd(root, store)],
|
|
255
|
+
[join(".github", "copilot-instructions.md"), () => writeCopilotInstructions(root, store)],
|
|
256
|
+
[join(".cursor", "rules", "hunch.mdc"), () => writeCursorRule(root, store)],
|
|
257
|
+
[join(".windsurf", "rules", "hunch.md"), () => writeWindsurfRule(root, store)],
|
|
258
|
+
];
|
|
259
|
+
const changed = [];
|
|
260
|
+
for (const [rel, write] of targets) {
|
|
261
|
+
const file = join(root, rel);
|
|
262
|
+
if (!existsSync(file))
|
|
263
|
+
continue; // refresh-only: never scaffold a doc the project doesn't have
|
|
264
|
+
const before = readFileSync(file, "utf8");
|
|
265
|
+
write();
|
|
266
|
+
if (readFileSync(file, "utf8") !== before)
|
|
267
|
+
changed.push(rel);
|
|
268
|
+
}
|
|
269
|
+
return changed;
|
|
270
|
+
}
|
|
244
271
|
/** Scaffold MCP config + grounding for all supported assistants. Returns a
|
|
245
272
|
* per-assistant summary for `hunch init` to print. Each assistant is isolated:
|
|
246
273
|
* a writer that refuses to clobber a malformed file degrades to a warning rather
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davesheffer/hunch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Dave Sheffer <dave.sheffer1@gmail.com>",
|
|
6
6
|
"description": "Hunch — an Engineering Memory OS: a persistent, git-native reasoning graph over a codebase, exposed to Claude Code via MCP.",
|