Kronika documentation

Library API

The npm package @wisent-ai/kronika exposes the same adoption, selection, generation, audit, and sync contract as the CLI, as a dependency-free ES module for Node.js 22+. The entry point is dist/src/index.js; everything below is a named export of the package root.

Workspace adoption

initializeDocumentationWorkspace(options: InitializeWorkspaceOptions): InitializeWorkspaceResult is the library boundary used by kronika init. It validates existing Markdown and evidence paths within one repository, then atomically creates or explicitly replaces the schema-version-1 sync manifest. It does not read document bodies into its result, generate text, call Brama, or execute repository commands.

import { initializeDocumentationWorkspace } from "@wisent-ai/kronika";

const result = initializeDocumentationWorkspace({
  repo: "/path/to/existing-project",
  manifestPath: "kronika.sync.json",
  documents: ["README.md", "docs"],
  sources: ["src"],
});

The result separates imported, unchanged, conflicting, and rejected. An identical manifest is unchanged; a different existing manifest is preserved unless replace: true. The accepted paths, defaults, and failures are documented under kronika init.

The completion boundary

All model access goes through one interface, so any client can substitute for Brama in tests or embeddings:

interface CompletionClient {
  complete(request: {
    messages: { role: "system" | "user" | "assistant"; content: string }[];
    model: string;
    maxTokens: number;
  }): Promise<{ content: string; model?: string }>;
}
  • BramaClient — the production implementation. Constructor options: url, apiKey, optional agentId/authSecret (both or neither), timeoutMs (default 120000), and fetchImpl to inject a fetch. The request and header contract is in configuration.
  • signedHeaders(body, agentId, authSecret, timestampSeconds?) — the HMAC header set (x-agent-id, x-agent-timestamp, x-agent-signature) for a given JSON body, exported so other callers can sign identically.

The seam is real, not theoretical: checkDocumentation, writeDocumentation, and syncDocumentation all take the client as their second argument, so a test double is one object:

import { checkDocumentation, type CompletionClient } from "@wisent-ai/kronika";

const canned: CompletionClient = {
  async complete() {
    return { content: JSON.stringify({ passed: true, summary: "covered", findings: [] }) };
  },
};

const audit = await checkDocumentation({
  repo: "/path/to/project",
  output: "docs/usage.md",
  sources: ["src"],
  base: "origin/main",
  head: "HEAD",
  model: "any",
}, canned);

The verdict still passes through parseDocumentationCheck — a double that answers malformed JSON fails exactly like a misbehaving model (runbook).

Selection

  • collectSources(options: SourceOptions): SourceCollection — builds the bounded source manifest; the rules are in sources. SourceOptions is { repo, sources?, output, maxInputBytes?, maxFileBytes? }; the result is { documents, skipped, totalBytes }. An unset limit reads every selected source whole; a stated non-positive one throws Source byte limits must be positive.

Generation

  • writeDocumentation(options: WriteDocumentationOptions, client): Promise<WriteDocumentationResult> — one completion over the selected sources; with apply: true the output file is atomically replaced. The result carries content, outputPath, applied, model?, sources, and skipped.
  • buildDocumentationMessages(options, collection): ChatMessage[] — the exact write prompt (system rules plus source payload), exported for inspection or reuse.

Audit

  • checkDocumentation(options: CheckDocumentationOptions, client): Promise<CheckDocumentationResult> — audits one base...head range; the semantics are in cli. diffPaths restricts the audited diff to given pathspecs — sync passes each document's declared sources here.
  • buildDocumentationCheckMessages(options, collection, change): ChatMessage[] — the exact audit prompt.
  • parseDocumentationCheck(content) — the strict verdict parser: JSON only (a surrounding code fence is tolerated), validated finding shape, kebab-case codes, and a passed value that must equal "no blockers".

Sync

  • syncDocumentation(options: SyncOptions, client): Promise<SyncResult> — one reconciliation tick over a manifest; the state machine is in sync. SyncOptions is { repo, manifestPath, statePath, dryRun, defaults }; the result is { headSha, outcomes, stateWritten }. Committing and pushing are CLI concerns, not library ones. Manifest and state validation sentences are in the runbook.
  • loadSyncManifest(path): SyncManifest — reads and validates a manifest.
  • SYNC_MANIFEST_FILE, SYNC_STATE_FILE — the default file names, kronika.sync.json and kronika.sync-state.json.

Types

All contract types are exported: InitializeWorkspaceOptions, InitializeWorkspaceResult, ChatMessage, CompletionClient, CompletionRequest, CompletionResult, SourceOptions, SourceDocument, SkippedSource, SourceCollection, DocumentationFinding, CheckDocumentationOptions, CheckDocumentationResult, WriteDocumentationOptions, WriteDocumentationResult, SyncDefaults, SyncDocument, SyncManifest, SyncOptions, SyncOutcome, SyncResult, and SyncState.

Example

import { BramaClient, writeDocumentation } from "@wisent-ai/kronika";

const client = new BramaClient({
  url: process.env.BRAMA_URL!,
  apiKey: process.env.BRAMA_API_KEY!,
});

const result = await writeDocumentation({
  repo: "/path/to/project",
  output: "docs/architecture.md",
  sources: ["src", "README.md"],
  instruction: "Document components, request flow, and failure modes.",
  model: "any",
  apply: false,
}, client);

process.stdout.write(result.content);