synomem 0.9.6 → 0.10.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/CHANGELOG.md +9 -0
- package/README.md +5 -3
- package/dist/actor-directory.d.ts +34 -0
- package/dist/actor-directory.d.ts.map +1 -0
- package/dist/actor-directory.js +52 -0
- package/dist/actor-directory.js.map +1 -0
- package/dist/backend.d.ts +3 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +26 -3
- package/dist/backend.js.map +1 -1
- package/dist/bookmarks.d.ts +30 -0
- package/dist/bookmarks.d.ts.map +1 -0
- package/dist/bookmarks.js +87 -0
- package/dist/bookmarks.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +291 -61
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +115 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +854 -138
- package/dist/client.js.map +1 -1
- package/dist/cursors.d.ts +30 -0
- package/dist/cursors.d.ts.map +1 -0
- package/dist/cursors.js +101 -0
- package/dist/cursors.js.map +1 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -1
- package/dist/import.d.ts +605 -39
- package/dist/import.d.ts.map +1 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +329 -22
- package/dist/mcp/index.js.map +1 -1
- package/dist/mutation-receipts.d.ts +8 -0
- package/dist/mutation-receipts.d.ts.map +1 -0
- package/dist/mutation-receipts.js +2 -0
- package/dist/mutation-receipts.js.map +1 -0
- package/dist/notifications.d.ts +73 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.js +309 -0
- package/dist/notifications.js.map +1 -0
- package/dist/participation-repository.d.ts +46 -0
- package/dist/participation-repository.d.ts.map +1 -0
- package/dist/participation-repository.js +296 -0
- package/dist/participation-repository.js.map +1 -0
- package/dist/participation.d.ts +97 -0
- package/dist/participation.d.ts.map +1 -0
- package/dist/participation.js +10 -0
- package/dist/participation.js.map +1 -0
- package/dist/policy.d.ts +31 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +71 -0
- package/dist/policy.js.map +1 -0
- package/dist/ports/repository.d.ts +23 -0
- package/dist/ports/repository.d.ts.map +1 -1
- package/dist/profiles.d.ts +12 -0
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +2 -1
- package/dist/profiles.js.map +1 -1
- package/dist/projections.d.ts.map +1 -1
- package/dist/projections.js +29 -11
- package/dist/projections.js.map +1 -1
- package/dist/remote.d.ts +79 -0
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +65 -6
- package/dist/remote.js.map +1 -1
- package/dist/schemas.d.ts +746 -58
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +114 -16
- package/dist/schemas.js.map +1 -1
- package/dist/search.d.ts +25 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +2 -0
- package/dist/search.js.map +1 -0
- package/dist/service.d.ts +89 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/storage.d.ts +38 -3
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +494 -365
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +65 -34
- package/dist/types.d.ts.map +1 -1
- package/docs/cli.md +6 -0
- package/docs/human-participation.md +20 -0
- package/docs/mcp.md +2 -0
- package/docs/storage-format.md +4 -15
- package/openapi/synomem-v1.yaml +187 -10
- package/package.json +2 -1
- package/skills/synomem/SKILL.md +2 -0
- package/src/actor-directory.ts +87 -0
- package/src/backend.ts +29 -3
- package/src/bookmarks.ts +127 -0
- package/src/cli.ts +941 -546
- package/src/client.ts +1143 -279
- package/src/cursors.ts +132 -0
- package/src/errors.ts +2 -0
- package/src/index.ts +50 -0
- package/src/mcp/index.ts +412 -96
- package/src/mutation-receipts.ts +7 -0
- package/src/notifications.ts +483 -0
- package/src/participation-repository.ts +406 -0
- package/src/participation.ts +103 -0
- package/src/policy.ts +109 -0
- package/src/ports/repository.ts +33 -0
- package/src/profiles.ts +2 -1
- package/src/projections.ts +49 -48
- package/src/remote.ts +227 -37
- package/src/schemas.ts +116 -16
- package/src/search.ts +24 -0
- package/src/service.ts +122 -8
- package/src/storage.ts +1039 -697
- package/src/types.ts +67 -32
package/src/projections.ts
CHANGED
|
@@ -21,7 +21,6 @@ import type {
|
|
|
21
21
|
TaskRecord,
|
|
22
22
|
TodoRecord,
|
|
23
23
|
} from './types.js';
|
|
24
|
-
|
|
25
24
|
/**
|
|
26
25
|
* The instant a deadline has passed.
|
|
27
26
|
*
|
|
@@ -34,13 +33,10 @@ export function dueInstant(due: TaskDue | undefined): string | undefined {
|
|
|
34
33
|
if (!due) return undefined;
|
|
35
34
|
return due.kind === 'date' ? `${due.date}T23:59:59.999Z` : due.datetime;
|
|
36
35
|
}
|
|
37
|
-
|
|
38
36
|
const generatedMarker = '<!-- Generated by Synomem. Rebuild with `synomem rebuild`. -->';
|
|
39
|
-
|
|
40
37
|
function manifestPath(home: string, path: string): string {
|
|
41
38
|
return relative(home, path).split(sep).join('/');
|
|
42
39
|
}
|
|
43
|
-
|
|
44
40
|
export function escapeMarkdown(value: string): string {
|
|
45
41
|
return value
|
|
46
42
|
.replaceAll('&', '&')
|
|
@@ -49,13 +45,11 @@ export function escapeMarkdown(value: string): string {
|
|
|
49
45
|
.replace(/([\\`*_{}[\]()#+!|])/g, '\\$1')
|
|
50
46
|
.replace(/^(\s*)(-|\d+\.)\s/gm, '$1\\$2 ');
|
|
51
47
|
}
|
|
52
|
-
|
|
53
48
|
function evidenceLine(evidence: EvidenceReference): string {
|
|
54
49
|
const kind = evidence.kind.replace('-', ' ');
|
|
55
50
|
const label = evidence.label ? `${escapeMarkdown(evidence.label)} — ` : '';
|
|
56
51
|
return `- **${escapeMarkdown(kind[0]?.toUpperCase() + kind.slice(1))}:** ${label}${escapeMarkdown(evidence.value)}`;
|
|
57
52
|
}
|
|
58
|
-
|
|
59
53
|
function recordMarkdown(record: KudosRecord, includeTitle = true): string {
|
|
60
54
|
const event = record.event;
|
|
61
55
|
const lines = [
|
|
@@ -75,7 +69,6 @@ function recordMarkdown(record: KudosRecord, includeTitle = true): string {
|
|
|
75
69
|
lines.push(`**Kudos ID:** \`${event.id}\``, '');
|
|
76
70
|
return lines.join('\n');
|
|
77
71
|
}
|
|
78
|
-
|
|
79
72
|
function winsMarkdown(profile: AgentProfile, records: KudosRecord[], rebuiltAt: string): string {
|
|
80
73
|
const active = records.filter((record) => !record.revocation);
|
|
81
74
|
const lines = [
|
|
@@ -101,7 +94,6 @@ function winsMarkdown(profile: AgentProfile, records: KudosRecord[], rebuiltAt:
|
|
|
101
94
|
}
|
|
102
95
|
return `${lines.join('\n')}\n`;
|
|
103
96
|
}
|
|
104
|
-
|
|
105
97
|
function inboxMarkdown(record: KudosRecord): string {
|
|
106
98
|
return `${[
|
|
107
99
|
generatedMarker,
|
|
@@ -111,7 +103,6 @@ function inboxMarkdown(record: KudosRecord): string {
|
|
|
111
103
|
recordMarkdown(record, false),
|
|
112
104
|
].join('\n')}\n`;
|
|
113
105
|
}
|
|
114
|
-
|
|
115
106
|
function memoInboxMarkdown(record: MemoRecord): string {
|
|
116
107
|
return `${[
|
|
117
108
|
generatedMarker,
|
|
@@ -126,7 +117,6 @@ function memoInboxMarkdown(record: MemoRecord): string {
|
|
|
126
117
|
'',
|
|
127
118
|
].join('\n')}\n`;
|
|
128
119
|
}
|
|
129
|
-
|
|
130
120
|
function taskInboxMarkdown(record: TaskRecord): string {
|
|
131
121
|
const due =
|
|
132
122
|
record.current.due?.kind === 'date'
|
|
@@ -147,7 +137,6 @@ function taskInboxMarkdown(record: TaskRecord): string {
|
|
|
147
137
|
...(record.current.description ? [escapeMarkdown(record.current.description), ''] : []),
|
|
148
138
|
].join('\n')}\n`;
|
|
149
139
|
}
|
|
150
|
-
|
|
151
140
|
function memoryMarkdown(profile: AgentProfile, records: NoteRecord[], rebuiltAt: string): string {
|
|
152
141
|
const active = records.filter((record) => record.status === 'active');
|
|
153
142
|
const lines = [
|
|
@@ -172,7 +161,6 @@ function memoryMarkdown(profile: AgentProfile, records: NoteRecord[], rebuiltAt:
|
|
|
172
161
|
}
|
|
173
162
|
return `${lines.join('\n')}\n`;
|
|
174
163
|
}
|
|
175
|
-
|
|
176
164
|
function tasksMarkdown(profile: AgentProfile, records: TaskRecord[], rebuiltAt: string): string {
|
|
177
165
|
const lines = [
|
|
178
166
|
generatedMarker,
|
|
@@ -202,7 +190,6 @@ function tasksMarkdown(profile: AgentProfile, records: TaskRecord[], rebuiltAt:
|
|
|
202
190
|
}
|
|
203
191
|
return `${lines.join('\n')}\n`;
|
|
204
192
|
}
|
|
205
|
-
|
|
206
193
|
export function recordsFromEvents(events: SynomemEvent[]): KudosRecord[] {
|
|
207
194
|
const acknowledgments = new Map<string, KudosRecord['acknowledgment']>();
|
|
208
195
|
const revocations = new Map<string, KudosRecord['revocation']>();
|
|
@@ -232,7 +219,6 @@ export function recordsFromEvents(events: SynomemEvent[]): KudosRecord[] {
|
|
|
232
219
|
b.event.createdAt.localeCompare(a.event.createdAt) || b.event.id.localeCompare(a.event.id),
|
|
233
220
|
);
|
|
234
221
|
}
|
|
235
|
-
|
|
236
222
|
export function memoRecordsFromEvents(events: SynomemEvent[]): MemoRecord[] {
|
|
237
223
|
const records = new Map<string, MemoRecord>();
|
|
238
224
|
for (const event of events) {
|
|
@@ -254,7 +240,6 @@ export function memoRecordsFromEvents(events: SynomemEvent[]): MemoRecord[] {
|
|
|
254
240
|
}
|
|
255
241
|
return [...records.values()].sort((a, b) => b.event.createdAt.localeCompare(a.event.createdAt));
|
|
256
242
|
}
|
|
257
|
-
|
|
258
243
|
/**
|
|
259
244
|
* Rebuilds posts from their events, acknowledgements included.
|
|
260
245
|
*
|
|
@@ -269,6 +254,7 @@ export function postRecordsFromEvents(events: SynomemEvent[]): PostRecord[] {
|
|
|
269
254
|
records.set(event.id, {
|
|
270
255
|
event,
|
|
271
256
|
edits: [],
|
|
257
|
+
mentions: event.mentions ?? [],
|
|
272
258
|
acknowledgments: [],
|
|
273
259
|
status: 'active',
|
|
274
260
|
title: event.title,
|
|
@@ -286,6 +272,7 @@ export function postRecordsFromEvents(events: SynomemEvent[]): PostRecord[] {
|
|
|
286
272
|
const record = records.get(event.postId);
|
|
287
273
|
if (record) {
|
|
288
274
|
record.edits.push(event);
|
|
275
|
+
record.mentions = event.mentions ?? [];
|
|
289
276
|
record.title = event.title;
|
|
290
277
|
record.body = event.body;
|
|
291
278
|
if (event.tags) record.tags = event.tags;
|
|
@@ -323,7 +310,6 @@ export function postRecordsFromEvents(events: SynomemEvent[]): PostRecord[] {
|
|
|
323
310
|
}
|
|
324
311
|
return [...records.values()];
|
|
325
312
|
}
|
|
326
|
-
|
|
327
313
|
export function noteRecordsFromEvents(events: SynomemEvent[]): NoteRecord[] {
|
|
328
314
|
const records = new Map<string, NoteRecord>();
|
|
329
315
|
for (const event of events) {
|
|
@@ -364,7 +350,6 @@ export function noteRecordsFromEvents(events: SynomemEvent[]): NoteRecord[] {
|
|
|
364
350
|
}
|
|
365
351
|
return [...records.values()].sort((a, b) => b.event.createdAt.localeCompare(a.event.createdAt));
|
|
366
352
|
}
|
|
367
|
-
|
|
368
353
|
/**
|
|
369
354
|
* Builds private Todo records.
|
|
370
355
|
*
|
|
@@ -431,7 +416,6 @@ export function todoRecordsFromEvents(events: SynomemEvent[]): TodoRecord[] {
|
|
|
431
416
|
}
|
|
432
417
|
return [...records.values()];
|
|
433
418
|
}
|
|
434
|
-
|
|
435
419
|
export function taskRecordsFromEvents(events: SynomemEvent[]): TaskRecord[] {
|
|
436
420
|
const records = new Map<string, TaskRecord>();
|
|
437
421
|
for (const event of events) {
|
|
@@ -466,6 +450,14 @@ export function taskRecordsFromEvents(events: SynomemEvent[]): TaskRecord[] {
|
|
|
466
450
|
version: event.aggregateVersion,
|
|
467
451
|
};
|
|
468
452
|
}
|
|
453
|
+
} else if (event.type === 'task.decision_overridden') {
|
|
454
|
+
const record = records.get(event.taskId);
|
|
455
|
+
if (record) {
|
|
456
|
+
record.status = event.nextStatus;
|
|
457
|
+
record.current.version = event.aggregateVersion;
|
|
458
|
+
record.overrides = [...(record.overrides ?? []), event];
|
|
459
|
+
delete record.terminal;
|
|
460
|
+
}
|
|
469
461
|
} else if (event.type === 'task.accepted') {
|
|
470
462
|
const record = records.get(event.taskId);
|
|
471
463
|
if (record) {
|
|
@@ -513,7 +505,6 @@ export function taskRecordsFromEvents(events: SynomemEvent[]): TaskRecord[] {
|
|
|
513
505
|
}
|
|
514
506
|
return [...records.values()].sort((a, b) => b.event.createdAt.localeCompare(a.event.createdAt));
|
|
515
507
|
}
|
|
516
|
-
|
|
517
508
|
/** Render a portable human-readable export without reading generated projections. */
|
|
518
509
|
export function renderMarkdownExport(events: SynomemEvent[]): string {
|
|
519
510
|
const sections = [
|
|
@@ -536,16 +527,18 @@ export function renderMarkdownExport(events: SynomemEvent[]): string {
|
|
|
536
527
|
];
|
|
537
528
|
return `${sections.join('\n\n')}\n`;
|
|
538
529
|
}
|
|
539
|
-
|
|
540
530
|
export class ProjectionManager implements ProjectionWriter {
|
|
541
531
|
constructor(private readonly storage: SynomemStorage) {}
|
|
542
|
-
|
|
543
|
-
|
|
532
|
+
rebuild(): {
|
|
533
|
+
generated: string[];
|
|
534
|
+
removed: string[];
|
|
535
|
+
} {
|
|
544
536
|
this.storage.assertWritable();
|
|
545
537
|
const events = this.storage.getEvents();
|
|
546
538
|
this.storage.transactionSync(() => {
|
|
547
539
|
this.storage.rebuildKudosCurrentIndex();
|
|
548
540
|
this.storage.rebuildItemsCurrentIndex();
|
|
541
|
+
this.storage.rebuildParticipationCurrentIndex();
|
|
549
542
|
});
|
|
550
543
|
const profiles = this.storage.listAgents();
|
|
551
544
|
const records = recordsFromEvents(events);
|
|
@@ -554,7 +547,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
554
547
|
const tasks = taskRecordsFromEvents(events);
|
|
555
548
|
const rebuiltAt = events.at(-1)?.createdAt ?? new Date(0).toISOString();
|
|
556
549
|
const generated: string[] = [];
|
|
557
|
-
|
|
558
550
|
for (const profile of profiles) {
|
|
559
551
|
const agentDirectory = join(this.storage.home, profile.handle);
|
|
560
552
|
assertNoSymlinkEscape(this.storage.home, agentDirectory);
|
|
@@ -571,7 +563,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
571
563
|
ensureDirectory(kudosInboxDirectory);
|
|
572
564
|
ensureDirectory(memoInboxDirectory);
|
|
573
565
|
ensureDirectory(taskInboxDirectory);
|
|
574
|
-
|
|
575
566
|
atomicWriteDerivedFile(
|
|
576
567
|
profilePath,
|
|
577
568
|
`${JSON.stringify({ _generatedBy: 'synomem', ...profile }, null, 2)}\n`,
|
|
@@ -583,19 +574,26 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
583
574
|
`# Notes — ${profile.displayName}\n\n<!-- Human-owned. Synomem will never overwrite this file. -->\n`,
|
|
584
575
|
);
|
|
585
576
|
}
|
|
586
|
-
|
|
587
|
-
|
|
577
|
+
const agentRecords = records.filter(
|
|
578
|
+
(record) =>
|
|
579
|
+
record.event.recipient?.kind === 'agent' && record.event.recipient.id === profile.id,
|
|
580
|
+
);
|
|
588
581
|
if (this.storage.config.projection.writeWinsMarkdown) {
|
|
589
582
|
atomicWriteDerivedFile(winsPath, winsMarkdown(profile, agentRecords, rebuiltAt));
|
|
590
583
|
generated.push(manifestPath(this.storage.home, winsPath));
|
|
591
584
|
}
|
|
592
|
-
const agentNotes = notes.filter(
|
|
585
|
+
const agentNotes = notes.filter(
|
|
586
|
+
(record) => record.event.owner?.kind === 'agent' && record.event.owner.id === profile.id,
|
|
587
|
+
);
|
|
593
588
|
if (this.storage.config.projection.writeMemoryMarkdown) {
|
|
594
589
|
const memoryPath = join(agentDirectory, 'MEMORY.md');
|
|
595
590
|
atomicWriteDerivedFile(memoryPath, memoryMarkdown(profile, agentNotes, rebuiltAt));
|
|
596
591
|
generated.push(manifestPath(this.storage.home, memoryPath));
|
|
597
592
|
}
|
|
598
|
-
const agentTasks = tasks.filter(
|
|
593
|
+
const agentTasks = tasks.filter(
|
|
594
|
+
(record) =>
|
|
595
|
+
record.event.assignee?.kind === 'agent' && record.event.assignee.id === profile.id,
|
|
596
|
+
);
|
|
599
597
|
if (this.storage.config.projection.writeTasksMarkdown) {
|
|
600
598
|
const tasksPath = join(agentDirectory, 'TASKS.md');
|
|
601
599
|
atomicWriteDerivedFile(tasksPath, tasksMarkdown(profile, agentTasks, rebuiltAt));
|
|
@@ -610,7 +608,10 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
610
608
|
generated.push(manifestPath(this.storage.home, inboxPath));
|
|
611
609
|
}
|
|
612
610
|
for (const record of memos.filter(
|
|
613
|
-
(item) =>
|
|
611
|
+
(item) =>
|
|
612
|
+
item.event.recipient?.kind === 'agent' &&
|
|
613
|
+
item.event.recipient.id === profile.id &&
|
|
614
|
+
item.status === 'unread',
|
|
614
615
|
)) {
|
|
615
616
|
const inboxPath = join(memoInboxDirectory, `${record.event.id}.md`);
|
|
616
617
|
atomicWriteDerivedFile(inboxPath, memoInboxMarkdown(record));
|
|
@@ -625,7 +626,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
625
626
|
}
|
|
626
627
|
}
|
|
627
628
|
}
|
|
628
|
-
|
|
629
629
|
const keep = new Set(generated);
|
|
630
630
|
const removed: string[] = [];
|
|
631
631
|
for (const stale of this.storage.projectionManifest()) {
|
|
@@ -643,7 +643,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
643
643
|
this.storage.replaceProjectionManifest(generated, rebuiltAt);
|
|
644
644
|
return { generated: generated.sort(), removed: removed.sort() };
|
|
645
645
|
}
|
|
646
|
-
|
|
647
646
|
/**
|
|
648
647
|
* Move an agent's directory when its handle changes.
|
|
649
648
|
*
|
|
@@ -680,23 +679,28 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
680
679
|
renameSync(from, to);
|
|
681
680
|
this.storage.renameProjectionManifestPrefix(previousHandle, nextHandle);
|
|
682
681
|
}
|
|
683
|
-
|
|
684
|
-
|
|
682
|
+
syncAgent(agentId: string): {
|
|
683
|
+
generated: string[];
|
|
684
|
+
removed: string[];
|
|
685
|
+
} {
|
|
685
686
|
this.storage.assertWritable();
|
|
686
687
|
const profile = this.storage.getAgent(agentId);
|
|
687
688
|
if (!profile) throw new SynomemError('AGENT_NOT_FOUND', `Unknown agent: ${agentId}`);
|
|
688
689
|
const events = this.storage.getEvents();
|
|
689
690
|
const records = recordsFromEvents(events).filter(
|
|
690
|
-
(record) =>
|
|
691
|
+
(record) =>
|
|
692
|
+
record.event.recipient?.kind === 'agent' && record.event.recipient.id === profile.id,
|
|
691
693
|
);
|
|
692
694
|
const memos = memoRecordsFromEvents(events).filter(
|
|
693
|
-
(record) =>
|
|
695
|
+
(record) =>
|
|
696
|
+
record.event.recipient?.kind === 'agent' && record.event.recipient.id === profile.id,
|
|
694
697
|
);
|
|
695
698
|
const notes = noteRecordsFromEvents(events).filter(
|
|
696
|
-
(record) => record.event.
|
|
699
|
+
(record) => record.event.owner?.kind === 'agent' && record.event.owner.id === profile.id,
|
|
697
700
|
);
|
|
698
701
|
const tasks = taskRecordsFromEvents(events).filter(
|
|
699
|
-
(record) =>
|
|
702
|
+
(record) =>
|
|
703
|
+
record.event.assignee?.kind === 'agent' && record.event.assignee.id === profile.id,
|
|
700
704
|
);
|
|
701
705
|
const rebuiltAt = events.at(-1)?.createdAt ?? new Date(0).toISOString();
|
|
702
706
|
const agentDirectory = join(this.storage.home, profile.handle);
|
|
@@ -711,7 +715,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
711
715
|
ensureDirectory(kudosInboxDirectory);
|
|
712
716
|
ensureDirectory(memoInboxDirectory);
|
|
713
717
|
ensureDirectory(taskInboxDirectory);
|
|
714
|
-
|
|
715
718
|
const generated: string[] = [];
|
|
716
719
|
const profilePath = join(agentDirectory, 'profile.json');
|
|
717
720
|
atomicWriteDerivedFile(
|
|
@@ -719,7 +722,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
719
722
|
`${JSON.stringify({ _generatedBy: 'synomem', ...profile }, null, 2)}\n`,
|
|
720
723
|
);
|
|
721
724
|
generated.push(manifestPath(this.storage.home, profilePath));
|
|
722
|
-
|
|
723
725
|
const notesPath = join(agentDirectory, 'NOTES.md');
|
|
724
726
|
if (!existsSync(notesPath)) {
|
|
725
727
|
atomicWriteFile(
|
|
@@ -727,25 +729,21 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
727
729
|
`# Notes — ${profile.displayName}\n\n<!-- Human-owned. Synomem will never overwrite this file. -->\n`,
|
|
728
730
|
);
|
|
729
731
|
}
|
|
730
|
-
|
|
731
732
|
if (this.storage.config.projection.writeWinsMarkdown) {
|
|
732
733
|
const winsPath = join(agentDirectory, 'WINS.md');
|
|
733
734
|
atomicWriteDerivedFile(winsPath, winsMarkdown(profile, records, rebuiltAt));
|
|
734
735
|
generated.push(manifestPath(this.storage.home, winsPath));
|
|
735
736
|
}
|
|
736
|
-
|
|
737
737
|
if (this.storage.config.projection.writeMemoryMarkdown) {
|
|
738
738
|
const memoryPath = join(agentDirectory, 'MEMORY.md');
|
|
739
739
|
atomicWriteDerivedFile(memoryPath, memoryMarkdown(profile, notes, rebuiltAt));
|
|
740
740
|
generated.push(manifestPath(this.storage.home, memoryPath));
|
|
741
741
|
}
|
|
742
|
-
|
|
743
742
|
if (this.storage.config.projection.writeTasksMarkdown) {
|
|
744
743
|
const tasksPath = join(agentDirectory, 'TASKS.md');
|
|
745
744
|
atomicWriteDerivedFile(tasksPath, tasksMarkdown(profile, tasks, rebuiltAt));
|
|
746
745
|
generated.push(manifestPath(this.storage.home, tasksPath));
|
|
747
746
|
}
|
|
748
|
-
|
|
749
747
|
if (this.storage.config.projection.writeInboxEntries) {
|
|
750
748
|
for (const record of records.filter(
|
|
751
749
|
(item) => item.status === 'unacknowledged' && item.revocationStatus === 'active',
|
|
@@ -770,7 +768,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
770
768
|
generated.push(relativePath);
|
|
771
769
|
}
|
|
772
770
|
}
|
|
773
|
-
|
|
774
771
|
const keep = new Set(generated);
|
|
775
772
|
const prefixes = [`${profile.handle}/`, `${profile.handle}\\`];
|
|
776
773
|
const removed: string[] = [];
|
|
@@ -791,7 +788,6 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
791
788
|
this.storage.replaceAgentProjectionManifest(profile.handle, generated, rebuiltAt);
|
|
792
789
|
return { generated: generated.sort(), removed: removed.sort() };
|
|
793
790
|
}
|
|
794
|
-
|
|
795
791
|
/*
|
|
796
792
|
* The paths a rebuild would produce, for comparison against the manifest.
|
|
797
793
|
*
|
|
@@ -817,20 +813,25 @@ export class ProjectionManager implements ProjectionWriter {
|
|
|
817
813
|
if (this.storage.config.projection.writeInboxEntries) {
|
|
818
814
|
for (const record of records.filter(
|
|
819
815
|
(item) =>
|
|
820
|
-
item.event.
|
|
816
|
+
item.event.recipient?.kind === 'agent' &&
|
|
817
|
+
item.event.recipient.id === profile.id &&
|
|
821
818
|
item.status === 'unacknowledged' &&
|
|
822
819
|
item.revocationStatus === 'active',
|
|
823
820
|
)) {
|
|
824
821
|
paths.push(`${profile.handle}/inbox/kudos/${record.event.id}.md`);
|
|
825
822
|
}
|
|
826
823
|
for (const record of memos.filter(
|
|
827
|
-
(item) =>
|
|
824
|
+
(item) =>
|
|
825
|
+
item.event.recipient?.kind === 'agent' &&
|
|
826
|
+
item.event.recipient.id === profile.id &&
|
|
827
|
+
item.status === 'unread',
|
|
828
828
|
)) {
|
|
829
829
|
paths.push(`${profile.handle}/inbox/memos/${record.event.id}.md`);
|
|
830
830
|
}
|
|
831
831
|
for (const record of tasks.filter(
|
|
832
832
|
(item) =>
|
|
833
|
-
item.event.
|
|
833
|
+
item.event.assignee?.kind === 'agent' &&
|
|
834
|
+
item.event.assignee.id === profile.id &&
|
|
834
835
|
(item.status === 'open' || item.status === 'assigned'),
|
|
835
836
|
)) {
|
|
836
837
|
paths.push(`${profile.handle}/inbox/tasks/${record.event.id}.md`);
|