@davesheffer/hunch 1.43.0 → 1.45.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.
Files changed (57) hide show
  1. package/README.md +16 -16
  2. package/dist/cli/index.js +267 -89
  3. package/dist/core/agenthook.d.ts +1 -0
  4. package/dist/core/agenthook.js +11 -0
  5. package/dist/core/changeProof.js +2 -1
  6. package/dist/core/commitrepair.d.ts +9 -3
  7. package/dist/core/commitrepair.js +23 -6
  8. package/dist/core/correction.d.ts +1 -1
  9. package/dist/core/correction.js +4 -3
  10. package/dist/core/docanchors.d.ts +11 -2
  11. package/dist/core/docanchors.js +232 -65
  12. package/dist/core/drift.d.ts +1 -1
  13. package/dist/core/drift.js +10 -3
  14. package/dist/core/eol.d.ts +2 -0
  15. package/dist/core/eol.js +6 -0
  16. package/dist/core/escalations.d.ts +20 -0
  17. package/dist/core/escalations.js +47 -0
  18. package/dist/core/hookText.js +1 -1
  19. package/dist/core/procstart.d.ts +15 -4
  20. package/dist/core/procstart.js +56 -18
  21. package/dist/core/runbookDraft.d.ts +7 -0
  22. package/dist/core/runbookDraft.js +43 -0
  23. package/dist/core/taskTouched.d.ts +2 -0
  24. package/dist/core/taskTouched.js +1 -1
  25. package/dist/extractors/git.d.ts +36 -6
  26. package/dist/extractors/git.js +86 -9
  27. package/dist/extractors/indexer.js +53 -14
  28. package/dist/extractors/k8sManifest.d.ts +31 -1
  29. package/dist/extractors/k8sManifest.js +133 -8
  30. package/dist/integrations/claudemd.d.ts +2 -0
  31. package/dist/integrations/claudemd.js +5 -3
  32. package/dist/integrations/gitignore.d.ts +23 -0
  33. package/dist/integrations/gitignore.js +48 -0
  34. package/dist/integrations/hooks.d.ts +15 -0
  35. package/dist/integrations/hooks.js +49 -1
  36. package/dist/integrations/mergeDriver.d.ts +2 -0
  37. package/dist/integrations/mergeDriver.js +2 -2
  38. package/dist/integrations/providers.d.ts +16 -0
  39. package/dist/integrations/providers.js +35 -6
  40. package/dist/integrations/scaffold.d.ts +5 -0
  41. package/dist/integrations/scaffold.js +13 -8
  42. package/dist/integrations/uninstall.d.ts +40 -0
  43. package/dist/integrations/uninstall.js +435 -0
  44. package/dist/mcp/leanToolList.d.ts +9 -0
  45. package/dist/mcp/leanToolList.js +89 -0
  46. package/dist/mcp/server.d.ts +2 -1
  47. package/dist/mcp/server.js +62 -6
  48. package/dist/serve/mcpHttp.js +2 -0
  49. package/dist/serve/writelock.d.ts +7 -0
  50. package/dist/serve/writelock.js +30 -3
  51. package/dist/store/changeLedger.d.ts +5 -2
  52. package/dist/store/changeLedger.js +88 -37
  53. package/dist/store/hunchStore.js +4 -1
  54. package/package.json +3 -6
  55. package/server.json +2 -2
  56. package/tooling/md1-benchmark.mjs +1 -1
  57. package/tooling/competitive-watch.mjs +0 -142
@@ -1,142 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const repos = [
4
- "davesheffer/hunch",
5
- "gitmem-dev/gitmem",
6
- "ismaelkedir/knowit",
7
- "weigibbor/mnemo",
8
- "oldskultxo/aictx",
9
- "riponcm/projectmem",
10
- "Cranot/roam-code",
11
- "blackwell-systems/knowing",
12
- "markmhendrickson/neotoma",
13
- ];
14
-
15
- const distinctivePhrases = [
16
- "Causal Merge Verdict",
17
- "corrections become enforced",
18
- "content-matched constraints",
19
- "deterministic Change Gate for AI-assisted codebases",
20
- ];
21
-
22
- let token = process.env.GITHUB_TOKEN?.trim();
23
- // A rejected token must DEGRADE the run, never kill it: ambient CI/proxy tokens
24
- // are often invalid for api.github.com, and the metadata half of this watch
25
- // works unauthenticated. Flipped on the first 401 so every later call skips
26
- // the bad credential instead of failing eight times.
27
- let tokenRejected = false;
28
-
29
- function headers() {
30
- return {
31
- Accept: "application/vnd.github+json",
32
- "User-Agent": "hunch-competitive-watch",
33
- "X-GitHub-Api-Version": "2022-11-28",
34
- ...(token && !tokenRejected ? { Authorization: `Bearer ${token}` } : {}),
35
- };
36
- }
37
-
38
- async function github(path) {
39
- let response = await fetch(`https://api.github.com${path}`, { headers: headers() });
40
- if (response.status === 401 && token && !tokenRejected) {
41
- tokenRejected = true;
42
- process.stderr.write("competitive-watch: GITHUB_TOKEN rejected (401) — continuing unauthenticated; phrase search will be skipped.\n");
43
- response = await fetch(`https://api.github.com${path}`, { headers: headers() });
44
- }
45
- if (!response.ok) {
46
- const detail = (await response.text()).slice(0, 300).replaceAll("\n", " ");
47
- throw new Error(`GitHub ${response.status} for ${path}: ${detail}`);
48
- }
49
- return response.json();
50
- }
51
-
52
- async function repoSnapshot(repo) {
53
- // One vanished/renamed repo is itself a signal worth a row — never a reason
54
- // to lose the other seven.
55
- try {
56
- const data = await github(`/repos/${repo}`);
57
- return {
58
- repo,
59
- created: data.created_at,
60
- pushed: data.pushed_at,
61
- stars: data.stargazers_count,
62
- forks: data.forks_count,
63
- issues: data.open_issues_count,
64
- url: data.html_url,
65
- };
66
- } catch (error) {
67
- return { repo, error: error instanceof Error ? error.message : String(error) };
68
- }
69
- }
70
-
71
- async function phraseSnapshot(phrase) {
72
- const query = encodeURIComponent(`"${phrase}"`);
73
- const data = await github(`/search/code?q=${query}&per_page=100`);
74
- const external = data.items
75
- .filter((item) => !item.repository.full_name.startsWith("davesheffer/"))
76
- .map((item) => ({
77
- repo: item.repository.full_name,
78
- path: item.path,
79
- url: item.html_url,
80
- }));
81
- return { phrase, total: data.total_count, external };
82
- }
83
-
84
- function render(snapshot, phrases) {
85
- const lines = [
86
- `# Competitive watch — ${new Date().toISOString()}`,
87
- "",
88
- "## Public repository signals",
89
- "",
90
- "| Repository | Created | Last push | Stars | Forks | Open issues |",
91
- "| --- | --- | --- | ---: | ---: | ---: |",
92
- ];
93
-
94
- for (const item of snapshot) {
95
- if (item.error) {
96
- lines.push(`| ${item.repo} | — | — | — | — | — |`);
97
- continue;
98
- }
99
- lines.push(
100
- `| [${item.repo}](${item.url}) | ${item.created.slice(0, 10)} | ${item.pushed.slice(0, 10)} | ${item.stars} | ${item.forks} | ${item.issues} |`,
101
- );
102
- }
103
- const failed = snapshot.filter((item) => item.error);
104
- if (failed.length) {
105
- lines.push("");
106
- for (const item of failed) lines.push(`- ⚠ ${item.repo}: ${item.error}`);
107
- }
108
-
109
- lines.push("", "## Distinctive phrase search", "");
110
- if (!token) {
111
- lines.push("Skipped: set `GITHUB_TOKEN` to enable authenticated GitHub code search.");
112
- } else if (tokenRejected) {
113
- lines.push("Skipped: `GITHUB_TOKEN` was rejected by api.github.com (401) — repo metadata above was collected unauthenticated. Provide a valid token (e.g. `GITHUB_TOKEN=\"$(gh auth token)\"`) to run the phrase-copy check.");
114
- } else {
115
- for (const result of phrases) {
116
- lines.push(`- **${result.phrase}** — ${result.external.length} external indexed match(es)`);
117
- for (const match of result.external) {
118
- lines.push(` - [${match.repo} · ${match.path}](${match.url})`);
119
- }
120
- }
121
- }
122
-
123
- lines.push(
124
- "",
125
- "> Signals are leads, not copying findings. Re-check chronology and substantial similarity before drawing a conclusion.",
126
- );
127
- return `${lines.join("\n")}\n`;
128
- }
129
-
130
- try {
131
- const snapshot = [];
132
- // Sequential on purpose: the first call settles token validity before the
133
- // rest, and unauthenticated rate limits are too small to burst against.
134
- for (const repo of repos) snapshot.push(await repoSnapshot(repo));
135
- const phrases = token && !tokenRejected
136
- ? await Promise.all(distinctivePhrases.map(phraseSnapshot))
137
- : [];
138
- process.stdout.write(render(snapshot, phrases));
139
- } catch (error) {
140
- process.stderr.write(`competitive-watch: ${error instanceof Error ? error.message : String(error)}\n`);
141
- process.exitCode = 1;
142
- }