@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.
- package/README.md +4 -4
- package/dist/ai/crux.d.ts +31 -3
- package/dist/ai/crux.d.ts.map +1 -1
- package/dist/ai/crux.js +88 -10
- package/dist/ai/crux.js.map +1 -1
- package/dist/ai/llm/openai.d.ts +101 -0
- package/dist/ai/llm/openai.d.ts.map +1 -1
- package/dist/ai/llm/openai.js +396 -6
- package/dist/ai/llm/openai.js.map +1 -1
- package/dist/ai/llm/recover-tool.d.ts +2 -0
- package/dist/ai/llm/recover-tool.d.ts.map +1 -1
- package/dist/ai/llm/recover-tool.js +1 -1
- package/dist/ai/llm/recover-tool.js.map +1 -1
- package/dist/ai/synthesize.d.ts.map +1 -1
- package/dist/ai/synthesize.js +100 -1
- package/dist/ai/synthesize.js.map +1 -1
- package/dist/claude/format.js +1 -1
- package/dist/claude/format.js.map +1 -1
- package/dist/claude/hooks.d.ts +0 -18
- package/dist/claude/hooks.d.ts.map +1 -1
- package/dist/claude/hooks.js +24 -77
- package/dist/claude/hooks.js.map +1 -1
- package/dist/claude/init.js +3 -3
- package/dist/claude/init.js.map +1 -1
- package/dist/claude/note-signals.d.ts +28 -0
- package/dist/claude/note-signals.d.ts.map +1 -0
- package/dist/claude/note-signals.js +325 -0
- package/dist/claude/note-signals.js.map +1 -0
- package/dist/claude/shim-template.d.ts.map +1 -1
- package/dist/claude/shim-template.js +10 -4
- package/dist/claude/shim-template.js.map +1 -1
- package/dist/claude/skill-template.d.ts.map +1 -1
- package/dist/claude/skill-template.js +49 -18
- package/dist/claude/skill-template.js.map +1 -1
- package/dist/claude/state.d.ts +4 -3
- package/dist/claude/state.d.ts.map +1 -1
- package/dist/claude/state.js.map +1 -1
- package/dist/claude/sync-run.js +1 -1
- package/dist/claude/sync-run.js.map +1 -1
- package/dist/cli-picker.d.ts +12 -5
- package/dist/cli-picker.d.ts.map +1 -1
- package/dist/cli-picker.js +24 -8
- package/dist/cli-picker.js.map +1 -1
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +131 -38
- package/dist/cli.js.map +1 -1
- package/dist/context/batches.d.ts +29 -0
- package/dist/context/batches.d.ts.map +1 -0
- package/dist/context/batches.js +130 -0
- package/dist/context/batches.js.map +1 -0
- package/dist/context/build.d.ts +7 -2
- package/dist/context/build.d.ts.map +1 -1
- package/dist/context/build.js +84 -50
- package/dist/context/build.js.map +1 -1
- package/dist/context/node-file.d.ts.map +1 -1
- package/dist/context/node-file.js +41 -4
- package/dist/context/node-file.js.map +1 -1
- package/dist/engine.d.ts +2 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +1 -0
- package/dist/engine.js.map +1 -1
- package/dist/graph/cards.d.ts.map +1 -1
- package/dist/graph/cards.js +9 -4
- package/dist/graph/cards.js.map +1 -1
- package/dist/graph/enrich.d.ts.map +1 -1
- package/dist/graph/enrich.js +8 -3
- package/dist/graph/enrich.js.map +1 -1
- package/dist/graph/generic.d.ts.map +1 -1
- package/dist/graph/generic.js +207 -6
- package/dist/graph/generic.js.map +1 -1
- package/dist/graph/lsp/client.d.ts +18 -0
- package/dist/graph/lsp/client.d.ts.map +1 -1
- package/dist/graph/lsp/client.js +40 -2
- package/dist/graph/lsp/client.js.map +1 -1
- package/dist/graph/lsp/enrich.d.ts.map +1 -1
- package/dist/graph/lsp/enrich.js +9 -1
- package/dist/graph/lsp/enrich.js.map +1 -1
- package/dist/graph/lsp/registry.d.ts +7 -0
- package/dist/graph/lsp/registry.d.ts.map +1 -1
- package/dist/graph/lsp/registry.js +27 -2
- package/dist/graph/lsp/registry.js.map +1 -1
- package/dist/graph/queries/gleam.scm +51 -0
- package/dist/graph/resolve.d.ts.map +1 -1
- package/dist/graph/resolve.js +65 -3
- package/dist/graph/resolve.js.map +1 -1
- package/dist/graph/workspace-cli.d.ts +2 -0
- package/dist/graph/workspace-cli.d.ts.map +1 -1
- package/dist/graph/workspace-cli.js +1 -1
- package/dist/graph/workspace-cli.js.map +1 -1
- package/dist/notes/branches.d.ts +7 -1
- package/dist/notes/branches.d.ts.map +1 -1
- package/dist/notes/branches.js +31 -3
- package/dist/notes/branches.js.map +1 -1
- package/dist/notes/cold-start.d.ts +12 -2
- package/dist/notes/cold-start.d.ts.map +1 -1
- package/dist/notes/cold-start.js +46 -5
- package/dist/notes/cold-start.js.map +1 -1
- package/dist/notes/credit.d.ts +37 -0
- package/dist/notes/credit.d.ts.map +1 -0
- package/dist/notes/credit.js +78 -0
- package/dist/notes/credit.js.map +1 -0
- package/dist/notes/find-notes.d.ts +17 -0
- package/dist/notes/find-notes.d.ts.map +1 -0
- package/dist/notes/find-notes.js +48 -0
- package/dist/notes/find-notes.js.map +1 -0
- package/dist/notes/flatten.d.ts +31 -0
- package/dist/notes/flatten.d.ts.map +1 -0
- package/dist/notes/flatten.js +73 -0
- package/dist/notes/flatten.js.map +1 -0
- package/dist/notes/git-facts.d.ts +2 -0
- package/dist/notes/git-facts.d.ts.map +1 -1
- package/dist/notes/git-facts.js +6 -0
- package/dist/notes/git-facts.js.map +1 -1
- package/dist/notes/home.d.ts +24 -6
- package/dist/notes/home.d.ts.map +1 -1
- package/dist/notes/home.js +82 -15
- package/dist/notes/home.js.map +1 -1
- package/dist/notes/learning-fields.d.ts +102 -0
- package/dist/notes/learning-fields.d.ts.map +1 -0
- package/dist/notes/learning-fields.js +214 -0
- package/dist/notes/learning-fields.js.map +1 -0
- package/dist/notes/memory-notes.d.ts +71 -0
- package/dist/notes/memory-notes.d.ts.map +1 -0
- package/dist/notes/memory-notes.js +239 -0
- package/dist/notes/memory-notes.js.map +1 -0
- package/dist/notes/note-gate.d.ts +42 -0
- package/dist/notes/note-gate.d.ts.map +1 -0
- package/dist/notes/note-gate.js +181 -0
- package/dist/notes/note-gate.js.map +1 -0
- package/dist/notes/notes.d.ts +29 -85
- package/dist/notes/notes.d.ts.map +1 -1
- package/dist/notes/notes.js +69 -254
- package/dist/notes/notes.js.map +1 -1
- package/dist/notes/pr-reviews.d.ts +35 -7
- package/dist/notes/pr-reviews.d.ts.map +1 -1
- package/dist/notes/pr-reviews.js +156 -46
- package/dist/notes/pr-reviews.js.map +1 -1
- package/dist/notes/secrets.d.ts +28 -0
- package/dist/notes/secrets.d.ts.map +1 -0
- package/dist/notes/secrets.js +362 -0
- package/dist/notes/secrets.js.map +1 -0
- package/dist/notes/targets.d.ts +37 -0
- package/dist/notes/targets.d.ts.map +1 -0
- package/dist/notes/targets.js +108 -0
- package/dist/notes/targets.js.map +1 -0
- package/dist/notes/team-check.d.ts +22 -0
- package/dist/notes/team-check.d.ts.map +1 -0
- package/dist/notes/team-check.js +130 -0
- package/dist/notes/team-check.js.map +1 -0
- package/dist/notes/trail-home.d.ts +3 -0
- package/dist/notes/trail-home.d.ts.map +1 -0
- package/dist/notes/trail-home.js +12 -0
- package/dist/notes/trail-home.js.map +1 -0
- package/dist/skills/answers-prompt.d.ts +13 -0
- package/dist/skills/answers-prompt.d.ts.map +1 -0
- package/dist/skills/answers-prompt.js +83 -0
- package/dist/skills/answers-prompt.js.map +1 -0
- package/dist/skills/never-save.d.ts +5 -0
- package/dist/skills/never-save.d.ts.map +1 -0
- package/dist/skills/never-save.js +158 -0
- package/dist/skills/never-save.js.map +1 -0
- package/dist/skills/params.d.ts +39 -0
- package/dist/skills/params.d.ts.map +1 -0
- package/dist/skills/params.js +275 -0
- package/dist/skills/params.js.map +1 -0
- package/dist/skills/ran-less.d.ts +5 -0
- package/dist/skills/ran-less.d.ts.map +1 -0
- package/dist/skills/ran-less.js +51 -0
- package/dist/skills/ran-less.js.map +1 -0
- package/dist/skills/risk-delta.d.ts +32 -0
- package/dist/skills/risk-delta.d.ts.map +1 -0
- package/dist/skills/risk-delta.js +56 -0
- package/dist/skills/risk-delta.js.map +1 -0
- package/dist/skills/risk.d.ts +73 -0
- package/dist/skills/risk.d.ts.map +1 -0
- package/dist/skills/risk.js +396 -0
- package/dist/skills/risk.js.map +1 -0
- package/dist/skills/types.d.ts +422 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/telemetry/contract.d.ts.map +1 -1
- package/dist/telemetry/contract.js +8 -6
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/telemetry/notice.d.ts.map +1 -1
- package/dist/telemetry/notice.js +3 -1
- package/dist/telemetry/notice.js.map +1 -1
- package/dist/trace/check-reads.d.ts +36 -0
- package/dist/trace/check-reads.d.ts.map +1 -0
- package/dist/trace/check-reads.js +57 -0
- package/dist/trace/check-reads.js.map +1 -0
- package/dist/trace/host.d.ts +40 -0
- package/dist/trace/host.d.ts.map +1 -0
- package/dist/trace/host.js +84 -0
- package/dist/trace/host.js.map +1 -0
- package/dist/trace/redact.d.ts +8 -0
- package/dist/trace/redact.d.ts.map +1 -0
- package/dist/trace/redact.js +63 -0
- package/dist/trace/redact.js.map +1 -0
- package/dist/trace/seen-cache.d.ts +9 -0
- package/dist/trace/seen-cache.d.ts.map +1 -0
- package/dist/trace/seen-cache.js +46 -0
- package/dist/trace/seen-cache.js.map +1 -0
- package/dist/trace/shell-scan.d.ts +52 -0
- package/dist/trace/shell-scan.d.ts.map +1 -0
- package/dist/trace/shell-scan.js +318 -0
- package/dist/trace/shell-scan.js.map +1 -0
- package/dist/trace/shell-words.d.ts +91 -0
- package/dist/trace/shell-words.d.ts.map +1 -0
- package/dist/trace/shell-words.js +558 -0
- package/dist/trace/shell-words.js.map +1 -0
- package/dist/trace/shell.d.ts +91 -0
- package/dist/trace/shell.d.ts.map +1 -0
- package/dist/trace/shell.js +435 -0
- package/dist/trace/shell.js.map +1 -0
- package/dist/trace/state.d.ts +27 -0
- package/dist/trace/state.d.ts.map +1 -0
- package/dist/trace/state.js +98 -0
- package/dist/trace/state.js.map +1 -0
- package/dist/trace/tamper-code.d.ts +9 -0
- package/dist/trace/tamper-code.d.ts.map +1 -0
- package/dist/trace/tamper-code.js +174 -0
- package/dist/trace/tamper-code.js.map +1 -0
- package/dist/trace/tamper-git.d.ts +12 -0
- package/dist/trace/tamper-git.d.ts.map +1 -0
- package/dist/trace/tamper-git.js +77 -0
- package/dist/trace/tamper-git.js.map +1 -0
- package/dist/trace/types.d.ts +477 -0
- package/dist/trace/types.d.ts.map +1 -0
- package/dist/trace/types.js +12 -0
- package/dist/trace/types.js.map +1 -0
- package/dist/trace/walls-glob.d.ts +11 -0
- package/dist/trace/walls-glob.d.ts.map +1 -0
- package/dist/trace/walls-glob.js +264 -0
- package/dist/trace/walls-glob.js.map +1 -0
- package/dist/trace/walls-quoted.d.ts +25 -0
- package/dist/trace/walls-quoted.d.ts.map +1 -0
- package/dist/trace/walls-quoted.js +81 -0
- package/dist/trace/walls-quoted.js.map +1 -0
- package/dist/upkeep.d.ts +1 -1
- package/dist/upkeep.d.ts.map +1 -1
- package/dist/upkeep.js +4 -1
- package/dist/upkeep.js.map +1 -1
- package/dist/util/actions-folder.d.ts +2 -0
- package/dist/util/actions-folder.d.ts.map +1 -0
- package/dist/util/actions-folder.js +9 -0
- package/dist/util/actions-folder.js.map +1 -0
- package/dist/util/front-matter.d.ts +31 -4
- package/dist/util/front-matter.d.ts.map +1 -1
- package/dist/util/front-matter.js +95 -3
- package/dist/util/front-matter.js.map +1 -1
- package/dist/util/private-file.d.ts +14 -0
- package/dist/util/private-file.d.ts.map +1 -0
- package/dist/util/private-file.js +82 -0
- package/dist/util/private-file.js.map +1 -0
- package/dist/util/private-fs.d.ts +25 -0
- package/dist/util/private-fs.d.ts.map +1 -0
- package/dist/util/private-fs.js +253 -0
- package/dist/util/private-fs.js.map +1 -0
- package/dist/util/state.d.ts.map +1 -1
- package/dist/util/state.js +3 -0
- package/dist/util/state.js.map +1 -1
- package/dist/viewer/app.js +2 -2
- package/package.json +5 -5
- package/scripts/run-tests.mjs +14 -2
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a learning says about itself beyond its title, author and date: a
|
|
3
|
+
* stable id, what kind of learning it is, who it is for, whether it still
|
|
4
|
+
* holds, and which older learning it replaces.
|
|
5
|
+
*
|
|
6
|
+
* A file written before these fields existed reads with defaults: its id
|
|
7
|
+
* comes from its file name (the same id a new file of that name is given),
|
|
8
|
+
* its status is active, and its scope comes from where it sits. A value a
|
|
9
|
+
* learning can't hold (an unknown kind, a malformed id, a line break in a
|
|
10
|
+
* repo key) is dropped rather than carried into what an agent reads.
|
|
11
|
+
*
|
|
12
|
+
* `replaces` means the newest wins: recall and `trail check` read only the
|
|
13
|
+
* live learnings (`liveLearnings`), never one a newer learning replaced.
|
|
14
|
+
*/
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
16
|
+
import { flatLine } from "./flatten.js";
|
|
17
|
+
export const KINDS = ["preference", "guardrail", "decision", "lesson"];
|
|
18
|
+
export const SCOPES = ["personal", "repo", "team"];
|
|
19
|
+
export const STATUSES = ["active", "held", "replaced", "retired"];
|
|
20
|
+
export const SOURCES = ["person", "init-typed", "init-review", "error-class", "agent", "correction", "repair"];
|
|
21
|
+
export const CHECKS = ["no-timeout"];
|
|
22
|
+
export const ENFORCES = ["sure-fail"];
|
|
23
|
+
/**
|
|
24
|
+
* The wall catalog's classes at run time, in the catalog's order (trace/walls.ts). Equal to the WallClass type and
|
|
25
|
+
* to telemetry's wall_hit.class values; a test holds all three equal.
|
|
26
|
+
*/
|
|
27
|
+
export const WALL_CLASSES = [
|
|
28
|
+
"timeout-missing", "zsh-no-match", "git-https-auth", "docker-rootless", "npm-e401-eotp", "claude-not-logged-in", "enospc",
|
|
29
|
+
];
|
|
30
|
+
/** A personal learning's `applies` when it holds in every repo, not just one. */
|
|
31
|
+
export const EVERY_REPO = "every repo";
|
|
32
|
+
/** The front-matter keys, in the order they're written. */
|
|
33
|
+
export const LEARNING_KEYS = ["id", "kind", "scope", "applies", "status", "replaces", "src", "skill", "check", "enforce", "wall", "evidence"];
|
|
34
|
+
/** `l-` and 6 to 16 lowercase hex digits. */
|
|
35
|
+
export const LEARNING_ID = /^l-[0-9a-f]{6,16}$/;
|
|
36
|
+
/** A repo key as `home.ts` makes them: `github.com/acme/api`, `local/…`. */
|
|
37
|
+
const REPO_KEY = /^[a-z0-9._-]+(?:\/[a-z0-9._-]+)*$/;
|
|
38
|
+
const EVIDENCE_MAX = 160;
|
|
39
|
+
/** A skill name as compile gives them (compile-words.ts NAME_RE, no `--`, no trailing `-`). Kept here so notes don't load compile. */
|
|
40
|
+
const SKILL_NAME = /^(?=[a-z0-9-]*[a-z])[a-z0-9][a-z0-9-]{1,47}$/;
|
|
41
|
+
function skillName(v) {
|
|
42
|
+
if (typeof v !== "string")
|
|
43
|
+
return undefined;
|
|
44
|
+
const s = v.trim().toLowerCase();
|
|
45
|
+
return SKILL_NAME.test(s) && !/--|-$/.test(s) ? s : undefined;
|
|
46
|
+
}
|
|
47
|
+
/** The file name in a path: after the last `/`, `\\` or a branch ref's `:`. */
|
|
48
|
+
export function learningFileName(path) {
|
|
49
|
+
return path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"), path.lastIndexOf(":")) + 1);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The id of a learning file that doesn't say its own: `l-` and the first 6 hex
|
|
53
|
+
* digits of the file name's sha1. Files written before ids keep this one.
|
|
54
|
+
*/
|
|
55
|
+
export function learningId(fileName) {
|
|
56
|
+
return `l-${createHash("sha1").update(fileName).digest("hex").slice(0, 6)}`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The id a new learning is written with: the first 8 hex digits of the same
|
|
60
|
+
* sha1, so a repo with hundreds of learnings doesn't hand two the same one.
|
|
61
|
+
* Its first 6 are the id the file would get if its id line were lost.
|
|
62
|
+
*/
|
|
63
|
+
export function newLearningId(fileName) {
|
|
64
|
+
return `l-${createHash("sha1").update(fileName).digest("hex").slice(0, 8)}`;
|
|
65
|
+
}
|
|
66
|
+
/** `v` as one of `allowed`, ignoring case and padding, or undefined. */
|
|
67
|
+
function oneOf(v, allowed) {
|
|
68
|
+
if (typeof v !== "string")
|
|
69
|
+
return undefined;
|
|
70
|
+
const s = v.trim().toLowerCase();
|
|
71
|
+
return allowed.includes(s) ? s : undefined;
|
|
72
|
+
}
|
|
73
|
+
/** A learning id, normalised, or undefined when `v` isn't one. */
|
|
74
|
+
export function asLearningId(v) {
|
|
75
|
+
if (typeof v !== "string")
|
|
76
|
+
return undefined;
|
|
77
|
+
const s = v.trim().toLowerCase();
|
|
78
|
+
return LEARNING_ID.test(s) ? s : undefined;
|
|
79
|
+
}
|
|
80
|
+
function appliesValue(v) {
|
|
81
|
+
if (typeof v !== "string")
|
|
82
|
+
return undefined;
|
|
83
|
+
const s = v.trim().toLowerCase();
|
|
84
|
+
if (s === EVERY_REPO)
|
|
85
|
+
return EVERY_REPO;
|
|
86
|
+
return s.length <= 200 && REPO_KEY.test(s) ? s : undefined;
|
|
87
|
+
}
|
|
88
|
+
/** The fields of a learning's front matter `d`, read from the file `fileName`, with defaults for what it lacks. */
|
|
89
|
+
export function readLearningFields(d, fileName) {
|
|
90
|
+
const out = { id: asLearningId(d.id) ?? learningId(fileName), status: oneOf(d.status, STATUSES) ?? "active" };
|
|
91
|
+
const kind = oneOf(d.kind, KINDS);
|
|
92
|
+
const scope = oneOf(d.scope, SCOPES);
|
|
93
|
+
const applies = appliesValue(d.applies);
|
|
94
|
+
const replaces = asLearningId(d.replaces);
|
|
95
|
+
const src = oneOf(d.src, SOURCES);
|
|
96
|
+
const skill = skillName(d.skill);
|
|
97
|
+
const check = oneOf(d.check, CHECKS);
|
|
98
|
+
const enforce = oneOf(d.enforce, ENFORCES);
|
|
99
|
+
const wall = oneOf(d.wall, WALL_CLASSES);
|
|
100
|
+
// One line, the way every field an agent reads is (flatten.ts).
|
|
101
|
+
const evidence = flatLine(d.evidence, EVIDENCE_MAX) || undefined;
|
|
102
|
+
if (kind)
|
|
103
|
+
out.kind = kind;
|
|
104
|
+
if (scope)
|
|
105
|
+
out.scope = scope;
|
|
106
|
+
if (applies)
|
|
107
|
+
out.applies = applies;
|
|
108
|
+
if (replaces && replaces !== out.id)
|
|
109
|
+
out.replaces = replaces;
|
|
110
|
+
if (src)
|
|
111
|
+
out.src = src;
|
|
112
|
+
if (skill)
|
|
113
|
+
out.skill = skill;
|
|
114
|
+
if (check)
|
|
115
|
+
out.check = check;
|
|
116
|
+
if (enforce)
|
|
117
|
+
out.enforce = enforce;
|
|
118
|
+
if (wall)
|
|
119
|
+
out.wall = wall;
|
|
120
|
+
if (evidence)
|
|
121
|
+
out.evidence = evidence;
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
/** Whether following `replaces` from `x` comes back round to the id `to`. */
|
|
125
|
+
function leadsTo(x, to, byId) {
|
|
126
|
+
const seen = new Set();
|
|
127
|
+
const todo = x.replaces ? [x.replaces] : [];
|
|
128
|
+
while (todo.length) {
|
|
129
|
+
const id = todo.pop();
|
|
130
|
+
if (id === to)
|
|
131
|
+
return true;
|
|
132
|
+
if (seen.has(id))
|
|
133
|
+
continue;
|
|
134
|
+
seen.add(id);
|
|
135
|
+
for (const n of byId.get(id) ?? [])
|
|
136
|
+
if (n.replaces)
|
|
137
|
+
todo.push(n.replaces);
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
function byIdOf(notes) {
|
|
142
|
+
const byId = new Map();
|
|
143
|
+
for (const n of notes)
|
|
144
|
+
byId.set(n.id, [...(byId.get(n.id) ?? []), n]);
|
|
145
|
+
return byId;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Whether `r` replaces `x`. Only a learning someone has seen through counts:
|
|
149
|
+
* not one on a teammate's unmerged branch, nor one held for a yes. A
|
|
150
|
+
* just-for-you learning never hides one the repo or team shares. The newest
|
|
151
|
+
* wins; on the same day the replacement does, and of learnings that replace
|
|
152
|
+
* each other in a circle (only a hand edit makes one), the later file name.
|
|
153
|
+
*/
|
|
154
|
+
function replaces(r, x, byId) {
|
|
155
|
+
if (r === x || r.replaces !== x.id || r.id === x.id)
|
|
156
|
+
return false;
|
|
157
|
+
if (r.ref || r.status === "held")
|
|
158
|
+
return false;
|
|
159
|
+
if (r.scope === "personal" && x.scope !== "personal")
|
|
160
|
+
return false;
|
|
161
|
+
if (r.date !== x.date)
|
|
162
|
+
return r.date > x.date;
|
|
163
|
+
return r.path > x.path || !leadsTo(x, r.id, byId);
|
|
164
|
+
}
|
|
165
|
+
/** Active and not replaced (the rule both lists below share). */
|
|
166
|
+
function stillHold(notes, counts) {
|
|
167
|
+
const byTarget = new Map();
|
|
168
|
+
for (const r of notes)
|
|
169
|
+
if (r.replaces)
|
|
170
|
+
byTarget.set(r.replaces, [...(byTarget.get(r.replaces) ?? []), r]);
|
|
171
|
+
const byId = byIdOf(notes);
|
|
172
|
+
return notes.filter((x) => (x.status ?? "active") === "active" && !(byTarget.get(x.id) ?? []).some((r) => replaces(r, x, byId) && counts(r, x)));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The learnings that still hold: active ones (a file without a status is
|
|
176
|
+
* active) that no newer learning replaces. Order is kept. `counts(r, x)` can
|
|
177
|
+
* turn a replacement down: `trail check` lets only one on the base branch
|
|
178
|
+
* hide a learning that is there.
|
|
179
|
+
*
|
|
180
|
+
* 1b (R47): never a `lesson`. Session start, recall, standing learnings and
|
|
181
|
+
* `trail check` all read through here, and a lesson loads only through
|
|
182
|
+
* `lastTimeText` once it has worked twice (`liveLessons`).
|
|
183
|
+
*/
|
|
184
|
+
export function liveLearnings(notes, counts = () => true) {
|
|
185
|
+
return stillHold(notes, counts).filter((x) => x.kind !== "lesson");
|
|
186
|
+
}
|
|
187
|
+
/** The lessons that still hold, by the same rule: what `lastTimeText`'s caller reads (4.10). */
|
|
188
|
+
export function liveLessons(notes) {
|
|
189
|
+
return stillHold(notes, () => true).filter((x) => x.kind === "lesson");
|
|
190
|
+
}
|
|
191
|
+
/** The learnings among `notes` that replace `x` by the rule above, newest first. */
|
|
192
|
+
export function replacementsOf(notes, x) {
|
|
193
|
+
const byId = byIdOf(notes);
|
|
194
|
+
return notes.filter((r) => replaces(r, x, byId)).sort((a, b) => (a.date === b.date ? b.path.localeCompare(a.path) : b.date.localeCompare(a.date)));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* The learning `ref` names: by id, or by its file name (with or without `.md`,
|
|
198
|
+
* or a path ending in it). An id is copied from file to file by hand, so when
|
|
199
|
+
* two share one, the one in this checkout or on this machine comes before one
|
|
200
|
+
* on a teammate's branch.
|
|
201
|
+
*/
|
|
202
|
+
export function findLearning(notes, ref) {
|
|
203
|
+
const id = asLearningId(ref);
|
|
204
|
+
if (id) {
|
|
205
|
+
const named = notes.filter((n) => n.id === id);
|
|
206
|
+
return named.find((n) => !n.ref) ?? named[0];
|
|
207
|
+
}
|
|
208
|
+
const name = learningFileName(ref.trim());
|
|
209
|
+
if (!name)
|
|
210
|
+
return undefined;
|
|
211
|
+
const file = name.endsWith(".md") ? name : `${name}.md`;
|
|
212
|
+
return notes.find((n) => learningFileName(n.path) === file);
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=learning-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learning-fields.js","sourceRoot":"","sources":["../../src/notes/learning-fields.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type Note } from "./notes.js";
|
|
2
|
+
export type MemoryType = "project" | "reference" | "feedback" | "user" | "other";
|
|
3
|
+
/** One of Claude Code's memory notes, as written. */
|
|
4
|
+
export interface MemoryNote {
|
|
5
|
+
/** Absolute path of the note. */
|
|
6
|
+
path: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
type: MemoryType;
|
|
10
|
+
body: string;
|
|
11
|
+
/** YYYY-MM-DD it was last changed. */
|
|
12
|
+
updated: string;
|
|
13
|
+
}
|
|
14
|
+
/** A memory note as `trail init` offers it. */
|
|
15
|
+
export interface MemoryCandidate {
|
|
16
|
+
title: string;
|
|
17
|
+
/** Markdown under `## Decided` and maybe `## Watch out`, secrets scrubbed. */
|
|
18
|
+
body: string;
|
|
19
|
+
/** Tied to code that exists now and not already said: offered for the team, ticked. */
|
|
20
|
+
forTeam: boolean;
|
|
21
|
+
touches: string[];
|
|
22
|
+
/** The note it came from, for the once-per-note mark. */
|
|
23
|
+
path: string;
|
|
24
|
+
updated: string;
|
|
25
|
+
}
|
|
26
|
+
/** The memory folders of this repo's checkouts on this machine: its own, its worktrees', and other clones'. */
|
|
27
|
+
export declare function memoryDirs(repo: string, home?: string): string[];
|
|
28
|
+
/** One memory note, or null when it isn't one (no frontmatter, empty, the MEMORY.md index). */
|
|
29
|
+
export declare function readMemoryNote(path: string): MemoryNote | null;
|
|
30
|
+
/** Every memory note of the repo's checkouts on this machine, newest first. */
|
|
31
|
+
export declare function memoryNotes(repo: string, home?: string): MemoryNote[];
|
|
32
|
+
/** A title a person reads: the note's name when it's words, else its description's first clause. */
|
|
33
|
+
export declare function memoryTitle(note: Pick<MemoryNote, "name" | "description">): string;
|
|
34
|
+
/**
|
|
35
|
+
* A memory note's body as a learning's: what it says, with its **Why:**,
|
|
36
|
+
* under `## Decided`; its **How to apply:** under `## Watch out`. Its own
|
|
37
|
+
* headings become bold lines so they don't break the learning's sections.
|
|
38
|
+
*/
|
|
39
|
+
export declare function memoryBody(note: Pick<MemoryNote, "body">): string;
|
|
40
|
+
/**
|
|
41
|
+
* A short fact with its reason, not a work log. Status write-ups, and long
|
|
42
|
+
* notes with no **Why:**, stay in Claude's memory: as a learning they'd read
|
|
43
|
+
* as a diary, and be wrong by next week.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readsAsLearning(body: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* What `trail init` offers from Claude Code's memory of this repo, for the
|
|
48
|
+
* team: project and reference notes that read as a learning, are tied to code
|
|
49
|
+
* that exists now, and aren't already said. Notes offered before and
|
|
50
|
+
* unchanged since are left out.
|
|
51
|
+
*/
|
|
52
|
+
export declare function memoryCandidates(repo: string, opts?: {
|
|
53
|
+
home?: string;
|
|
54
|
+
offered?: Set<string>;
|
|
55
|
+
}): MemoryCandidate[];
|
|
56
|
+
/** The memory notes init offered in this repo before, unchanged since. */
|
|
57
|
+
export declare function offeredBefore(repo: string): Set<string>;
|
|
58
|
+
/** Each kept candidate as a learning: the team's in `.trail/learnings/`, the person's own in ~/.trail. */
|
|
59
|
+
export declare function saveMemoryCandidates(repo: string, kept: MemoryCandidate[], author?: string, date?: string): Note[];
|
|
60
|
+
/**
|
|
61
|
+
* Save the candidates the person keeps and remember every one was offered.
|
|
62
|
+
* Without `keep` (no terminal to ask on), the team ones are kept: the
|
|
63
|
+
* person's own are already in their Claude's memory. `keep` resolving null
|
|
64
|
+
* means they cancelled: nothing is saved or marked, and the next init asks again.
|
|
65
|
+
*/
|
|
66
|
+
export declare function finishMemoryRead(repo: string, candidates: MemoryCandidate[], keep?: (candidates: MemoryCandidate[]) => Promise<MemoryCandidate[] | null>): Promise<{
|
|
67
|
+
saved: Note[];
|
|
68
|
+
kept: MemoryCandidate[];
|
|
69
|
+
cancelled: boolean;
|
|
70
|
+
}>;
|
|
71
|
+
//# sourceMappingURL=memory-notes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-notes.d.ts","sourceRoot":"","sources":["../../src/notes/memory-notes.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAwB,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAI7D,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjF,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAQD,+GAA+G;AAC/G,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,EAAE,CAE3E;AAmBD,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAyB9D;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,UAAU,EAAE,CAehF;AAMD,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,MAAM,CAOlF;AAeD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,MAAM,CAQjE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGrD;AAKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAO,GAAG,eAAe,EAAE,CAsBrH;AAYD,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAEvD;AAED,0GAA0G;AAC1G,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,MAAM,SAAmB,EAAE,IAAI,SAAwC,GAAG,IAAI,EAAE,CAc3J;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,eAAe,EAAE,EAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,EAAE,KAAK,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,GAC1E,OAAO,CAAC;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,IAAI,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAuBzE"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learnings from the notes Claude Code keeps for this repo on this machine
|
|
3
|
+
* (`~/.claude/projects/<folder>/memory/*.md`), for `trail init` to offer on
|
|
4
|
+
* day one. Those notes are Claude's own memory of the repo: what it was told
|
|
5
|
+
* about the project, where things are, how the person likes to work. They
|
|
6
|
+
* never leave this machine, so a teammate's Claude starts without them.
|
|
7
|
+
*
|
|
8
|
+
* No model reads them: each note is already short and written for Claude.
|
|
9
|
+
* trail keeps a project or reference note as a team learning only when it
|
|
10
|
+
* names code that exists now and the repo doesn't already say it; the rest,
|
|
11
|
+
* and the person's feedback notes, are offered as their own. Notes about the
|
|
12
|
+
* person (`user`) are never offered. Anything that looks like a secret is
|
|
13
|
+
* scrubbed, and a note that still looks like one is skipped.
|
|
14
|
+
*/
|
|
15
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { basename, join } from "node:path";
|
|
18
|
+
import { countBucket } from "../telemetry/contract.js";
|
|
19
|
+
import { track } from "../telemetry/track.js";
|
|
20
|
+
import { readJson, writeJsonAtomic } from "../util/state.js";
|
|
21
|
+
import { sameRepoRoots, scrub } from "./cold-start.js";
|
|
22
|
+
import { noteAuthor } from "./git-facts.js";
|
|
23
|
+
import { ensureRepoHome } from "./home.js";
|
|
24
|
+
import { shortDate, writeNote } from "./notes.js";
|
|
25
|
+
import { claudeProjectDir } from "./session-cost.js";
|
|
26
|
+
import { alreadySaid, codeAnchors, knownText } from "./team-check.js";
|
|
27
|
+
const BODY_CHARS = 1500;
|
|
28
|
+
/* -------------------------------------------------------------------------- */
|
|
29
|
+
/* Reading the notes */
|
|
30
|
+
/* -------------------------------------------------------------------------- */
|
|
31
|
+
/** The memory folders of this repo's checkouts on this machine: its own, its worktrees', and other clones'. */
|
|
32
|
+
export function memoryDirs(repo, home = homedir()) {
|
|
33
|
+
return [...new Set(sameRepoRoots(repo, home).map((r) => join(claudeProjectDir(r, home), "memory")))];
|
|
34
|
+
}
|
|
35
|
+
/** The value of `key:` in a frontmatter block, top level or under `metadata:`, unquoted. */
|
|
36
|
+
function field(front, key) {
|
|
37
|
+
const m = new RegExp(`^\\s*${key}:\\s*(.*)$`, "m").exec(front);
|
|
38
|
+
if (!m)
|
|
39
|
+
return "";
|
|
40
|
+
const v = m[1].trim();
|
|
41
|
+
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) {
|
|
42
|
+
try {
|
|
43
|
+
return v.startsWith('"') ? JSON.parse(v) : v.slice(1, -1);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return v.slice(1, -1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return v;
|
|
50
|
+
}
|
|
51
|
+
const TYPES = ["project", "reference", "feedback", "user"];
|
|
52
|
+
/** One memory note, or null when it isn't one (no frontmatter, empty, the MEMORY.md index). */
|
|
53
|
+
export function readMemoryNote(path) {
|
|
54
|
+
if (basename(path) === "MEMORY.md")
|
|
55
|
+
return null;
|
|
56
|
+
let text;
|
|
57
|
+
let updated;
|
|
58
|
+
try {
|
|
59
|
+
text = readFileSync(path, "utf8");
|
|
60
|
+
updated = statSync(path).mtime.toISOString().slice(0, 10);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(text);
|
|
66
|
+
if (!m)
|
|
67
|
+
return null;
|
|
68
|
+
const front = m[1];
|
|
69
|
+
const body = m[2].trim();
|
|
70
|
+
if (!body)
|
|
71
|
+
return null;
|
|
72
|
+
const raw = field(front, "type").toLowerCase();
|
|
73
|
+
const modified = /^\d{4}-\d{2}-\d{2}/.exec(field(front, "modified"))?.[0];
|
|
74
|
+
return {
|
|
75
|
+
path,
|
|
76
|
+
name: field(front, "name") || basename(path, ".md"),
|
|
77
|
+
description: field(front, "description"),
|
|
78
|
+
type: TYPES.includes(raw) ? raw : "other",
|
|
79
|
+
body,
|
|
80
|
+
updated: modified ?? updated,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Every memory note of the repo's checkouts on this machine, newest first. */
|
|
84
|
+
export function memoryNotes(repo, home = homedir()) {
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const dir of memoryDirs(repo, home)) {
|
|
87
|
+
let files;
|
|
88
|
+
try {
|
|
89
|
+
files = readdirSync(dir).filter((f) => f.endsWith(".md"));
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
for (const f of files) {
|
|
95
|
+
const note = readMemoryNote(join(dir, f));
|
|
96
|
+
if (note)
|
|
97
|
+
out.push(note);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return out.sort((a, b) => b.updated.localeCompare(a.updated));
|
|
101
|
+
}
|
|
102
|
+
/* -------------------------------------------------------------------------- */
|
|
103
|
+
/* As learnings */
|
|
104
|
+
/* -------------------------------------------------------------------------- */
|
|
105
|
+
/** A title a person reads: the note's name when it's words, else its description's first clause. */
|
|
106
|
+
export function memoryTitle(note) {
|
|
107
|
+
const words = /\s/.test(note.name.trim()) ? note.name.trim() : "";
|
|
108
|
+
const first = note.description.split(/(?<=[a-z0-9)`])\.\s|;\s| — | -- /)[0].trim();
|
|
109
|
+
let t = words || first || note.name.replace(/[-_]+/g, " ");
|
|
110
|
+
t = t.replace(/\.$/, "");
|
|
111
|
+
if (t.length > 90)
|
|
112
|
+
t = `${t.slice(0, 89).replace(/\s+\S*$/, "")}…`;
|
|
113
|
+
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
114
|
+
}
|
|
115
|
+
/** `[[name]]` links to other memory notes read as plain words outside Claude's memory. */
|
|
116
|
+
function unlink(s) {
|
|
117
|
+
return s.replace(/\[\[([^\]]+)\]\]/g, "$1");
|
|
118
|
+
}
|
|
119
|
+
/** At most `max` characters, cut at a paragraph or line break when there is one. */
|
|
120
|
+
function clip(s, max) {
|
|
121
|
+
if (s.length <= max)
|
|
122
|
+
return s;
|
|
123
|
+
const cut = s.slice(0, max);
|
|
124
|
+
const at = Math.max(cut.lastIndexOf("\n\n"), cut.lastIndexOf("\n"));
|
|
125
|
+
return `${(at > max / 2 ? cut.slice(0, at) : cut).trimEnd()}\n…`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A memory note's body as a learning's: what it says, with its **Why:**,
|
|
129
|
+
* under `## Decided`; its **How to apply:** under `## Watch out`. Its own
|
|
130
|
+
* headings become bold lines so they don't break the learning's sections.
|
|
131
|
+
*/
|
|
132
|
+
export function memoryBody(note) {
|
|
133
|
+
const text = unlink(note.body).replace(/^#{1,6}\s+(.+)$/gm, "**$1**");
|
|
134
|
+
const split = /\*\*How to apply:?\*\*:?/i.exec(text);
|
|
135
|
+
const decided = (split ? text.slice(0, split.index) : text).trim();
|
|
136
|
+
const apply = split ? text.slice(split.index + split[0].length).trim() : "";
|
|
137
|
+
let out = `## Decided\n${clip(decided, BODY_CHARS)}`;
|
|
138
|
+
if (apply)
|
|
139
|
+
out += `\n\n## Watch out\n${clip(apply, 600)}`;
|
|
140
|
+
return scrub(out);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* A short fact with its reason, not a work log. Status write-ups, and long
|
|
144
|
+
* notes with no **Why:**, stay in Claude's memory: as a learning they'd read
|
|
145
|
+
* as a diary, and be wrong by next week.
|
|
146
|
+
*/
|
|
147
|
+
export function readsAsLearning(body) {
|
|
148
|
+
if (/\*\*Status\b|^Status:|Shipped on branch|SLA breach|\bnot merged yet\b/im.test(body))
|
|
149
|
+
return false;
|
|
150
|
+
return body.split(/\s+/).filter(Boolean).length <= 150 || /\*\*Why:?\*\*/i.test(body);
|
|
151
|
+
}
|
|
152
|
+
/** Still looks like a credential after scrubbing, or names where one lives: not worth the risk of committing. */
|
|
153
|
+
const SECRETISH = /\b(?:AWS_SECRET_ACCESS_KEY|PRIVATE KEY|client_secret|BEGIN OPENSSH)\b|\[redacted\]/;
|
|
154
|
+
/**
|
|
155
|
+
* What `trail init` offers from Claude Code's memory of this repo, for the
|
|
156
|
+
* team: project and reference notes that read as a learning, are tied to code
|
|
157
|
+
* that exists now, and aren't already said. Notes offered before and
|
|
158
|
+
* unchanged since are left out.
|
|
159
|
+
*/
|
|
160
|
+
export function memoryCandidates(repo, opts = {}) {
|
|
161
|
+
const known = knownText(repo);
|
|
162
|
+
const team = [];
|
|
163
|
+
const titles = new Set();
|
|
164
|
+
for (const note of memoryNotes(repo, opts.home)) {
|
|
165
|
+
// Only what the team can use: Claude already reads the rest of its memory
|
|
166
|
+
// on this machine, so offering it again as a personal learning repeats it.
|
|
167
|
+
if (note.type !== "project" && note.type !== "reference")
|
|
168
|
+
continue;
|
|
169
|
+
if (opts.offered?.has(offerKey(note)))
|
|
170
|
+
continue;
|
|
171
|
+
if (!readsAsLearning(note.body))
|
|
172
|
+
continue;
|
|
173
|
+
const title = memoryTitle(note);
|
|
174
|
+
const key = title.toLowerCase();
|
|
175
|
+
if (titles.has(key))
|
|
176
|
+
continue;
|
|
177
|
+
const body = memoryBody(note);
|
|
178
|
+
if (SECRETISH.test(body))
|
|
179
|
+
continue;
|
|
180
|
+
if (alreadySaid(known, title, body))
|
|
181
|
+
continue;
|
|
182
|
+
titles.add(key);
|
|
183
|
+
const touches = codeAnchors(repo, `${note.description}\n${note.body}`);
|
|
184
|
+
if (!touches.length)
|
|
185
|
+
continue;
|
|
186
|
+
team.push({ title, body, forTeam: true, touches, path: note.path, updated: note.updated });
|
|
187
|
+
}
|
|
188
|
+
return team;
|
|
189
|
+
}
|
|
190
|
+
/** A note is offered again only once it changes. */
|
|
191
|
+
function offerKey(note) {
|
|
192
|
+
return `${note.path}@${note.updated}`;
|
|
193
|
+
}
|
|
194
|
+
/** Where a repo remembers which memory notes init offered, on this machine. */
|
|
195
|
+
function offeredMark(repo) {
|
|
196
|
+
return join(ensureRepoHome(repo).place.dir, "memory-notes.json");
|
|
197
|
+
}
|
|
198
|
+
/** The memory notes init offered in this repo before, unchanged since. */
|
|
199
|
+
export function offeredBefore(repo) {
|
|
200
|
+
return new Set(readJson(offeredMark(repo))?.offered ?? []);
|
|
201
|
+
}
|
|
202
|
+
/** Each kept candidate as a learning: the team's in `.trail/learnings/`, the person's own in ~/.trail. */
|
|
203
|
+
export function saveMemoryCandidates(repo, kept, author = noteAuthor(repo), date = new Date().toISOString().slice(0, 10)) {
|
|
204
|
+
return kept.map((c) => writeNote(repo, {
|
|
205
|
+
title: c.title,
|
|
206
|
+
author,
|
|
207
|
+
date,
|
|
208
|
+
body: `${c.body.trim()}\n\n_From Claude Code's memory of this repo, last updated ${shortDate(c.updated)}._`,
|
|
209
|
+
touches: c.touches,
|
|
210
|
+
}, c.forTeam ? "repo" : "personal"));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Save the candidates the person keeps and remember every one was offered.
|
|
214
|
+
* Without `keep` (no terminal to ask on), the team ones are kept: the
|
|
215
|
+
* person's own are already in their Claude's memory. `keep` resolving null
|
|
216
|
+
* means they cancelled: nothing is saved or marked, and the next init asks again.
|
|
217
|
+
*/
|
|
218
|
+
export async function finishMemoryRead(repo, candidates, keep) {
|
|
219
|
+
const chosen = candidates.length && keep ? await keep(candidates) : candidates.filter((c) => c.forTeam);
|
|
220
|
+
const kept = chosen ?? [];
|
|
221
|
+
const saved = kept.length ? saveMemoryCandidates(repo, kept) : [];
|
|
222
|
+
if (chosen !== null && candidates.length) {
|
|
223
|
+
const offered = offeredBefore(repo);
|
|
224
|
+
for (const c of candidates)
|
|
225
|
+
offered.add(offerKey(c));
|
|
226
|
+
writeJsonAtomic(offeredMark(repo), { at: Date.now(), offered: [...offered] }, true);
|
|
227
|
+
}
|
|
228
|
+
const team = candidates.filter((c) => c.forTeam);
|
|
229
|
+
track("cold_start", {
|
|
230
|
+
source: "memory",
|
|
231
|
+
outcome: chosen === null ? "cancelled" : candidates.length ? "found" : "none_found",
|
|
232
|
+
offered_bucket: countBucket(candidates.length),
|
|
233
|
+
picked_bucket: countBucket(saved.length),
|
|
234
|
+
team_offered_bucket: countBucket(team.length),
|
|
235
|
+
team_picked_bucket: countBucket(kept.filter((c) => c.forTeam).length),
|
|
236
|
+
}, { repo });
|
|
237
|
+
return { saved, kept, cancelled: chosen === null };
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=memory-notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-notes.js","sourceRoot":"","sources":["../../src/notes/memory-notes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Note } from "./notes.js";
|
|
2
|
+
/** Past this many words a learning gets skimmed: a warning, never a refusal. */
|
|
3
|
+
export declare const LONG_NOTE_WORDS = 250;
|
|
4
|
+
export interface GateInput {
|
|
5
|
+
title: string;
|
|
6
|
+
body: string;
|
|
7
|
+
/** Kept in ~/.trail for this person, not the team: only the status and repeat checks apply. */
|
|
8
|
+
personal: boolean;
|
|
9
|
+
/** Repo files the note names that exist (from `mentionedFiles`), relative to the checkout. */
|
|
10
|
+
files: string[];
|
|
11
|
+
/** Whether the note names a function, type or other symbol that's in the repo's code. */
|
|
12
|
+
namesSymbol: boolean;
|
|
13
|
+
/** What it will touch, for the repeat check. */
|
|
14
|
+
touches: string[];
|
|
15
|
+
/** The id of the learning it says it replaces (`--replaces`). */
|
|
16
|
+
replaces?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface GateResult {
|
|
19
|
+
/** Why it can't be saved as it is, each with how to fix it. Empty: it passes. */
|
|
20
|
+
problems: string[];
|
|
21
|
+
warnings: string[];
|
|
22
|
+
}
|
|
23
|
+
/** The learning this one repeats: same files, and much the same title or text. */
|
|
24
|
+
export declare function repeatOf(input: Pick<GateInput, "title" | "body" | "touches" | "replaces" | "personal">, existing: Note[]): Note | null;
|
|
25
|
+
/** The checks, on a learning about to be saved. `existing`: the learnings already there. */
|
|
26
|
+
export declare function gateNote(input: GateInput, existing: Note[]): GateResult;
|
|
27
|
+
/** The names a note uses that might be symbols, most likely first: backticked, then code-shaped. At most `limit`. */
|
|
28
|
+
export declare function symbolCandidates(text: string, limit?: number): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Whether any of `names` is in the repo's code: a whole-word `git grep` over
|
|
31
|
+
* tracked files, leaving out trail's own files and markdown, which would find
|
|
32
|
+
* the note's own words. Outside git, false: the files it names still count.
|
|
33
|
+
*/
|
|
34
|
+
export declare function namesRepoSymbol(repo: string, names: string[]): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Of `files` (relative to the checkout at `repo`), the ones git tracks. A
|
|
37
|
+
* learning's `touches:` lists these, plus files the session itself edited:
|
|
38
|
+
* an untracked file that was already lying around (a token, a scratch file)
|
|
39
|
+
* is never what a learning is about. Outside git, every file that exists.
|
|
40
|
+
*/
|
|
41
|
+
export declare function trackedFiles(repo: string, files: string[]): Set<string>;
|
|
42
|
+
//# sourceMappingURL=note-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"note-gate.d.ts","sourceRoot":"","sources":["../../src/notes/note-gate.ts"],"names":[],"mappings":"AAgBA,OAAO,EAA4C,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAEjF,gFAAgF;AAChF,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,QAAQ,EAAE,OAAO,CAAC;IAClB,8FAA8F;IAC9F,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yFAAyF;IACzF,WAAW,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAiED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,CAYtI;AAED,4FAA4F;AAC5F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,UAAU,CAsCvE;AAMD,qHAAqH;AACrH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE,CAUlE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CActE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAQvE"}
|