@davesheffer/hunch 1.31.1 → 1.32.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.
Files changed (223) hide show
  1. package/README.md +2 -1
  2. package/dist/cli/automaticReviewMemory.d.ts +13 -0
  3. package/dist/cli/dna.d.ts +2 -0
  4. package/dist/cli/index.d.ts +16 -0
  5. package/dist/cli/index.js +606 -43
  6. package/dist/cli/integrations.d.ts +2 -0
  7. package/dist/cli/integrations.js +5 -2
  8. package/dist/cli/invocation.d.ts +35 -0
  9. package/dist/cli/preflight.d.ts +1 -0
  10. package/dist/cli/reviewMemory.d.ts +4 -0
  11. package/dist/cli/reviewMemoryProvider.d.ts +14 -0
  12. package/dist/cli/serve.d.ts +2 -0
  13. package/dist/cli/taskReport.d.ts +6 -0
  14. package/dist/cli/taskReport.js +128 -0
  15. package/dist/cli/update.d.ts +14 -0
  16. package/dist/client/state.d.ts +248 -0
  17. package/dist/constitution/adapters.d.ts +29 -0
  18. package/dist/constitution/behaviorAttestationBinding.d.ts +3 -0
  19. package/dist/constitution/behaviorEvaluator.d.ts +8 -0
  20. package/dist/constitution/behaviorProof.d.ts +9 -0
  21. package/dist/constitution/behaviorWorkspace.d.ts +25 -0
  22. package/dist/constitution/bootstrap.d.ts +30 -0
  23. package/dist/constitution/canonical.d.ts +15 -0
  24. package/dist/constitution/card.d.ts +58 -0
  25. package/dist/constitution/compiler.d.ts +52 -0
  26. package/dist/constitution/composition.d.ts +10 -0
  27. package/dist/constitution/corpus.d.ts +7 -0
  28. package/dist/constitution/correctionPolicyMaterializer.d.ts +57 -0
  29. package/dist/constitution/delta.d.ts +4 -0
  30. package/dist/constitution/disposition.d.ts +20 -0
  31. package/dist/constitution/evaluator.d.ts +47 -0
  32. package/dist/constitution/experiment.d.ts +466 -0
  33. package/dist/constitution/experimentRunner.d.ts +7 -0
  34. package/dist/constitution/g2.d.ts +209 -0
  35. package/dist/constitution/g2BehaviorAttestation.d.ts +45 -0
  36. package/dist/constitution/g2BehaviorCandidates.d.ts +123 -0
  37. package/dist/constitution/g2BehaviorDependencies.d.ts +83 -0
  38. package/dist/constitution/g2BehaviorMaterialization.d.ts +77 -0
  39. package/dist/constitution/g2BehaviorPolicyMaterializer.d.ts +48 -0
  40. package/dist/constitution/g2CandidateAttestation.d.ts +43 -0
  41. package/dist/constitution/g2Candidates.d.ts +80 -0
  42. package/dist/constitution/g2Drills.d.ts +33 -0
  43. package/dist/constitution/g3.d.ts +311 -0
  44. package/dist/constitution/g3Conformance.d.ts +33 -0
  45. package/dist/constitution/lifecycle.d.ts +25 -0
  46. package/dist/constitution/mutation.d.ts +15 -0
  47. package/dist/constitution/nodeTestEvidence.d.ts +13 -0
  48. package/dist/constitution/plan.d.ts +18 -0
  49. package/dist/constitution/policyRuntime.d.ts +5 -0
  50. package/dist/constitution/proof.d.ts +11 -0
  51. package/dist/constitution/repairPolicies.d.ts +34 -0
  52. package/dist/constitution/replacementFreeGit.d.ts +14 -0
  53. package/dist/constitution/replay.d.ts +40 -0
  54. package/dist/constitution/replayCache.d.ts +14 -0
  55. package/dist/constitution/replayWorker.d.ts +1 -0
  56. package/dist/constitution/repository.d.ts +129 -0
  57. package/dist/constitution/safeCheckout.d.ts +9 -0
  58. package/dist/constitution/schema.d.ts +1763 -0
  59. package/dist/constitution/scorecard.d.ts +219 -0
  60. package/dist/constitution/service.d.ts +398 -0
  61. package/dist/constitution/shadow.d.ts +54 -0
  62. package/dist/constitution/sourceMutation.d.ts +15 -0
  63. package/dist/constitution/staticGraphBaseline.d.ts +13 -0
  64. package/dist/constitution/structural.d.ts +64 -0
  65. package/dist/core/agenthook.d.ts +63 -0
  66. package/dist/core/agenthook.js +1 -0
  67. package/dist/core/automaticReviewMemory.d.ts +60 -0
  68. package/dist/core/autoreview.d.ts +66 -0
  69. package/dist/core/canonicalOrder.d.ts +3 -0
  70. package/dist/core/capturetoken.d.ts +19 -0
  71. package/dist/core/changeIdentity.d.ts +22 -0
  72. package/dist/core/changeProof.d.ts +14 -0
  73. package/dist/core/checkreport.d.ts +140 -0
  74. package/dist/core/commitrepair.d.ts +171 -0
  75. package/dist/core/commitrepair.js +238 -0
  76. package/dist/core/compare.d.ts +21 -0
  77. package/dist/core/config.d.ts +20 -0
  78. package/dist/core/conformance.d.ts +35 -0
  79. package/dist/core/constraintmatch.d.ts +54 -0
  80. package/dist/core/correction.d.ts +42 -0
  81. package/dist/core/correctionStage.d.ts +224 -0
  82. package/dist/core/declarationClusters.d.ts +149 -0
  83. package/dist/core/delivery.d.ts +110 -0
  84. package/dist/core/docanchors.d.ts +32 -0
  85. package/dist/core/docscan.d.ts +26 -0
  86. package/dist/core/drift.d.ts +13 -0
  87. package/dist/core/drift.js +31 -1
  88. package/dist/core/dupdetect.d.ts +43 -0
  89. package/dist/core/escalations.d.ts +129 -0
  90. package/dist/core/escalations.js +165 -0
  91. package/dist/core/events.d.ts +29 -0
  92. package/dist/core/evidenceMap.d.ts +164 -0
  93. package/dist/core/externalImports.d.ts +8 -0
  94. package/dist/core/format.d.ts +13 -0
  95. package/dist/core/glob.d.ts +9 -0
  96. package/dist/core/groundingLag.d.ts +84 -0
  97. package/dist/core/groundingLag.js +16 -2
  98. package/dist/core/groundingMerge.d.ts +15 -0
  99. package/dist/core/groundingMerge.js +95 -0
  100. package/dist/core/hookObservations.d.ts +9 -0
  101. package/dist/core/hookObservations.js +33 -0
  102. package/dist/core/hookcache.d.ts +10 -0
  103. package/dist/core/hookpolicy.d.ts +47 -0
  104. package/dist/core/ids.d.ts +36 -0
  105. package/dist/core/importReview.d.ts +30 -0
  106. package/dist/core/io.d.ts +23 -0
  107. package/dist/core/jsonc.d.ts +4 -0
  108. package/dist/core/landscapeAdoption.d.ts +66 -0
  109. package/dist/core/landscapeDelivery.d.ts +76 -0
  110. package/dist/core/memorylog.d.ts +37 -0
  111. package/dist/core/migrate.d.ts +28 -0
  112. package/dist/core/outcomeExperience.d.ts +89 -0
  113. package/dist/core/overlaySafety.d.ts +24 -0
  114. package/dist/core/overlaySafety.js +7 -1
  115. package/dist/core/paths.d.ts +31 -0
  116. package/dist/core/pipeline.d.ts +289 -0
  117. package/dist/core/premises.d.ts +43 -0
  118. package/dist/core/provenance.d.ts +21 -0
  119. package/dist/core/publication.d.ts +54 -0
  120. package/dist/core/refrepair.d.ts +24 -0
  121. package/dist/core/refrepair.js +1 -1
  122. package/dist/core/relativeImports.d.ts +11 -0
  123. package/dist/core/repair.d.ts +44 -0
  124. package/dist/core/repairqueue.d.ts +40 -0
  125. package/dist/core/repairqueue.js +133 -0
  126. package/dist/core/reviewMemory.d.ts +40 -0
  127. package/dist/core/reviewqueue.d.ts +54 -0
  128. package/dist/core/safeRepoFile.d.ts +20 -0
  129. package/dist/core/served.d.ts +57 -0
  130. package/dist/core/served.js +14 -0
  131. package/dist/core/stateContract.d.ts +979 -0
  132. package/dist/core/stateDelivery.d.ts +78 -0
  133. package/dist/core/stateRecords.d.ts +383 -0
  134. package/dist/core/stats.d.ts +88 -0
  135. package/dist/core/strictgate.d.ts +33 -0
  136. package/dist/core/taskReport.d.ts +226 -0
  137. package/dist/core/taskReport.js +514 -0
  138. package/dist/core/taskReportCapture.d.ts +8 -0
  139. package/dist/core/taskReportCapture.js +36 -0
  140. package/dist/core/taskReportEvidence.d.ts +28 -0
  141. package/dist/core/taskReportEvidence.js +272 -0
  142. package/dist/core/taskReportHook.d.ts +20 -0
  143. package/dist/core/taskReportHook.js +76 -0
  144. package/dist/core/taskReportPaths.d.ts +3 -0
  145. package/dist/core/taskReportPaths.js +23 -0
  146. package/dist/core/taskReportPublic.d.ts +31 -0
  147. package/dist/core/taskReportPublic.js +45 -0
  148. package/dist/core/taskReportRender.d.ts +6 -0
  149. package/dist/core/taskReportRender.js +97 -0
  150. package/dist/core/topics.d.ts +73 -0
  151. package/dist/core/types.d.ts +1239 -0
  152. package/dist/core/version.d.ts +10 -0
  153. package/dist/eval/guards.d.ts +45 -0
  154. package/dist/eval/harness.d.ts +58 -0
  155. package/dist/extractors/adrImport.d.ts +59 -0
  156. package/dist/extractors/comments.d.ts +7 -0
  157. package/dist/extractors/correctionSources.d.ts +11 -0
  158. package/dist/extractors/diff.d.ts +40 -0
  159. package/dist/extractors/git.d.ts +304 -0
  160. package/dist/extractors/git.js +208 -20
  161. package/dist/extractors/helm.d.ts +31 -0
  162. package/dist/extractors/indexer.d.ts +55 -0
  163. package/dist/extractors/landscapeDiscovery.d.ts +41 -0
  164. package/dist/extractors/languages.d.ts +77 -0
  165. package/dist/extractors/nativeTreeSitter.d.ts +16 -0
  166. package/dist/extractors/parse.d.ts +54 -0
  167. package/dist/extractors/php.d.ts +26 -0
  168. package/dist/extractors/repoSource.d.ts +53 -0
  169. package/dist/extractors/testreport.d.ts +36 -0
  170. package/dist/integrations/ciAction.d.ts +8 -0
  171. package/dist/integrations/claudeConfig.d.ts +44 -0
  172. package/dist/integrations/claudemd.d.ts +13 -0
  173. package/dist/integrations/claudemd.js +11 -2
  174. package/dist/integrations/gitignore.d.ts +16 -0
  175. package/dist/integrations/gitignore.js +7 -0
  176. package/dist/integrations/health.d.ts +74 -0
  177. package/dist/integrations/health.js +32 -2
  178. package/dist/integrations/hooks.d.ts +41 -0
  179. package/dist/integrations/hooks.js +92 -66
  180. package/dist/integrations/madrExport.d.ts +39 -0
  181. package/dist/integrations/madrManifest.d.ts +69 -0
  182. package/dist/integrations/mergeDriver.d.ts +3 -0
  183. package/dist/integrations/mergeDriver.js +25 -8
  184. package/dist/integrations/probe.d.ts +4 -0
  185. package/dist/integrations/providers.d.ts +103 -0
  186. package/dist/integrations/scaffold.d.ts +29 -0
  187. package/dist/integrations/sync.d.ts +30 -0
  188. package/dist/integrations/sync.js +3 -2
  189. package/dist/integrations/team.d.ts +70 -0
  190. package/dist/integrations/worktree.d.ts +8 -0
  191. package/dist/mcp/roots.d.ts +16 -0
  192. package/dist/mcp/server.d.ts +36 -0
  193. package/dist/mcp/server.js +74 -22
  194. package/dist/mcp/taskReportTools.d.ts +188 -0
  195. package/dist/mcp/taskReportTools.js +147 -0
  196. package/dist/serve/app.d.ts +36 -0
  197. package/dist/serve/config.d.ts +100 -0
  198. package/dist/serve/writelock.d.ts +22 -0
  199. package/dist/store/changeLedger.d.ts +132 -0
  200. package/dist/store/compact.d.ts +33 -0
  201. package/dist/store/db.d.ts +9 -0
  202. package/dist/store/embedder.d.ts +32 -0
  203. package/dist/store/hunchStore.d.ts +624 -0
  204. package/dist/store/hunchStore.js +6 -3
  205. package/dist/store/jsonStore.d.ts +125 -0
  206. package/dist/store/merge.d.ts +39 -0
  207. package/dist/store/privateMigrate.d.ts +24 -0
  208. package/dist/store/replay.d.ts +56 -0
  209. package/dist/store/schema.d.ts +17 -0
  210. package/dist/store/stateBinding.d.ts +145 -0
  211. package/dist/store/stateCapture.d.ts +15 -0
  212. package/dist/synthesis/cliAdapter.d.ts +22 -0
  213. package/dist/synthesis/initiator.d.ts +13 -0
  214. package/dist/synthesis/provider.d.ts +307 -0
  215. package/dist/synthesis/synthesize.d.ts +117 -0
  216. package/dist/synthesis/tripwires.d.ts +9 -0
  217. package/dist/taskReports.d.ts +79 -0
  218. package/dist/taskReports.js +69 -0
  219. package/dist/wiki/adopt.d.ts +22 -0
  220. package/dist/wiki/graph.d.ts +87 -0
  221. package/dist/wiki/wiki.d.ts +242 -0
  222. package/package.json +6 -5
  223. package/server.json +2 -2
@@ -0,0 +1,39 @@
1
+ /**
2
+ * MADR export (the MADR bridge, export half — roadmap's "compiler" projection).
3
+ *
4
+ * Renders the PUBLIC decision graph as a regenerated MADR 3.x corpus: one
5
+ * NNNN-slug.md per decision, superseded links derived from superseded_by /
6
+ * valid_to, rejected alternatives under Considered Options. The projection is a
7
+ * DISPOSABLE build artifact — the graph stays the source of truth, numbers are
8
+ * assigned per export (date order), and every emitted file carries a generated
9
+ * marker. The writer only ever overwrites files bearing that marker: a
10
+ * hand-written ADR corpus in the target directory is untouchable (refused with
11
+ * a warning), so `hunch import-adr` + `hunch export-adr` can share a repo
12
+ * without the export eating its own import source.
13
+ *
14
+ * Privacy boundary: rendering takes an explicit PUBLIC-only decision list —
15
+ * callers must pass store.json.loadAll("decisions"), never the overlay union.
16
+ */
17
+ import type { Decision } from "../core/types.js";
18
+ export declare const MADR_EXPORT_MARKER = "<!-- hunch:generated madr-export \u2014 regenerated by `hunch export-adr`; edits will be overwritten -->";
19
+ export interface MadrFile {
20
+ /** file name only, NNNN-slug.md */
21
+ name: string;
22
+ text: string;
23
+ decisionId: string;
24
+ }
25
+ export interface MadrExportResult {
26
+ files: MadrFile[];
27
+ /** the one-line Backstage catalog-info annotation for this corpus */
28
+ backstageAnnotation: string;
29
+ }
30
+ /** Render one decision as a MADR 3.x document. Deterministic: content depends
31
+ * only on the decision record and the corpus's name map. */
32
+ export declare function renderMadr(d: Decision, nameOf: Map<string, string>): string;
33
+ /** Project a PUBLIC decision list into a MADR corpus. Numbering is date order
34
+ * (valid_from, then date, then id for determinism) and assigned per export —
35
+ * the projection is disposable, links inside it are internally consistent. */
36
+ export declare function exportMadrCorpus(decisions: readonly Decision[], dirForAnnotation: string): MadrExportResult;
37
+ /** True when an existing file may be overwritten by the export: only our own
38
+ * generated output ever qualifies. */
39
+ export declare function isRegenerableMadr(existingText: string): boolean;
@@ -0,0 +1,69 @@
1
+ import type { Decision } from "../core/types.js";
2
+ import type { DriftFinding } from "../core/drift.js";
3
+ export interface MadrManifest {
4
+ version: 1;
5
+ /** repo-relative POSIX dir the corpus was exported to */
6
+ dir: string;
7
+ /** keyed by file name (NNNN-slug.md) — the export assigns numbers per run */
8
+ files: Record<string, {
9
+ decision: string;
10
+ hash: string;
11
+ bytes: string;
12
+ generated: string;
13
+ }>;
14
+ }
15
+ export declare function madrManifestPath(root: string): string;
16
+ export declare function readMadrManifest(root: string): MadrManifest | null;
17
+ export declare function writeMadrManifest(root: string, manifest: MadrManifest): void;
18
+ /** The projected-content hash for one file. Content, not mtime: a re-export that
19
+ * changes nothing must not read as drift. */
20
+ export declare const madrContentHash: (text: string) => string;
21
+ /**
22
+ * Build the manifest for a corpus that was just written.
23
+ *
24
+ * `written` carries the bytes actually placed on disk, which may differ from the
25
+ * rendered text when a file was refused (hand-written corpus in the target dir).
26
+ * Refused files are absent from the manifest, so they are never later reported
27
+ * as edited — they were never ours.
28
+ */
29
+ export declare function buildMadrManifest(dir: string, entries: ReadonlyArray<{
30
+ name: string;
31
+ text: string;
32
+ decisionId: string;
33
+ }>, generatedAt: string): MadrManifest;
34
+ /**
35
+ * Drift for the MADR projection. Fires ONLY where a manifest exists — a repo that
36
+ * never ran `hunch export-adr` sees zero noise, matching the wiki's rule.
37
+ *
38
+ * Takes the PUBLIC decision list, never the overlay union: the projection is a
39
+ * committable artifact, so its freshness must be computed from exactly the
40
+ * records that are allowed to reach it. Passing the union here would leak the
41
+ * existence of overlay decisions into a public drift report.
42
+ */
43
+ export declare function computeMadrDrift(publicDecisions: readonly Decision[], root: string): DriftFinding[];
44
+ /**
45
+ * Keep an adopted corpus fresh automatically.
46
+ *
47
+ * Called from the post-commit sync path (and from any writer that changes the
48
+ * public graph out of band, such as the memory service's HTTP write path), so a
49
+ * user who ran `hunch export-adr` once never has to run it again — the
50
+ * projection tracks the graph the way the SQLite index does.
51
+ *
52
+ * Deliberately narrow:
53
+ * - No manifest → no-op. Adoption stays an explicit act.
54
+ * - Refuses to touch a file that was hand-edited, because silently discarding
55
+ * someone's edit is worse than a stale file; `madr-edited` drift reports it
56
+ * and the human decides.
57
+ * - Removes generated files the new numbering dropped, so the corpus stays
58
+ * internally consistent, but never removes a file it did not generate.
59
+ *
60
+ * Returns what changed so callers can log it; throws nothing the caller must
61
+ * handle — a projection refresh must never take down a commit or an HTTP write.
62
+ */
63
+ export interface MadrRefreshResult {
64
+ dir: string;
65
+ written: number;
66
+ removed: number;
67
+ skippedEdited: string[];
68
+ }
69
+ export declare function refreshMadrCorpus(publicDecisions: readonly Decision[], root: string, now: string): MadrRefreshResult | null;
@@ -0,0 +1,3 @@
1
+ export declare function installMergeDriver(root: string, invShell: string): {
2
+ action: string;
3
+ };
@@ -1,17 +1,30 @@
1
1
  /**
2
- * Wires up the structured `.hunch/` git merge driver (store/merge.ts):
3
- * - `.gitattributes` (committed) routes the .hunch JSON files through merge=hunch,
4
- * - local git config maps merge=hunch to `hunch merge-driver …` (per clone, so
5
- * each teammate runs `hunch init` to register it).
2
+ * Wires up two independent git merge drivers:
3
+ * - `merge=hunch` the structured `.hunch/` JSON driver (store/merge.ts):
4
+ * resolves concurrent edits by record id.
5
+ * - `merge=hunch-grounding` the generated grounding docs (core/groundingMerge.ts):
6
+ * auto-resolves a hard conflict confined to the record-counts sentence,
7
+ * leaving any other conflict untouched (dec_ba5b0dfa22).
8
+ * Both routes live in `.gitattributes` (committed, travels with the repo);
9
+ * both drivers are registered in LOCAL git config only (per-clone, since each
10
+ * references this machine's node + cli path — teammates re-run `hunch init`).
6
11
  */
7
12
  import { execFileSync } from "node:child_process";
8
13
  import { readFileSync, existsSync } from "node:fs";
9
14
  import { writeFileAtomic } from "../core/io.js";
10
15
  import { assertSafeTopLevelConfigFile } from "./gitignore.js";
16
+ import { GROUNDING_DOC_PATHS } from "./providers.js";
11
17
  // Route the .hunch JSON records through the structured driver — but NOT the
12
18
  // manifest (an id-less `{schema_version}` object the driver can't merge by id; a
13
19
  // normal text merge with conflict markers is the right behavior for it).
14
- const ATTR_LINES = [".hunch/**/*.json merge=hunch", ".hunch/manifest.json merge=text"];
20
+ //
21
+ // The five generated grounding docs get the OTHER driver — narrower in scope
22
+ // (it only ever touches a hard conflict confined to the counts sentence).
23
+ const ATTR_LINES = [
24
+ ".hunch/**/*.json merge=hunch",
25
+ ".hunch/manifest.json merge=text",
26
+ ...GROUNDING_DOC_PATHS.map((f) => `${f} merge=hunch-grounding`),
27
+ ];
15
28
  function targetRepositoryEnv() {
16
29
  const env = { ...process.env };
17
30
  for (const key of [
@@ -43,17 +56,21 @@ export function installMergeDriver(root, invShell) {
43
56
  assertSafeTopLevelConfigFile(root, ".gitattributes");
44
57
  writeFileAtomic(attrPath, text);
45
58
  }
46
- // 2. Local git config — the driver definition is per-clone (it references this
47
- // machine's node + cli path), so it is NOT committed; teammates re-run init.
59
+ // 2. Local git config — the driver definitions are per-clone (they reference
60
+ // this machine's node + cli path), so they are NOT committed; teammates
61
+ // re-run init.
48
62
  const driver = `${invShell} merge-driver "%O" "%A" "%B" "%P"`;
63
+ const groundingDriver = `${invShell} merge-driver-grounding "%O" "%A" "%B" "%P"`;
49
64
  const env = targetRepositoryEnv();
50
65
  try {
51
66
  execFileSync("git", ["config", "merge.hunch.name", "hunch structured JSON merge"], { cwd: root, env });
52
67
  execFileSync("git", ["config", "merge.hunch.driver", driver], { cwd: root, env });
68
+ execFileSync("git", ["config", "merge.hunch-grounding.name", "hunch grounding-counts merge"], { cwd: root, env });
69
+ execFileSync("git", ["config", "merge.hunch-grounding.driver", groundingDriver], { cwd: root, env });
53
70
  }
54
71
  catch {
55
72
  return { action: `${attrAction} .gitattributes — but \`git config\` failed (not a git repo?)` };
56
73
  }
57
- return { action: `${attrAction} .gitattributes + registered merge.hunch driver` };
74
+ return { action: `${attrAction} .gitattributes + registered merge.hunch + merge.hunch-grounding drivers` };
58
75
  }
59
76
  //# sourceMappingURL=mergeDriver.js.map
@@ -0,0 +1,4 @@
1
+ import { type Harness, type IntegrationHealth } from "./health.js";
2
+ /** Opt-in: starts a fresh configured MCP process, never claims the current
3
+ * harness connection or hook delivery has been tested. No model is invoked. */
4
+ export declare function probeIntegration(root: string, harness: Harness, report: IntegrationHealth, timeoutMs?: number): Promise<void>;
@@ -0,0 +1,103 @@
1
+ import type { HunchStore } from "../store/hunchStore.js";
2
+ import type { Invocation } from "./scaffold.js";
3
+ /** Cursor: .cursor/mcp.json — same `mcpServers` shape as Claude Desktop/Code. */
4
+ export declare function writeCursorMcp(root: string, inv: Invocation): string;
5
+ /** VS Code (Copilot agent mode): .vscode/mcp.json — root key is `servers`, and
6
+ * each stdio entry carries an explicit `type: "stdio"` (VS Code's schema). */
7
+ export declare function writeVscodeMcp(root: string, inv: Invocation): string;
8
+ /** Google Antigravity's global MCP config moved between releases. Resolve
9
+ * adaptively: an existing config wins, else an existing parent dir, else null
10
+ * (Antigravity not installed — we never create a global config for an absent
11
+ * tool). The current project-local config is handled separately below. `home`
12
+ * is injectable for tests so we never touch the real ~/.gemini. */
13
+ export declare function antigravityMcpFile(home?: string): string | null;
14
+ /** Antigravity: merge the hunch stdio server into the global mcp_config.json — same
15
+ * `mcpServers` { command, args } shape as Cursor/Claude (stdio; `serverUrl` is only for
16
+ * HTTP servers). Returns null when Antigravity isn't detected. Grounding needs nothing
17
+ * extra: Antigravity reads the project-root AGENTS.md Hunch already writes. */
18
+ export declare function writeAntigravityMcp(inv: Invocation, home?: string): string | null;
19
+ /** Current Antigravity IDE/CLI project config. Unlike a global config this is
20
+ * committed with the repository, so every clone gets the same private/local
21
+ * Hunch server without touching a user's home directory. */
22
+ export declare function writeAntigravityWorkspaceMcp(root: string, inv: Invocation): string;
23
+ /** Codex CLI: .codex/config.toml — `[mcp_servers.hunch]` stdio entry. We own only
24
+ * a marker-delimited block; any other TOML the user has is preserved. Paths use
25
+ * TOML single-quote LITERAL strings so Windows backslashes need no escaping. */
26
+ export declare function writeCodexConfig(root: string, inv: Invocation): string;
27
+ /** AGENTS.md — the cross-tool ambient-instruction standard (Codex and a growing
28
+ * set of assistants read it). Marker-delimited so user prose is preserved. */
29
+ export declare function writeAgentsMd(root: string, store: HunchStore): string;
30
+ /** GitHub Copilot custom instructions (VS Code / github.com). Same grounding. */
31
+ export declare function writeCopilotInstructions(root: string, store: HunchStore): string;
32
+ /** Cursor project rule (.mdc = frontmatter + body). `alwaysApply` keeps the Hunch
33
+ * grounding in context for every request. Fully managed by Hunch (overwritten). */
34
+ export declare function writeCursorRule(root: string, store: HunchStore): string;
35
+ /** Windsurf (Cascade): .windsurf/mcp_config.json — same `mcpServers` shape as
36
+ * Cursor. Repo-local (committed, shared via git) to match Hunch's other configs,
37
+ * rather than the global ~/.codeium/windsurf path. Merges; refuses to clobber. */
38
+ export declare function writeWindsurfMcp(root: string, inv: Invocation): string;
39
+ /** Current Windsurf also discovers a user config at ~/.codeium/windsurf. Only
40
+ * touch it when the tool is already installed/configured; Hunch never creates a
41
+ * global configuration for an application the user does not have. */
42
+ export declare function windsurfMcpFile(home?: string): string | null;
43
+ export declare function writeWindsurfGlobalMcp(inv: Invocation, home?: string): string | null;
44
+ /** Windsurf project rule (.windsurf/rules/hunch.md). `trigger: always_on` keeps the
45
+ * Hunch grounding in Cascade's context for every request. Fully managed (overwritten). */
46
+ export declare function writeWindsurfRule(root: string, store: HunchStore): string;
47
+ /** Cursor's hook API is beta, but its project-level config accepts this standard
48
+ * event map. Context delivery is opportunistic; the always-on rule and MCP
49
+ * registration remain the durable grounding path if a Cursor build suppresses
50
+ * a hook's agent_message. */
51
+ export declare function writeCursorHooks(root: string, inv: Invocation): string;
52
+ /** VS Code's native workspace hook location. It supports all lifecycle events
53
+ * Hunch needs and uses the same stdout contract as Claude Code, with different
54
+ * camelCase tool fields normalized in core/agenthook.ts. */
55
+ export declare function writeVscodeHooks(root: string, inv: Invocation): string;
56
+ /** Windsurf's documented workspace hooks. It only supports deterministic
57
+ * pre-hook blocking via exit code 2, so Hunch uses rules + MCP for context and
58
+ * reserves the hook for strict edit protection and pipeline observation. */
59
+ export declare function writeWindsurfHooks(root: string, inv: Invocation): string;
60
+ /** Antigravity keeps hook groups at the top level (not under `hooks`). Hunch
61
+ * owns only the `hunch` group and replaces its own old entries idempotently. */
62
+ export declare function writeAntigravityHooks(root: string, inv: Invocation): string;
63
+ /** Rewrite the auto-maintained Hunch section in EVERY assistant grounding doc
64
+ * (CLAUDE.md, AGENTS.md, Copilot instructions, Cursor + Windsurf rules) from the
65
+ * current store — without touching the MCP/provider config files. `hunch private
66
+ * --migrate` calls this AFTER emptying the public store so the committed public
67
+ * docs reflect that no engineering memory is published here (renderHunchSection
68
+ * reads the public store only, so private records never leak into them). */
69
+ export declare function regenerateGrounding(root: string, store: HunchStore): string[];
70
+ /** The five grounding docs, repo-relative (POSIX separators, as git prints them). */
71
+ export declare const GROUNDING_DOC_PATHS: readonly string[];
72
+ /** Self-heal: refresh the Hunch section in each grounding doc that ALREADY exists,
73
+ * and report which ones actually changed. Unlike regenerateGrounding it NEVER creates
74
+ * a file (so it can't scaffold grounding into a project that opted out of an
75
+ * assistant). Run by `hunch index` and non-hook `hunch sync` so a project silently
76
+ * picks up generator fixes (e.g. corrected MCP tool param names) and fresh record
77
+ * counts on the next refresh — no manual `hunch init`. */
78
+ export declare function refreshExistingGrounding(root: string, store: HunchStore): string[];
79
+ /** Capture-commit refresh: rewrite grounding docs that are git-clean OR whose only
80
+ * divergence from HEAD is generated content, and return the absolute paths to fold
81
+ * into the memory commit (commitAndPushHunch alsoStage). This keeps committed record
82
+ * counts permanently true — every capture used to bump the count and re-stale the
83
+ * committed docs, failing the release gate's clean-tree check on the next CI index
84
+ * (the refresh-counts treadmill). The generated-dirt branch closes the second half
85
+ * (fnd_b269d5c422): once a doc went stale-dirty, the clean-only rule skipped it on
86
+ * every later flush FOREVER, and each release needed a manual chore commit. A doc
87
+ * whose USER PROSE differs from HEAD is still left completely untouched. */
88
+ export declare function refreshCommittableGrounding(root: string, store: HunchStore): string[];
89
+ export interface ProviderScaffold {
90
+ assistant: string;
91
+ files: string[];
92
+ /** Set when this assistant was skipped (e.g. an unparseable existing config we
93
+ * refused to clobber) — surfaced as a warning, not a fatal init failure. */
94
+ error?: string;
95
+ }
96
+ /** Scaffold MCP config + grounding for all supported assistants. Returns a
97
+ * per-assistant summary for `hunch init` to print. Each assistant is isolated:
98
+ * a writer that refuses to clobber a malformed file degrades to a warning rather
99
+ * than aborting the rest. Claude Code is handled separately by scaffold.ts. */
100
+ export declare function scaffoldProviders(root: string, inv: Invocation, store: HunchStore, options?: {
101
+ agentHooks?: boolean;
102
+ home?: string;
103
+ }): ProviderScaffold[];
@@ -0,0 +1,29 @@
1
+ export interface Invocation {
2
+ command: string;
3
+ args: string[];
4
+ }
5
+ /** Merge a `hunch` server entry into .mcp.json, preserving other servers.
6
+ * A non-empty file we cannot parse THROWS instead of being silently replaced
7
+ * (con_8460b6770f — it may hold the user's other MCP servers); the caller
8
+ * degrades that to a warning. */
9
+ export declare function writeMcpJson(root: string, inv: Invocation): string;
10
+ export interface ClaudeHookInstall {
11
+ path: string;
12
+ action: "created" | "updated" | "unchanged";
13
+ }
14
+ /**
15
+ * Install the Claude Code AGENT hooks into `.claude/settings.json` so the agent
16
+ * is grounded in Hunch automatically (not by remembering to call the tools):
17
+ * - PreToolUse (Edit|Write|MultiEdit) → inject the relevant Hunch slice before
18
+ * an edit, and (at strict firmness) deny edits that hit a blocking invariant.
19
+ * - UserPromptSubmit → remind the agent to consult Hunch.
20
+ * Both invoke `hunch hook`, which reads the firmness level from .hunch/config.json
21
+ * at run time — so changing firmness needs no settings.json edit. We own only our
22
+ * entries (matched by isHunchHook): other hooks and settings are preserved, and a
23
+ * non-empty file we cannot parse THROWS rather than clobbering the user's config.
24
+ */
25
+ export declare function installClaudeHooks(root: string, hookCmd: string): ClaudeHookInstall;
26
+ export declare function writeSlashCommands(root: string): {
27
+ written: string[];
28
+ skipped: string[];
29
+ };
@@ -0,0 +1,30 @@
1
+ import type { HunchStore } from "../store/hunchStore.js";
2
+ import { type HunchRemoteContract, type GitMemoryObserver } from "../extractors/git.js";
3
+ /** Bind one command/server Store instance to the graph epoch that admitted it.
4
+ * Every later flush from that instance reuses the same verifying contract. */
5
+ export declare function pinSharedRemote(store: HunchStore, remote: HunchRemoteContract): void;
6
+ /** Return the route admitted for this Store instance. Command paths that flush
7
+ * directly (rather than through flushCapture) must use this accessor too, or a
8
+ * coherent team.json/origin rewrite could switch graphs mid-command. */
9
+ export declare function sharedRemoteFor(store: HunchStore): HunchRemoteContract | undefined;
10
+ export type MemoryHome = "public" | "private";
11
+ /** Flush one exact artifact home. Constitution repositories can explicitly
12
+ * choose public even in unified mode, so this must not infer routing through
13
+ * captureHome(isPrivate). The caller supplies the repository's actual home. */
14
+ export declare function flushMemoryHome(store: HunchStore, publicHunchDir: string, home: MemoryHome, message: string, remoteOverride?: HunchRemoteContract): "pushed" | "committed" | null;
15
+ /** One completion flush per touched home. A mixed ingest/bootstrap can write
16
+ * both homes; unchanged homes are cheap no-ops after the memory-only stage
17
+ * check, while each real home becomes durable exactly once. */
18
+ export declare function flushMemoryHomes(store: HunchStore, publicHunchDir: string, homes: Iterable<MemoryHome>, message: string, remoteOverride?: HunchRemoteContract): Partial<Record<MemoryHome, "pushed" | "committed" | null>>;
19
+ /** Auto-commit + push the overlay after a private write, when auto-commit is on. No-op
20
+ * otherwise (manual `hunch private --sync` still works). Never throws. */
21
+ export declare function flushPrivate(store: HunchStore, message: string): void;
22
+ /** Auto-commit the store a capture landed in. Returns what ACTUALLY happened so callers
23
+ * never report a commit that was skipped: "pushed" (overlay committed + pushed),
24
+ * "committed" (commit created but not pushed — public .hunch/ rides the next push; an
25
+ * overlay commit whose merge/push failed retries on the next flush), or null (auto-commit
26
+ * off, no overlay for a private record, or the commit was skipped — lock held, safety
27
+ * backstop, nothing staged; the record stays on disk and the next flush sweeps it up). */
28
+ export declare function flushCapture(store: HunchStore, publicHunchDir: string, isPrivate: boolean, message: string,
29
+ /** Long-lived callers can pin the route snapshot that admitted the write. */
30
+ remoteOverride?: HunchRemoteContract, observe?: GitMemoryObserver): "pushed" | "committed" | null;
@@ -73,13 +73,14 @@ export function flushPrivate(store, message) {
73
73
  * backstop, nothing staged; the record stays on disk and the next flush sweeps it up). */
74
74
  export function flushCapture(store, publicHunchDir, isPrivate, message,
75
75
  /** Long-lived callers can pin the route snapshot that admitted the write. */
76
- remoteOverride) {
76
+ remoteOverride, observe) {
77
77
  // Follow the same routing as HunchStore.captureHome: unified ("shared") mode homes
78
78
  // EVERY capture in the overlay, so the flush must go there too — one source of truth.
79
79
  if (store.captureHome(isPrivate) === "private") {
80
80
  if (store.privateAutoCommit && store.privateDir) {
81
81
  return commitAndPushHunch(store.privateDir, message, {
82
82
  push: true,
83
+ observe,
83
84
  protectedRepoRoot: store.publicRoot,
84
85
  remote: remoteOverride ?? sharedRemoteFor(store),
85
86
  });
@@ -92,6 +93,6 @@ remoteOverride) {
92
93
  // them into the SAME memory commit — otherwise every capture re-stales the committed
93
94
  // counts and the release gate's clean-tree check fails on the next CI index.
94
95
  const grounding = refreshCommittableGrounding(dirname(publicHunchDir), store);
95
- return commitAndPushHunch(publicHunchDir, message, { push: false, alsoStage: grounding });
96
+ return commitAndPushHunch(publicHunchDir, message, { push: false, alsoStage: grounding, observe });
96
97
  }
97
98
  //# sourceMappingURL=sync.js.map
@@ -0,0 +1,70 @@
1
+ import { type HunchRemoteContract } from "../extractors/git.js";
2
+ export interface TeamConfig {
3
+ shared_repo: string;
4
+ /** Canonical remote branch for the one shared graph. Legacy files omit it;
5
+ * route proof then derives the sole existing/upstream branch from the clone. */
6
+ shared_ref?: string;
7
+ }
8
+ export declare const DEFAULT_TEAM_REF = "refs/heads/main";
9
+ export declare function safeTeamRef(value: string): string | null;
10
+ export declare function teamSharedRef(team: TeamConfig): string;
11
+ /** SECURITY GATE for team.json's URL. team.json is COMMITTED — in a freshly cloned
12
+ * (possibly untrusted) repo it is attacker-controlled, and ensureTeamOverlay auto-clones
13
+ * it on MCP server start. Without this gate a value like `--upload-pack=…` (argument
14
+ * smuggling) or `ext::sh -c …` (git's ext transport) is remote code execution from
15
+ * merely opening a repo. Allow only credential-free https://, ssh://, git://,
16
+ * scp-style git@host:path, and never anything that could parse as a Git flag. */
17
+ export declare function safeGitUrl(url: string): string | null;
18
+ /** The committed team pointer, or null. Tolerant — an invalid file reads as absent, and
19
+ * a URL that fails the safety gate reads as absent too (never propagated to a consumer). */
20
+ export declare function readTeamConfig(root: string): TeamConfig | null;
21
+ /** Publish the team's shared-store URL (atomic; committed with the repo). */
22
+ export declare function writeTeamConfig(root: string, cfg: TeamConfig): void;
23
+ /** Git environment for every shared-route setup operation. Preserve ordinary
24
+ * credential configuration, but discard inherited repository/object selectors
25
+ * and executable transport/prompt/template overrides from the caller. */
26
+ export declare function boundedTeamGitEnv(): NodeJS.ProcessEnv;
27
+ /** Prove that the physical overlay reads from and writes to the repository
28
+ * advertised by the committed team config. Path/mode checks alone are not
29
+ * enough: an old healthy clone can otherwise report "current" against a stale
30
+ * origin after team.json changes, silently splitting the team graph.
31
+ *
32
+ * Require one exact fetch URL and one exact push URL for origin, plus an origin
33
+ * upstream/push selector when those branch-level overrides exist. Git's
34
+ * Applicable local or global URL rewrite rules are rejected, so the exact URLs
35
+ * captured from local config remain the URLs handed to Git at the network seam. */
36
+ export declare function overlayMatchesTeamRemote(root: string, overlayRoot: string): boolean;
37
+ /** Snapshot the effective URLs after proving the committed pointer, local
38
+ * transport configuration, and canonical ref all agree. Sync commands receive
39
+ * this object and re-run `verify` immediately around every network operation. */
40
+ export declare function teamRemoteContract(root: string, overlayRoot: string): HunchRemoteContract | null;
41
+ /** Setup-time form of the same contract, used before team.json is published.
42
+ * It proves the existing overlay's physical origin/config against the explicit
43
+ * command arguments so attach/refresh cannot traverse an ambient refspec or
44
+ * transport override during the setup command itself. */
45
+ export declare function explicitTeamRemoteContract(overlayRoot: string, sharedRepo: string, sharedRepoCwd: string, sharedRef: string): HunchRemoteContract | null;
46
+ /** Undefined means this checkout does not advertise team routing. Once the
47
+ * committed file exists, failure to prove it returns an always-refusing
48
+ * contract so a late config change can strand a local commit but can never fall
49
+ * through to ambient `git push`. */
50
+ export declare function advertisedTeamRemoteContract(root: string, overlayRoot: string): HunchRemoteContract | undefined;
51
+ export type ValidatedTeamClone = {
52
+ sharedRef: string;
53
+ empty: boolean;
54
+ };
55
+ /** Clone a shared memory repository without checking out attacker-controlled
56
+ * paths, validate its exact route/OID/tree/attributes, and only then publish the
57
+ * fully materialized clone at `destination`. Failure removes both quarantine and
58
+ * destination so callers cannot accidentally wire a partially validated graph. */
59
+ export declare function cloneValidatedTeamOverlay(sharedRepo: string, sharedRepoCwd: string, destination: string, opts?: {
60
+ sharedRef?: string;
61
+ timeoutMs?: number;
62
+ }): ValidatedTeamClone | null;
63
+ /** Auto-wire this checkout to the team's shared store advertised in `.hunch/team.json`:
64
+ * clone it to the worktree-stable anchor, and register the gitignored local pointer +
65
+ * the git-common-dir pointer (mode "shared", auto-commit on) so every consumer — CLI,
66
+ * MCP server, hooks, all worktrees — resolves the same single source of truth.
67
+ * No-op (null) when an overlay is already configured, there's no team.json, or the
68
+ * clone fails (best-effort: never throws, never blocks startup). Returns the overlay
69
+ * hunch dir when wired. */
70
+ export declare function ensureTeamOverlay(root: string): string | null;
@@ -0,0 +1,8 @@
1
+ /** Register the resolved private overlay at the shared git common dir, so every worktree
2
+ * of this repo auto-discovers the same memory. Idempotent (writes only when missing or
3
+ * changed). Stored ABSOLUTE — a worktree resolves relative paths from its OWN root.
4
+ * Carries the overlay MODE so every worktree routes captures identically (shared =
5
+ * unified store, private = split). Returns true once the shared pointer is in place
6
+ * (memory is worktree-shared), false when there's no overlay configured or no git
7
+ * common dir. Reused by `init`/`worktree`/`private`/`shared`. */
8
+ export declare function ensureSharedOverlayPointer(root: string, overlayDir: string | undefined, autoCommit: boolean, mode?: "private" | "shared"): boolean;
@@ -0,0 +1,16 @@
1
+ /** One canonical spelling per directory. `findRoot` only resolve()s, but a
2
+ * client's roots/list URI can spell the same repo differently — VS Code sends
3
+ * a lowercase drive letter (`c:\…`) while the spawn cwd has `C:\…`, and Git
4
+ * for Windows can surface 8.3/short names. Raw string comparison then treats
5
+ * ONE repo as different roots: a full re-prepare (new store + reindex) on
6
+ * every connect, or a false "multiple roots equally plausible" refusal
7
+ * (issue #54). realpathSync.native returns the on-disk spelling for all of
8
+ * these; fall back to the input when the path is transiently unreadable. */
9
+ export declare function canonicalRootPath(root: string): string;
10
+ /**
11
+ * Returns null when several advertised repositories are equally plausible.
12
+ * The roots protocol exposes a set of URI/name pairs, not an "active root" bit;
13
+ * choosing the first Hunch store in that case could silently write repo B's
14
+ * decision into repo A.
15
+ */
16
+ export declare function resolveActiveRoot(rootUris: readonly string[], fallbackCwd: string): string | null;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * MCP server — the structured two-way API into the Hunch (DESIGN.md §7 / App. A).
3
+ * Exposes read tools (query/why/bug_lineage/check_constraints/get_dependents) and
4
+ * a write tool (record_decision). Registered with Claude Code via .mcp.json.
5
+ *
6
+ * STDIO PROTOCOL RULE: stdout carries JSON-RPC — never console.log here. All
7
+ * diagnostics go to stderr.
8
+ */
9
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ export declare const publicationVocabulary: (hunchDir: string) => RegExp[];
11
+ export type RootControlledServer = {
12
+ server: McpServer;
13
+ getRoot: () => string;
14
+ setRoot: (next: string) => void;
15
+ /** True when the root was pinned at launch (`hunch mcp --root`): client roots and per-call
16
+ * `cwd` hints are ignored, so a served partition stays the partition whatever workspace
17
+ * the client opened. */
18
+ pinned: boolean;
19
+ /** Drop a swap parked by `setRoot` while a request was in flight. The roots
20
+ * wiring calls this when a LATER resolution is ambiguous, so a stale parked
21
+ * swap can never apply after the client stopped unambiguously advertising it. */
22
+ cancelPendingRoot: () => void;
23
+ };
24
+ export interface RootControlOptions {
25
+ /** Serve exactly `initialRoot`; never re-home to client roots or `cwd` hints. */
26
+ pinned?: boolean;
27
+ }
28
+ export declare function buildServerWithRootControl(initialRoot: string, options?: RootControlOptions): RootControlledServer;
29
+ /** Back-compatible server construction for tests and callers that do not need
30
+ * to drive roots directly. The server still owns and closes its active store. */
31
+ export declare function buildServer(root: string): McpServer;
32
+ /** Query client roots after initialization and follow later list changes.
33
+ * Generation ordering prevents a slow stale roots/list response from winning. */
34
+ export declare function wireClientRoots(control: RootControlledServer, fallback: string): void;
35
+ /** Start the stdio server (called by `hunch mcp`). */
36
+ export declare function startServer(cwd?: string, options?: RootControlOptions): Promise<void>;