@nanonets/graft 0.23.1 → 0.24.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 (266) hide show
  1. package/README.md +4 -4
  2. package/dist/ai/crux.d.ts +31 -3
  3. package/dist/ai/crux.d.ts.map +1 -1
  4. package/dist/ai/crux.js +88 -10
  5. package/dist/ai/crux.js.map +1 -1
  6. package/dist/ai/llm/openai.d.ts +101 -0
  7. package/dist/ai/llm/openai.d.ts.map +1 -1
  8. package/dist/ai/llm/openai.js +396 -6
  9. package/dist/ai/llm/openai.js.map +1 -1
  10. package/dist/ai/llm/recover-tool.d.ts +2 -0
  11. package/dist/ai/llm/recover-tool.d.ts.map +1 -1
  12. package/dist/ai/llm/recover-tool.js +1 -1
  13. package/dist/ai/llm/recover-tool.js.map +1 -1
  14. package/dist/ai/synthesize.d.ts.map +1 -1
  15. package/dist/ai/synthesize.js +100 -1
  16. package/dist/ai/synthesize.js.map +1 -1
  17. package/dist/claude/format.js +1 -1
  18. package/dist/claude/format.js.map +1 -1
  19. package/dist/claude/hooks.d.ts +0 -18
  20. package/dist/claude/hooks.d.ts.map +1 -1
  21. package/dist/claude/hooks.js +24 -77
  22. package/dist/claude/hooks.js.map +1 -1
  23. package/dist/claude/init.js +3 -3
  24. package/dist/claude/init.js.map +1 -1
  25. package/dist/claude/note-signals.d.ts +28 -0
  26. package/dist/claude/note-signals.d.ts.map +1 -0
  27. package/dist/claude/note-signals.js +325 -0
  28. package/dist/claude/note-signals.js.map +1 -0
  29. package/dist/claude/shim-template.d.ts.map +1 -1
  30. package/dist/claude/shim-template.js +10 -4
  31. package/dist/claude/shim-template.js.map +1 -1
  32. package/dist/claude/skill-template.d.ts.map +1 -1
  33. package/dist/claude/skill-template.js +49 -18
  34. package/dist/claude/skill-template.js.map +1 -1
  35. package/dist/claude/state.d.ts +4 -3
  36. package/dist/claude/state.d.ts.map +1 -1
  37. package/dist/claude/state.js.map +1 -1
  38. package/dist/claude/sync-run.js +1 -1
  39. package/dist/claude/sync-run.js.map +1 -1
  40. package/dist/cli-picker.d.ts +12 -5
  41. package/dist/cli-picker.d.ts.map +1 -1
  42. package/dist/cli-picker.js +24 -8
  43. package/dist/cli-picker.js.map +1 -1
  44. package/dist/cli.d.ts +2 -0
  45. package/dist/cli.d.ts.map +1 -1
  46. package/dist/cli.js +131 -38
  47. package/dist/cli.js.map +1 -1
  48. package/dist/context/batches.d.ts +29 -0
  49. package/dist/context/batches.d.ts.map +1 -0
  50. package/dist/context/batches.js +130 -0
  51. package/dist/context/batches.js.map +1 -0
  52. package/dist/context/build.d.ts +7 -2
  53. package/dist/context/build.d.ts.map +1 -1
  54. package/dist/context/build.js +84 -50
  55. package/dist/context/build.js.map +1 -1
  56. package/dist/context/node-file.d.ts.map +1 -1
  57. package/dist/context/node-file.js +41 -4
  58. package/dist/context/node-file.js.map +1 -1
  59. package/dist/engine.d.ts +2 -0
  60. package/dist/engine.d.ts.map +1 -1
  61. package/dist/engine.js +1 -0
  62. package/dist/engine.js.map +1 -1
  63. package/dist/graph/cards.d.ts.map +1 -1
  64. package/dist/graph/cards.js +9 -4
  65. package/dist/graph/cards.js.map +1 -1
  66. package/dist/graph/enrich.d.ts.map +1 -1
  67. package/dist/graph/enrich.js +8 -3
  68. package/dist/graph/enrich.js.map +1 -1
  69. package/dist/graph/generic.d.ts.map +1 -1
  70. package/dist/graph/generic.js +207 -6
  71. package/dist/graph/generic.js.map +1 -1
  72. package/dist/graph/lsp/client.d.ts +18 -0
  73. package/dist/graph/lsp/client.d.ts.map +1 -1
  74. package/dist/graph/lsp/client.js +40 -2
  75. package/dist/graph/lsp/client.js.map +1 -1
  76. package/dist/graph/lsp/enrich.d.ts.map +1 -1
  77. package/dist/graph/lsp/enrich.js +9 -1
  78. package/dist/graph/lsp/enrich.js.map +1 -1
  79. package/dist/graph/lsp/registry.d.ts +7 -0
  80. package/dist/graph/lsp/registry.d.ts.map +1 -1
  81. package/dist/graph/lsp/registry.js +27 -2
  82. package/dist/graph/lsp/registry.js.map +1 -1
  83. package/dist/graph/queries/gleam.scm +51 -0
  84. package/dist/graph/resolve.d.ts.map +1 -1
  85. package/dist/graph/resolve.js +65 -3
  86. package/dist/graph/resolve.js.map +1 -1
  87. package/dist/graph/workspace-cli.d.ts +2 -0
  88. package/dist/graph/workspace-cli.d.ts.map +1 -1
  89. package/dist/graph/workspace-cli.js +1 -1
  90. package/dist/graph/workspace-cli.js.map +1 -1
  91. package/dist/notes/branches.d.ts +7 -1
  92. package/dist/notes/branches.d.ts.map +1 -1
  93. package/dist/notes/branches.js +31 -3
  94. package/dist/notes/branches.js.map +1 -1
  95. package/dist/notes/cold-start.d.ts +12 -2
  96. package/dist/notes/cold-start.d.ts.map +1 -1
  97. package/dist/notes/cold-start.js +46 -5
  98. package/dist/notes/cold-start.js.map +1 -1
  99. package/dist/notes/credit.d.ts +37 -0
  100. package/dist/notes/credit.d.ts.map +1 -0
  101. package/dist/notes/credit.js +78 -0
  102. package/dist/notes/credit.js.map +1 -0
  103. package/dist/notes/find-notes.d.ts +17 -0
  104. package/dist/notes/find-notes.d.ts.map +1 -0
  105. package/dist/notes/find-notes.js +48 -0
  106. package/dist/notes/find-notes.js.map +1 -0
  107. package/dist/notes/flatten.d.ts +31 -0
  108. package/dist/notes/flatten.d.ts.map +1 -0
  109. package/dist/notes/flatten.js +73 -0
  110. package/dist/notes/flatten.js.map +1 -0
  111. package/dist/notes/git-facts.d.ts +2 -0
  112. package/dist/notes/git-facts.d.ts.map +1 -1
  113. package/dist/notes/git-facts.js +6 -0
  114. package/dist/notes/git-facts.js.map +1 -1
  115. package/dist/notes/home.d.ts +24 -6
  116. package/dist/notes/home.d.ts.map +1 -1
  117. package/dist/notes/home.js +82 -15
  118. package/dist/notes/home.js.map +1 -1
  119. package/dist/notes/learning-fields.d.ts +102 -0
  120. package/dist/notes/learning-fields.d.ts.map +1 -0
  121. package/dist/notes/learning-fields.js +214 -0
  122. package/dist/notes/learning-fields.js.map +1 -0
  123. package/dist/notes/memory-notes.d.ts +71 -0
  124. package/dist/notes/memory-notes.d.ts.map +1 -0
  125. package/dist/notes/memory-notes.js +239 -0
  126. package/dist/notes/memory-notes.js.map +1 -0
  127. package/dist/notes/note-gate.d.ts +42 -0
  128. package/dist/notes/note-gate.d.ts.map +1 -0
  129. package/dist/notes/note-gate.js +181 -0
  130. package/dist/notes/note-gate.js.map +1 -0
  131. package/dist/notes/notes.d.ts +29 -85
  132. package/dist/notes/notes.d.ts.map +1 -1
  133. package/dist/notes/notes.js +69 -254
  134. package/dist/notes/notes.js.map +1 -1
  135. package/dist/notes/pr-reviews.d.ts +35 -7
  136. package/dist/notes/pr-reviews.d.ts.map +1 -1
  137. package/dist/notes/pr-reviews.js +156 -46
  138. package/dist/notes/pr-reviews.js.map +1 -1
  139. package/dist/notes/secrets.d.ts +28 -0
  140. package/dist/notes/secrets.d.ts.map +1 -0
  141. package/dist/notes/secrets.js +362 -0
  142. package/dist/notes/secrets.js.map +1 -0
  143. package/dist/notes/targets.d.ts +37 -0
  144. package/dist/notes/targets.d.ts.map +1 -0
  145. package/dist/notes/targets.js +108 -0
  146. package/dist/notes/targets.js.map +1 -0
  147. package/dist/notes/team-check.d.ts +22 -0
  148. package/dist/notes/team-check.d.ts.map +1 -0
  149. package/dist/notes/team-check.js +130 -0
  150. package/dist/notes/team-check.js.map +1 -0
  151. package/dist/notes/trail-home.d.ts +3 -0
  152. package/dist/notes/trail-home.d.ts.map +1 -0
  153. package/dist/notes/trail-home.js +12 -0
  154. package/dist/notes/trail-home.js.map +1 -0
  155. package/dist/skills/answers-prompt.d.ts +13 -0
  156. package/dist/skills/answers-prompt.d.ts.map +1 -0
  157. package/dist/skills/answers-prompt.js +83 -0
  158. package/dist/skills/answers-prompt.js.map +1 -0
  159. package/dist/skills/never-save.d.ts +5 -0
  160. package/dist/skills/never-save.d.ts.map +1 -0
  161. package/dist/skills/never-save.js +158 -0
  162. package/dist/skills/never-save.js.map +1 -0
  163. package/dist/skills/params.d.ts +39 -0
  164. package/dist/skills/params.d.ts.map +1 -0
  165. package/dist/skills/params.js +275 -0
  166. package/dist/skills/params.js.map +1 -0
  167. package/dist/skills/ran-less.d.ts +5 -0
  168. package/dist/skills/ran-less.d.ts.map +1 -0
  169. package/dist/skills/ran-less.js +51 -0
  170. package/dist/skills/ran-less.js.map +1 -0
  171. package/dist/skills/risk-delta.d.ts +32 -0
  172. package/dist/skills/risk-delta.d.ts.map +1 -0
  173. package/dist/skills/risk-delta.js +56 -0
  174. package/dist/skills/risk-delta.js.map +1 -0
  175. package/dist/skills/risk.d.ts +73 -0
  176. package/dist/skills/risk.d.ts.map +1 -0
  177. package/dist/skills/risk.js +396 -0
  178. package/dist/skills/risk.js.map +1 -0
  179. package/dist/skills/types.d.ts +422 -0
  180. package/dist/skills/types.d.ts.map +1 -0
  181. package/dist/skills/types.js +2 -0
  182. package/dist/skills/types.js.map +1 -0
  183. package/dist/telemetry/contract.d.ts.map +1 -1
  184. package/dist/telemetry/contract.js +8 -6
  185. package/dist/telemetry/contract.js.map +1 -1
  186. package/dist/telemetry/notice.d.ts.map +1 -1
  187. package/dist/telemetry/notice.js +3 -1
  188. package/dist/telemetry/notice.js.map +1 -1
  189. package/dist/trace/check-reads.d.ts +36 -0
  190. package/dist/trace/check-reads.d.ts.map +1 -0
  191. package/dist/trace/check-reads.js +57 -0
  192. package/dist/trace/check-reads.js.map +1 -0
  193. package/dist/trace/host.d.ts +40 -0
  194. package/dist/trace/host.d.ts.map +1 -0
  195. package/dist/trace/host.js +84 -0
  196. package/dist/trace/host.js.map +1 -0
  197. package/dist/trace/redact.d.ts +8 -0
  198. package/dist/trace/redact.d.ts.map +1 -0
  199. package/dist/trace/redact.js +63 -0
  200. package/dist/trace/redact.js.map +1 -0
  201. package/dist/trace/seen-cache.d.ts +9 -0
  202. package/dist/trace/seen-cache.d.ts.map +1 -0
  203. package/dist/trace/seen-cache.js +46 -0
  204. package/dist/trace/seen-cache.js.map +1 -0
  205. package/dist/trace/shell-scan.d.ts +52 -0
  206. package/dist/trace/shell-scan.d.ts.map +1 -0
  207. package/dist/trace/shell-scan.js +318 -0
  208. package/dist/trace/shell-scan.js.map +1 -0
  209. package/dist/trace/shell-words.d.ts +91 -0
  210. package/dist/trace/shell-words.d.ts.map +1 -0
  211. package/dist/trace/shell-words.js +558 -0
  212. package/dist/trace/shell-words.js.map +1 -0
  213. package/dist/trace/shell.d.ts +91 -0
  214. package/dist/trace/shell.d.ts.map +1 -0
  215. package/dist/trace/shell.js +435 -0
  216. package/dist/trace/shell.js.map +1 -0
  217. package/dist/trace/state.d.ts +27 -0
  218. package/dist/trace/state.d.ts.map +1 -0
  219. package/dist/trace/state.js +98 -0
  220. package/dist/trace/state.js.map +1 -0
  221. package/dist/trace/tamper-code.d.ts +9 -0
  222. package/dist/trace/tamper-code.d.ts.map +1 -0
  223. package/dist/trace/tamper-code.js +174 -0
  224. package/dist/trace/tamper-code.js.map +1 -0
  225. package/dist/trace/tamper-git.d.ts +12 -0
  226. package/dist/trace/tamper-git.d.ts.map +1 -0
  227. package/dist/trace/tamper-git.js +77 -0
  228. package/dist/trace/tamper-git.js.map +1 -0
  229. package/dist/trace/types.d.ts +477 -0
  230. package/dist/trace/types.d.ts.map +1 -0
  231. package/dist/trace/types.js +12 -0
  232. package/dist/trace/types.js.map +1 -0
  233. package/dist/trace/walls-glob.d.ts +11 -0
  234. package/dist/trace/walls-glob.d.ts.map +1 -0
  235. package/dist/trace/walls-glob.js +264 -0
  236. package/dist/trace/walls-glob.js.map +1 -0
  237. package/dist/trace/walls-quoted.d.ts +25 -0
  238. package/dist/trace/walls-quoted.d.ts.map +1 -0
  239. package/dist/trace/walls-quoted.js +81 -0
  240. package/dist/trace/walls-quoted.js.map +1 -0
  241. package/dist/upkeep.d.ts +1 -1
  242. package/dist/upkeep.d.ts.map +1 -1
  243. package/dist/upkeep.js +4 -1
  244. package/dist/upkeep.js.map +1 -1
  245. package/dist/util/actions-folder.d.ts +2 -0
  246. package/dist/util/actions-folder.d.ts.map +1 -0
  247. package/dist/util/actions-folder.js +9 -0
  248. package/dist/util/actions-folder.js.map +1 -0
  249. package/dist/util/front-matter.d.ts +31 -4
  250. package/dist/util/front-matter.d.ts.map +1 -1
  251. package/dist/util/front-matter.js +95 -3
  252. package/dist/util/front-matter.js.map +1 -1
  253. package/dist/util/private-file.d.ts +14 -0
  254. package/dist/util/private-file.d.ts.map +1 -0
  255. package/dist/util/private-file.js +82 -0
  256. package/dist/util/private-file.js.map +1 -0
  257. package/dist/util/private-fs.d.ts +25 -0
  258. package/dist/util/private-fs.d.ts.map +1 -0
  259. package/dist/util/private-fs.js +253 -0
  260. package/dist/util/private-fs.js.map +1 -0
  261. package/dist/util/state.d.ts.map +1 -1
  262. package/dist/util/state.js +3 -0
  263. package/dist/util/state.js.map +1 -1
  264. package/dist/viewer/app.js +2 -2
  265. package/package.json +5 -5
  266. package/scripts/run-tests.mjs +14 -2
@@ -0,0 +1,181 @@
1
+ /**
2
+ * What `trail note` checks before it saves a learning for the team: that a
3
+ * teammate's Claude would act differently for reading it. A learning that
4
+ * names no code never reaches anyone (learnings arrive when Claude opens the
5
+ * files they name), one about setting trail up isn't about the repo, status
6
+ * ("PR is open") is wrong by next week, a decision without its reason can't be
7
+ * weighed, and a second copy of a learning buries the first.
8
+ *
9
+ * Each check that fails says how to fix it, and the agent saves again. A long
10
+ * learning only gets a warning. `--anyway` saves past the checks, for when
11
+ * one of them is wrong.
12
+ */
13
+ import { execFileSync } from "node:child_process";
14
+ import { existsSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { trailOwnPath } from "./git-facts.js";
17
+ import { noteName, notePlace, SECTIONS, shortDate } from "./notes.js";
18
+ /** Past this many words a learning gets skimmed: a warning, never a refusal. */
19
+ export const LONG_NOTE_WORDS = 250;
20
+ /** Setting trail (or graft) up, said in a title or body. */
21
+ const SETUP_TALK = /\b(?:trail|graft)\b[^.\n]{0,40}\b(?:init|setup|set up|install(?:ed|ing)?|hooks?|wiring|wired)\b|\b(?:setting up|set up|install(?:ed|ing)?|wiring)\b[^.\n]{0,20}\b(?:trail|graft)\b/i;
22
+ /** Status: true when written, wrong a week later. */
23
+ const STATUS = [
24
+ /\b(?:PR|pull request|MR)\s*#?\d*\s+(?:is|was|got|has been|now)\s+(?:open|opened|merged|closed|approved|up|green|fixed|pushed)\b/i,
25
+ /\bnot (?:merged|pushed|released|published|deployed|reviewed) yet\b/i,
26
+ /\bpushed and not merged\b/i,
27
+ /\b(?:today|tomorrow|yesterday|tonight|this (?:morning|afternoon|evening|week))\b/i,
28
+ /\b(?:waiting on|blocked on|still open|awaiting review|in review)\b/i,
29
+ ];
30
+ /** A reason: a cause, an error, a number, or a word that brings one. */
31
+ const WHY = /\b(?:because|since|so that|so|otherwise|or else|else|due to|caused?|causes|causing|means|meant|breaks?|broke|broken|fails?|failed|failing|errors?|exceptions?|crash(?:es|ed)?|hangs?|leaks?|slow(?:er)?|faster|cheaper|costs?|instead|to avoid|to keep|to stop|to prevent|in order to|unless|only if|rejects?|refuses?|blocks?|loses?|lost|drops?|wipes?|overwrites?|but|though|doubles?|twice|half|latency|memory|wrong|incorrect|missing|stale|races?|timeouts?|times out|deadlocks?|conflicts?|regress(?:es|ion)?|can't|cannot|won't|doesn't|don't|isn't|aren't|never)\b|\d|["“][^"”]{4,}["”]|→|=>/i;
32
+ const STOP = new Set("the and for with from that this what when where which into does how why are was were not but you your our out its it's can should would could about after before over under use using used fix find make".split(" "));
33
+ function words(s) {
34
+ return new Set(s.toLowerCase().split(/[^a-z0-9_]+/).filter((t) => t.length >= 3 && !STOP.has(t)));
35
+ }
36
+ function jaccard(a, b) {
37
+ if (!a.size || !b.size)
38
+ return 0;
39
+ let both = 0;
40
+ for (const t of a)
41
+ if (b.has(t))
42
+ both++;
43
+ return both / (a.size + b.size - both);
44
+ }
45
+ /** The body without fenced code, which quotes errors and commands rather than saying status. */
46
+ function prose(body) {
47
+ return body.replace(/```[\s\S]*?```/g, "");
48
+ }
49
+ /** The lines a reason belongs on: under Decided and Tried and ruled out, or the whole body when it has neither. */
50
+ function decisionLines(body) {
51
+ const lines = prose(body).split(/\r?\n/);
52
+ const wanted = new Set([SECTIONS[0].heading.toLowerCase(), SECTIONS[1].heading.toLowerCase()]);
53
+ const out = [];
54
+ let section = null;
55
+ let sawSection = false;
56
+ for (const raw of lines) {
57
+ const l = raw.trim();
58
+ const h = /^#{1,6}\s+(.*)$/.exec(l);
59
+ if (h) {
60
+ section = h[1].trim().toLowerCase();
61
+ if (wanted.has(section))
62
+ sawSection = true;
63
+ continue;
64
+ }
65
+ if (l && section && wanted.has(section))
66
+ out.push(l);
67
+ }
68
+ if (sawSection)
69
+ return out;
70
+ return lines.map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
71
+ }
72
+ function clip(s, n = 70) {
73
+ const t = s.trim().replace(/^[-*]\s+/, "");
74
+ return t.length > n ? `${t.slice(0, n - 1).trimEnd()}…` : t;
75
+ }
76
+ /** The learning this one repeats: same files, and much the same title or text. */
77
+ export function repeatOf(input, existing) {
78
+ const files = new Set(input.touches.map((t) => t.split("#")[0]));
79
+ const title = words(input.title);
80
+ const body = words(input.body);
81
+ for (const n of existing) {
82
+ if (input.replaces && n.id === input.replaces)
83
+ continue;
84
+ const shared = n.touches.some((t) => files.has(t.split("#")[0]));
85
+ const sameTitle = jaccard(title, words(n.title));
86
+ const sameBody = jaccard(body, words(n.body));
87
+ if (shared ? sameTitle >= 0.5 || sameBody >= 0.5 : (input.personal || !files.size) && sameTitle >= 0.6)
88
+ return n;
89
+ }
90
+ return null;
91
+ }
92
+ /** The checks, on a learning about to be saved. `existing`: the learnings already there. */
93
+ export function gateNote(input, existing) {
94
+ const problems = [];
95
+ const warnings = [];
96
+ const text = `${input.title}\n${prose(input.body)}`;
97
+ if (!input.personal) {
98
+ const code = input.files.filter((f) => !trailOwnPath(f));
99
+ const onlyTrail = input.files.length > 0 && code.length === 0;
100
+ if (!code.length && !input.namesSymbol) {
101
+ problems.push(SETUP_TALK.test(text) || onlyTrail
102
+ ? "It reads as a note about setting trail up, not this repo's code. Skip it, or keep it with --personal if it's about your machine."
103
+ : "It names no file or function in this repo. Name what it's about (`src/x.ts`, `parseConfig`), so a teammate's Claude gets it when it opens that file.");
104
+ }
105
+ }
106
+ for (const line of text.split(/\r?\n/)) {
107
+ if (STATUS.some((re) => re.test(line))) {
108
+ problems.push(`"${clip(line)}" is status: true today, wrong next week. Keep what stays true (the cause, the rule, the why) and put status in the PR.`);
109
+ break;
110
+ }
111
+ }
112
+ if (!input.personal && !decisionLines(input.body).some((l) => WHY.test(l))) {
113
+ problems.push('No line says why. Give each decision its reason: the cause, the error it hit, or the number that settled it ("because…", "otherwise…", "fails with…").');
114
+ }
115
+ const twin = repeatOf(input, existing);
116
+ if (twin) {
117
+ problems.push(`It repeats ${notePlace(twin)} ("${clip(twin.title, 50)}"${twin.author ? `, ${twin.author}` : ""}, ${shortDate(twin.date)}). If it updates that one, add --replaces ${noteName(twin)}: the old file stays as the record and yours is read instead. If it's different, say how in the title.`);
118
+ }
119
+ const count = input.body.split(/\s+/).filter(Boolean).length;
120
+ if (count > LONG_NOTE_WORDS)
121
+ warnings.push(`long: ${count} words. Long learnings get skimmed; cut it to the fact and the why.`);
122
+ return { problems, warnings };
123
+ }
124
+ /** `parseConfig`, `Client.Do`, `default_retry_max`, `retry()`: words in a note shaped like code. */
125
+ const BACKTICKED = /`([A-Za-z_$][\w$]*(?:(?:\.|::|#)[A-Za-z_$][\w$]*)*)(?:\(\))?`/g;
126
+ const CODE_SHAPED = /\b([a-z]+[A-Z][\w]*|[A-Z][a-z0-9]+[A-Z][\w]*|[a-z][a-z0-9]*_[a-z0-9_]+|[A-Za-z_]\w*(?=\(\)))\b/g;
127
+ /** The names a note uses that might be symbols, most likely first: backticked, then code-shaped. At most `limit`. */
128
+ export function symbolCandidates(text, limit = 8) {
129
+ const out = [];
130
+ const add = (s) => {
131
+ const name = s.split(/\.|::|#/).pop();
132
+ if (name.length < 3 || /\.[A-Za-z]{1,5}$/.test(s) || out.includes(name))
133
+ return;
134
+ out.push(name);
135
+ };
136
+ for (const m of text.matchAll(BACKTICKED))
137
+ add(m[1]);
138
+ for (const m of text.matchAll(CODE_SHAPED))
139
+ add(m[1]);
140
+ return out.slice(0, limit);
141
+ }
142
+ /**
143
+ * Whether any of `names` is in the repo's code: a whole-word `git grep` over
144
+ * tracked files, leaving out trail's own files and markdown, which would find
145
+ * the note's own words. Outside git, false: the files it names still count.
146
+ */
147
+ export function namesRepoSymbol(repo, names) {
148
+ if (!names.length)
149
+ return false;
150
+ for (const name of names) {
151
+ try {
152
+ execFileSync("git", ["grep", "-q", "-w", "-F", "-e", name, "--", ".", ":(exclude).trail", ":(exclude).claude", ":(exclude)*.md"], {
153
+ cwd: repo,
154
+ stdio: "ignore",
155
+ });
156
+ return true;
157
+ }
158
+ catch {
159
+ /* not found, or not a repo */
160
+ }
161
+ }
162
+ return false;
163
+ }
164
+ /**
165
+ * Of `files` (relative to the checkout at `repo`), the ones git tracks. A
166
+ * learning's `touches:` lists these, plus files the session itself edited:
167
+ * an untracked file that was already lying around (a token, a scratch file)
168
+ * is never what a learning is about. Outside git, every file that exists.
169
+ */
170
+ export function trackedFiles(repo, files) {
171
+ if (!files.length)
172
+ return new Set();
173
+ try {
174
+ const out = execFileSync("git", ["ls-files", "-z", "--", ...files], { cwd: repo, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
175
+ return new Set(out.split("\0").filter(Boolean));
176
+ }
177
+ catch {
178
+ return new Set(files.filter((f) => existsSync(join(repo, f))));
179
+ }
180
+ }
181
+ //# sourceMappingURL=note-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"note-gate.js","sourceRoot":"","sources":["../../src/notes/note-gate.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,14 @@
1
+ import type { NoteHit } from "./find-notes.js";
2
+ import { type LearningFields } from "./learning-fields.js";
3
+ export { findNotes, type NoteHit } from "./find-notes.js";
4
+ export { mentionedFiles, noteTargets, type NoteTarget } from "./targets.js";
5
+ export { commitLines, namesLabel, PR_SPEEDUP, setupCommitLine, TOKEN_CREDIT_FLOOR, tokensLabel, tokensWorthSaying } from "./credit.js";
1
6
  export interface NoteCost {
2
7
  minutes?: number;
3
8
  tokens?: number;
4
9
  }
5
- export interface Note {
10
+ /** A learning. Its id, kind, scope, status and the rest are in `LearningFields`. */
11
+ export interface Note extends LearningFields {
6
12
  /** Where the note is: an absolute path on this machine. */
7
13
  path: string;
8
14
  title: string;
@@ -16,12 +22,14 @@ export interface Note {
16
22
  body: string;
17
23
  /** Written by someone other than whoever is asking. */
18
24
  teammate?: boolean;
19
- /** `repo`: in the repo's `.trail/learnings/`, for everyone. `personal`: in ~/.trail, this machine only. */
20
- scope?: "repo" | "personal";
21
25
  /** A rule or preference for every session here, not knowledge about one
22
26
  * task: what the user kept having to tell Claude. The session-start hook
23
27
  * lists these up front, since no single task would bring them up. */
24
28
  standing?: boolean;
29
+ /** The file name of an earlier learning this one takes over from. The old
30
+ * file stays, as the record of what that session knew, but `listNotes`
31
+ * reads this one instead. */
32
+ replaces?: string;
25
33
  /** Found on a teammate's pushed branch (`origin/kumar/jitter`) rather than in
26
34
  * this checkout. `path` is then `<ref>:.trail/learnings/<name>`, readable
27
35
  * with `git show`, and the whole body travels with the note. */
@@ -44,7 +52,11 @@ export declare const SECTIONS: readonly [{
44
52
  readonly label: "watch out";
45
53
  }];
46
54
  export declare function renderNote(n: Omit<Note, "path">): string;
47
- /** A note file, or null when it isn't one (no title in its frontmatter). */
55
+ /**
56
+ * A note file, or null when it isn't one (no title in its frontmatter), or
57
+ * when its front matter is refused (anchors, aliases, a list for a title) or
58
+ * isn't valid YAML, which says so once on stderr.
59
+ */
48
60
  export declare function parseNote(text: string, path: string): Note | null;
49
61
  /** The file name a note is known by, wherever it sits: one learning on a branch and in the tree is one learning. */
50
62
  export declare function noteName(n: Note): string;
@@ -75,73 +87,32 @@ export interface WriteNoteInput {
75
87
  cost?: NoteCost;
76
88
  touches?: string[];
77
89
  standing?: boolean;
90
+ /** The fields a new learning may be given; its id, status and scope come from where it is written. */
91
+ kind?: LearningFields["kind"];
92
+ replaces?: string;
93
+ src?: LearningFields["src"];
94
+ evidence?: string;
95
+ /** Personal only: defaults to this repo. */
96
+ applies?: string;
78
97
  }
79
98
  /**
80
99
  * Write a new learning for the repo `dir` is in, and return it: into the
81
100
  * repo's `.trail/learnings/` (made if needed), or with `scope: "personal"`,
82
101
  * or outside git, into ~/.trail. Never overwrites: a second one with the same
83
- * name on the same day gets `-2`, `-3`.
102
+ * name on the same day gets `-2`, `-3`. Its id is 8 hex digits from the file
103
+ * name it gets (`newLearningId`), written into the file.
84
104
  */
85
105
  export declare function writeNote(dir: string, input: WriteNoteInput, scope?: LearningScope): Note;
86
106
  /**
87
107
  * The standing learnings for `dir`: the team's in the checkout and the
88
108
  * person's own, never ones on a teammate's unmerged branch, which nobody has
89
- * reviewed yet.
109
+ * reviewed yet, and only live ones (nothing retired or replaced).
90
110
  */
91
111
  export declare function standingLearnings(dir: string): Note[];
92
112
  /** Where a learning is, as the agent and the person read it: `.trail/learnings/x.md`, `~/.trail/…`, or `origin/b:.trail/…`. */
93
113
  export declare function notePlace(n: Note): string;
94
- export interface NoteTarget {
95
- /** A folder in the repo the note goes to. */
96
- dir: string;
97
- /** What the session touched there, relative to the top of that checkout. */
98
- touches: string[];
99
- /** What it only read there, same form; set when the session said what it read. */
100
- read?: string[];
101
- }
102
- /**
103
- * Which repos a session's note belongs in, and what it touched in each.
104
- *
105
- * The repo the note was saved from gets the files it has uncommitted or
106
- * committed since `since`. Every other repo the session edited (`edited`:
107
- * absolute paths, from the agent's transcript) gets the note too, with its
108
- * own files, so a session that changed a backend and the library it calls
109
- * leaves a note in both. Saved from a folder that holds several repos, the
110
- * note goes to each repo the session changed, or stays with the folder when
111
- * it changed none. Two worktrees of one repo are one repo.
112
- *
113
- * `session.read`, when the transcript was found: the files the session opened.
114
- * Then the transcript says what was touched, and the working tree's other
115
- * uncommitted files, there before the session began, are left out.
116
- */
117
- export declare function noteTargets(dir: string, edited?: string[], since?: number, session?: {
118
- read: string[];
119
- }): NoteTarget[];
120
- /**
121
- * Files of the checkout at `dir` that a note's text names by path. A session
122
- * that only read code edits nothing, so without these its note would touch no
123
- * file, and nothing that looks a note up by file (`trail check`, the ranked
124
- * search) would ever find it.
125
- */
126
- export declare function mentionedFiles(dir: string, body: string): string[];
127
- export interface NoteHit {
128
- note: Note;
129
- score: number;
130
- /** Files the note touches that this query's results also point into. */
131
- shared: string[];
132
- }
133
- /**
134
- * The notes worth showing next to a query's results: ones whose title or body
135
- * share the query's words, or that touch a file the results point into. At
136
- * most `limit`, best first. A note has to clear a bar — two of the query's
137
- * words, or one in its title, or a shared file — so an unrelated note never
138
- * rides along just because it exists.
139
- */
140
- export declare function findNotes(notes: Note[], query: string, files?: string[], limit?: number): NoteHit[];
141
114
  /** `2026-10-07` → `Oct 7`; anything else as it came. */
142
115
  export declare function shortDate(date: string): string;
143
- /** `~9.6k tokens`, `~600 tokens`. */
144
- export declare function tokensLabel(n: number): string;
145
116
  /** `took 12 min and ~9.6k tokens to work out`, or null when the note has no cost. */
146
117
  export declare function costLabel(cost?: NoteCost): string | null;
147
118
  /** What reading a note costs an agent, in tokens: its text at ~4 characters a token. */
@@ -151,7 +122,7 @@ export declare function readingTokens(n: Note): number;
151
122
  * it costs. 0 when it carries no token cost, or reading it costs as much.
152
123
  */
153
124
  export declare function savedByNote(n: Note): number;
154
- /** `Anirudh's learning`, `a learning`, `Kumar's learning on kumar/jitter`. */
125
+ /** `Maya's learning`, `a learning`, `Kumar's learning on kumar/jitter`. */
155
126
  export declare function whoseLearning(n: Note): string;
156
127
  /**
157
128
  * The block `ask` prints above its results: whose learning each is, when,
@@ -159,39 +130,12 @@ export declare function whoseLearning(n: Note): string;
159
130
  * where to read the rest. A learning on a teammate's unmerged branch says so,
160
131
  * with the `git show` that prints it, since there's no file here to open. An agent
161
132
  * relays the cost when it says what the turn saved, which is how the saving
162
- * becomes countable.
133
+ * becomes countable. Every field is flattened to one line: a learning's text
134
+ * comes from whoever wrote it, and a line of its own could pass for trail's.
163
135
  */
164
136
  export declare function formatNoteHits(hits: NoteHit[]): string[];
165
137
  /** The line an agent closes its reply with after saving a learning just for the user. */
166
138
  export declare const PERSONAL_SAVED_LINE = "\uD83D\uDCDD Saved just for you \u00B7 stays on this machine, out of the repo";
167
- /** `Anay`, `Anay and Rushil`, `Anay, Rushil and 3 others`. */
168
- export declare function namesLabel(names: string[]): string;
169
- /** What starting from a teammate's learning is worth when its tokens are too few to say: time to a PR. */
170
- export declare const PR_SPEEDUP = "3x faster";
171
- /**
172
- * Below this many tokens, what a learning saves is too small a number to
173
- * impress, so trail credits it as a faster PR instead.
174
- */
175
- export declare const TOKEN_CREDIT_FLOOR = 80000;
176
- /** Whether a token count is big enough to be the credit. */
177
- export declare function tokensWorthSaying(tokens: number | undefined): boolean;
178
- /**
179
- * The lines that close a reply after a team learning is saved, one for each
180
- * way the turn can end, since only the agent knows whether it committed the
181
- * learning by then. Uncommitted, it makes the case for committing: who else
182
- * works on the same files, and the head start their agents would get, which
183
- * is what the learning took to work out, or a faster PR when that's small.
184
- */
185
- export declare function commitLines(note: Pick<Note, "cost">, teammates: string[], where?: "files" | "repo"): {
186
- committed: string;
187
- uncommitted: string;
188
- };
189
- /**
190
- * The line asking for trail's shared setup to be committed, once: `.trail/`
191
- * and the SessionStart entry in `.claude/settings.json` are what let a
192
- * teammate's Claude read the learnings before they install anything.
193
- */
194
- export declare function setupCommitLine(teammates: string[]): string;
195
139
  /**
196
140
  * What starting from these learnings is worth, for the agent's closing line:
197
141
  * the tokens they saved, less what reading them costs, when that's worth
@@ -1 +1 @@
1
- {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/notes/notes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/notes/notes.ts"],"names":[],"mappings":"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"}