@davesheffer/hunch 0.11.0 → 0.11.1
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 +24 -5
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -55,7 +55,7 @@ program
|
|
|
55
55
|
.description("Scaffold .hunch/, index the repo, install the git hook, and wire up Claude Code.")
|
|
56
56
|
.option("--no-index", "skip the initial repo index")
|
|
57
57
|
.option("--no-enforce", "do not install the advisory pre-commit constraint guard")
|
|
58
|
-
.option("--enforce-strict", "make the pre-commit guard FAIL the commit on a
|
|
58
|
+
.option("--enforce-strict", "make the pre-commit guard FAIL the commit on a direct, high-confidence, non-stale blocking invariant")
|
|
59
59
|
.option("--no-providers", "skip scaffolding non-Claude assistant configs (Cursor / VS Code / Codex / AGENTS.md)")
|
|
60
60
|
.option("--no-agent-hooks", "skip installing the Claude Code agent hooks (.claude/settings.json)")
|
|
61
61
|
.option("--firmness <level>", "agent-hook firmness: off | advisory | firm | strict")
|
|
@@ -91,7 +91,7 @@ program
|
|
|
91
91
|
if (opts.enforce !== false || opts.enforceStrict) {
|
|
92
92
|
const strict = !!opts.enforceStrict;
|
|
93
93
|
const p = installPreCommitHook(root, inv.shell, strict);
|
|
94
|
-
console.log(` ✓ pre-commit constraint guard ${p.action} (${strict ? "strict —
|
|
94
|
+
console.log(` ✓ pre-commit constraint guard ${p.action} (${strict ? "strict — fails only on direct, high-confidence, non-stale blocking invariants" : "advisory — flags invariants in scope or blast radius"})`);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
else {
|
|
@@ -144,20 +144,39 @@ program
|
|
|
144
144
|
store.close();
|
|
145
145
|
});
|
|
146
146
|
// ---- backfill -------------------------------------------------------------
|
|
147
|
+
/** Run an async fn over items with at most `limit` in flight. A fixed pool of
|
|
148
|
+
* workers pulls from a shared cursor — no per-batch barrier, so a slow item
|
|
149
|
+
* never stalls the others. Used by backfill to overlap per-commit LLM spawns. */
|
|
150
|
+
async function mapPool(items, limit, fn) {
|
|
151
|
+
let next = 0;
|
|
152
|
+
const worker = async () => {
|
|
153
|
+
while (next < items.length) {
|
|
154
|
+
const i = next++;
|
|
155
|
+
await fn(items[i], i);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));
|
|
159
|
+
}
|
|
147
160
|
program
|
|
148
161
|
.command("backfill")
|
|
149
162
|
.description("Replay git history to seed decisions (cold-start fix).")
|
|
150
163
|
.option("--since <spec>", "how far back, e.g. 90d", "90d")
|
|
151
164
|
.option("--max <n>", "max commits to process", "40")
|
|
165
|
+
.option("--concurrency <n>", "commits to synthesize in parallel (the LLM call is the bottleneck)", "4")
|
|
152
166
|
.action(async (opts) => {
|
|
153
167
|
const { store, root } = storeFor();
|
|
154
168
|
if (!isGitRepo(root))
|
|
155
169
|
return fail("backfill needs a git repo");
|
|
156
170
|
store.json.ensureDirs();
|
|
157
171
|
const commits = logSince(opts.since, root, Number(opts.max));
|
|
158
|
-
|
|
172
|
+
const conc = Math.max(1, Math.min(16, Number(opts.concurrency) || 4));
|
|
173
|
+
console.log(`Backfilling from ${commits.length} commit(s) since ${opts.since} (concurrency ${conc})…`);
|
|
159
174
|
let written = 0, skipped = 0, llm = 0, heuristic = 0;
|
|
160
|
-
|
|
175
|
+
// The per-commit cost is the Claude synthesis spawn; run several at once. Safe:
|
|
176
|
+
// each commit drafts independently and writes its OWN decision file atomically,
|
|
177
|
+
// and the store's JS-side reads/writes run synchronously between awaits (single
|
|
178
|
+
// thread) — only the LLM spawns overlap. reindex() runs once, after the pool.
|
|
179
|
+
await mapPool(commits, conc, async (sha) => {
|
|
161
180
|
const r = await syncCommit(store, root, sha);
|
|
162
181
|
if (r.status === "written") {
|
|
163
182
|
written++;
|
|
@@ -169,7 +188,7 @@ program
|
|
|
169
188
|
}
|
|
170
189
|
else
|
|
171
190
|
skipped++;
|
|
172
|
-
}
|
|
191
|
+
});
|
|
173
192
|
store.reindex();
|
|
174
193
|
updateClaudeMd(root, store);
|
|
175
194
|
// Honest tally of where the tokens went: trivial commits are seeded by the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davesheffer/hunch",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"license": "MIT",
|
|
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.",
|