v0.2.6
Added
- Python client
sagewiki(clients/python/, P4-3). Typed sync
(SageWiki) and async (AsyncSageWiki) clients over the/v1REST API —
one shared request-building implementation,httpxas the only
dependency, stdlib dataclass models,py.typedshipped. One method per
route; the full error-code vocabulary maps to exception classes (branch
on code, never message);compile/lintreturn aJobwhose
wait(timeout)requires an explicit timeout (raisesJobTimeout,
JobFailed; returns oncancelled);Conflict.active_job_idexposes
the 409 details; idempotency keys forwarded verbatim and required before
any write is retried. Contract-tested against a live server in CI
(scripts/p4-fixture-server.sh— a keyless fixture seeded through the
write API). Pre-1.0 — pin a version. - TypeScript client
sagewiki(clients/typescript/, P4-4). Typed,
zero-runtime-dependency client over/v1using globalfetch— runs on
Node ≥18, Deno, Bun, and edge runtimes (no Node built-ins in the main
entry, statically asserted). Dual ESM + CJS output with types.
Compile-submit bodies are discriminated unions: mixingtopicwith
compile flags is a compile-time error. Same error taxonomy as the Python
client (instanceofandswitch (e.code)both work),AbortSignalon
every method including job waits,waitUntilDone({ timeoutMs })with a
required timeout. Contract-tested against a live server in CI. - Framework examples (
examples/, P4-6). Two CI-exercised, keyless
examples:examples/langgraph/— retrieval + capture nodes showing the
uncompiled_sources > 0→ topic-compile-and-wait pattern (stubbed LLM);
examples/vercel-ai-sdk/—search,graphQuery,provenanceas AI
SDK tools, with the edge-deployability note. Both run headlessly in CI
against the fixture server and assert a non-empty result. Exactly two, by
design. - Publish workflows.
publish-python.yml(PyPI Trusted Publisher) and
publish-typescript.yml(npm with provenance), manual-dispatch or
py-v*/ts-v*tag triggered, version-match checked, with a post-publish
pin-resolution verification step. Publishing itself remains maintainer-run.
Fixed
- Jobs submitted via
/v1/jobs/*were cancelled the instant their202
was sent. The job goroutine derived its context from the HTTP request,
which net/http cancels when the handler returns — so every job died as
soon as submission completed (invisible to httptest, which never
reproduces request lifecycle cancellation; caught by the Python client's
live contract test). Job contexts now derive fromcontext.Background()
with the existing 2-hour cap, pinned by a regression test that drives a
real server and client.
Added
- Async job API for compile and lint (
/v1/jobs/*, P4-2). Long-running
operations are now job submissions over REST:POST /v1/jobs/compile
(full mode via compile flags, or topic mode via{topic, max_sources?})
andPOST /v1/jobs/lintreturn202 Acceptedwith ajob_id; poll
GET /v1/jobs/{id}throughpending → running → done | failed | cancelled, list recent jobs viaGET /v1/jobs(bounded to 100, FIFO
eviction), cancel viaDELETE /v1/jobs/{id}(best-effort; the compile
checkpoint stays resumable). Submitting while a compile is active returns
409 conflictwith the active job's ID;Idempotency-Keyon submit
replays the samejob_idwithout re-dispatching (per-kind scoped,
X-Idempotent-Replay: true); compile jobs mirror the shared progress hub
into the job'sprogressfield. Jobs dispatch to the same compile/lint
functions the MCP tools call — no parallel job system; records are
in-memory (same restart semantics as the idempotency store). MCP tool
behaviour is unchanged. - Agent skills:
sage-wikireference +sage-wiki-integratepipeline
(P4-5). Two installable skills generated from the live MCP tool
registry (go run ./tools/skillgen/): the reference skill documents all
18 MCP tools with REST equivalents, the fixed error-code vocabulary,
opt-in flags with their true defaults, tiers 0/1/3, and async compile
semantics; the pipeline skill wires sage-wiki into an existing repo
(detect language → client or MCP config → smoke test). A CI drift check
regenerates andgit diff --exit-codes theskills/tree, so a tool
change cannot ship with stale skills. Install:
npx skills add https://github.com/xoai/sage-wiki --skill sage-wiki.
Fixed
- Batch API truncation no longer silently drops sources (#124). Also
fixes a pre-existing Gemini batch bug: retrieve failed SSRF validation on
any port-bearing base URL (host comparison dropped the port). A
truncated 200-OK results body previously produced a partial result set
that was processed as complete (malformed JSONL lines were skipped
silently). Retrieving batch results now retries truncation-class errors
with backoff on all providers, malformed lines error out instead of
skipping, and the resume path hard-fails with the missing source names
before any processing when a batch returns fewer results than expected —
the checkpoint is kept for re-poll instead of consumed.
Added
- Evidence gates for low-evidence concepts (#128). Bare acronyms scraped
from legends and passing references no longer become standalone
boilerplate concept articles: extraction dedup now merges concepts on
normalized alias overlap (an extracted "rap" folds into
"remedial-action-plan" when the alias is known, in-batch or from prior
compiles via new manifest-stored aliases), and a new
compiler.min_concept_sourcesgate (default 1; 0 disables) fully
suppresses concepts with no declared sources — no article, no LLM call,
no manifest entry, on all three compile paths. The extraction prompt also
tells the model not to emit unresolvable acronyms as standalone concepts.
Fixed
initno longer destroys user files (#127). Re-runningsage-wiki init
preserves.gitignore(appends.sage/instead of clobbering) and
.manifest.json(skips when present — previously every re-init wiped
compile history and orphaned the vault). New--forceflag rewrites both
intentionally (config.yamlstays preserved unconditionally). Also:
sage-wiki init <dir>now honors the positional directory argument —
previously it was silently ignored and the current directory was
initialized instead, which could scatter (and wipe) the wrong directory.
More than one positional argument is now an explicit error.
Added
-
Backend-neutral reconciler (P3-7). The startup reconcile now honors
storage.backend: on a Postgres vault it heals the Postgres store
(previously it always opened the SQLite file, reconciling nothing real on
PG vaults).wiki.ReconcileBackendis the new primary entry; the legacy
Reconcilepath is behavior-identical for SQLite (all existing call
sites unchanged). Completes the graph storage
backend seam — see.sage/docs/design/graph-storage-backend.mdfor the
cookbook 3-table mapping, traversal rationale, and the Neo4j follow-on.
Note: on Postgres, a contended writer open at startup stalls up to
storage.lock_timeoutthen skips reconcile with a warning (never blocks
startup). -
/v1REST facade + OpenAPI 3.1 + drift check (P4-1). sage-wiki is
now callable from any language: 16 synchronous routes under/v1
dispatch 1:1 to the existing MCP tool handlers (sage-wiki serve --ui),
with a single JSON error envelope and fixed code vocabulary, structured
/v1/status, edge validation for precise 400s,412 feature_disabled
pre-checks foras_of/mode=global, a 100 KB cap on capture (413), and
Idempotency-Keyreplay on every write (in-memory, bounded — keys do not
survive restart, documented). Auth reuses the existing Bearer + Host
allowlist middleware;/api/*and all 18 MCP tool names are provably
unchanged (regression tests). The hand-authoredapi/openapi.yamlis
enforced against the registered routes and the tool registry by a new
drift test (internal/api), including a self-test that proves it catches
drift. Async job endpoints for compile/lint follow in P4-2. Guide:
docs/guides/http-api.md. -
Added the MIT
LICENSEfile (P4-0). The README has always said MIT but
no license text shipped in the tree, leaving the default legal position at
all-rights-reserved and blocking corporate adoption review.LICENSEis
tracked in git, linked from the README's License section, and is picked up
by the release workflow's existing[ -f LICENSE ]guard, so release
archives include it from the next tag. -
make cinow covers the translation-drift check. The documented local
gate claimed to mirror CI but omitted MAINT-05, so a README.md-only change
could passmake ciand still fail CI after merge. Newmake translations
(same merge-base semantics as the CI job) andmake translations-self-test;
CONTRIBUTING documents the translations rule and the maintainer fork-PR
workflow-approval step, and PRs get a checklist template. (#126) -
pkg/sagewiki— in-process Go embedding (#112). A supported, non-internal
entry point for embedding sage-wiki in another Go program without spawning
sage-wiki serveas a subprocess.NewServer(projectDir)returns a handle
exposingMCPServer()andClose(); pair it with mcp-go's
client.NewInProcessClientto call the same wiki tools an editor integration
calls over stdio.SetVersionlets an embedder report its own version string
in the initialize response. The package is experimental while sage-wiki is
pre-1.0: the Go signatures are meant to stay put, but tool names, argument
schemas, andconfig.yamllayout can change in any release.
Fixed
- MCP server reports the real build version.
initializereturned a
hardcoded0.1.0inserverInfo.versionregardless of the binary's actual
version; it now reports the-ldflags-injected build version (devfrom a
plaingo build), mirroringinternal/pack.Version.