@jigyasudham/veto 3.3.0 → 3.5.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 (164) hide show
  1. package/README.md +89 -7
  2. package/dist/adapters/index.d.ts.map +1 -1
  3. package/dist/adapters/index.js +1 -0
  4. package/dist/adapters/index.js.map +1 -1
  5. package/dist/agents/llm-runner.d.ts.map +1 -1
  6. package/dist/agents/llm-runner.js +78 -8
  7. package/dist/agents/llm-runner.js.map +1 -1
  8. package/dist/cli/context-guidance.d.ts +16 -0
  9. package/dist/cli/context-guidance.d.ts.map +1 -0
  10. package/dist/cli/context-guidance.js +20 -0
  11. package/dist/cli/context-guidance.js.map +1 -0
  12. package/dist/cli/leftover-guides.d.ts +38 -0
  13. package/dist/cli/leftover-guides.d.ts.map +1 -0
  14. package/dist/cli/leftover-guides.js +135 -0
  15. package/dist/cli/leftover-guides.js.map +1 -0
  16. package/dist/cli/lessons.d.ts +17 -0
  17. package/dist/cli/lessons.d.ts.map +1 -0
  18. package/dist/cli/lessons.js +448 -0
  19. package/dist/cli/lessons.js.map +1 -0
  20. package/dist/cli/statusline-hosts.d.ts +36 -0
  21. package/dist/cli/statusline-hosts.d.ts.map +1 -0
  22. package/dist/cli/statusline-hosts.js +212 -0
  23. package/dist/cli/statusline-hosts.js.map +1 -0
  24. package/dist/cli/statusline.d.ts +7 -0
  25. package/dist/cli/statusline.d.ts.map +1 -1
  26. package/dist/cli/statusline.js +69 -11
  27. package/dist/cli/statusline.js.map +1 -1
  28. package/dist/cli.js +114 -47
  29. package/dist/cli.js.map +1 -1
  30. package/dist/council/llm-council.d.ts.map +1 -1
  31. package/dist/council/llm-council.js +13 -8
  32. package/dist/council/llm-council.js.map +1 -1
  33. package/dist/lessons/adapters/claude.d.ts +10 -0
  34. package/dist/lessons/adapters/claude.d.ts.map +1 -0
  35. package/dist/lessons/adapters/claude.js +18 -0
  36. package/dist/lessons/adapters/claude.js.map +1 -0
  37. package/dist/lessons/adapters/codex.d.ts +7 -0
  38. package/dist/lessons/adapters/codex.d.ts.map +1 -0
  39. package/dist/lessons/adapters/codex.js +9 -0
  40. package/dist/lessons/adapters/codex.js.map +1 -0
  41. package/dist/lessons/adapters/gemini.d.ts +4 -0
  42. package/dist/lessons/adapters/gemini.d.ts.map +1 -0
  43. package/dist/lessons/adapters/gemini.js +44 -0
  44. package/dist/lessons/adapters/gemini.js.map +1 -0
  45. package/dist/lessons/adapters/index.d.ts +6 -0
  46. package/dist/lessons/adapters/index.d.ts.map +1 -0
  47. package/dist/lessons/adapters/index.js +14 -0
  48. package/dist/lessons/adapters/index.js.map +1 -0
  49. package/dist/lessons/adapters/markdown.d.ts +16 -0
  50. package/dist/lessons/adapters/markdown.d.ts.map +1 -0
  51. package/dist/lessons/adapters/markdown.js +130 -0
  52. package/dist/lessons/adapters/markdown.js.map +1 -0
  53. package/dist/lessons/adapters/types.d.ts +27 -0
  54. package/dist/lessons/adapters/types.d.ts.map +1 -0
  55. package/dist/lessons/adapters/types.js +2 -0
  56. package/dist/lessons/adapters/types.js.map +1 -0
  57. package/dist/lessons/classify.d.ts +33 -0
  58. package/dist/lessons/classify.d.ts.map +1 -0
  59. package/dist/lessons/classify.js +108 -0
  60. package/dist/lessons/classify.js.map +1 -0
  61. package/dist/lessons/consent.d.ts +30 -0
  62. package/dist/lessons/consent.d.ts.map +1 -0
  63. package/dist/lessons/consent.js +86 -0
  64. package/dist/lessons/consent.js.map +1 -0
  65. package/dist/lessons/discover.d.ts +26 -0
  66. package/dist/lessons/discover.d.ts.map +1 -0
  67. package/dist/lessons/discover.js +65 -0
  68. package/dist/lessons/discover.js.map +1 -0
  69. package/dist/lessons/harvest.d.ts +84 -0
  70. package/dist/lessons/harvest.d.ts.map +1 -0
  71. package/dist/lessons/harvest.js +271 -0
  72. package/dist/lessons/harvest.js.map +1 -0
  73. package/dist/lessons/identity.d.ts +23 -0
  74. package/dist/lessons/identity.d.ts.map +1 -0
  75. package/dist/lessons/identity.js +81 -0
  76. package/dist/lessons/identity.js.map +1 -0
  77. package/dist/lessons/manage.d.ts +163 -0
  78. package/dist/lessons/manage.d.ts.map +1 -0
  79. package/dist/lessons/manage.js +337 -0
  80. package/dist/lessons/manage.js.map +1 -0
  81. package/dist/lessons/mask.d.ts +6 -0
  82. package/dist/lessons/mask.d.ts.map +1 -0
  83. package/dist/lessons/mask.js +22 -0
  84. package/dist/lessons/mask.js.map +1 -0
  85. package/dist/lessons/on-save.d.ts +18 -0
  86. package/dist/lessons/on-save.d.ts.map +1 -0
  87. package/dist/lessons/on-save.js +53 -0
  88. package/dist/lessons/on-save.js.map +1 -0
  89. package/dist/lessons/select.d.ts +23 -0
  90. package/dist/lessons/select.d.ts.map +1 -0
  91. package/dist/lessons/select.js +136 -0
  92. package/dist/lessons/select.js.map +1 -0
  93. package/dist/lessons/source-project.d.ts +9 -0
  94. package/dist/lessons/source-project.d.ts.map +1 -0
  95. package/dist/lessons/source-project.js +149 -0
  96. package/dist/lessons/source-project.js.map +1 -0
  97. package/dist/lessons/store.d.ts +135 -0
  98. package/dist/lessons/store.d.ts.map +1 -0
  99. package/dist/lessons/store.js +222 -0
  100. package/dist/lessons/store.js.map +1 -0
  101. package/dist/memory/config.d.ts +27 -0
  102. package/dist/memory/config.d.ts.map +1 -1
  103. package/dist/memory/config.js +67 -0
  104. package/dist/memory/config.js.map +1 -1
  105. package/dist/memory/local.d.ts.map +1 -1
  106. package/dist/memory/local.js +19 -1
  107. package/dist/memory/local.js.map +1 -1
  108. package/dist/memory/schema.d.ts +1 -1
  109. package/dist/memory/schema.d.ts.map +1 -1
  110. package/dist/memory/schema.js +104 -0
  111. package/dist/memory/schema.js.map +1 -1
  112. package/dist/server/handlers/council.d.ts.map +1 -1
  113. package/dist/server/handlers/council.js +40 -4
  114. package/dist/server/handlers/council.js.map +1 -1
  115. package/dist/server/handlers/memory.d.ts.map +1 -1
  116. package/dist/server/handlers/memory.js +13 -3
  117. package/dist/server/handlers/memory.js.map +1 -1
  118. package/dist/server/handlers/session.d.ts.map +1 -1
  119. package/dist/server/handlers/session.js +61 -21
  120. package/dist/server/handlers/session.js.map +1 -1
  121. package/dist/server.d.ts.map +1 -1
  122. package/dist/server.js +12 -3
  123. package/dist/server.js.map +1 -1
  124. package/dist/transcripts/cache.d.ts +1 -0
  125. package/dist/transcripts/cache.d.ts.map +1 -1
  126. package/dist/transcripts/cache.js +0 -0
  127. package/dist/transcripts/cache.js.map +1 -1
  128. package/dist/transcripts/claude-paths.d.ts +5 -0
  129. package/dist/transcripts/claude-paths.d.ts.map +1 -0
  130. package/dist/transcripts/claude-paths.js +21 -0
  131. package/dist/transcripts/claude-paths.js.map +1 -0
  132. package/dist/transcripts/context.d.ts +41 -0
  133. package/dist/transcripts/context.d.ts.map +1 -0
  134. package/dist/transcripts/context.js +144 -0
  135. package/dist/transcripts/context.js.map +1 -0
  136. package/dist/transcripts/discover.d.ts +12 -2
  137. package/dist/transcripts/discover.d.ts.map +1 -1
  138. package/dist/transcripts/discover.js +55 -7
  139. package/dist/transcripts/discover.js.map +1 -1
  140. package/dist/transcripts/manage.d.ts +8 -0
  141. package/dist/transcripts/manage.d.ts.map +1 -1
  142. package/dist/transcripts/manage.js +28 -13
  143. package/dist/transcripts/manage.js.map +1 -1
  144. package/dist/transcripts/mapping.d.ts.map +1 -1
  145. package/dist/transcripts/mapping.js +4 -2
  146. package/dist/transcripts/mapping.js.map +1 -1
  147. package/dist/transcripts/on-save.d.ts +9 -0
  148. package/dist/transcripts/on-save.d.ts.map +1 -1
  149. package/dist/transcripts/on-save.js +36 -9
  150. package/dist/transcripts/on-save.js.map +1 -1
  151. package/dist/transcripts/project-key.d.ts +4 -0
  152. package/dist/transcripts/project-key.d.ts.map +1 -0
  153. package/dist/transcripts/project-key.js +30 -0
  154. package/dist/transcripts/project-key.js.map +1 -0
  155. package/dist/transcripts/recall.d.ts +4 -0
  156. package/dist/transcripts/recall.d.ts.map +1 -1
  157. package/dist/transcripts/recall.js +6 -5
  158. package/dist/transcripts/recall.js.map +1 -1
  159. package/dist/transcripts/stopwords.d.ts +2 -0
  160. package/dist/transcripts/stopwords.d.ts.map +1 -0
  161. package/dist/transcripts/stopwords.js +8 -0
  162. package/dist/transcripts/stopwords.js.map +1 -0
  163. package/package.json +1 -1
  164. package/server.json +2 -2
@@ -0,0 +1,163 @@
1
+ import { type LessonSource } from './adapters/index.js';
2
+ import type { LessonScope } from './classify.js';
3
+ import { type LessonSyncReport } from './harvest.js';
4
+ import { type LessonRow, type ProjectExclusion } from './store.js';
5
+ export declare const HOST_NAMES: Record<LessonSource, string>;
6
+ /**
7
+ * Re-read every source so what is shown matches the files as they are now.
8
+ * Only with consent. A pass run from a command has no time budget: a person
9
+ * waiting for output would rather wait than be told a half-truth.
10
+ */
11
+ export declare function refreshLessons(home?: string, options?: {
12
+ forced?: boolean;
13
+ }): LessonSyncReport | null;
14
+ export declare const lessonTitle: (row: LessonRow) => string;
15
+ export declare function projectName(row: Pick<LessonRow, 'project_identity' | 'project_label'>): string;
16
+ /** The label every note carries: which AI wrote it, for which project, when. */
17
+ export declare function provenance(row: LessonRow): string;
18
+ export type LessonReach = 'any-project' | 'own-project' | 'nowhere';
19
+ /**
20
+ * Where a note may be selected (select.ts `eligible`): project notes and held
21
+ * notes only into their own project; the rest into any project. A held note
22
+ * from a global file, or any note of a folder no session can open under, has
23
+ * no project to go to.
24
+ */
25
+ export declare function lessonReach(row: LessonRow): LessonReach;
26
+ /** Which AIs may receive it. The AI that wrote it already reads it, except Claude in other folders. */
27
+ export declare function receivingHosts(row: LessonRow): string;
28
+ export declare const quarantineText: (reason: string | null) => string;
29
+ export type LessonExplanation = {
30
+ row: LessonRow;
31
+ provenance: string;
32
+ scope: string;
33
+ held: string | null;
34
+ reach: string;
35
+ hostDisabled: string | null;
36
+ };
37
+ export declare function explainLesson(row: LessonRow): LessonExplanation;
38
+ export type LessonFilter = {
39
+ scope?: LessonScope;
40
+ source?: LessonSource;
41
+ projectDir?: string;
42
+ shared?: boolean;
43
+ held?: boolean;
44
+ };
45
+ export declare function listLessons(filter?: LessonFilter): LessonRow[];
46
+ export type FindLesson = {
47
+ row: LessonRow;
48
+ } | {
49
+ error: 'too-short' | 'not-found';
50
+ } | {
51
+ error: 'ambiguous';
52
+ matches: LessonRow[];
53
+ };
54
+ /** A note by its ID or any unique prefix of it (list shows the first 8 characters). */
55
+ export declare function findLesson(idOrPrefix: string): FindLesson;
56
+ /** Permanent: the note and every copy of it are deleted and never harvested again. */
57
+ export declare function forgetLesson(row: LessonRow): {
58
+ removed: number;
59
+ };
60
+ export type LessonsOffResult = {
61
+ wasOn: boolean;
62
+ notes: number;
63
+ shadowLog: number;
64
+ remaining: number;
65
+ };
66
+ /**
67
+ * Turn sharing off and delete everything harvested, plus the would-have-shared
68
+ * log. Forgotten-note tombstones, exclusions and aliases stay: they are the
69
+ * user's own decisions and hold no note text. `remaining` is the purge proof.
70
+ */
71
+ export declare function turnLessonsOff(): LessonsOffResult;
72
+ export type LessonFlow = {
73
+ source: LessonSource;
74
+ projectIdentity: string;
75
+ projectLabel: string;
76
+ notes: number;
77
+ anyProject: number;
78
+ ownProject: number;
79
+ nowhere: number;
80
+ /** Notes whose scope would have let them travel, kept home by quarantine, by reason. */
81
+ heldBack: Record<string, number>;
82
+ unresolved: boolean;
83
+ };
84
+ /** Source → destination, one line per AI and project the notes came from. */
85
+ export declare function lessonFlows(): LessonFlow[];
86
+ /** The link that would most likely fix an unlinked folder. `aliasPath` is null when only the project is known, not the folder's own path. */
87
+ export type AliasSuggestion = {
88
+ aliasPath: string | null;
89
+ targetDir: string;
90
+ };
91
+ export type UnresolvedFolder = {
92
+ identity: string;
93
+ label: string;
94
+ notes: number;
95
+ suggestion: AliasSuggestion | null;
96
+ };
97
+ /**
98
+ * The same project checked out on this machine: a known folder whose slug is
99
+ * the unlinked one's with another root (F:/a/b for D:/a/b, whose folder path
100
+ * is then known too), or failing that, one whose slug it ends with (a backup
101
+ * nested deeper, whose own path cannot be read back from its lossy slug).
102
+ * Anything but exactly one candidate suggests nothing.
103
+ */
104
+ export declare function suggestAlias(identity: string, known: string[]): AliasSuggestion | null;
105
+ /** Memory whose project Veto could not trace to a folder that exists: its project notes reach no session. */
106
+ export declare function unresolvedFolders(): UnresolvedFolder[];
107
+ /** Checkouts treated as one project: only groups of two or more folders are worth showing. */
108
+ export declare function aliasGroups(): Array<{
109
+ identity: string;
110
+ paths: string[];
111
+ }>;
112
+ export type SetAliasResult =
113
+ /** memoryFolders: Claude memory folders this path names; 0 usually means a mistyped path. */
114
+ {
115
+ ok: true;
116
+ identity: string;
117
+ label: string;
118
+ memoryFolders: number;
119
+ } | {
120
+ ok: false;
121
+ error: 'target-missing' | 'same-folder' | 'different-repository';
122
+ };
123
+ /**
124
+ * Treat `aliasPath` as another checkout of the project at `targetDir`: its
125
+ * notes then count as that project's. For a drive that is not mounted, which
126
+ * is the case this exists for, the alias path need not exist. A folder that
127
+ * does exist and is a different repository is refused, since aliasing it
128
+ * would carry one project's private notes into another.
129
+ */
130
+ export declare function setProjectAlias(aliasPath: string, targetDir: string): SetAliasResult;
131
+ export declare function removeProjectAlias(aliasPath: string): boolean;
132
+ export declare function excludeProjectDir(projectDir: string): {
133
+ label: string;
134
+ added: boolean;
135
+ removed: number;
136
+ };
137
+ export declare function includeProjectDir(projectDir: string): {
138
+ label: string;
139
+ removed: boolean;
140
+ };
141
+ /** Switch a host's harvester back on after a format change, and check it again straight away. */
142
+ export declare function recheckSource(source: LessonSource, home?: string): {
143
+ wasDisabled: boolean;
144
+ stillDisabled: string | null;
145
+ report: LessonSyncReport | null;
146
+ };
147
+ export type LessonsStatus = {
148
+ sharing: boolean;
149
+ /** Consent was given for an older disclosure; sharing stays off until it is accepted again. */
150
+ needsReconsent: boolean;
151
+ consentAt: string | null;
152
+ notes: number;
153
+ byHost: Record<LessonSource, number>;
154
+ anyProject: number;
155
+ held: number;
156
+ disabledHosts: Map<LessonSource, string>;
157
+ excluded: ProjectExclusion[];
158
+ unresolved: number;
159
+ forgotten: number;
160
+ shadowLog: number;
161
+ };
162
+ export declare function lessonsStatus(): LessonsStatus;
163
+ //# sourceMappingURL=manage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../src/lessons/manage.ts"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGxE,OAAO,EAEL,KAAK,SAAS,EAAE,KAAK,gBAAgB,EACtC,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAA0D,CAAC;AAE/G;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,gBAAgB,GAAG,IAAI,CAEzG;AAaD,eAAO,MAAM,WAAW,GAAI,KAAK,SAAS,KAAG,MAAkD,CAAC;AAWhG,wBAAgB,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,kBAAkB,GAAG,eAAe,CAAC,GAAG,MAAM,CAE9F;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAEjD;AAED,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,aAAa,GAAG,SAAS,CAAC;AAEpE;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,WAAW,CAGvD;AAED,uGAAuG;AACvG,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAIrD;AAmBD,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,GAAG,IAAI,KAAG,MAA0D,CAAC;AAElH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,SAAS,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,iBAAiB,CAe/D;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjI,wBAAgB,WAAW,CAAC,MAAM,GAAE,YAAiB,GAAG,SAAS,EAAE,CAalE;AAID,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,WAAW,GAAG,WAAW,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AAElI,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAMzD;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAEhE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvG;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,gBAAgB,CASjD;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,WAAW,IAAI,UAAU,EAAE,CAwB1C;AAID,6IAA6I;AAC7I,MAAM,MAAM,eAAe,GAAG;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAA;CAAE,CAAC;AA+BtH;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,GAAG,IAAI,CActF;AAED,6GAA6G;AAC7G,wBAAgB,iBAAiB,IAAI,gBAAgB,EAAE,CAWtD;AAED,8FAA8F;AAC9F,wBAAgB,WAAW,IAAI,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAM1E;AAED,MAAM,MAAM,cAAc;AACxB,6FAA6F;AAC3F;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa,GAAG,sBAAsB,CAAA;CAAE,CAAC;AAEpF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAcpF;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI7D;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAGxG;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAMzF;AAED,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAA;CAAE,CAO1J;AAID,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,+FAA+F;IAC/F,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACzC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,aAAa,IAAI,aAAa,CAqB7C"}
@@ -0,0 +1,337 @@
1
+ // The `veto lessons` surface: what Veto has harvested from each AI's own
2
+ // memory, where each note may go, and the controls that stop it (council
3
+ // 320c40dc, UX conditions). Everything here reads or changes Veto's own tables;
4
+ // no host's memory file is ever written.
5
+ import { existsSync, realpathSync, statSync } from 'node:fs';
6
+ import { basename, dirname } from 'node:path';
7
+ import { getConfig, disableLessonsSharing, isLessonsSharingEnabled, LESSONS_CONSENT_VERSION } from '../memory/config.js';
8
+ import { getDb } from '../memory/local.js';
9
+ import { LESSON_SOURCES } from './adapters/index.js';
10
+ import { syncLessonSources } from './harvest.js';
11
+ import { addProjectAlias, canonicalProjectPath, computeProjectIdentity, resolveProjectIdentity } from './identity.js';
12
+ import { claudeProjectSlug, sameClaudeSlug } from './source-project.js';
13
+ import { clearLessonFileState, disabledLessonSourceReasons, enableLessonSource, excludedProjects, excludeProject, includeProject, tombstoneLesson, } from './store.js';
14
+ export const HOST_NAMES = { claude: 'Claude', codex: 'Codex', gemini: 'Gemini' };
15
+ /**
16
+ * Re-read every source so what is shown matches the files as they are now.
17
+ * Only with consent. A pass run from a command has no time budget: a person
18
+ * waiting for output would rather wait than be told a half-truth.
19
+ */
20
+ export function refreshLessons(home, options = {}) {
21
+ return isLessonsSharingEnabled() ? syncLessonSources({ home, forced: options.forced }) : null;
22
+ }
23
+ /**
24
+ * Forget what every file looked like, so the next pass reads them all again.
25
+ * Needed after a decision that changes what a file would yield without
26
+ * touching the file: re-including a project, or pointing an alias somewhere
27
+ * new. Without this the fast path would skip exactly the files that changed
28
+ * meaning.
29
+ */
30
+ function invalidateHarvestedState() {
31
+ clearLessonFileState();
32
+ }
33
+ export const lessonTitle = (row) => row.text_masked.split('\n', 1)[0].trim();
34
+ const isGlobal = (identity) => identity.startsWith('global:');
35
+ /** A project no session can ever open under: a Claude folder never traced to a directory, or a folder that is not there. */
36
+ function isUnresolved(identity) {
37
+ if (identity.startsWith('claude-slug:'))
38
+ return true;
39
+ if (!identity.startsWith('path:'))
40
+ return false;
41
+ try {
42
+ return !statSync(identity.slice('path:'.length)).isDirectory();
43
+ }
44
+ catch {
45
+ return true;
46
+ }
47
+ }
48
+ export function projectName(row) {
49
+ return isGlobal(row.project_identity) ? 'all projects' : row.project_label ?? row.project_identity;
50
+ }
51
+ /** The label every note carries: which AI wrote it, for which project, when. */
52
+ export function provenance(row) {
53
+ return `from ${HOST_NAMES[row.source_cli]} memory · ${projectName(row)} · ${row.source_mtime.slice(0, 10)}`;
54
+ }
55
+ /**
56
+ * Where a note may be selected (select.ts `eligible`): project notes and held
57
+ * notes only into their own project; the rest into any project. A held note
58
+ * from a global file, or any note of a folder no session can open under, has
59
+ * no project to go to.
60
+ */
61
+ export function lessonReach(row) {
62
+ if (row.scope !== 'project' && row.quarantined === 0)
63
+ return 'any-project';
64
+ return isGlobal(row.project_identity) || isUnresolved(row.project_identity) ? 'nowhere' : 'own-project';
65
+ }
66
+ /** Which AIs may receive it. The AI that wrote it already reads it, except Claude in other folders. */
67
+ export function receivingHosts(row) {
68
+ if (row.source_cli === 'claude')
69
+ return 'Codex and Gemini, and Claude working in another folder';
70
+ return LESSON_SOURCES.filter(host => host !== row.source_cli).map(host => HOST_NAMES[host]).join(' and ')
71
+ + ` (${HOST_NAMES[row.source_cli]} already reads it)`;
72
+ }
73
+ const SCOPE_REASONS = {
74
+ 'global-file': row => `it is in ${HOST_NAMES[row.source_cli]}'s global file, which it reads in every project`,
75
+ 'names-project': row => `it names its own project (${projectName(row)}), so it is about that project`,
76
+ 'user-entry': () => 'Claude saved it as a note about you (type: user)',
77
+ 'feedback-entry': () => 'Claude saved it as feedback on how to work (type: feedback)',
78
+ 'environment-heading': () => "its heading is about this machine's shell, console or network",
79
+ 'project-default': () => 'anything not clearly about you or this machine stays with its project',
80
+ };
81
+ const QUARANTINE_REASONS = {
82
+ sensitive: 'it is about secrets, credentials, identity or personal details',
83
+ credential: 'it contains something that looks like a credential',
84
+ url: 'it contains a web address',
85
+ command: 'it contains a shell or network command',
86
+ directive: 'it tells an AI to fetch, send or run something, or to ignore its instructions',
87
+ };
88
+ export const quarantineText = (reason) => QUARANTINE_REASONS[reason ?? ''] ?? reason ?? '';
89
+ export function explainLesson(row) {
90
+ const reason = row.scope_reason ? SCOPE_REASONS[row.scope_reason]?.(row) : null;
91
+ const reach = lessonReach(row);
92
+ const where = reach === 'any-project' ? 'any project'
93
+ : reach === 'own-project' ? `${projectName(row)} only`
94
+ : isGlobal(row.project_identity) ? 'nowhere: it is held back and has no project of its own'
95
+ : 'nowhere yet: Veto cannot tell which folder this memory belongs to (see veto lessons alias)';
96
+ return {
97
+ row,
98
+ provenance: provenance(row),
99
+ scope: `${row.scope}: ${reason ?? 'classified before Veto recorded why'}`,
100
+ held: row.quarantined ? `kept in its own project: ${quarantineText(row.quarantine_reason)}` : null,
101
+ reach: reach === 'nowhere' ? where : `${where}, in ${receivingHosts(row)}`,
102
+ hostDisabled: disabledLessonSourceReasons().get(row.source_cli) ?? null,
103
+ };
104
+ }
105
+ export function listLessons(filter = {}) {
106
+ const identity = filter.projectDir ? resolveProjectIdentity(filter.projectDir) : null;
107
+ const rows = getDb().prepare('SELECT * FROM lessons').all();
108
+ return rows
109
+ .filter(row => (!filter.scope || row.scope === filter.scope)
110
+ && (!filter.source || row.source_cli === filter.source)
111
+ && (!identity || row.project_identity === identity)
112
+ && (!filter.shared || lessonReach(row) === 'any-project')
113
+ && (!filter.held || row.quarantined === 1))
114
+ .sort((a, b) => Number(isGlobal(a.project_identity)) - Number(isGlobal(b.project_identity))
115
+ || projectName(a).localeCompare(projectName(b))
116
+ || b.source_mtime.localeCompare(a.source_mtime)
117
+ || a.id.localeCompare(b.id));
118
+ }
119
+ const MIN_ID_PREFIX = 4;
120
+ /** A note by its ID or any unique prefix of it (list shows the first 8 characters). */
121
+ export function findLesson(idOrPrefix) {
122
+ const prefix = idOrPrefix.trim().toLowerCase();
123
+ if (prefix.length < MIN_ID_PREFIX)
124
+ return { error: 'too-short' };
125
+ const matches = getDb().prepare("SELECT * FROM lessons WHERE substr(id, 1, ?) = ? ORDER BY id LIMIT 6").all(prefix.length, prefix);
126
+ if (matches.length === 1)
127
+ return { row: matches[0] };
128
+ return matches.length ? { error: 'ambiguous', matches } : { error: 'not-found' };
129
+ }
130
+ /** Permanent: the note and every copy of it are deleted and never harvested again. */
131
+ export function forgetLesson(row) {
132
+ return { removed: tombstoneLesson(row) };
133
+ }
134
+ /**
135
+ * Turn sharing off and delete everything harvested, plus the would-have-shared
136
+ * log. Forgotten-note tombstones, exclusions and aliases stay: they are the
137
+ * user's own decisions and hold no note text. `remaining` is the purge proof.
138
+ */
139
+ export function turnLessonsOff() {
140
+ const wasOn = isLessonsSharingEnabled();
141
+ disableLessonsSharing();
142
+ const db = getDb();
143
+ const notes = Number(db.prepare('DELETE FROM lessons').run().changes);
144
+ clearLessonFileState();
145
+ const shadowLog = Number(db.prepare('DELETE FROM lesson_shadow_log').run().changes);
146
+ const count = (table) => db.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get().n;
147
+ return { wasOn, notes, shadowLog, remaining: count('lessons') + count('lesson_shadow_log') };
148
+ }
149
+ /** Source → destination, one line per AI and project the notes came from. */
150
+ export function lessonFlows() {
151
+ const flows = new Map();
152
+ for (const row of getDb().prepare('SELECT * FROM lessons').all()) {
153
+ const key = `${row.source_cli}\n${row.project_identity}`;
154
+ let flow = flows.get(key);
155
+ if (!flow) {
156
+ flow = {
157
+ source: row.source_cli, projectIdentity: row.project_identity, projectLabel: projectName(row),
158
+ notes: 0, anyProject: 0, ownProject: 0, nowhere: 0, heldBack: {}, unresolved: isUnresolved(row.project_identity),
159
+ };
160
+ flows.set(key, flow);
161
+ }
162
+ flow.notes++;
163
+ const reach = lessonReach(row);
164
+ if (reach === 'any-project')
165
+ flow.anyProject++;
166
+ else if (reach === 'own-project')
167
+ flow.ownProject++;
168
+ else
169
+ flow.nowhere++;
170
+ if (row.quarantined && row.scope !== 'project') {
171
+ const reason = row.quarantine_reason ?? 'held';
172
+ flow.heldBack[reason] = (flow.heldBack[reason] ?? 0) + 1;
173
+ }
174
+ }
175
+ return [...flows.values()].sort((a, b) => Number(isGlobal(a.projectIdentity)) - Number(isGlobal(b.projectIdentity))
176
+ || b.notes - a.notes || a.projectLabel.localeCompare(b.projectLabel));
177
+ }
178
+ const isDirectory = (path) => { try {
179
+ return statSync(path).isDirectory();
180
+ }
181
+ catch {
182
+ return false;
183
+ } };
184
+ /** A folder as the file system spells it (D:/Veto, not the case-folded d:/veto the alias table keeps). */
185
+ const trueCase = (dir) => { try {
186
+ return realpathSync.native(dir);
187
+ }
188
+ catch {
189
+ return dir;
190
+ } };
191
+ /** A Claude folder slug without its root: `F--a-b` and `D--a-b` differ only in the drive. */
192
+ function slugTail(slug) {
193
+ const drive = /^([A-Za-z])--(.*)$/.exec(slug);
194
+ return drive ? { drive: drive[1], tail: drive[2] } : { drive: null, tail: slug.replace(/^-+/, '') };
195
+ }
196
+ /** Project folders on this machine that Veto has seen, spelled as the file system spells them. */
197
+ function knownProjectDirs() {
198
+ const db = getDb();
199
+ const dirs = new Map();
200
+ for (const sql of [
201
+ 'SELECT DISTINCT project_dir AS dir FROM sessions WHERE project_dir IS NOT NULL',
202
+ 'SELECT alias_path AS dir FROM project_identity_aliases',
203
+ ]) {
204
+ try {
205
+ for (const { dir } of db.prepare(sql).all()) {
206
+ const key = canonicalProjectPath(dir);
207
+ if (!dirs.has(key) && isDirectory(dir))
208
+ dirs.set(key, trueCase(dir));
209
+ }
210
+ }
211
+ catch { /* table absent in an old database */ }
212
+ }
213
+ return [...dirs.values()];
214
+ }
215
+ /**
216
+ * The same project checked out on this machine: a known folder whose slug is
217
+ * the unlinked one's with another root (F:/a/b for D:/a/b, whose folder path
218
+ * is then known too), or failing that, one whose slug it ends with (a backup
219
+ * nested deeper, whose own path cannot be read back from its lossy slug).
220
+ * Anything but exactly one candidate suggests nothing.
221
+ */
222
+ export function suggestAlias(identity, known) {
223
+ const exactPath = identity.startsWith('path:') ? identity.slice('path:'.length) : null;
224
+ const unlinked = slugTail(exactPath ? claudeProjectSlug(exactPath) : identity.slice('claude-slug:'.length));
225
+ const same = known.filter(dir => sameClaudeSlug(slugTail(claudeProjectSlug(dir)).tail, unlinked.tail));
226
+ const nested = known.filter(dir => {
227
+ const tail = slugTail(claudeProjectSlug(dir)).tail;
228
+ return unlinked.tail.length > tail.length + 1 && sameClaudeSlug(unlinked.tail.slice(-(tail.length + 1)), `-${tail}`);
229
+ });
230
+ const match = same.length ? same : nested;
231
+ if (match.length !== 1)
232
+ return null;
233
+ const targetDir = match[0];
234
+ if (exactPath)
235
+ return { aliasPath: exactPath, targetDir };
236
+ const drive = same.length && unlinked.drive && /^[A-Za-z]:/.test(targetDir) ? `${unlinked.drive.toUpperCase()}:${targetDir.slice(2)}` : null;
237
+ return { aliasPath: drive, targetDir };
238
+ }
239
+ /** Memory whose project Veto could not trace to a folder that exists: its project notes reach no session. */
240
+ export function unresolvedFolders() {
241
+ const rows = getDb().prepare('SELECT project_identity, project_label, COUNT(*) AS notes FROM lessons GROUP BY project_identity, project_label')
242
+ .all();
243
+ const unresolved = rows.filter(row => isUnresolved(row.project_identity));
244
+ const known = unresolved.length ? knownProjectDirs() : [];
245
+ return unresolved.map(row => ({
246
+ identity: row.project_identity,
247
+ label: row.project_label ?? row.project_identity,
248
+ notes: row.notes,
249
+ suggestion: suggestAlias(row.project_identity, known),
250
+ }));
251
+ }
252
+ /** Checkouts treated as one project: only groups of two or more folders are worth showing. */
253
+ export function aliasGroups() {
254
+ const rows = getDb().prepare('SELECT alias_path, project_identity FROM project_identity_aliases ORDER BY alias_path')
255
+ .all();
256
+ const groups = new Map();
257
+ for (const row of rows)
258
+ groups.set(row.project_identity, [...(groups.get(row.project_identity) ?? []), row.alias_path]);
259
+ return [...groups].filter(([, paths]) => paths.length > 1).map(([identity, paths]) => ({ identity, paths }));
260
+ }
261
+ /**
262
+ * Treat `aliasPath` as another checkout of the project at `targetDir`: its
263
+ * notes then count as that project's. For a drive that is not mounted, which
264
+ * is the case this exists for, the alias path need not exist. A folder that
265
+ * does exist and is a different repository is refused, since aliasing it
266
+ * would carry one project's private notes into another.
267
+ */
268
+ export function setProjectAlias(aliasPath, targetDir) {
269
+ if (!isDirectory(targetDir))
270
+ return { ok: false, error: 'target-missing' };
271
+ if (canonicalProjectPath(aliasPath) === canonicalProjectPath(targetDir))
272
+ return { ok: false, error: 'same-folder' };
273
+ const identity = resolveProjectIdentity(targetDir);
274
+ if (existsSync(aliasPath)) {
275
+ const own = computeProjectIdentity(aliasPath);
276
+ if (own.startsWith('git:') && own !== identity)
277
+ return { ok: false, error: 'different-repository' };
278
+ }
279
+ addProjectAlias(aliasPath, identity);
280
+ invalidateHarvestedState();
281
+ const slug = claudeProjectSlug(canonicalProjectPath(aliasPath));
282
+ const folders = getDb().prepare("SELECT DISTINCT source_path FROM lessons WHERE source_cli = 'claude'").all();
283
+ const memoryFolders = new Set(folders.map(row => basename(dirname(dirname(row.source_path)))).filter(folder => sameClaudeSlug(folder, slug))).size;
284
+ return { ok: true, identity, label: basename(targetDir.replace(/[\\/]+$/, '')) || targetDir, memoryFolders };
285
+ }
286
+ export function removeProjectAlias(aliasPath) {
287
+ const removed = Number(getDb().prepare('DELETE FROM project_identity_aliases WHERE alias_path = ?').run(canonicalProjectPath(aliasPath)).changes) > 0;
288
+ if (removed)
289
+ invalidateHarvestedState();
290
+ return removed;
291
+ }
292
+ export function excludeProjectDir(projectDir) {
293
+ const label = basename(projectDir.replace(/[\\/]+$/, '')) || projectDir;
294
+ return { label, ...excludeProject(resolveProjectIdentity(projectDir), label) };
295
+ }
296
+ export function includeProjectDir(projectDir) {
297
+ const removed = includeProject(resolveProjectIdentity(projectDir));
298
+ // The project's files are untouched, so only forgetting their fingerprints
299
+ // brings its notes back.
300
+ if (removed)
301
+ invalidateHarvestedState();
302
+ return { label: basename(projectDir.replace(/[\\/]+$/, '')) || projectDir, removed };
303
+ }
304
+ /** Switch a host's harvester back on after a format change, and check it again straight away. */
305
+ export function recheckSource(source, home) {
306
+ const wasDisabled = enableLessonSource(source);
307
+ // The file that tripped the canary has not changed; only our willingness to
308
+ // read it has.
309
+ if (wasDisabled)
310
+ invalidateHarvestedState();
311
+ const report = refreshLessons(home, { forced: true });
312
+ return { wasDisabled, stillDisabled: disabledLessonSourceReasons().get(source) ?? null, report };
313
+ }
314
+ export function lessonsStatus() {
315
+ const config = getConfig().lessons;
316
+ const db = getDb();
317
+ const rows = db.prepare('SELECT * FROM lessons').all();
318
+ const byHost = { claude: 0, codex: 0, gemini: 0 };
319
+ for (const row of rows)
320
+ byHost[row.source_cli] = (byHost[row.source_cli] ?? 0) + 1;
321
+ const count = (table) => db.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get().n;
322
+ return {
323
+ sharing: isLessonsSharingEnabled(config),
324
+ needsReconsent: config.enabled && config.consent_version !== LESSONS_CONSENT_VERSION,
325
+ consentAt: config.consent_at,
326
+ notes: rows.length,
327
+ byHost,
328
+ anyProject: rows.filter(row => lessonReach(row) === 'any-project').length,
329
+ held: rows.filter(row => row.quarantined === 1).length,
330
+ disabledHosts: disabledLessonSourceReasons(),
331
+ excluded: excludedProjects(),
332
+ unresolved: unresolvedFolders().length,
333
+ forgotten: db.prepare('SELECT COUNT(DISTINCT forget_id) AS n FROM lesson_tombstones').get().n,
334
+ shadowLog: count('lesson_shadow_log'),
335
+ };
336
+ }
337
+ //# sourceMappingURL=manage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.js","sourceRoot":"","sources":["../../src/lessons/manage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** Remove data that must not leave the originating native-memory document. */
2
+ export declare function maskLessonText(input: string): {
3
+ text: string;
4
+ secrets: number;
5
+ };
6
+ //# sourceMappingURL=mask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../../src/lessons/mask.ts"],"names":[],"mappings":"AAWA,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAU/E"}
@@ -0,0 +1,22 @@
1
+ import { mask } from '../transcripts/mask.js';
2
+ const EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
3
+ // A home directory in every spelling a note can carry it: C:\Users\x (also
4
+ // JSON-escaped), C:/Users/x, Git Bash /c/Users/x, /Users/x and /home/x. The
5
+ // lookbehind keeps a URL path like example.com/home/x from matching.
6
+ const WINDOWS_HOME_RE = /\b[A-Z]:(?:\\\\|\\|\/)Users(?:\\\\|\\|\/)[^\\\/\s"'`)]+/gi;
7
+ const POSIX_HOME_RE = /(?<![\w.:\/~-])(?:\/[a-z](?=\/Users\/))?\/(?:Users|home)\/[^\/\s"'`)]+/gi;
8
+ // Claude's project-folder slug of a home path: C--Users-<name>-...
9
+ const HOME_SLUG_RE = /\b([A-Z])--Users-[^-\s/\\]+/gi;
10
+ /** Remove data that must not leave the originating native-memory document. */
11
+ export function maskLessonText(input) {
12
+ const masked = mask(input);
13
+ return {
14
+ secrets: masked.count,
15
+ text: masked.text
16
+ .replace(EMAIL_RE, '[email redacted]')
17
+ .replace(WINDOWS_HOME_RE, '~')
18
+ .replace(POSIX_HOME_RE, '~')
19
+ .replace(HOME_SLUG_RE, '$1--Users-[user]'),
20
+ };
21
+ }
22
+ //# sourceMappingURL=mask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.js","sourceRoot":"","sources":["../../src/lessons/mask.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,MAAM,QAAQ,GAAG,6CAA6C,CAAC;AAC/D,2EAA2E;AAC3E,4EAA4E;AAC5E,qEAAqE;AACrE,MAAM,eAAe,GAAG,2DAA2D,CAAC;AACpF,MAAM,aAAa,GAAG,0EAA0E,CAAC;AACjG,mEAAmE;AACnE,MAAM,YAAY,GAAG,+BAA+B,CAAC;AAErD,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,KAAK;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI;aACd,OAAO,CAAC,QAAQ,EAAE,kBAAkB,CAAC;aACrC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;aAC7B,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;aAC3B,OAAO,CAAC,YAAY,EAAE,kBAAkB,CAAC;KAC7C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ export type OnSaveLessons = {
2
+ /** Notes added, changed and removed; all zero means nothing is worth saying. */
3
+ added: number;
4
+ updated: number;
5
+ removed: number;
6
+ /** Sources left for the next save because the budget ran out. */
7
+ pending: number;
8
+ note?: string;
9
+ };
10
+ /**
11
+ * Harvest what changed since the last pass. Returns null when there is nothing
12
+ * to report — sharing is off, the switch is off, or no note moved — so a save
13
+ * that changed nothing says nothing.
14
+ */
15
+ export declare function harvestOnSave(options?: {
16
+ home?: string;
17
+ }): OnSaveLessons | null;
18
+ //# sourceMappingURL=on-save.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-save.d.ts","sourceRoot":"","sources":["../../src/lessons/on-save.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,aAAa,GAAG;IAC1B,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,aAAa,GAAG,IAAI,CAqBnF"}
@@ -0,0 +1,53 @@
1
+ // Save-time harvesting.
2
+ //
3
+ // Recording a lesson by hand is the step that never happens, so saving a
4
+ // session re-reads each AI's own memory and records what changed. The pass is
5
+ // consent-gated, time-boxed and idempotent: anything it does not reach waits
6
+ // for the next save.
7
+ //
8
+ // It never throws. The caller wraps it too, but a harvest problem must not be
9
+ // able to affect whether a session was saved.
10
+ //
11
+ // Nothing here delivers a note to any AI. Delivery is a separate, still-gated
12
+ // step that requires its own consent version (council 534e2bd5).
13
+ import { firstHarvestOnSave, isHarvestOnSaveEnabled } from '../memory/config.js';
14
+ import { syncLessonSources } from './harvest.js';
15
+ /**
16
+ * A quiet pass costs one stat per file and opens no transaction, so this bound
17
+ * is only ever reached by a genuinely cold one: a first run, an upgrade that
18
+ * bumped HARVESTER_VERSION, or a day's worth of edits at once. Such a pass
19
+ * stops here and the rest is picked up by the next save.
20
+ */
21
+ const BUDGET_MS = 150;
22
+ const FIRST_NOTE = 'Veto now re-reads your AIs\' notes when you save. See them with `veto lessons list`; stop it with `veto lessons off`.';
23
+ /**
24
+ * Harvest what changed since the last pass. Returns null when there is nothing
25
+ * to report — sharing is off, the switch is off, or no note moved — so a save
26
+ * that changed nothing says nothing.
27
+ */
28
+ export function harvestOnSave(options = {}) {
29
+ if (!isHarvestOnSaveEnabled())
30
+ return null;
31
+ let report;
32
+ try {
33
+ report = syncLessonSources({ home: options.home, budgetMs: BUDGET_MS });
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ const added = report.inserted;
39
+ const { updated, removed } = report;
40
+ // Work still queued is not news. A cold pass drains over several saves, and
41
+ // saying "nothing changed, 66 to go" each time is noise about our own
42
+ // bookkeeping. Only a note actually moving is worth a line.
43
+ if (added === 0 && updated === 0 && removed === 0)
44
+ return null;
45
+ // Claimed only once anything was actually harvested, so the note lands on a
46
+ // save the user can see the result of.
47
+ const first = firstHarvestOnSave();
48
+ return {
49
+ added, updated, removed, pending: report.notReached,
50
+ ...(first ? { note: FIRST_NOTE } : {}),
51
+ };
52
+ }
53
+ //# sourceMappingURL=on-save.js.map