import { describe, expect, it } from 'vitest' import { ABOUT_YOU_MEMORY_CATEGORY_ID, ABOUT_YOU_MEMORY_CATEGORY_SYSTEM_KEY, memoryApplicationCommandContracts, memoryAgentRememberMcpOutputSchema, memoryAgentRememberResultSchema, memoryAgentRememberRequestSchema, memoryAgentResultSchema, memoryAgentSearchRequestSchema, memorySnapshotSchema} from './memory' describe('memory contracts', () => { const snapshot = { revision: 3, enabled: true, categories: [ { id: ABOUT_YOU_MEMORY_CATEGORY_ID, systemKey: ABOUT_YOU_MEMORY_CATEGORY_SYSTEM_KEY, autoRecall: true, revision: 1, createdAt: 1, updatedAt: 2, entries: [] }, { id: 'category-1', name: 'Experiments', guidance: 'Keep expensive debugging results here.', autoRecall: false, revision: 2, createdAt: 2, updatedAt: 3, entries: [ { id: 'entry-1', categoryId: 'category-1', categoryName: 'Experiments', projectId: 'project-1', projectName: 'Microscopy', content: 'The microscopy pipeline expects TIFF input.', origin: 'agent' as const, revision: 1, createdAt: 3, updatedAt: 3 } ] } ], projects: [ { projectId: 'project-1', name: 'Microscopy', archived: false, entries: [ { id: 'entry-1', categoryId: 'category-1', categoryName: 'Experiments', projectId: 'project-1', projectName: 'Microscopy', content: 'The microscopy pipeline expects TIFF input.', origin: 'agent' as const, revision: 1, createdAt: 3, updatedAt: 3 } ] } ] } it('accepts a snapshot without exposing persisted comparison keys or provenance identifiers', () => { expect(memorySnapshotSchema.parse(snapshot)).toEqual(snapshot) expect(() => memorySnapshotSchema.parse({ ...snapshot, categories: [ { ...snapshot.categories[1], nameKey: 'experiments', entries: [{ ...snapshot.categories[1].entries[0], sourceSessionId: 'session-secret' }] } ] }) ).toThrow() }) it('strictly validates category, entry, settings, and clear-all commands', () => { expect( memoryApplicationCommandContracts.createCategory.args.parse([ { name: 'Preferences', guidance: '', autoRecall: true } ]) ).toEqual([{ name: 'Preferences', guidance: '', autoRecall: true }]) expect( memoryApplicationCommandContracts.createEntry.args.parse([ { categoryId: ABOUT_YOU_MEMORY_CATEGORY_ID, content: 'Uses metric units.' } ]) ).toEqual([{ categoryId: ABOUT_YOU_MEMORY_CATEGORY_ID, content: 'Uses metric units.' }]) expect( memoryApplicationCommandContracts.createEntry.args.parse([ { projectId: 'project-1', categoryId: null, content: 'Use channel A.' } ]) ).toEqual([{ projectId: 'project-1', categoryId: null, content: 'Use channel A.' }]) expect(memoryApplicationCommandContracts.setEnabled.args.parse([{ enabled: false }])).toEqual([ { enabled: false } ]) expect(memoryApplicationCommandContracts.clearAll.args.parse([])).toEqual([]) expect(() => memoryApplicationCommandContracts.createCategory.args.parse([ { name: 'Preferences', guidance: '', autoRecall: true, systemKey: 'about-you' } ]) ).toThrow() }) it('shares strict Agent tool request validation with the host RPC boundary', () => { expect(() => memoryAgentRememberRequestSchema.parse({ categoryId: 'category-1', content: ' ' }) ).toThrow() expect(memoryAgentSearchRequestSchema.parse({ query: 'microscopy', limit: 4 })).toEqual({ query: 'microscopy', limit: 4 }) expect( memoryAgentRememberRequestSchema.parse({ content: 'Use channel A for this project.', categoryId: 'category-1', analysis: { scope: 'project', durability: 'cross-session', evidence: 'project-observed', subject: 'Microscopy channel', reason: 'Future sessions need the working channel.', categoryReason: 'This is an experimental setup detail.' } }) ).toMatchObject({ analysis: { scope: 'project', durability: 'cross-session' } }) expect(() => memoryAgentRememberRequestSchema.parse({ content: 'Use channel A for this project.', categoryId: 'category-1', analysis: { scope: 'project', durability: 'cross-session', evidence: 'project-observed', subject: 'Microscopy channel', reason: 'Future sessions need the working channel.' } }) ).toThrow() }) it('validates revision and bounded provenance on Agent memory results', () => { expect( memoryAgentResultSchema.parse({ id: 'entry-1', categoryId: 'category-1', categoryName: 'Research', scope: 'project', content: 'Use channel A.', revision: 2, provenance: { origin: 'agent', agentId: 'specialist-1' }, updatedAt: 3 }) ).toMatchObject({ revision: 2, provenance: { origin: 'agent', agentId: 'specialist-1' } }) expect(() => memoryAgentResultSchema.parse({ id: 'entry-1', categoryId: 'category-1', categoryName: 'Research', scope: 'project', content: 'Use channel A.', revision: 2, provenance: { origin: 'agent', sessionId: 'private-session' }, updatedAt: 3 }) ).toThrow() }) it('defines structured created, existing, and non-retryable rejected remember results', () => { expect( memoryAgentRememberResultSchema.parse({ status: 'rejected', retryable: false, code: 'invalid_analysis', reason: 'The note does not describe durable project knowledge.' }) ).toMatchObject({ status: 'rejected', retryable: false }) }) it('keeps every remember result branch strict in the MCP object schema', () => { const memory = { id: 'entry-1', categoryId: null, categoryName: null, scope: 'project', content: 'Use channel A.', revision: 2, provenance: { origin: 'agent', agentId: 'specialist-1' }, updatedAt: 3 } expect(memoryAgentRememberMcpOutputSchema.parse({ status: 'created', memory })).toMatchObject({ status: 'created' }) expect(memoryAgentRememberMcpOutputSchema.parse({ status: 'existing', memory })).toMatchObject({ status: 'existing' }) expect( memoryAgentRememberMcpOutputSchema.parse({ status: 'rejected', retryable: false, code: 'invalid_analysis', reason: 'The note does not describe durable project knowledge.' }) ).toMatchObject({ status: 'rejected', retryable: false }) expect(() => memoryAgentRememberMcpOutputSchema.parse({ status: 'created' })).toThrow() expect(() => memoryAgentRememberMcpOutputSchema.parse({ status: 'existing', memory, retryable: false, code: 'invalid_analysis', reason: 'A successful result cannot carry rejection fields.' }) ).toThrow() expect(() => memoryAgentRememberMcpOutputSchema.parse({ status: 'rejected', memory, retryable: false, code: 'invalid_analysis', reason: 'A rejected result cannot carry memory.' }) ).toThrow() })})
import { describe, expect, it } from 'vitest'
import {
ABOUT_YOU_MEMORY_CATEGORY_ID,
ABOUT_YOU_MEMORY_CATEGORY_SYSTEM_KEY,
memoryApplicationCommandContracts,
memoryAgentRememberMcpOutputSchema,
memoryAgentRememberResultSchema,
memoryAgentRememberRequestSchema,
memoryAgentResultSchema,
memoryAgentSearchRequestSchema,
memorySnapshotSchema
} from './memory'
describe('memory contracts', () => {
const snapshot = {
revision: 3,
enabled: true,
categories: [
{
id: ABOUT_YOU_MEMORY_CATEGORY_ID,
systemKey: ABOUT_YOU_MEMORY_CATEGORY_SYSTEM_KEY,
autoRecall: true,
revision: 1,
createdAt: 1,
updatedAt: 2,
entries: []
},
{
id: 'category-1',
name: 'Experiments',
guidance: 'Keep expensive debugging results here.',
autoRecall: false,
revision: 2,
createdAt: 2,
updatedAt: 3,
entries: [
{
id: 'entry-1',
categoryId: 'category-1',
categoryName: 'Experiments',
projectId: 'project-1',
projectName: 'Microscopy',
content: 'The microscopy pipeline expects TIFF input.',
origin: 'agent' as const,
revision: 1,
createdAt: 3,
updatedAt: 3
}
]
}
],
projects: [
{
projectId: 'project-1',
name: 'Microscopy',
archived: false,
entries: [
{
id: 'entry-1',
categoryId: 'category-1',
categoryName: 'Experiments',
projectId: 'project-1',
projectName: 'Microscopy',
content: 'The microscopy pipeline expects TIFF input.',
origin: 'agent' as const,
revision: 1,
createdAt: 3,
updatedAt: 3
}
]
}
]
}
it('accepts a snapshot without exposing persisted comparison keys or provenance identifiers', () => {
expect(memorySnapshotSchema.parse(snapshot)).toEqual(snapshot)
expect(() =>
memorySnapshotSchema.parse({
...snapshot,
categories: [
{
...snapshot.categories[1],
nameKey: 'experiments',
entries: [{ ...snapshot.categories[1].entries[0], sourceSessionId: 'session-secret' }]
}
]
})
).toThrow()
})
it('strictly validates category, entry, settings, and clear-all commands', () => {
expect(
memoryApplicationCommandContracts.createCategory.args.parse([
{ name: 'Preferences', guidance: '', autoRecall: true }
])
).toEqual([{ name: 'Preferences', guidance: '', autoRecall: true }])
expect(
memoryApplicationCommandContracts.createEntry.args.parse([
{ categoryId: ABOUT_YOU_MEMORY_CATEGORY_ID, content: 'Uses metric units.' }
])
).toEqual([{ categoryId: ABOUT_YOU_MEMORY_CATEGORY_ID, content: 'Uses metric units.' }])
expect(
memoryApplicationCommandContracts.createEntry.args.parse([
{ projectId: 'project-1', categoryId: null, content: 'Use channel A.' }
])
).toEqual([{ projectId: 'project-1', categoryId: null, content: 'Use channel A.' }])
expect(memoryApplicationCommandContracts.setEnabled.args.parse([{ enabled: false }])).toEqual([
{ enabled: false }
])
expect(memoryApplicationCommandContracts.clearAll.args.parse([])).toEqual([])
expect(() =>
memoryApplicationCommandContracts.createCategory.args.parse([
{ name: 'Preferences', guidance: '', autoRecall: true, systemKey: 'about-you' }
])
).toThrow()
})
it('shares strict Agent tool request validation with the host RPC boundary', () => {
expect(() =>
memoryAgentRememberRequestSchema.parse({ categoryId: 'category-1', content: ' ' })
).toThrow()
expect(memoryAgentSearchRequestSchema.parse({ query: 'microscopy', limit: 4 })).toEqual({
query: 'microscopy',
limit: 4
})
expect(
memoryAgentRememberRequestSchema.parse({
content: 'Use channel A for this project.',
categoryId: 'category-1',
analysis: {
scope: 'project',
durability: 'cross-session',
evidence: 'project-observed',
subject: 'Microscopy channel',
reason: 'Future sessions need the working channel.',
categoryReason: 'This is an experimental setup detail.'
}
})
).toMatchObject({ analysis: { scope: 'project', durability: 'cross-session' } })
expect(() =>
memoryAgentRememberRequestSchema.parse({
content: 'Use channel A for this project.',
categoryId: 'category-1',
analysis: {
scope: 'project',
durability: 'cross-session',
evidence: 'project-observed',
subject: 'Microscopy channel',
reason: 'Future sessions need the working channel.'
}
})
).toThrow()
})
it('validates revision and bounded provenance on Agent memory results', () => {
expect(
memoryAgentResultSchema.parse({
id: 'entry-1',
categoryId: 'category-1',
categoryName: 'Research',
scope: 'project',
content: 'Use channel A.',
revision: 2,
provenance: { origin: 'agent', agentId: 'specialist-1' },
updatedAt: 3
})
).toMatchObject({ revision: 2, provenance: { origin: 'agent', agentId: 'specialist-1' } })
expect(() =>
memoryAgentResultSchema.parse({
id: 'entry-1',
categoryId: 'category-1',
categoryName: 'Research',
scope: 'project',
content: 'Use channel A.',
revision: 2,
provenance: { origin: 'agent', sessionId: 'private-session' },
updatedAt: 3
})
).toThrow()
})
it('defines structured created, existing, and non-retryable rejected remember results', () => {
expect(
memoryAgentRememberResultSchema.parse({
status: 'rejected',
retryable: false,
code: 'invalid_analysis',
reason: 'The note does not describe durable project knowledge.'
})
).toMatchObject({ status: 'rejected', retryable: false })
})
it('keeps every remember result branch strict in the MCP object schema', () => {
const memory = {
id: 'entry-1',
categoryId: null,
categoryName: null,
scope: 'project',
content: 'Use channel A.',
revision: 2,
provenance: { origin: 'agent', agentId: 'specialist-1' },
updatedAt: 3
}
expect(memoryAgentRememberMcpOutputSchema.parse({ status: 'created', memory })).toMatchObject({
status: 'created'
})
expect(memoryAgentRememberMcpOutputSchema.parse({ status: 'existing', memory })).toMatchObject({
status: 'existing'
})
expect(
memoryAgentRememberMcpOutputSchema.parse({
status: 'rejected',
retryable: false,
code: 'invalid_analysis',
reason: 'The note does not describe durable project knowledge.'
})
).toMatchObject({ status: 'rejected', retryable: false })
expect(() => memoryAgentRememberMcpOutputSchema.parse({ status: 'created' })).toThrow()
expect(() =>
memoryAgentRememberMcpOutputSchema.parse({
status: 'existing',
memory,
retryable: false,
code: 'invalid_analysis',
reason: 'A successful result cannot carry rejection fields.'
})
).toThrow()
expect(() =>
memoryAgentRememberMcpOutputSchema.parse({
status: 'rejected',
memory,
retryable: false,
code: 'invalid_analysis',
reason: 'A rejected result cannot carry memory.'
})
).toThrow()
})
})