Skip to content

[codex] Add Loominary local archive service#32

Open
Coldaine wants to merge 1 commit into
Laumss:mainfrom
Coldaine:codex/loom-sprint-2-local-service
Open

[codex] Add Loominary local archive service#32
Coldaine wants to merge 1 commit into
Laumss:mainfrom
Coldaine:codex/loom-sprint-2-local-service

Conversation

@Coldaine
Copy link
Copy Markdown

@Coldaine Coldaine commented May 9, 2026

What changed

  • added a versioned Loominary local archive contract for conversations, branches, annotations, and captured context
  • added a small local HTTP service with MCP-style tool calls for list/search/fetch operations
  • added fixture archives and node-based tests covering the core contract, search, auth, and query flows
  • documented the trust model, index lifecycle, and consumer examples for other local AI tools

Why

Sprint 2 called for the first real local integration surface promised in the README. This PR turns that promise into a narrow, provider-agnostic local API that other tools can consume.

Validation

  • npm run test:local-service

Copilot AI review requested due to automatic review settings May 9, 2026 04:04
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a versioned “local archive” contract and a small loopback-oriented HTTP service (including an MCP-style JSON-RPC tool surface) so other local AI tools can list/search/fetch Loominary conversation + context data from disk.

Changes:

  • Added archive contract validation/loading + in-memory search indexing and branch-tree projection.
  • Added a local HTTP server with REST endpoints and an MCP tools/list + tools/call surface.
  • Added fixture archives, Node-based tests, and documentation for consumers and the trust/auth model.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/http-service.test.mjs Exercises REST + MCP endpoints and token/unauth behavior against fixtures.
tests/archive-loader.test.mjs Tests archive loading, search behavior, and branch tree projection.
tests/fixtures/archive-v1/manifest.json Fixture manifest for the v1 archive layout/trust model.
tests/fixtures/archive-v1/conversations/conv-alpha.json Fixture conversation including branching.
tests/fixtures/archive-v1/conversations/conv-beta.json Fixture conversation for search/list coverage.
tests/fixtures/archive-v1/contexts/conv-alpha.json Fixture captured context (project + memories).
tests/fixtures/archive-v1/annotations.json Fixture tags + favorites annotations.
server/service/mcpSurface.mjs MCP JSON-RPC handler exposing archive operations as tools.
server/service/httpServer.mjs Local HTTP server with REST routes + /mcp POST handling + auth gate.
server/loominary-local-service.mjs CLI entrypoint to load an archive and start the local service.
server/archive/searchIndex.mjs Builds/searches a simple in-memory full-text index + excerpt building.
server/archive/loadArchive.mjs Loads and validates archive files; provides LoomArchive query APIs.
server/archive/contract.mjs Schema version constants + contract validation helpers.
docs/local-service-consumer-guide.md Consumer-facing guide with REST/MCP examples and expectations.
docs/local-archive-contract.md Formal v1 archive contract documentation and trust/index lifecycle notes.
README.md Updates README to point to the new local integration surface + docs.
package.json Adds local-service and test:local-service scripts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (!manifest.layout || typeof manifest.layout !== 'object') {
throw new Error('Archive manifest is missing layout.');
}

Comment on lines +9 to +18
function parseArguments(args) {
if (!args) {
return {};
}

if (typeof args === 'string') {
return JSON.parse(args);
}

return args;
Comment on lines +21 to +28
async function readJsonBody(request) {
const chunks = [];
for await (const chunk of request) {
chunks.push(chunk);
}

const body = Buffer.concat(chunks).toString('utf8');
return body ? JSON.parse(body) : {};
Comment thread README.md
## Contributing

A contributing guide and development roadmap are on the way. In the meantime, if you have any idea, please [open an discussion](https://github.com/Laumss/Loominary/discussions). No newline at end of file
A contributing guide and development roadmap are on the way. In the meantime, if you have any idea, please [open an discussion](https://github.com/Laumss/Loominary/discussions).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants