@deposition.cloud/memory 1.0.2

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 ADDED
@@ -0,0 +1,30 @@
1
+ # memory
2
+
3
+ Reusable governance memory and thought-management utilities.
4
+
5
+ ## Package
6
+
7
+ This repo publishes `@deposition.cloud/memory`.
8
+
9
+ It extracts the generic memory and thought-stream mechanics from governance repos so they can be reused across public and private overlays without copying implementation details.
10
+
11
+ ## Included
12
+
13
+ - Current-thought lifecycle helpers
14
+ - Archived-thought listing
15
+ - Memory vigor checks
16
+ - Memory compaction prompt generation
17
+
18
+ ## Development
19
+
20
+ ```bash
21
+ pnpm install
22
+ pnpm test
23
+ pnpm build
24
+ ```
25
+
26
+ ## Release
27
+
28
+ The release pipeline follows the same GitLab CI and `semantic-release` shape used by `deposition.cloud/libs/folksonomy`.
29
+
30
+ Conventional commits on `main` drive versioning and publishing.
@@ -0,0 +1,11 @@
1
+ export interface CurrentThoughtsResult {
2
+ action: 'exists' | 'initialized';
3
+ currentThoughtsPath: string;
4
+ }
5
+ export interface CurrentThoughtsSnapshot {
6
+ snapshotPath: string;
7
+ currentThoughtsPath: string;
8
+ }
9
+ export declare function createCurrentThoughtsTemplate(startedAt?: string): string;
10
+ export declare function initializeCurrentThoughts(thoughtsDir: string, startedAt?: string): CurrentThoughtsResult;
11
+ export declare function snapshotCurrentThoughts(thoughtsDir: string, timestamp?: string): CurrentThoughtsSnapshot;
@@ -0,0 +1,67 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export function createCurrentThoughtsTemplate(startedAt = 'pending') {
4
+ return `# Current Thoughts
5
+
6
+ ## Session
7
+
8
+ - started_at: ${startedAt}
9
+ - topic: pending
10
+ - keywords: []
11
+
12
+ ## Context
13
+
14
+ <What governance change or question is being worked on?>
15
+
16
+ ## Working Notes
17
+
18
+ -
19
+
20
+ ## Promotion Candidates
21
+
22
+ - ADR:
23
+ - Codex:
24
+ - Registry:
25
+ - Template:
26
+
27
+ ## Verification
28
+
29
+ -
30
+ `;
31
+ }
32
+ export function initializeCurrentThoughts(thoughtsDir, startedAt = new Date().toISOString()) {
33
+ const currentThoughtsPath = path.join(thoughtsDir, 'current-thoughts.md');
34
+ fs.mkdirSync(thoughtsDir, { recursive: true });
35
+ if (fs.existsSync(currentThoughtsPath)) {
36
+ const existing = fs.readFileSync(currentThoughtsPath, 'utf8');
37
+ if (existing.trim() !== '') {
38
+ return {
39
+ action: 'exists',
40
+ currentThoughtsPath
41
+ };
42
+ }
43
+ }
44
+ fs.writeFileSync(currentThoughtsPath, createCurrentThoughtsTemplate(startedAt));
45
+ return {
46
+ action: 'initialized',
47
+ currentThoughtsPath
48
+ };
49
+ }
50
+ export function snapshotCurrentThoughts(thoughtsDir, timestamp = new Date().toISOString().replaceAll(':', '-')) {
51
+ const currentThoughtsPath = path.join(thoughtsDir, 'current-thoughts.md');
52
+ if (!fs.existsSync(currentThoughtsPath)) {
53
+ throw new Error(`No current thoughts file found at ${currentThoughtsPath}`);
54
+ }
55
+ const current = fs.readFileSync(currentThoughtsPath, 'utf8').trim();
56
+ if (current === '') {
57
+ throw new Error('Current thoughts file is empty.');
58
+ }
59
+ const snapshotPath = path.join(thoughtsDir, `thought-${timestamp}.md`);
60
+ fs.writeFileSync(snapshotPath, `${current}\n`);
61
+ fs.writeFileSync(currentThoughtsPath, createCurrentThoughtsTemplate());
62
+ return {
63
+ snapshotPath,
64
+ currentThoughtsPath
65
+ };
66
+ }
67
+ //# sourceMappingURL=current-thoughts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"current-thoughts.js","sourceRoot":"","sources":["../src/current-thoughts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAY5B,MAAM,UAAU,6BAA6B,CAAC,SAAS,GAAG,SAAS;IACjE,OAAO;;;;gBAIO,SAAS;;;;;;;;;;;;;;;;;;;;;;CAsBxB,CAAA;AACD,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,WAAmB,EACnB,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IAEpC,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAA;IACzE,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE9C,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAA;QAC7D,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3B,OAAO;gBACL,MAAM,EAAE,QAAQ;gBAChB,mBAAmB;aACpB,CAAA;QACH,CAAC;IACH,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,mBAAmB,EAAE,6BAA6B,CAAC,SAAS,CAAC,CAAC,CAAA;IAE/E,OAAO;QACL,MAAM,EAAE,aAAa;QACrB,mBAAmB;KACpB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,WAAmB,EACnB,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC;IAEzD,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAA;IAEzE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,qCAAqC,mBAAmB,EAAE,CAAC,CAAA;IAC7E,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAA;IACnE,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACpD,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,SAAS,KAAK,CAAC,CAAA;IACtE,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,GAAG,OAAO,IAAI,CAAC,CAAA;IAC9C,EAAE,CAAC,aAAa,CAAC,mBAAmB,EAAE,6BAA6B,EAAE,CAAC,CAAA;IAEtE,OAAO;QACL,YAAY;QACZ,mBAAmB;KACpB,CAAA;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { createCurrentThoughtsTemplate, initializeCurrentThoughts, snapshotCurrentThoughts } from './current-thoughts.js';
6
+ const tempDirs = [];
7
+ function makeTempDir() {
8
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'governance-memory-thoughts-'));
9
+ tempDirs.push(dir);
10
+ return dir;
11
+ }
12
+ afterEach(() => {
13
+ while (tempDirs.length > 0) {
14
+ fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
15
+ }
16
+ });
17
+ describe('current thought utilities', () => {
18
+ it('creates a template with the provided timestamp', () => {
19
+ const template = createCurrentThoughtsTemplate('2026-03-22T00:00:00.000Z');
20
+ expect(template).toMatch(/started_at: 2026-03-22T00:00:00.000Z/);
21
+ expect(template).toMatch(/Promotion Candidates/);
22
+ });
23
+ it('initializes current thoughts in an empty directory', () => {
24
+ const thoughtsDir = makeTempDir();
25
+ const result = initializeCurrentThoughts(thoughtsDir, '2026-03-22T00:00:00.000Z');
26
+ expect(result.action).toBe('initialized');
27
+ expect(fs.existsSync(result.currentThoughtsPath)).toBe(true);
28
+ });
29
+ it('does not overwrite a non-empty current thoughts file', () => {
30
+ const thoughtsDir = makeTempDir();
31
+ const currentThoughtsPath = path.join(thoughtsDir, 'current-thoughts.md');
32
+ fs.mkdirSync(thoughtsDir, { recursive: true });
33
+ fs.writeFileSync(currentThoughtsPath, '# Existing\n');
34
+ const result = initializeCurrentThoughts(thoughtsDir);
35
+ expect(result.action).toBe('exists');
36
+ expect(fs.readFileSync(currentThoughtsPath, 'utf8')).toBe('# Existing\n');
37
+ });
38
+ it('snapshots current thoughts and resets the working file', () => {
39
+ const thoughtsDir = makeTempDir();
40
+ fs.mkdirSync(thoughtsDir, { recursive: true });
41
+ fs.writeFileSync(path.join(thoughtsDir, 'current-thoughts.md'), '# Current\n');
42
+ const result = snapshotCurrentThoughts(thoughtsDir, '2026-03-22T00-00-00.000Z');
43
+ const snapshot = fs.readFileSync(result.snapshotPath, 'utf8');
44
+ const current = fs.readFileSync(result.currentThoughtsPath, 'utf8');
45
+ expect(snapshot).toMatch(/^# Current/);
46
+ expect(result.snapshotPath).toMatch(/thought-2026-03-22T00-00-00.000Z\.md$/);
47
+ expect(current).toMatch(/# Current Thoughts/);
48
+ });
49
+ it('throws when no current thoughts file exists', () => {
50
+ const thoughtsDir = makeTempDir();
51
+ expect(() => snapshotCurrentThoughts(thoughtsDir, '2026-03-22T00-00-00.000Z')).toThrow(/No current thoughts file found/);
52
+ });
53
+ });
54
+ //# sourceMappingURL=current-thoughts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"current-thoughts.test.js","sourceRoot":"","sources":["../src/current-thoughts.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './current-thoughts.js';
2
+ export * from './memory.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './current-thoughts.js';
2
+ export * from './memory.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AACrC,cAAc,aAAa,CAAA"}
@@ -0,0 +1,21 @@
1
+ export declare const VIGOR_THRESHOLDS: {
2
+ readonly greenMax: 8;
3
+ readonly yellowMax: 14;
4
+ readonly redMin: 15;
5
+ };
6
+ export interface MemoryVigor {
7
+ status: 'GREEN' | 'YELLOW' | 'RED';
8
+ count: number;
9
+ archivedThoughts: string[];
10
+ exitCode: 0 | 1;
11
+ }
12
+ export interface MemoryCompactionPromptOptions {
13
+ thoughtsDir: string;
14
+ monthlyDir: string;
15
+ patternsDir: string;
16
+ now?: Date;
17
+ }
18
+ export declare function listArchivedThoughts(thoughtsDir: string): string[];
19
+ export declare function getMemoryVigor(thoughtsDir: string): MemoryVigor;
20
+ export declare function formatMemoryVigor(vigor: MemoryVigor): string;
21
+ export declare function createMemoryCompactionPrompt({ thoughtsDir, monthlyDir, patternsDir, now }: MemoryCompactionPromptOptions): string;
package/dist/memory.js ADDED
@@ -0,0 +1,72 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export const VIGOR_THRESHOLDS = {
4
+ greenMax: 8,
5
+ yellowMax: 14,
6
+ redMin: 15
7
+ };
8
+ export function listArchivedThoughts(thoughtsDir) {
9
+ const entries = fs.existsSync(thoughtsDir)
10
+ ? fs.readdirSync(thoughtsDir, { withFileTypes: true })
11
+ : [];
12
+ return entries
13
+ .filter((entry) => entry.isFile() && /^thought-.*\.md$/.test(entry.name))
14
+ .map((entry) => entry.name)
15
+ .sort();
16
+ }
17
+ export function getMemoryVigor(thoughtsDir) {
18
+ const archivedThoughts = listArchivedThoughts(thoughtsDir);
19
+ const count = archivedThoughts.length;
20
+ if (count >= VIGOR_THRESHOLDS.redMin) {
21
+ return { status: 'RED', count, archivedThoughts, exitCode: 1 };
22
+ }
23
+ if (count > VIGOR_THRESHOLDS.greenMax) {
24
+ return { status: 'YELLOW', count, archivedThoughts, exitCode: 0 };
25
+ }
26
+ return { status: 'GREEN', count, archivedThoughts, exitCode: 0 };
27
+ }
28
+ export function formatMemoryVigor(vigor) {
29
+ const lines = [
30
+ `Memory vigor: ${vigor.status}`,
31
+ `- archived_thoughts: ${vigor.count}`,
32
+ `- thresholds: GREEN <= ${VIGOR_THRESHOLDS.greenMax}, YELLOW 9-14, RED >= ${VIGOR_THRESHOLDS.redMin}`
33
+ ];
34
+ if (vigor.status !== 'GREEN') {
35
+ lines.push('Recommendation: run `pnpm memory:compact` and promote durable reasoning.');
36
+ }
37
+ return lines.join('\n');
38
+ }
39
+ export function createMemoryCompactionPrompt({ thoughtsDir, monthlyDir, patternsDir, now = new Date() }) {
40
+ const archivedThoughts = listArchivedThoughts(thoughtsDir);
41
+ const currentMonth = now.toISOString().slice(0, 7);
42
+ const monthlyPath = path.join(monthlyDir, `${currentMonth}.md`);
43
+ const lines = [
44
+ '# Memory Compaction Prompt',
45
+ '',
46
+ 'Use this prompt to compact governance memory.',
47
+ '',
48
+ '## Inputs',
49
+ '',
50
+ `- Thoughts directory: ${thoughtsDir}`,
51
+ `- Monthly synthesis target: ${monthlyPath}`,
52
+ `- Patterns directory: ${patternsDir}`,
53
+ `- Archived thought files: ${archivedThoughts.length}`,
54
+ '',
55
+ '## Actions',
56
+ '',
57
+ '1. Read the most relevant recent thought snapshots.',
58
+ '2. Update the monthly synthesis with durable developments.',
59
+ '3. Promote repeatable standards into docs/patterns/ or .agents/codex/.',
60
+ '4. Keep thoughts as episodic memory, not canonical law.',
61
+ '5. Re-run `pnpm memory:vigor` after compaction.',
62
+ ''
63
+ ];
64
+ if (archivedThoughts.length > 0) {
65
+ lines.push('## Recent Thoughts', '');
66
+ for (const thought of archivedThoughts.slice(-10)) {
67
+ lines.push(`- ${thought}`);
68
+ }
69
+ }
70
+ return lines.join('\n');
71
+ }
72
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { createMemoryCompactionPrompt, formatMemoryVigor, getMemoryVigor, listArchivedThoughts } from './memory.js';
6
+ const tempDirs = [];
7
+ function makeTempDir() {
8
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'governance-memory-'));
9
+ tempDirs.push(dir);
10
+ return dir;
11
+ }
12
+ afterEach(() => {
13
+ while (tempDirs.length > 0) {
14
+ fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
15
+ }
16
+ });
17
+ describe('memory utilities', () => {
18
+ it('lists only archived thought snapshots', () => {
19
+ const dir = makeTempDir();
20
+ fs.writeFileSync(path.join(dir, 'thought-1.md'), 'a');
21
+ fs.writeFileSync(path.join(dir, 'thought-2.md'), 'b');
22
+ fs.writeFileSync(path.join(dir, 'current-thoughts.md'), 'working');
23
+ fs.writeFileSync(path.join(dir, 'notes.md'), 'ignore');
24
+ expect(listArchivedThoughts(dir)).toEqual(['thought-1.md', 'thought-2.md']);
25
+ });
26
+ it('returns GREEN at eight or fewer archived thoughts', () => {
27
+ const dir = makeTempDir();
28
+ for (let i = 0; i < 8; i += 1) {
29
+ fs.writeFileSync(path.join(dir, `thought-${i}.md`), 'x');
30
+ }
31
+ const vigor = getMemoryVigor(dir);
32
+ expect(vigor.status).toBe('GREEN');
33
+ expect(vigor.exitCode).toBe(0);
34
+ });
35
+ it('returns YELLOW between nine and fourteen archived thoughts', () => {
36
+ const dir = makeTempDir();
37
+ for (let i = 0; i < 9; i += 1) {
38
+ fs.writeFileSync(path.join(dir, `thought-${i}.md`), 'x');
39
+ }
40
+ const vigor = getMemoryVigor(dir);
41
+ expect(vigor.status).toBe('YELLOW');
42
+ expect(vigor.exitCode).toBe(0);
43
+ });
44
+ it('returns RED at fifteen or more archived thoughts', () => {
45
+ const dir = makeTempDir();
46
+ for (let i = 0; i < 15; i += 1) {
47
+ fs.writeFileSync(path.join(dir, `thought-${i}.md`), 'x');
48
+ }
49
+ const vigor = getMemoryVigor(dir);
50
+ expect(vigor.status).toBe('RED');
51
+ expect(vigor.exitCode).toBe(1);
52
+ });
53
+ it('formats a recommendation for non-green vigor', () => {
54
+ const output = formatMemoryVigor({
55
+ status: 'YELLOW',
56
+ count: 10,
57
+ archivedThoughts: [],
58
+ exitCode: 0
59
+ });
60
+ expect(output).toMatch(/Memory vigor: YELLOW/);
61
+ expect(output).toMatch(/Recommendation: run `pnpm memory:compact`/);
62
+ });
63
+ it('builds a compaction prompt with recent thoughts', () => {
64
+ const thoughtsDir = makeTempDir();
65
+ const monthlyDir = makeTempDir();
66
+ const patternsDir = makeTempDir();
67
+ fs.writeFileSync(path.join(thoughtsDir, 'thought-a.md'), 'a');
68
+ fs.writeFileSync(path.join(thoughtsDir, 'thought-b.md'), 'b');
69
+ const prompt = createMemoryCompactionPrompt({
70
+ thoughtsDir,
71
+ monthlyDir,
72
+ patternsDir,
73
+ now: new Date('2026-03-22T00:00:00.000Z')
74
+ });
75
+ expect(prompt).toMatch(/Monthly synthesis target: .*2026-03\.md/);
76
+ expect(prompt).toMatch(/thought-a\.md/);
77
+ expect(prompt).toMatch(/thought-b\.md/);
78
+ });
79
+ });
80
+ //# sourceMappingURL=memory.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.test.js","sourceRoot":"","sources":["../src/memory.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACrB,MAAM,aAAa,CAAA;AAEpB,MAAM,QAAQ,GAAa,EAAE,CAAA;AAE7B,SAAS,WAAW;IAClB,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAA;IACxE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,CAAC,GAAG,EAAE;IACb,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9D,CAAC;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QACzB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,CAAA;QACrD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,CAAA;QACrD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,EAAE,SAAS,CAAC,CAAA;QAClE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;QAEtD,MAAM,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;QAC1D,CAAC;QAED,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAClC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;QAC1D,CAAC;QAED,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;QAC1D,CAAC;QAED,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,MAAM,GAAG,iBAAiB,CAAC;YAC/B,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,EAAE;YACT,gBAAgB,EAAE,EAAE;YACpB,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAA;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,WAAW,GAAG,WAAW,EAAE,CAAA;QACjC,MAAM,UAAU,GAAG,WAAW,EAAE,CAAA;QAChC,MAAM,WAAW,GAAG,WAAW,EAAE,CAAA;QAEjC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,CAAA;QAC7D,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,CAAA;QAE7D,MAAM,MAAM,GAAG,4BAA4B,CAAC;YAC1C,WAAW;YACX,UAAU;YACV,WAAW;YACX,GAAG,EAAE,IAAI,IAAI,CAAC,0BAA0B,CAAC;SAC1C,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAA;QACjE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@deposition.cloud/memory",
3
+ "version": "1.0.2",
4
+ "description": "Reusable governance memory and thought-management utilities",
5
+ "type": "module",
6
+ "private": false,
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "main": "dist/index.js",
14
+ "types": "dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
+ }
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+ssh://git@gitlab.com/deposition.cloud/libs/governance/memory.git"
24
+ },
25
+ "author": "reply@deposition.cloud",
26
+ "license": "Hippocratic",
27
+ "bugs": {
28
+ "url": "https://gitlab.com/deposition.cloud/libs/governance/memory/issues"
29
+ },
30
+ "homepage": "https://gitlab.com/deposition.cloud/libs/governance/memory#readme",
31
+ "dependencies": {
32
+ "@semantic-release/commit-analyzer": "^13.0.1",
33
+ "@semantic-release/changelog": "^6.0.3",
34
+ "@semantic-release/npm": "^12.0.2",
35
+ "@semantic-release/release-notes-generator": "^14.1.0",
36
+ "@semantic-release/git": "^10.0.1",
37
+ "@semantic-release/gitlab": "^13.2.5",
38
+ "@types/node": "^22.15.24",
39
+ "only-allow": "^1.2.1",
40
+ "semantic-release": "^24.2.5",
41
+ "tsx": "^4.19.4",
42
+ "typescript": "^5.8.3",
43
+ "vitest": "^3.1.4"
44
+ },
45
+ "devDependencies": {
46
+ "@semantic-release/exec": "^7.1.0"
47
+ },
48
+ "scripts": {
49
+ "preinstall": "npx -y only-allow pnpm || (echo 'Use pnpm only'; exit 1)",
50
+ "build": "tsc -p tsconfig.json",
51
+ "test": "vitest run",
52
+ "test:watch": "vitest",
53
+ "release": "tsx ./node_modules/.bin/semantic-release"
54
+ }
55
+ }