Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
`newer_db` / `unstamped` / `no_schema`) is unchanged.

### Changed
- The published `atomicmemory-core migrate` command now calls the
programmatic migration API directly, so npm installs can run the documented
migration command without the command word being reparsed as a migration
option.
- **BREAKING**: All API endpoints are now mounted under `/v1/` (e.g. `POST /v1/memories/ingest`, `PUT /v1/agents/trust`). Update clients to prefix requests with `/v1`. The unversioned `/health` liveness probe is unchanged.
- Phase 2 removes `src/db/schema.sql`; the migrations folder is now the
single source of truth. The build-time `dist/db/schema-sha256.json`
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@atomicmemory/core",
"version": "1.0.5",
"version": "1.0.6",
"description": "Open-source memory engine for AI applications — semantic retrieval, AUDN mutation, and contradiction-safe claim versioning.",
"type": "module",
"license": "Apache-2.0",
Expand Down
63 changes: 63 additions & 0 deletions packages/core/src/__tests__/bin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Tests for the published `atomicmemory-core` npm binary entry point.
*
* These cover command dispatch only; migration behavior itself lives in the
* migration API test suite. The key regression guard is that `migrate` must
* call the programmatic API directly instead of importing the standalone
* migration CLI, which reparses the original process argv.
*/

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const mocks = vi.hoisted(() => ({
migrate: vi.fn(),
}));

vi.mock('../db/migration-api.js', () => ({
migrate: mocks.migrate,
}));

vi.mock('../db/migrate.js', () => {
throw new Error('standalone migration CLI must not be imported by bin.ts');
});

import { parseCliArgs, runCommand } from '../bin.js';

describe('core CLI entry point', () => {
beforeEach(() => {
vi.clearAllMocks();
vi.spyOn(console, 'log').mockImplementation(() => {});
mocks.migrate.mockResolvedValue({
ranSchemaSql: true,
schemaVersion: {
sdkVersion: '1.0.6',
schemaSha256: 'abcdef1234567890',
appliedAt: new Date('2026-05-20T00:00:00.000Z'),
notes: null,
},
reconciledEmbeddingDimension: false,
});
});

afterEach(() => {
vi.restoreAllMocks();
});

it('parses the local migrate command without passing command text onward', () => {
expect(parseCliArgs(['migrate', '--profile', 'local'])).toEqual({
command: 'migrate',
help: false,
profile: 'local',
});
});

it('runs migrations through the programmatic API', async () => {
await runCommand('migrate');

expect(mocks.migrate).toHaveBeenCalledOnce();
expect(mocks.migrate).toHaveBeenCalledWith();
expect(console.log).toHaveBeenCalledWith(
'[migrate] Migration complete (ranSchemaSql=true, version=1.0.6, sha=abcdef123456..., reconciledEmbeddingDimension=false).',
);
});
});
12 changes: 10 additions & 2 deletions packages/core/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,20 @@ function assertLocalProfileReady(): void {
);
}

async function runCommand(command: CommandName): Promise<void> {
export async function runCommand(command: CommandName): Promise<void> {
if (command === 'start') {
await import('./server.js');
return;
}
await import('./db/migrate.js');
const { migrate } = await import('./db/migration-api.js');
const result = await migrate();
console.log(
`[migrate] Migration complete ` +
`(ranSchemaSql=${result.ranSchemaSql}, ` +
`version=${result.schemaVersion.sdkVersion}, ` +
`sha=${result.schemaVersion.schemaSha256.slice(0, 12)}..., ` +
`reconciledEmbeddingDimension=${result.reconciledEmbeddingDimension}).`,
);
}

async function main(argv: string[]): Promise<void> {
Expand Down
Loading