Workspace and operations¶
Path ownership¶
JUSTPEN_KNOWLEDGEBASE_WORKSPACE_DIR must be an existing absolute directory.
Relative evidence paths are resolved from its pinned root. An absolute import is
accepted only when it is lexically beneath either the configured root spelling
or its resolved root alias. Child symlinks, hard-linked source files, parent
components, managed database/evidence/staging paths, and paths outside the
workspace are rejected.
Import opens one stable regular source and copies its bytes into content-addressed storage. A copy takeover or retry restarts at byte 0; partial copy progress is not resumed. Do not modify the source while it is being copied.
Capacity and concurrency¶
The default advisory reserve is 1.5 GiB: twice the 256 MiB WAL high-water mark plus 1 GiB. The server checks the copy device first and separately checks other managed devices, repeating during a copy every 8 MiB. This can reject early, but it is not a hard quota or an atomic reservation. Database and evidence paths may be on different devices, and concurrent/external writers can still consume space.
Database requests use one writer, 1–8 readers (2 by default), a shared reader queue of 128, a writer queue of 128, and a control queue of 16. The 10-second foreground deadline includes time waiting in those queues. Native evidence work uses one short and one bulk lane with process-local bounded admission. Short ingest and cleanup groups alternate when both are waiting; this is not global round-robin or a completion-time promise.
WAL pressure and retry¶
The persisted workspace policy, not a per-process environment override, controls
WAL and retention thresholds. At or above the low watermark for logical WAL
frames, while below pressure, maintenance tries a nonblocking opportunistic
reset. Under pressure it performs bounded drain/reset attempts. kb_status.wal exposes phase, stale_normal, cache ages, cooldown
fields, retry advice, and whether evaluation was requested. A cached normal
sample can be stale; a failed cache refresh is not a healthy zero.
For BUSY, WAL_PRESSURE, or reset-pending errors, honor retry_after_ms (at
least one second), add jitter, and increase subsequent delay within roughly
1–5 seconds. Re-check kb_status; do not assume a fixed 10–15 second completion
window.
An external sqlite3 reader can hold back checkpointing. Keep read transactions
short and close the CLI promptly. kb_status cannot report the age of an
external reader it does not own.
Upgrade and offline copy¶
Before an upgrade, stop every MCP process using the workspace. Reopen it with the same compatible release. The startup guard checks schema/catalog/index compatibility; it does not migrate an incompatible database automatically.
An incompatible workspace fails with CONFIGURATION and an authored reason
naming which part of the stored contract differs: the schema version, the
catalog version, the catalog fingerprint, the index format version, or the
managed paths. When several differ the coarsest one is reported. The catalog
fingerprint covers the parsed content of the bundled public suffix list and
service-name whitelist, so a release that refreshes either one refuses
workspaces created by an earlier release, exactly as a catalog change does. The reason
names the category only; it never contains a stored value or a filesystem path.
A managed-paths reason means this process is configured with a different
managed directory layout than the one the workspace was created with, not that
a directory is missing. One route stays undifferentiated: a settings row that
cannot be read at all names no dimension and still reports maintenance unavailable.
Unreleased v1 workspaces must also contain the required job scheduling and
ownership indexes with the expected definitions, plus the checked nullable
jobs.blob_sha256 ownership column. The locator is independent of job progress
JSON and includes jobs awaiting purge. A missing ownership column or incompatible
supporting index fails startup with CONFIGURATION and an authored
offline workspace upgrade required reason identifying the layout category. Use the creating build to access or
export its data, preserve a complete offline copy, then recreate the workspace
or apply an explicitly reviewed offline upgrade. Startup does not install
missing indexes or modify an older layout silently.
For an offline backup or move:
- Stop every MCP process and every other writer.
- Copy
graph.sqlite3, anygraph.sqlite3-walandgraph.sqlite3-shm, the evidence directory, and every configured managed data/tmp/lock path as one coordinated set, including paths on different devices. - Preserve committed WAL after a hard stop. Never discard it or copy only
graph.sqlite3and assume the result is current.
SIGTERM/SIGINT grants 30 seconds for coordinated shutdown, but that grace period
is not a hard timeout for native SQLite close or fsync. A supervisor may stop an
unresponsive process after diagnostics. shutdown_timeout includes the PID and
states that the supervisor must kill if cleanup cannot finish; the server keeps
waiting for its native owners. Remaining committed WAL is valid input
for SQLite recovery on the next open.
The v1 server logs diagnostics to stderr and optional OTLP exporters. It does not
create file logs and has no LOG_DIR setting.
For HTTP on a wildcard address, explicitly list the public Host aliases in
JUSTPEN_KNOWLEDGEBASE_ALLOWED_HOSTS as a JSON array, for example
["kb.example.test"]. Each entry is a concrete lowercase DNS name or IP literal;
up to 16 entries are accepted. This changes Host admission only. FastMCP still
checks Origin, and non-loopback binding still requires
JUSTPEN_KNOWLEDGEBASE_ALLOW_NON_LOOPBACK=true.
Startup configuration errors name the setting and expected rule without echoing values. Known startup failures report their application error code without a traceback: configuration/path errors exit with code 2, operational failures with code 1. Maintenance retries remain one second apart; identical failure-category logs are limited to one per 30 seconds. Category changes log immediately, and a fresh successful cycle logs one recovery summary with a bounded suppressed count.