minnimemory 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +39 -0
  2. package/README.md +824 -0
  3. package/dist/bench.d.ts +98 -0
  4. package/dist/bench.js +142 -0
  5. package/dist/benchReport.d.ts +12 -0
  6. package/dist/benchReport.js +128 -0
  7. package/dist/bounds.d.ts +40 -0
  8. package/dist/bounds.js +44 -0
  9. package/dist/cli.d.ts +15 -0
  10. package/dist/cli.js +503 -0
  11. package/dist/compile.d.ts +187 -0
  12. package/dist/compile.js +516 -0
  13. package/dist/discover.d.ts +125 -0
  14. package/dist/discover.js +520 -0
  15. package/dist/doctor.d.ts +9 -0
  16. package/dist/doctor.js +67 -0
  17. package/dist/episodic.d.ts +47 -0
  18. package/dist/episodic.js +130 -0
  19. package/dist/hook.d.ts +45 -0
  20. package/dist/hook.js +104 -0
  21. package/dist/index.d.ts +18 -0
  22. package/dist/index.js +18 -0
  23. package/dist/init.d.ts +125 -0
  24. package/dist/init.js +475 -0
  25. package/dist/instructions.d.ts +60 -0
  26. package/dist/instructions.js +270 -0
  27. package/dist/mcp.d.ts +109 -0
  28. package/dist/mcp.js +252 -0
  29. package/dist/mcpServer.d.ts +136 -0
  30. package/dist/mcpServer.js +997 -0
  31. package/dist/paths.d.ts +25 -0
  32. package/dist/paths.js +47 -0
  33. package/dist/recall.d.ts +113 -0
  34. package/dist/recall.js +256 -0
  35. package/dist/recallDir.d.ts +50 -0
  36. package/dist/recallDir.js +187 -0
  37. package/dist/reorganize.d.ts +62 -0
  38. package/dist/reorganize.js +216 -0
  39. package/dist/report.d.ts +16 -0
  40. package/dist/report.js +204 -0
  41. package/dist/router.d.ts +141 -0
  42. package/dist/router.js +314 -0
  43. package/dist/rules.d.ts +32 -0
  44. package/dist/rules.js +651 -0
  45. package/dist/scan.d.ts +110 -0
  46. package/dist/scan.js +173 -0
  47. package/dist/text.d.ts +158 -0
  48. package/dist/text.js +395 -0
  49. package/dist/tokenizer.d.ts +26 -0
  50. package/dist/tokenizer.js +69 -0
  51. package/dist/types.d.ts +156 -0
  52. package/dist/types.js +17 -0
  53. package/dist/version.d.ts +7 -0
  54. package/dist/version.js +7 -0
  55. package/dist/writeProtocol.d.ts +19 -0
  56. package/dist/writeProtocol.js +45 -0
  57. package/examples/CLAUDE.md +75 -0
  58. package/examples/README.md +7 -0
  59. package/package.json +52 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * The compiler: turn one memory file into a cache-stable AlwaysOnMemory body plus routed
3
+ * OnDemandMemory files.
4
+ *
5
+ * Pure by design. Everything here is string in, strings out, so the whole compile can be
6
+ * tested from fixtures and diffed before anything touches a user's disk.
7
+ *
8
+ * Structure follows the tiered-memory pattern already running in production in the Minni
9
+ * agents (AlwaysOnMemory.md, OnDemandMemory/, fixed assembly order), and the emitted
10
+ * instruction block comes from the MinniMemory v1.0 research set. See instructions.ts.
11
+ */
12
+ import { type Instruction, type ProfileName } from "./instructions.js";
13
+ import { type MemoryKind } from "./episodic.js";
14
+ /** Marker identifying a host file this tool generated, so it is never double counted. */
15
+ export declare const STUB_MARKER = "<!-- minnimemory:stub v1 -->";
16
+ export interface OnDemandFile {
17
+ /** slug, also the OnDemandMemory file id used in triggers and ordering */
18
+ name: string;
19
+ /** path relative to the compiled directory */
20
+ file: string;
21
+ heading: string;
22
+ content: string;
23
+ tokens: number;
24
+ triggers: string[];
25
+ sourceStartLine: number;
26
+ sourceEndLine: number;
27
+ /** why it was routed out of AlwaysOnMemory; `generated` is emitted by the compiler, not from the source */
28
+ reason: "task-specific" | "volatile" | "over-budget" | "generated";
29
+ /** O2: semantic (edited in place), episodic (append-only), procedural (a learned rule) */
30
+ kind?: MemoryKind;
31
+ /** true for OnDemandMemory files the compiler writes itself (the O9 write protocol) */
32
+ generated?: boolean;
33
+ /**
34
+ * True when this file came from splitting an oversized section at its subheadings (O7).
35
+ * `mergeSmall` never merges these: they were separated on purpose, and merging them back
36
+ * would undo the split and, worse, glue the last piece to whatever section follows.
37
+ */
38
+ split?: boolean;
39
+ }
40
+ /** Default always-loaded budget in tokens; matches doctor's MM001 default. */
41
+ export declare const DEFAULT_BUDGET = 2000;
42
+ export interface CompileOptions {
43
+ /** basename of the source memory file, for provenance */
44
+ sourceName: string;
45
+ /** always-loaded token budget AlwaysOnMemory must fit inside; always-on-like sections that do not fit are demoted */
46
+ budget?: number;
47
+ /** instruction profile to embed; defaults to the routing profile */
48
+ profile?: Instruction[];
49
+ /** named profile, used when `profile` is not supplied */
50
+ profileName?: ProfileName;
51
+ /** heading level to split OnDemandMemory files on; auto-detected when omitted */
52
+ splitLevel?: number;
53
+ /**
54
+ * Use this OnDemandMemory file list instead of the one compiled from the source. `init
55
+ * --update` passes the files already on disk plus any new ones, so the list and stub are
56
+ * rendered for the real file set.
57
+ */
58
+ onDemandFilesOverride?: OnDemandFile[];
59
+ /** emit the O9 write-protocol file; on unless a caller says otherwise */
60
+ writeProtocol?: boolean;
61
+ /** O3: write episodic files as JSON instead of Markdown */
62
+ episodicJson?: boolean;
63
+ }
64
+ export interface Compiled {
65
+ title: string;
66
+ sourceName: string;
67
+ sourceHash: string;
68
+ /** leading YAML frontmatter carried through verbatim; empty when the source had none */
69
+ frontmatter: string;
70
+ alwaysOnBody: string;
71
+ onDemandList: string;
72
+ /** alwaysOnBody + onDemandList joined, exactly what gets written to .minnimemory/AlwaysOnMemory.md */
73
+ alwaysOn: string;
74
+ stub: string;
75
+ onDemandFiles: OnDemandFile[];
76
+ /** always-loaded tokens before compilation */
77
+ before: number;
78
+ /** always-loaded tokens after compilation, which is the stub */
79
+ after: number;
80
+ /** how much of `after` is the injected instruction block rather than the user's content */
81
+ instructionTokens: number;
82
+ /** the budget AlwaysOnMemory placement was held to */
83
+ budget: number;
84
+ /** always-on-like sections routed to OnDemandMemory files because AlwaysOnMemory would not fit the budget with them */
85
+ demoted: {
86
+ heading: string;
87
+ tokens: number;
88
+ }[];
89
+ }
90
+ /** Headings whose content is identity or invariant, so it belongs in AlwaysOnMemory. */
91
+ export declare const ALWAYS_ON_HINTS: RegExp;
92
+ declare function hash(text: string): string;
93
+ /**
94
+ * The hash MM010 and recall's drift check both compare against a manifest entry.
95
+ *
96
+ * CRLF-normalised and trailing-whitespace-trimmed on purpose: a checkout can rewrite line
97
+ * endings with nobody editing anything, and a file that differs only that way has not drifted.
98
+ * One copy, because the dated-bullet regex taught us what three copies of a rule costs
99
+ * (2026-09-13 audit, D7).
100
+ */
101
+ export declare function driftHash(content: string): string;
102
+ /**
103
+ * Shared with rules.ts's MM010 check against AlwaysOnMemory.md and the stub: sha256 slice 16
104
+ * with no normalisation, the caller's job (CRLF-only, no trimEnd - those files are written
105
+ * verbatim, so trimming would blur an edit driftHash would forgive on purpose for OnDemandMemory
106
+ * files but should not here).
107
+ */
108
+ export { hash as verbatimHash };
109
+ /**
110
+ * The list title is deliberately not derived from the document title: a title can carry a
111
+ * date or a status word ("Minni (renamed 2026-08-11)"), and the list must stay free of anything
112
+ * the volatility rules would flag. The whole list is fenced with markers so `doctor` can tell a
113
+ * routing manifest from prose.
114
+ *
115
+ * One line per OnDemandMemory file and nothing that restates a Part 2 rule (P4). Rules 15, 16,
116
+ * 22 and 23 already say how to use the list and sit in the same prefix whenever a discipline
117
+ * block is embedded; the previous table-plus-prose form repeated them at 159 tokens per compile.
118
+ * Only the `none` profile, which embeds no block, gets one routing line after the list. Assembly
119
+ * order is the manifest's `order`, not prefix text.
120
+ */
121
+ /** The directory `init` writes next to the host file. Named here, where the stub's
122
+ * OnDemandMemory list is rendered, so the two can never disagree about where a file lives. */
123
+ export declare const COMPILED_DIR_NAME = ".minnimemory";
124
+ /** The one always-loaded file inside the compiled directory: AlwaysOnMemory body plus the
125
+ * OnDemandMemory list. */
126
+ export declare const ALWAYS_ON_FILE_NAME = "AlwaysOnMemory.md";
127
+ /** The OnDemandMemory files directory inside the compiled directory. */
128
+ export declare const ON_DEMAND_DIR_NAME = "OnDemandMemory";
129
+ /**
130
+ * Is this host file a stub this tool generated? Only a marker on the first line after any
131
+ * frontmatter counts. A marker quoted in a code block, or anywhere else in prose, is text
132
+ * (security audit 2026-09-02, finding 5).
133
+ */
134
+ export declare function isStub(source: string): boolean;
135
+ export declare function compile(source: string, options: CompileOptions): Compiled;
136
+ export interface Manifest {
137
+ /**
138
+ * 4: renames the `modules` key to `onDemandFiles` (vocabulary sweep); loadManifest still
139
+ * accepts a version 3 file and normalises it in memory.
140
+ * 3: records the stub's hash so MM010 can see drift in the host file itself.
141
+ * 2: AlwaysOnMemory.md replaces the separate core.md/index.md, OnDemandMemory/ replaces modules/
142
+ */
143
+ version: 4;
144
+ tokenizer: string;
145
+ generatedFrom: string;
146
+ sourceHash: string;
147
+ /**
148
+ * Whether the embedded discipline block has been measured. Lives here, not in the block
149
+ * itself, so the agent is not charged for a disclaimer on every turn (P3). Names the
150
+ * measured pass and what remains unmeasured; see the README's Measurement policy
151
+ * for what counts.
152
+ */
153
+ instructionStatus?: string;
154
+ order: string[];
155
+ prefix: {
156
+ before: number;
157
+ after: number;
158
+ };
159
+ /** the one always-loaded file: AlwaysOnMemory body plus the OnDemandMemory list, AlwaysOnMemory.md */
160
+ always: {
161
+ file: string;
162
+ tokens: number;
163
+ hash: string;
164
+ };
165
+ /**
166
+ * The host file init rewrote (CLAUDE.md and friends). Hashed because it is the prefix the
167
+ * agent actually reloads every turn: content appended to it is un-routed and paid for on
168
+ * every call, and MM010 has no other way to notice.
169
+ */
170
+ stub: {
171
+ file: string;
172
+ tokens: number;
173
+ hash: string;
174
+ };
175
+ onDemandFiles: {
176
+ name: string;
177
+ file: string;
178
+ tokens: number;
179
+ hash: string;
180
+ triggers: string[];
181
+ sourceLines: [number, number];
182
+ reason: string;
183
+ kind?: MemoryKind;
184
+ generated?: boolean;
185
+ }[];
186
+ }
187
+ export declare function buildManifest(compiled: Compiled, tokenizer: string): Manifest;