From 6bc43a795f8712cf20cac3faae1275b96520ee40 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Sun, 24 May 2026 05:42:44 -0500 Subject: [PATCH] docs: add memory and models section --- content/docs/familiars/index.mdx | 2 + content/docs/memory-models/anthropic.mdx | 31 +++++ .../docs/memory-models/episodic-memory.mdx | 31 +++++ content/docs/memory-models/index.mdx | 45 +++++++ content/docs/memory-models/local-models.mdx | 33 +++++ content/docs/memory-models/memory-search.mdx | 35 ++++++ content/docs/memory-models/memory.mdx | 41 +++++++ content/docs/memory-models/meta.json | 20 +++ content/docs/memory-models/models.mdx | 31 +++++ content/docs/memory-models/openai.mdx | 31 +++++ .../docs/memory-models/persistent-memory.mdx | 34 +++++ .../docs/memory-models/provider-boundary.mdx | 56 +++++++++ .../docs/memory-models/semantic-memory.mdx | 30 +++++ content/docs/memory-models/working-memory.mdx | 32 +++++ content/docs/meta.json | 2 +- content/docs/reference/migration-map.mdx | 2 + package.json | 3 +- scripts/check-memory-models-docs.mjs | 116 ++++++++++++++++++ 18 files changed, 573 insertions(+), 2 deletions(-) create mode 100644 content/docs/memory-models/anthropic.mdx create mode 100644 content/docs/memory-models/episodic-memory.mdx create mode 100644 content/docs/memory-models/index.mdx create mode 100644 content/docs/memory-models/local-models.mdx create mode 100644 content/docs/memory-models/memory-search.mdx create mode 100644 content/docs/memory-models/memory.mdx create mode 100644 content/docs/memory-models/meta.json create mode 100644 content/docs/memory-models/models.mdx create mode 100644 content/docs/memory-models/openai.mdx create mode 100644 content/docs/memory-models/persistent-memory.mdx create mode 100644 content/docs/memory-models/provider-boundary.mdx create mode 100644 content/docs/memory-models/semantic-memory.mdx create mode 100644 content/docs/memory-models/working-memory.mdx create mode 100644 scripts/check-memory-models-docs.mjs diff --git a/content/docs/familiars/index.mdx b/content/docs/familiars/index.mdx index 1e14c21..e532c40 100644 --- a/content/docs/familiars/index.mdx +++ b/content/docs/familiars/index.mdx @@ -8,3 +8,5 @@ import { HubCards } from '@/components/hub-cards'; The runtime primitives that own a familiar's state, attach to harnesses, and route work between channels. + +For continuity and provider boundaries, see [Memory + Models](/docs/memory-models/memory). diff --git a/content/docs/memory-models/anthropic.mdx b/content/docs/memory-models/anthropic.mdx new file mode 100644 index 0000000..798b9f0 --- /dev/null +++ b/content/docs/memory-models/anthropic.mdx @@ -0,0 +1,31 @@ +--- +title: "Anthropic" +summary: "Anthropic model access currently flows through the Claude Code harness, not the Coven daemon." +description: "Anthropic model access in Coven through Claude Code, including setup, doctor checks, and credential boundary." +read_when: + - Connecting Claude Code-backed work to Coven + - Debugging Claude auth failures under Coven +--- + +# Anthropic + +Anthropic model access currently flows through Claude Code. + +```bash +npm install -g @anthropic-ai/claude-code +claude doctor +coven doctor +coven run claude "polish this UI" +``` + +## Boundary + +Claude Code owns Anthropic provider credentials and model calls. Coven owns the session record, PTY supervision, attach/replay behavior, and event log. + +Coven does not read Anthropic API keys, OAuth state, or Claude Code credential stores. If Claude Code setup is incomplete, run `claude doctor` and retry. + +## Related + +- [Claude Code harness](/docs/harnesses/claude-code) +- [Provider boundary](/docs/memory-models/provider-boundary) +- [Models](/docs/memory-models/models) diff --git a/content/docs/memory-models/episodic-memory.mdx b/content/docs/memory-models/episodic-memory.mdx new file mode 100644 index 0000000..921c17e --- /dev/null +++ b/content/docs/memory-models/episodic-memory.mdx @@ -0,0 +1,31 @@ +--- +title: "Episodic Memory" +summary: "Episodic memory records specific events, sessions, decisions, outcomes, and evidence." +description: "Episodic memory for OpenCoven familiars: remembering concrete past work without flattening it into generic facts." +read_when: + - Recording what happened in a session + - Looking for previous decisions, merges, releases, or incidents +--- + +# Episodic Memory + +Episodic memory remembers specific events. It answers "what happened?" and "when did we decide that?" + +## Examples + +- A docs PR merged and production deployed. +- A daemon issue was traced to stale socket metadata. +- A release failed because a provider token expired. +- A design decision was made after comparing alternatives. + +## Relationship to the event log + +The session ledger and event log are the raw evidence. Episodic memory is the human-sized summary: enough detail to recover the story, with links or ids back to the source when useful. + +Do not replace evidence with vibes. A good episodic note names concrete dates, PRs, commits, commands, or symptoms when they matter. + +## Promotion + +Episodic memory can later become persistent memory when the lesson is durable. For example, "PR #6 deployed" is episodic; "docs PRs need red/green guards before merge" may become persistent process memory. + +See [Memory search](/docs/memory-models/memory-search) for recall patterns. diff --git a/content/docs/memory-models/index.mdx b/content/docs/memory-models/index.mdx new file mode 100644 index 0000000..b1b7729 --- /dev/null +++ b/content/docs/memory-models/index.mdx @@ -0,0 +1,45 @@ +--- +title: "Memory + Models" +summary: "How persistent familiars remember across sessions and reach model providers without making Coven a credential gateway." +description: "Overview of Coven memory layers, memory search, model access, provider boundaries, and current OpenAI/Anthropic/local model posture." +read_when: + - Designing continuity for a familiar + - Auditing whether Coven stores model credentials +--- + +import { Mermaid } from '@/components/mermaid'; + +# Memory + Models + +Memory is what turns a one-off harness session into a persistent familiar. Models are the provider side of that familiar's reasoning, but Coven does not become a model gateway. The durable runtime boundary is: Coven records sessions and events; clients/familiars derive memory from those events; harnesses own provider auth and model access. + + Ledger[(session ledger + event log)] + Ledger --> Memory[Memory layer] + Memory --> Working[Working memory] + Memory --> Persistent[Persistent memory] + Memory --> Episodic[Episodic memory] + Memory --> Semantic[Semantic memory] + Familiar[Familiar] --> Memory + Familiar --> Harness[Harness] + Harness --> Provider[Model provider] +`} /> + +## Section map + +- [Memory overview](/docs/memory-models/memory) defines the four memory layers. +- [Working memory](/docs/memory-models/working-memory) covers in-session context. +- [Persistent memory](/docs/memory-models/persistent-memory) covers durable facts and identity. +- [Episodic memory](/docs/memory-models/episodic-memory) covers specific sessions, decisions, and outcomes. +- [Semantic memory](/docs/memory-models/semantic-memory) covers embeddings and meaning-based recall. +- [Memory search](/docs/memory-models/memory-search) covers keyword and semantic lookup. +- [Models](/docs/memory-models/models) explains why Coven is not a model gateway. +- [Provider boundary](/docs/memory-models/provider-boundary) names the credential boundary. +- [OpenAI](/docs/memory-models/openai), [Anthropic](/docs/memory-models/anthropic), and [Local models](/docs/memory-models/local-models) cover provider-specific paths. + +## Related + +- [Session lifecycle](/docs/familiars/sessions) +- [Harness provider auth](/docs/harnesses/provider-auth) +- [Authentication and local access](/docs/reference/auth) diff --git a/content/docs/memory-models/local-models.mdx b/content/docs/memory-models/local-models.mdx new file mode 100644 index 0000000..65761f6 --- /dev/null +++ b/content/docs/memory-models/local-models.mdx @@ -0,0 +1,33 @@ +--- +title: "Local Models" +summary: "Local models are a future harness direction, not a daemon-owned provider shortcut." +description: "How local models should fit Coven through harnesses that talk to local runtimes such as Ollama or llama.cpp." +read_when: + - Planning offline or local-model support + - Deciding whether Coven should talk directly to a local model server +--- + +# Local Models + +Local models are a natural fit for Coven, but they should still arrive through the harness boundary. + +Examples of future local-model paths: + +- A harness CLI that talks to Ollama. +- A harness CLI that talks to llama.cpp. +- A custom adapter that runs a local model-backed agent process. + +## Current posture + +Local models are not a special daemon credential feature. The daemon should not grow provider-specific model routing just because the provider is local. + +The same rules apply: + +- Stable harness id. +- Fixed adapter command shape. +- Project-root and working-directory validation. +- PTY supervision. +- Session ledger and event log. +- No secret fields in the socket API. + +For adapter requirements, see [Custom adapters](/docs/harnesses/custom-adapters) and [Models](/docs/memory-models/models). diff --git a/content/docs/memory-models/memory-search.mdx b/content/docs/memory-models/memory-search.mdx new file mode 100644 index 0000000..b66fb95 --- /dev/null +++ b/content/docs/memory-models/memory-search.mdx @@ -0,0 +1,35 @@ +--- +title: "Memory Search" +summary: "Memory search combines keyword, semantic, and scoped recall without exposing unrestricted private history." +description: "How familiars and clients should search working, persistent, episodic, and semantic memory safely." +read_when: + - Designing a familiar recall feature + - Debugging why memory search returned too much or too little +--- + +# Memory Search + +Memory search is how a familiar finds relevant prior context. It should be scoped, attributable, and small enough to read. + +## Search modes + +| Mode | Good for | +| --- | --- | +| Keyword search | Exact filenames, commands, PR numbers, names, error strings. | +| Semantic search | Similar ideas, architecture patterns, repeated lessons. | +| Timeline search | Recent events and session chronology. | +| Manual pinned memory | Hard rules and durable preferences. | + +## Safety rules + +- Search only the memory scope the current surface is allowed to see. +- Return summaries with source references where possible. +- Prefer a few high-signal results over a large dump. +- Do not use search as permission to reveal private memory in shared contexts. +- Treat search hits as leads; read the source before acting. + +## Relationship to sessions + +The session ledger and event log are useful evidence sources, but not every event should enter memory search. Clients should index curated notes, summaries, and selected event text according to the familiar's privacy and retention rules. + +See [Episodic memory](/docs/memory-models/episodic-memory) and [Semantic memory](/docs/memory-models/semantic-memory). diff --git a/content/docs/memory-models/memory.mdx b/content/docs/memory-models/memory.mdx new file mode 100644 index 0000000..444fb21 --- /dev/null +++ b/content/docs/memory-models/memory.mdx @@ -0,0 +1,41 @@ +--- +title: "Memory" +summary: "The four-layer memory model for persistent familiars: working, persistent, episodic, and semantic." +description: "Memory overview for OpenCoven familiars and how memory relates to Coven sessions, event logs, and client-owned recall." +read_when: + - You need to explain how familiars remember + - You are choosing which memory layer a feature should write to +--- + +# Memory + +Coven's daemon records what happened. A familiar's memory layer decides what should be remembered, summarized, searched, and loaded into future sessions. + +The daemon does not enforce one memory backend. It gives clients a durable session ledger and event log. Familiar layers can build working, persistent, episodic, and semantic memory on top. + +## Four memory layers + +| Layer | Scope | Examples | +| --- | --- | --- | +| Working memory | One active session or task | Current goal, active files, constraints, recent turns. | +| Persistent memory | Cross-session durable facts | User preferences, familiar identity, project conventions. | +| Episodic memory | Specific events and outcomes | PR #6 merged, release succeeded, incident root cause found. | +| Semantic memory | Meaning-based recall | Similar past debugging patterns, docs topics, architecture concepts. | + +## What the daemon provides + +The daemon provides: + +- Session records. +- Append-only events. +- Project-rooted harness context. +- Attach and replay behavior. +- Local socket access for clients. + +Memory lives above that. A client can summarize a session into persistent memory, index event text into semantic memory, or load selected memories back into a familiar prompt. + +## Related + +- [Session lifecycle](/docs/familiars/sessions) +- [Memory search](/docs/memory-models/memory-search) +- [Familiars](/docs/familiars/sessions) diff --git a/content/docs/memory-models/meta.json b/content/docs/memory-models/meta.json new file mode 100644 index 0000000..a609d28 --- /dev/null +++ b/content/docs/memory-models/meta.json @@ -0,0 +1,20 @@ +{ + "title": "Memory + Models", + "description": "Memory layers, search, provider boundaries, and model access for persistent familiars.", + "root": true, + "icon": "LuBrainCircuit", + "pages": [ + "index", + "memory", + "working-memory", + "persistent-memory", + "episodic-memory", + "semantic-memory", + "memory-search", + "models", + "provider-boundary", + "openai", + "anthropic", + "local-models" + ] +} diff --git a/content/docs/memory-models/models.mdx b/content/docs/memory-models/models.mdx new file mode 100644 index 0000000..ab5425b --- /dev/null +++ b/content/docs/memory-models/models.mdx @@ -0,0 +1,31 @@ +--- +title: "Models" +summary: "Coven is not a model gateway. Harnesses own model provider access." +description: "Model access overview for Coven: OpenAI through Codex, Anthropic through Claude Code, local models through future harnesses, and no daemon credential ownership." +read_when: + - Auditing where model calls happen + - Deciding how a familiar should reach a provider +--- + +# Models + +Coven is not a model gateway. It does not store provider credentials, route model API calls, or mint provider tokens. A familiar reaches models through a harness. + +## Current model paths + +| Provider path | Current posture | +| --- | --- | +| OpenAI | Through the [Codex harness](/docs/harnesses/codex). | +| Anthropic | Through the [Claude Code harness](/docs/harnesses/claude-code). | +| Google | Future adapter direction; not current v0 support. | +| Local models | Future/local harness direction; not a daemon credential feature. | + +## What Coven sees + +Coven sees harness process output and exits. It does not see provider API requests unless the harness prints them. It does not need API keys to launch a session. + +## Client rule + +Clients should not pass model credentials into Coven. They should launch a harness whose provider auth is already complete and let the harness call the provider. + +For the exact credential boundary, see [Provider boundary](/docs/memory-models/provider-boundary) and [Harness provider auth](/docs/harnesses/provider-auth). diff --git a/content/docs/memory-models/openai.mdx b/content/docs/memory-models/openai.mdx new file mode 100644 index 0000000..aa44609 --- /dev/null +++ b/content/docs/memory-models/openai.mdx @@ -0,0 +1,31 @@ +--- +title: "OpenAI" +summary: "OpenAI model access currently flows through the Codex harness, not the Coven daemon." +description: "OpenAI model access in Coven through Codex, including login, doctor checks, and credential boundary." +read_when: + - Connecting OpenAI-backed work to Coven + - Debugging Codex auth failures under Coven +--- + +# OpenAI + +OpenAI model access currently flows through Codex. + +```bash +npm install -g @openai/codex +codex login +coven doctor +coven run codex "fix the failing tests" +``` + +## Boundary + +Codex owns OpenAI provider credentials and model calls. Coven owns the session record, PTY supervision, attach/replay behavior, and event log. + +Coven does not read OpenAI API keys, OAuth refresh tokens, or Codex auth files. If Codex auth expires, run `codex login` and retry. + +## Related + +- [Codex harness](/docs/harnesses/codex) +- [Provider boundary](/docs/memory-models/provider-boundary) +- [Models](/docs/memory-models/models) diff --git a/content/docs/memory-models/persistent-memory.mdx b/content/docs/memory-models/persistent-memory.mdx new file mode 100644 index 0000000..f6b552c --- /dev/null +++ b/content/docs/memory-models/persistent-memory.mdx @@ -0,0 +1,34 @@ +--- +title: "Persistent Memory" +summary: "Persistent memory stores stable facts that should survive sessions, daemon restarts, and context resets." +description: "Persistent memory for familiar identity, user preferences, project conventions, and long-term operating rules." +read_when: + - Capturing durable facts for a familiar + - Reviewing whether a memory should survive future sessions +--- + +# Persistent Memory + +Persistent memory is for stable facts that should survive context resets and daemon restarts. It is the layer that gives a familiar continuity. + +## Good persistent memories + +- Familiar identity and role. +- User preferences and communication style. +- Project conventions and hard rules. +- Stable infrastructure notes. +- Repeated lessons from prior incidents. + +## Poor persistent memories + +- Raw command output. +- One-off failed hypotheses. +- Secrets, tokens, or private URLs. +- Temporary task state. +- Facts that are likely to expire quickly. + +## Promotion rule + +Promote memory deliberately. A good persistent memory should still be useful weeks later and should not expose private material in the wrong context. + +For concrete sessions and outcomes, use [Episodic memory](/docs/memory-models/episodic-memory). For concept-based recall, use [Semantic memory](/docs/memory-models/semantic-memory). diff --git a/content/docs/memory-models/provider-boundary.mdx b/content/docs/memory-models/provider-boundary.mdx new file mode 100644 index 0000000..64f9ad9 --- /dev/null +++ b/content/docs/memory-models/provider-boundary.mdx @@ -0,0 +1,56 @@ +--- +title: "Provider Boundary" +summary: "The provider credential boundary sits at the harness CLI, not the Coven daemon." +description: "Why model provider credentials stay with Codex, Claude Code, or future harnesses instead of moving into Coven." +read_when: + - Reviewing whether a client should send model keys to Coven + - Explaining why Coven does not implement provider login +--- + +import { Mermaid } from '@/components/mermaid'; + +# Provider Boundary + +The provider credential boundary sits at the harness CLI. Coven launches and supervises the harness; the harness talks to the provider. + + Login["codex login / claude doctor"] + Login --> CredentialStore[(provider credential store)] + User --> Coven["coven run"] + Coven --> Daemon[Coven daemon] + Daemon --> Harness[Harness PTY] + Harness --> CredentialStore + Harness --> Provider[OpenAI / Anthropic / local runtime] + Daemon -. no provider credentials .-> Provider +`} /> + +## Why this boundary exists + +- Smaller daemon blast radius. +- No OAuth or API-key drift across providers. +- Clear troubleshooting ownership. +- Clients cannot widen credential access through the socket API. + +## What to do instead + +Use the provider's own setup flow: + +```bash +codex login +claude doctor +coven doctor +``` + +Then launch through Coven: + +```bash +coven run codex "audit this repo" +coven run claude "review this UI" +``` + +Related references: + +- [Authentication and local access](/docs/reference/auth) +- [Daemon security posture](/docs/daemon/security) +- [Harness provider auth](/docs/harnesses/provider-auth) diff --git a/content/docs/memory-models/semantic-memory.mdx b/content/docs/memory-models/semantic-memory.mdx new file mode 100644 index 0000000..2df8a29 --- /dev/null +++ b/content/docs/memory-models/semantic-memory.mdx @@ -0,0 +1,30 @@ +--- +title: "Semantic Memory" +summary: "Semantic memory uses embeddings or related indexing to recall concepts, patterns, and similar past work." +description: "Semantic memory for meaning-based recall across sessions, docs, project notes, and familiar history." +read_when: + - Adding concept-based recall + - Deciding when embeddings help more than keyword search +--- + +# Semantic Memory + +Semantic memory is meaning-based recall. It helps a familiar find related past work even when the exact words differ. + +## What it is good for + +- Similar debugging patterns. +- Related architecture decisions. +- Past docs sections about the same concept. +- Project conventions expressed in different language. +- Research notes and long-running themes. + +## What it is not + +Semantic memory is not an authority source by itself. It returns likely relevant material. The familiar should still read the underlying note, event, or document before acting on it. + +## Backend posture + +Coven does not require one embedding database or hosted vector store. A client can use SQLite extensions, local vector indexes, or a hosted backend. The important contract is that memory search returns bounded, attributable context instead of dumping unrestricted private history. + +For model-provider credential boundaries, see [Provider boundary](/docs/memory-models/provider-boundary). diff --git a/content/docs/memory-models/working-memory.mdx b/content/docs/memory-models/working-memory.mdx new file mode 100644 index 0000000..25fb0c5 --- /dev/null +++ b/content/docs/memory-models/working-memory.mdx @@ -0,0 +1,32 @@ +--- +title: "Working Memory" +summary: "Working memory is the short-lived context a familiar needs for one active session or task." +description: "Working memory for OpenCoven familiars: active goals, constraints, files, recent turns, and task-local state." +read_when: + - Designing in-session prompts + - Deciding what context should not become durable memory +--- + +# Working Memory + +Working memory is the task-local context a familiar needs right now. It is useful inside one active session, but it is not automatically worth preserving forever. + +## Common contents + +- Current user request. +- Active goal and acceptance criteria. +- Recent turns or tool results. +- Relevant files, diffs, diagnostics, and errors. +- Temporary constraints such as "do not touch generated files." + +## Lifecycle + +Working memory usually starts when a client creates or resumes a session and ends when the task is done. Parts of it may be promoted into episodic or persistent memory after review. + +Do not blindly promote all working memory. Transient logs, failed experiments, and noisy output make future recall worse if they become durable facts. + +## Relationship to harnesses + +Harnesses such as Codex and Claude Code receive working memory as prompt/context. Coven supervises the PTY and records events; it does not decide which prompt fragments are important enough to keep. + +For launch behavior, see [CLI run reference](/docs/cli/run) and [Harnesses](/docs/harnesses/what-is-a-harness). diff --git a/content/docs/meta.json b/content/docs/meta.json index cb0cef5..43e0474 100644 --- a/content/docs/meta.json +++ b/content/docs/meta.json @@ -1,3 +1,3 @@ { - "pages": ["guide", "daemon", "cli", "harnesses", "familiars", "reference"] + "pages": ["guide", "daemon", "cli", "harnesses", "memory-models", "familiars", "reference"] } diff --git a/content/docs/reference/migration-map.mdx b/content/docs/reference/migration-map.mdx index 74e869f..f67bbaa 100644 --- a/content/docs/reference/migration-map.mdx +++ b/content/docs/reference/migration-map.mdx @@ -11,6 +11,8 @@ This page tracks the gap between the original `OpenCoven/coven/docs` corpus and The goal is to keep the docs honest: current runtime behavior should be documented as current, while future hosted APIs, distributed orchestration, and harness handoffs should be labeled as roadmap work until shipped. +Current first-class migrations now include [Daemon](/docs/daemon/lifecycle), [CLI Reference](/docs/cli/run), [Harnesses](/docs/harnesses/what-is-a-harness), and [Memory + Models](/docs/memory-models/memory). + ## Current Stack to Show The public homepage should expose the actual Coven runtime stack, not only the familiar-facing abstraction. diff --git a/package.json b/package.json index c4b6e26..48680c7 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "type": "module", "scripts": { "dev": "next dev", - "build": "npm run check:english-only && npm run check:daemon-docs && npm run check:cli-docs && npm run check:harness-docs && next build", + "build": "npm run check:english-only && npm run check:daemon-docs && npm run check:cli-docs && npm run check:harness-docs && npm run check:memory-models-docs && next build", "check:fumadocs": "node scripts/check-fumadocs-platform.mjs", "check:english-only": "node scripts/check-english-only.mjs", "check:daemon-docs": "node scripts/check-daemon-docs.mjs", "check:cli-docs": "node scripts/check-cli-docs.mjs", "check:harness-docs": "node scripts/check-harness-docs.mjs", + "check:memory-models-docs": "node scripts/check-memory-models-docs.mjs", "check:links": "node scripts/validate-links.mjs", "check:mermaid": "node scripts/check-mermaid-transform.mjs && node scripts/check-mermaid-svg-normalize.mjs", "export:pdf": "node scripts/export-pdf.mjs", diff --git a/scripts/check-memory-models-docs.mjs b/scripts/check-memory-models-docs.mjs new file mode 100644 index 0000000..0ae5183 --- /dev/null +++ b/scripts/check-memory-models-docs.mjs @@ -0,0 +1,116 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; + +const root = process.cwd(); +const docsRoot = join(root, 'content', 'docs'); +const sectionRoot = join(docsRoot, 'memory-models'); + +const requiredPages = [ + 'index', + 'memory', + 'working-memory', + 'persistent-memory', + 'episodic-memory', + 'semantic-memory', + 'memory-search', + 'models', + 'provider-boundary', + 'openai', + 'anthropic', + 'local-models', +]; + +const requiredMentions = [ + 'Working memory', + 'Persistent memory', + 'Episodic memory', + 'Semantic memory', + 'Memory search', + 'session ledger', + 'event log', + 'provider credentials', + 'Codex', + 'Claude Code', + 'OpenAI', + 'Anthropic', + 'local models', +]; + +function fail(message) { + console.error(`Memory + Models docs check failed: ${message}`); + process.exit(1); +} + +function readJson(path) { + try { + return JSON.parse(readFileSync(path, 'utf8')); + } catch (error) { + fail(`could not read JSON at ${path}: ${error.message}`); + } +} + +const topLevelMeta = readJson(join(docsRoot, 'meta.json')); + +if (!Array.isArray(topLevelMeta.pages) || !topLevelMeta.pages.includes('memory-models')) { + fail('content/docs/meta.json must include a first-class "memory-models" nav section.'); +} + +const metaPath = join(sectionRoot, 'meta.json'); +if (!existsSync(metaPath)) { + fail('content/docs/memory-models/meta.json is missing.'); +} + +const meta = readJson(metaPath); + +if (meta.title !== 'Memory + Models') { + fail('content/docs/memory-models/meta.json must use title "Memory + Models".'); +} + +if (meta.description !== 'Memory layers, search, provider boundaries, and model access for persistent familiars.') { + fail('content/docs/memory-models/meta.json description must describe the memory and models section.'); +} + +const actualPages = Array.isArray(meta.pages) ? meta.pages : []; +const missingPages = requiredPages.filter((page) => !actualPages.includes(page)); +if (missingPages.length > 0) { + fail(`content/docs/memory-models/meta.json is missing pages: ${missingPages.join(', ')}.`); +} + +const sources = []; +for (const page of requiredPages) { + const file = join(sectionRoot, `${page}.mdx`); + if (!existsSync(file)) { + fail(`missing Memory + Models doc page: content/docs/memory-models/${page}.mdx.`); + } + + const source = readFileSync(file, 'utf8'); + sources.push(source); + + if (source.includes('Stub') || source.includes('fill in')) { + fail(`content/docs/memory-models/${page}.mdx still contains stub text.`); + } + + if (!source.includes('read_when:')) { + fail(`content/docs/memory-models/${page}.mdx is missing read_when frontmatter.`); + } +} + +const joined = sources.join('\n'); +const missingMentions = requiredMentions.filter((mention) => !joined.includes(mention)); +if (missingMentions.length > 0) { + fail(`Memory + Models docs are missing required mentions: ${missingMentions.join(', ')}.`); +} + +if (!joined.includes('/docs/familiars/sessions') || !joined.includes('/docs/harnesses/provider-auth')) { + fail('Memory + Models docs must cross-link session lifecycle and harness provider-auth docs.'); +} + +if (!readFileSync(join(sectionRoot, 'models.mdx'), 'utf8').includes('/docs/harnesses/codex')) { + fail('models page must link to the Codex harness page.'); +} + +if (!readFileSync(join(sectionRoot, 'provider-boundary.mdx'), 'utf8').includes('/docs/reference/auth')) { + fail('provider-boundary page must link to the authentication reference.'); +} + +console.log('Memory + Models docs check passed.');