@getbourdon/conformance 0.2.1 → 0.3.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 (61) hide show
  1. package/README.md +26 -4
  2. package/dist/index.cjs +30 -2
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +20 -1
  5. package/dist/index.d.ts +28 -11
  6. package/dist/index.js +51 -29
  7. package/dist/index.js.map +1 -1
  8. package/fixtures/README.md +11 -3
  9. package/fixtures/fed_seed_library/agents/claude-code.l5.yaml +31 -4
  10. package/fixtures/fed_seed_library/agents/codex.l5.yaml +15 -0
  11. package/fixtures/l5_manifests/invalid/bad-agent-type-enum.json +1 -1
  12. package/fixtures/l5_manifests/invalid/bad-spec-version-pattern.json +1 -1
  13. package/fixtures/l5_manifests/invalid/entity-bad-visibility-enum.json +1 -1
  14. package/fixtures/l5_manifests/invalid/entity-impossible-calendar-date.json +14 -0
  15. package/fixtures/l5_manifests/invalid/entity-missing-name.json +1 -1
  16. package/fixtures/l5_manifests/invalid/missing-required-last_updated.json +1 -1
  17. package/fixtures/l5_manifests/invalid/reasons.json +52 -0
  18. package/fixtures/l5_manifests/invalid/session-impossible-calendar-date.json +13 -0
  19. package/fixtures/l5_manifests/invalid/session-impossible-feb-30.json +13 -0
  20. package/fixtures/l5_manifests/valid/full.json +2 -2
  21. package/fixtures/l5_manifests/valid/minimal.json +1 -1
  22. package/fixtures/l5_manifests/valid/session-empty-date.json +16 -0
  23. package/fixtures/l5_manifests/valid/team-and-private.json +1 -1
  24. package/fixtures/l5_schema.json +216 -27
  25. package/fixtures/l5_todict.json +10 -10
  26. package/fixtures/leak_cases.json +1 -1
  27. package/fixtures/manifest.json +142 -32
  28. package/fixtures/mcp_snapshots/_normalizer.json +32 -2
  29. package/fixtures/mcp_snapshots/commit_to_federation.req.json +13 -1
  30. package/fixtures/mcp_snapshots/commit_to_federation.res.json +9 -2
  31. package/fixtures/mcp_snapshots/explain_memory_change.req.json +7 -0
  32. package/fixtures/mcp_snapshots/explain_memory_change.res.json +15 -0
  33. package/fixtures/mcp_snapshots/export_agents.res.json +47 -1
  34. package/fixtures/mcp_snapshots/get_cross_agent_summary.res.json +1 -1
  35. package/fixtures/mcp_snapshots/list_memory_versions.req.json +6 -0
  36. package/fixtures/mcp_snapshots/list_memory_versions.res.json +13 -0
  37. package/fixtures/mcp_snapshots/list_notes.req.json +8 -0
  38. package/fixtures/mcp_snapshots/list_notes.res.json +28 -0
  39. package/fixtures/mcp_snapshots/list_recent_work.res.json +1 -1
  40. package/fixtures/mcp_snapshots/list_workstreams.req.json +6 -0
  41. package/fixtures/mcp_snapshots/list_workstreams.res.json +23 -0
  42. package/fixtures/mcp_snapshots/prepare_recognition_context_drifting.req.json +8 -0
  43. package/fixtures/mcp_snapshots/prepare_recognition_context_drifting.res.json +26 -0
  44. package/fixtures/mcp_snapshots/resource_agent_memory.req.json +6 -0
  45. package/fixtures/mcp_snapshots/resource_agent_memory.res.json +80 -0
  46. package/fixtures/mcp_snapshots/resource_agents.req.json +4 -0
  47. package/fixtures/mcp_snapshots/resource_agents.res.json +4 -0
  48. package/fixtures/mcp_snapshots/resource_entity.req.json +6 -0
  49. package/fixtures/mcp_snapshots/resource_entity.res.json +19 -0
  50. package/fixtures/mcp_snapshots/rollback_agent_memory.req.json +7 -0
  51. package/fixtures/mcp_snapshots/rollback_agent_memory.res.json +7 -0
  52. package/fixtures/mcp_snapshots/seed_library.json +111 -3
  53. package/fixtures/native_stores/claude_code/expected_l5.json +8 -8
  54. package/fixtures/native_stores/claude_code/store/auto_memory/{clyde.md → alpha-agent.md} +2 -2
  55. package/fixtures/native_stores/claude_code/store/auto_memory/{ry-guy.md → example-user.md} +2 -2
  56. package/fixtures/native_stores/claude_code/store/knowledge_graph/memory.jsonl +2 -2
  57. package/fixtures/recognition_golden_v1.yaml +17 -17
  58. package/fixtures/recognition_vectors.json +23 -23
  59. package/fixtures/tier_matrix.json +2 -2
  60. package/fixtures.pin.json +5 -0
  61. package/package.json +6 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "spec_version": "0.1",
3
3
  "agent": {
4
- "id": "clair",
4
+ "id": "beta-agent",
5
5
  "type": "note-capture"
6
6
  },
7
7
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -4,17 +4,26 @@
4
4
  "title": "Bourdon L5 Agent Memory Manifest",
5
5
  "description": "A per-agent public memory glossary. L5 is a projection of L0-L4 personal memory into a standardized, agent-readable form with visibility filtering applied. L6 (the federation library) aggregates L5 manifests across agents.",
6
6
  "type": "object",
7
- "required": ["spec_version", "agent", "last_updated"],
7
+ "required": [
8
+ "spec_version",
9
+ "agent",
10
+ "last_updated"
11
+ ],
8
12
  "properties": {
9
13
  "spec_version": {
10
14
  "description": "Bourdon spec version this manifest conforms to (semver). L6 warns when reading a manifest with an incompatible version.",
11
15
  "type": "string",
12
16
  "pattern": "^\\d+\\.\\d+$",
13
- "examples": ["0.1"]
17
+ "examples": [
18
+ "0.1"
19
+ ]
14
20
  },
15
21
  "agent": {
16
22
  "type": "object",
17
- "required": ["id", "type"],
23
+ "required": [
24
+ "id",
25
+ "type"
26
+ ],
18
27
  "properties": {
19
28
  "id": {
20
29
  "description": "Unique slug for this agent. Used as the L6 filename and cross-agent reference key.",
@@ -22,7 +31,12 @@
22
31
  "pattern": "^[a-z0-9][a-z0-9_-]*$",
23
32
  "minLength": 1,
24
33
  "maxLength": 64,
25
- "examples": ["clyde", "claude-code", "codex", "clair"]
34
+ "examples": [
35
+ "alpha-agent",
36
+ "claude-code",
37
+ "codex",
38
+ "beta-agent"
39
+ ]
26
40
  },
27
41
  "type": {
28
42
  "description": "Agent category. Informs L6 query routing and UI grouping.",
@@ -43,12 +57,18 @@
43
57
  "description": "Optional machine/deployment identifier. Helps federate memory across multiple instances of the same agent on different machines.",
44
58
  "type": "string",
45
59
  "maxLength": 128,
46
- "examples": ["pc-threadripper", "mac-m1max"]
60
+ "examples": [
61
+ "workstation-01",
62
+ "laptop-01"
63
+ ]
47
64
  },
48
65
  "spec_version_compat": {
49
66
  "description": "Version range of Bourdon specs this manifest is compatible with. Uses npm-style semver ranges. If omitted, assumed equal to spec_version.",
50
67
  "type": "string",
51
- "examples": [">=0.1", "^0.1.0"]
68
+ "examples": [
69
+ ">=0.1",
70
+ "^0.1.0"
71
+ ]
52
72
  },
53
73
  "role_narrative": {
54
74
  "description": "Free-text description of the agent's role within a fleet. Differentiates agents that share the same `type` slug (e.g. multiple code-assistants playing different roles like manager, lead author, debugger, throwaway). Used by L6 to answer 'who should I ask about X?' style queries.",
@@ -58,7 +78,7 @@
58
78
  "Agentic manager and code-assistant. Coordinates the agent fleet, reviews PRs, and consults on solutions.",
59
79
  "Lead code-assistant. Organizes project code and executes prime code. Consults with Claude on solutions, problems, and issues via PR or Slack #agents channel.",
60
80
  "Code-assistant invoked for debugging, issues, quick fixes, and short-task throwaway sessions.",
61
- "General-purpose RADLAB assistant with deep project memory."
81
+ "General-purpose personal assistant with deep project memory."
62
82
  ]
63
83
  }
64
84
  }
@@ -78,19 +98,44 @@
78
98
  "uniqueItems": true,
79
99
  "maxItems": 64,
80
100
  "examples": [
81
- ["code-read", "code-write", "web-search", "image-analysis"]
101
+ [
102
+ "code-read",
103
+ "code-write",
104
+ "web-search",
105
+ "image-analysis"
106
+ ]
82
107
  ]
83
108
  },
84
109
  "recent_sessions": {
85
110
  "description": "Rolling window of recent sessions. Typical retention: 30 days or 100 sessions, whichever is greater. Older sessions should be rolled up into L3/L4 personal memory and omitted from L5.",
86
111
  "type": "array",
87
- "items": { "$ref": "#/$defs/Session" },
112
+ "items": {
113
+ "$ref": "#/$defs/Session"
114
+ },
88
115
  "maxItems": 500
89
116
  },
90
117
  "known_entities": {
91
118
  "description": "The glossary surface. Each entity is something this agent knows about and can provide context on. L6 uses this for cross-agent entity lookup. Respect visibility_policy when emitting.",
92
119
  "type": "array",
93
- "items": { "$ref": "#/$defs/Entity" },
120
+ "items": {
121
+ "$ref": "#/$defs/Entity"
122
+ },
123
+ "maxItems": 1000
124
+ },
125
+ "known_workstreams": {
126
+ "description": "Ongoing multi-session initiatives, distinct from a single dated Session and from a named glossary Entity. A workstream has a status and accrues sessions/entities over time. L6 uses this to answer 'what's currently in flight?' style queries.",
127
+ "type": "array",
128
+ "items": {
129
+ "$ref": "#/$defs/Workstream"
130
+ },
131
+ "maxItems": 200
132
+ },
133
+ "notes": {
134
+ "description": "Freestanding unstructured notes not tied to a specific named entity or a single session's action log. Closer to a journal entry than a glossary term.",
135
+ "type": "array",
136
+ "items": {
137
+ "$ref": "#/$defs/Note"
138
+ },
94
139
  "maxItems": 1000
95
140
  },
96
141
  "visibility_policy": {
@@ -103,13 +148,25 @@
103
148
  "private_tags": {
104
149
  "description": "Entity tags that auto-mark the entity as private (overriding any explicit visibility setting).",
105
150
  "type": "array",
106
- "items": { "type": "string" },
107
- "examples": [["personal", "financial", "credential", "health", "family"]]
151
+ "items": {
152
+ "type": "string"
153
+ },
154
+ "examples": [
155
+ [
156
+ "personal",
157
+ "financial",
158
+ "credential",
159
+ "health",
160
+ "family"
161
+ ]
162
+ ]
108
163
  },
109
164
  "team_tags": {
110
165
  "description": "Entity tags that mark entities as team-visibility (shared with team L6 but not public).",
111
166
  "type": "array",
112
- "items": { "type": "string" }
167
+ "items": {
168
+ "type": "string"
169
+ }
113
170
  }
114
171
  }
115
172
  }
@@ -117,17 +174,31 @@
117
174
  "$defs": {
118
175
  "Visibility": {
119
176
  "type": "string",
120
- "enum": ["public", "team", "private"],
177
+ "enum": [
178
+ "public",
179
+ "team",
180
+ "private"
181
+ ],
121
182
  "description": "public = published to all L6 stores | team = team L6 only | private = local L6 only, never federated outward"
122
183
  },
123
184
  "Session": {
124
185
  "type": "object",
125
- "required": ["date"],
186
+ "required": [
187
+ "date"
188
+ ],
126
189
  "properties": {
127
190
  "date": {
128
- "description": "ISO 8601 date the session occurred (date-only, no time).",
191
+ "description": "ISO 8601 date the session occurred (date-only, no time). An empty string means the native store carried no recognisable timestamp; readers MUST NOT substitute the current date, which would make a manifest look more current than reality. The pattern rejects impossible months/days (e.g. 2026-99-99) even under pattern-only validators; the anyOf format branch additionally rejects impossible calendar dates the pattern cannot express (e.g. Feb 30) wherever format checking is enabled.",
129
192
  "type": "string",
130
- "format": "date"
193
+ "pattern": "^(\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))?$",
194
+ "anyOf": [
195
+ {
196
+ "format": "date"
197
+ },
198
+ {
199
+ "const": ""
200
+ }
201
+ ]
131
202
  },
132
203
  "cwd": {
133
204
  "description": "Working directory of the session. Optional but highly useful for developer-tool participants.",
@@ -137,26 +208,37 @@
137
208
  "project_focus": {
138
209
  "description": "Entity IDs the session focused on. Cross-references known_entities.",
139
210
  "type": "array",
140
- "items": { "type": "string" }
211
+ "items": {
212
+ "type": "string"
213
+ }
141
214
  },
142
215
  "key_actions": {
143
216
  "description": "Brief list of what happened. 1-5 short strings.",
144
217
  "type": "array",
145
- "items": { "type": "string", "maxLength": 256 },
218
+ "items": {
219
+ "type": "string",
220
+ "maxLength": 256
221
+ },
146
222
  "maxItems": 10
147
223
  },
148
224
  "files_touched": {
149
225
  "description": "Paths or patterns modified during the session. Optional.",
150
226
  "type": "array",
151
- "items": { "type": "string" },
227
+ "items": {
228
+ "type": "string"
229
+ },
152
230
  "maxItems": 50
153
231
  },
154
- "visibility": { "$ref": "#/$defs/Visibility" }
232
+ "visibility": {
233
+ "$ref": "#/$defs/Visibility"
234
+ }
155
235
  }
156
236
  },
157
237
  "Entity": {
158
238
  "type": "object",
159
- "required": ["name"],
239
+ "required": [
240
+ "name"
241
+ ],
160
242
  "properties": {
161
243
  "name": {
162
244
  "description": "Human-readable entity name. Used for L0 keyword matching.",
@@ -172,7 +254,9 @@
172
254
  "aliases": {
173
255
  "description": "Alternative names or abbreviations that should also match for L0 detection.",
174
256
  "type": "array",
175
- "items": { "type": "string" },
257
+ "items": {
258
+ "type": "string"
259
+ },
176
260
  "maxItems": 16
177
261
  },
178
262
  "summary": {
@@ -182,28 +266,133 @@
182
266
  },
183
267
  "last_touched": {
184
268
  "type": "string",
185
- "format": "date"
269
+ "format": "date",
270
+ "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
186
271
  },
187
272
  "valid_from": {
188
273
  "description": "ISO 8601 date this entity became active in the agent's worldview. When omitted, the entity has either always been valid or its start date is unknown. L6 queries can filter on this to answer 'what was active in Q1 2026?' style questions. Inspired by Zep's Graphiti temporal validity model.",
189
274
  "type": "string",
190
- "format": "date"
275
+ "format": "date",
276
+ "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
191
277
  },
192
278
  "valid_to": {
193
279
  "description": "ISO 8601 date this entity stopped being active. Participants typically populate this when an entity is tagged 'archived' or 'canceled'. Absent (or null) means the entity is still active as of last_updated. Federation queries that filter by current time treat missing valid_to as 'still valid'.",
194
280
  "type": "string",
195
- "format": "date"
281
+ "format": "date",
282
+ "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
196
283
  },
197
284
  "tags": {
198
285
  "description": "Free-text tags. Used for visibility_policy.private_tags/team_tags matching and for filtering in L6 queries.",
199
286
  "type": "array",
200
- "items": { "type": "string" }
287
+ "items": {
288
+ "type": "string"
289
+ }
201
290
  },
202
291
  "visibility": {
203
292
  "$ref": "#/$defs/Visibility",
204
293
  "description": "Overrides visibility_policy.default for this entity. Private entities MUST be omitted from federated L6 stores."
205
294
  }
206
295
  }
296
+ },
297
+ "Workstream": {
298
+ "type": "object",
299
+ "required": [
300
+ "name",
301
+ "status"
302
+ ],
303
+ "properties": {
304
+ "name": {
305
+ "description": "Human-readable workstream name.",
306
+ "type": "string",
307
+ "minLength": 1,
308
+ "maxLength": 128
309
+ },
310
+ "summary": {
311
+ "description": "Short description of what this workstream is (~1-3 sentences, <500 chars).",
312
+ "type": "string",
313
+ "maxLength": 2000
314
+ },
315
+ "status": {
316
+ "description": "Current lifecycle state.",
317
+ "type": "string",
318
+ "enum": [
319
+ "active",
320
+ "paused",
321
+ "done",
322
+ "archived"
323
+ ]
324
+ },
325
+ "started": {
326
+ "description": "ISO 8601 date this workstream began.",
327
+ "type": "string",
328
+ "format": "date",
329
+ "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
330
+ },
331
+ "last_touched": {
332
+ "description": "ISO 8601 date of the most recent activity on this workstream.",
333
+ "type": "string",
334
+ "format": "date",
335
+ "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
336
+ },
337
+ "related_entities": {
338
+ "description": "Entity names this workstream references. Cross-references known_entities.",
339
+ "type": "array",
340
+ "items": {
341
+ "type": "string"
342
+ },
343
+ "maxItems": 32
344
+ },
345
+ "tags": {
346
+ "description": "Free-text tags. Used for visibility_policy matching and L6 query filtering.",
347
+ "type": "array",
348
+ "items": {
349
+ "type": "string"
350
+ }
351
+ },
352
+ "visibility": {
353
+ "$ref": "#/$defs/Visibility",
354
+ "description": "Overrides visibility_policy.default for this workstream. Private workstreams MUST be omitted from federated L6 stores."
355
+ }
356
+ }
357
+ },
358
+ "Note": {
359
+ "type": "object",
360
+ "required": [
361
+ "date",
362
+ "text"
363
+ ],
364
+ "properties": {
365
+ "date": {
366
+ "description": "ISO 8601 date the note was written.",
367
+ "type": "string",
368
+ "format": "date",
369
+ "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
370
+ },
371
+ "text": {
372
+ "description": "Freeform note content. Larger than a Session.key_actions line -- this is a journal entry, not an action log.",
373
+ "type": "string",
374
+ "maxLength": 4000
375
+ },
376
+ "related_entities": {
377
+ "description": "Entity names this note references. Cross-references known_entities. Optional.",
378
+ "type": "array",
379
+ "items": {
380
+ "type": "string"
381
+ },
382
+ "maxItems": 16
383
+ },
384
+ "tags": {
385
+ "description": "Free-text tags. Used for visibility_policy matching and L6 query filtering.",
386
+ "type": "array",
387
+ "items": {
388
+ "type": "string"
389
+ }
390
+ },
391
+ "visibility": {
392
+ "$ref": "#/$defs/Visibility",
393
+ "description": "Overrides visibility_policy.default for this note. Private notes MUST be omitted from federated L6 stores."
394
+ }
395
+ }
207
396
  }
208
397
  }
209
398
  }
@@ -6,7 +6,7 @@
6
6
  "input": {
7
7
  "spec_version": "0.1",
8
8
  "agent": {
9
- "id": "clyde",
9
+ "id": "alpha-agent",
10
10
  "type": "note-capture",
11
11
  "instance": null
12
12
  },
@@ -19,7 +19,7 @@
19
19
  "expected": {
20
20
  "spec_version": "0.1",
21
21
  "agent": {
22
- "id": "clyde",
22
+ "id": "alpha-agent",
23
23
  "type": "note-capture"
24
24
  },
25
25
  "last_updated": "2026-06-29T12:00:00+00:00"
@@ -30,7 +30,7 @@
30
30
  "input": {
31
31
  "spec_version": "0.1",
32
32
  "agent": {
33
- "id": "clair",
33
+ "id": "beta-agent",
34
34
  "type": "note-capture"
35
35
  },
36
36
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -53,7 +53,7 @@
53
53
  "expected": {
54
54
  "spec_version": "0.1",
55
55
  "agent": {
56
- "id": "clair",
56
+ "id": "beta-agent",
57
57
  "type": "note-capture"
58
58
  },
59
59
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -79,7 +79,7 @@
79
79
  "input": {
80
80
  "spec_version": "0.1",
81
81
  "agent": {
82
- "id": "clyde",
82
+ "id": "alpha-agent",
83
83
  "type": "note-capture"
84
84
  },
85
85
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -96,7 +96,7 @@
96
96
  "expected": {
97
97
  "spec_version": "0.1",
98
98
  "agent": {
99
- "id": "clyde",
99
+ "id": "alpha-agent",
100
100
  "type": "note-capture"
101
101
  },
102
102
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -114,7 +114,7 @@
114
114
  "input": {
115
115
  "spec_version": "0.1",
116
116
  "agent": {
117
- "id": "clyde",
117
+ "id": "alpha-agent",
118
118
  "type": "note-capture"
119
119
  },
120
120
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -123,7 +123,7 @@
123
123
  "expected": {
124
124
  "spec_version": "0.1",
125
125
  "agent": {
126
- "id": "clyde",
126
+ "id": "alpha-agent",
127
127
  "type": "note-capture"
128
128
  },
129
129
  "last_updated": "2026-06-29T12:00:00+00:00",
@@ -139,7 +139,7 @@
139
139
  "agent": {
140
140
  "id": "claude-code",
141
141
  "type": "code-assistant",
142
- "instance": "pc-threadripper",
142
+ "instance": "workstation-01",
143
143
  "spec_version_compat": ">=0.1",
144
144
  "role_narrative": "Lead code-assistant."
145
145
  },
@@ -196,7 +196,7 @@
196
196
  "agent": {
197
197
  "id": "claude-code",
198
198
  "type": "code-assistant",
199
- "instance": "pc-threadripper",
199
+ "instance": "workstation-01",
200
200
  "spec_version_compat": ">=0.1",
201
201
  "role_narrative": "Lead code-assistant."
202
202
  },
@@ -1,5 +1,5 @@
1
1
  {
2
- "_doc": "Cross-impl federation leak-audit parity. Oracle = core.leak_audit.audit_manifest. Each case feeds `manifest` through the auditor; `expected_findings` pins [{kind, location}] in the oracle's emission order (visibility entities, visibility sessions, then the total credential walk). kind in {'credential','visibility'}; location is a json-path like 'known_entities[0].summary'. audit_manifest NEVER raises -- garbage manifests yield []. Credential cases use keyword-shaped triggers only; no token literal is committed.",
2
+ "_doc": "Cross-impl federation leak-audit parity. Oracle = bourdon.core.leak_audit.audit_manifest. Each case feeds `manifest` through the auditor; `expected_findings` pins [{kind, location}] in the oracle's emission order (visibility entities, visibility sessions, then the total credential walk). kind in {'credential','visibility'}; location is a json-path like 'known_entities[0].summary'. audit_manifest NEVER raises -- garbage manifests yield []. Credential cases use keyword-shaped triggers only; no token literal is committed.",
3
3
  "audit_schema_version": "federation-leak-audit/v1",
4
4
  "private_tag_families": [
5
5
  "credential",