English | 简体中文
An AI-native runtime for spatial applications, built above the GeoVerse SDK on a strict hexagonal (ports-and-adapters) architecture: the kernel does not know what a "map" is.
Status(four-tier wording, per the Contract-Freeze discipline): implemented — RFC-0008 M1–M4, stage-2 workspace/remote/self-evolution tracks (T1–T17), stage-3 Runtime Contract Freeze (Gate 0+1) and stage-4 universalization U0/U2–U5 (geo-profile shared schemas, lazy state view, catalog search + selectors, eval harness, resource data plane, named-set addressing, checkout/commit via GeoVerse SyncClient, observation budget, jobs, composite engine, conformance kit, MCP-in bridge, manifest capabilities, prompt profiles) are code-complete; U1 multi-provider LLM work is deliberately deferred. The full local gate is
pnpm verify. verified-in-clean-CI — partial: CI temporarily runs the geoverse-free subset until@geoverse/editor-coreships to npm (G1-4 decision); full-matrix CI resumes then. published — none: packages are not yet on npm — see Develop from source. production-supported — no; treat everything as a technical preview.
Most agent frameworks orchestrate conversations. SAR orchestrates application state — and treats the human UI, the AI Copilot, the autonomous Agent and external MCP clients as the same runtime with different entries:
- Every ability is a Capability — self-describing (Zod schema), discoverable, invocable, composable. A capability descriptor is a Claude/MCP tool definition (
id ≡ name,inputJsonSchema ≡ input_schema) — one projection backs the UI command palette, the AI tool catalog and MCPtools/list. - Every operation goes through one funnel —
dispatcher.invoke: middleware onion → permissions → service checks → Zod validation → handler → write routing → events. UI clicks, AI tool calls and MCP calls differ only bycaller.entry. Cross-entry parity is pinned by tests, not by convention. - Domain-state undo is first class — engines plug in through a generic diff port (
StateEngine<TEntity, TDiff>+DiffAlgebra{merge, invert, apply}). Workflows pre-merge step diffs into one undo unit (macro undo) without touching the engine. - Writes are previewable —
dryRunreturns "what would change" as a diff without applying it; the agent's approval gate shows this diff to a human before executing. - Governance lives in the kernel, not in the agent loop — permission whitelists clip the catalog and gate invocation with the same predicate;
createAuditLogrecords every call across all entries;AbortSignalthreads through the funnel (no half-applied writes);createJournal/replayJournalpersist and replay transaction history with identical final state and undo granularity. - NL never enters the kernel — natural-language routing lives in the
planner/agentpackages behind provider-agnostic ports (LlmClient,AgentPolicy); every one of the 425 tests runs without a real LLM.
Entries (zero domain logic: project the catalog out, route calls back in)
program (kernel.invoke) · ui (toPaletteItems) · ai (skill) · planner (M3) · agent (M4) · mcp
│ caller.entry distinguishes; events are one shared stream
▼
@geoverse-sar/kernel (depends on zod only — enforced by an ESLint dependency gate)
Capability / Registry read | write | action
Dispatcher (single funnel) middleware → permissions → validation → handler → write routing
Workflow + TransactionGroup inter-step dataflow + macro undo
Governance AbortSignal · permissions · audit log · journal replay
Self-diagnosis runDoctor (assembly checks) · ErrorMonitor · explainError hints
│ the only abstraction the kernel knows: StateEngine<TEntity, TDiff> + DiffAlgebra
▼
Engines engine-memory (reference) · engine-geo (wraps @geoverse/editor-core, zero changes)
Capability packs capabilities-records (in-memory domain) · capabilities-geo (GeoJSON domain)
| Package | Role | Tests |
|---|---|---|
@geoverse-sar/kernel |
Pure mechanism: capability/registry/dispatcher/workflow/txgroup/events/permissions/doctor/audit/journal/store/SarClient + stage-4 data plane (resources/named sets/jobs/composite/manifest) |
175 |
@geoverse-sar/geo-profile |
Canonical geo schemas (leaf, zod-only): Geometry/Feature/FeatureRef/BBox/CRSRef/Quantity unit discipline |
9 |
@geoverse-sar/workspace |
Lifecycle assembly: openWorkspace — restore (snapshot + journal tail), checkpoint (undo horizon), single-writer lock |
26 |
@geoverse-sar/server |
Service form (Node-only): thin HTTP+WS layer — wire = InvokeOutcome, token → CallerInfo, EventBus bridged to WS |
23 |
@geoverse-sar/evolution |
Self-evolution starters: L2 workflow synthesis loop (mine → draft → dry-run validate → approve → register), kb port, ingest | 10 |
@geoverse-sar/otel |
OpenTelemetry exporter (optional): invoke spans via middleware + workflow/transaction event bridge, BYO SDK | 2 |
@geoverse-sar/engine-memory |
Reference engine + diff algebra (fast-check algebraic laws) | 11 |
@geoverse-sar/engine-geo |
GeoVerse adapter: wraps @geoverse/editor-core EditEngine untouched + dual-channel ChangeSetAlgebra + geometry bridge + sync bridge |
8 |
@geoverse-sar/capabilities-records |
Record-domain pack: 8 capabilities + a macro-undo workflow | 12 |
@geoverse-sar/capabilities-geo |
GeoJSON feature pack: 40+ capabilities incl. draw/split/merge, transforms, holes, query/analysis, referring expressions, checkout/commit | 62 |
@geoverse-sar/skill |
AI entry: toToolSpecs + handleToolCall (+ SarClient twins, byte-for-byte parity; failures carry actionable hints) |
18 |
@geoverse-sar/planner |
NL→capability routing: tool-use loop, SSE streaming LlmClient, headless chat controller, catalog selectors, prompt profiles |
23 |
@geoverse-sar/agent |
Autonomous entry: observe→plan→act loop, AgentPolicy port, approval gate, observation providers with token budget |
16 |
@geoverse-sar/mcp |
MCP entry: tools/list ≡ descriptor projection, tools/call → the same funnel, resources ≡ ResourcePort; MCP-in bridge |
13 |
@geoverse-sar/eval |
Deterministic eval harness: scenario = seed → plan → declarative expectations + canonical state hash (run-3×-same-hash) | 5 |
@geoverse-sar/conformance |
Capability-pack certification: 8 checks (doctor delegation, dryRun purity, invert∘apply reversibility via fast-check, effects probes, …) | 12 |
Five pages, one runtime — pnpm playground:dev then open http://localhost:8090:
| Page | What it shows |
|---|---|
/index.html |
Command palette (UI entry) + manual tool calls side by side, plus a one-click doctor report |
/chat.html |
Real LLM chat (DeepSeek) driving the in-memory domain — streaming, abort, macro undo |
/geo.html |
A real GeoVerse map (GMap): the LLM queries, draws, splits, merges features and switches basemaps |
/agent.html |
The autonomous agent: observe→plan→act trace, approval gate toggle, live audit panel |
/remote.html |
Remote mode: the whole page is one createRemoteClient — start pnpm playground:server first |
LLM pages need a DeepSeek key: put DEEPSEEK_API_KEY=... in a repo-root .env (gitignored; the key is injected by the Vite dev proxy and never reaches the browser bundle).
Prerequisites: Node ≥ 20, pnpm ≥ 10, and a sibling checkout of the geoverse repo (SAR links @geoverse/editor-core and @geoverse/core-ol via pnpm file: until they are published):
workspace/
├── geoverse/ # build it first: pnpm install && pnpm -r build
└── sar/ # this repo
pnpm install
pnpm build # inter-package resolution goes through dist — build first
pnpm typecheck && pnpm lint && pnpm test
pnpm playground:devSee CONTRIBUTING.md for the full development, debugging and verification guide (quality gates, smoke tests, real-LLM acceptance rules, commit conventions).
docs/ is a VitePress site (pnpm docs:dev to preview, pnpm docs:build to build — includes a typedoc API reference). Start with architecture & technical details for the exact pipeline, port contracts, invariants and error-code table. Reader guides: concepts · writing capability packs · workflows & macro undo · the entries · NL planner & headless chat · autonomous agent & governance · bringing your own engine · persistence · remote mode · self-evolution · doctor & error analysis · eval harness · extending SAR — plus a README per package.
Design records: RFC-0008 / RFC-0009 and ADR-0010…0013 (shared design vault, not in this repo).
MIT