chore: add .knowledge/ cards + knowledge.yaml

7 curated knowledge cards extracted from RFCs and docs:
- architecture: core pipeline, extension points, process isolation
- sense: compute behavior, Sense→Workflow, config
- workflow: engine, threads, WorkflowSpec
- adapter: AgentFn protocol, available adapters, extract layer
- coding-conventions: functional-first, Result type, naming
- monorepo: package structure, dependency rules
- knowledge-layer: sync/query CLI, embedding service

knowledge.yaml indexes .knowledge/**/*.md only.
This commit is contained in:
2026-04-29 09:29:29 +00:00
parent 526ca68c99
commit 97840e25ab
8 changed files with 280 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
# Agent Adapters (RFC-003)
Adapter = capability. Role = scenario. Workflows declare adapters directly via import.
## AgentFn Protocol
```ts
type AgentFn = (prompt: string, context: WorkflowContext) => Promise<string>
```
- Input: prompt + context (start frame, messages, workdir, AbortSignal)
- Output: raw string — structured extraction is separate
- Adapter handles tool-specific details internally
## Available Adapters
| Package | Adapter | Tool |
|---------|---------|------|
| `@uncaged/nerve-adapter-cursor` | `cursorAdapter` / `createCursorAdapter()` | cursor-agent CLI |
| `@uncaged/nerve-adapter-hermes` | `hermesAdapter` / `createHermesAdapter()` | hermes chat CLI |
Each exports a **default instance** (sensible defaults) and a **factory** for custom config.
## Usage in Workflows
```ts
import { cursorAdapter } from "@uncaged/nerve-adapter-cursor";
// RoleSpec
{ adapter: cursorAdapter, prompt: "...", meta: schema }
```
No registry, no nerve.yaml agent config. TypeScript catches missing adapters at compile time.
## Extract Layer
Parses agent raw string → typed meta. Configured in `nerve.yaml`:
```yaml
extract:
provider: dashscope
model: qwen-plus
```
Two-level merge: global → role override. Retry once on parse failure (feeds error back to LLM), then throw `ExtractError`.
+33
View File
@@ -0,0 +1,33 @@
# Nerve Architecture
Observation engine for autonomous agents — sense the world, react to changes, run workflows.
## Core Pipeline
```
External World → Sense → Signal → Reflex → Workflow → Log
```
Causality is **one-directional**. Logs are the end of the chain — they cannot trigger Reflexes (prevents feedback loops).
## Three Orthogonal Extension Points
| Extension | Question | Nature |
|-----------|----------|--------|
| **Sense** | What to compute | `compute()` function |
| **Reflex** | When to compute | Declarative YAML (interval / on) |
| **Workflow** | What to do | Roles + Moderator |
Each is independent. Reflex doesn't know compute internals, Sense doesn't know when it's triggered, Workflow doesn't know why it was started.
## Two Event Types
- **Signal** — from Sense compute (non-null return). Pure fact, no intent. Drives the front half (perception).
- **Command Event** — inside Workflow Threads. Has causal chain, must be responded to. Drives the back half (action).
## Process Isolation
- One worker per Sense group (long-lived)
- One worker per Workflow type (on-demand)
- Workers never talk to each other
- All user code runs in isolated Workers; kernel never loads user code directly
+57
View File
@@ -0,0 +1,57 @@
# Nerve Coding Conventions
## Functional-First
- `type` over `interface`, `function` over `class`
- No `this`, no inheritance, composition over inheritance
- Immutability first: `Readonly<T>`, `as const`
## No Optional Properties
Never use `?:`. Use `T | null` for nullable fields. Use discriminated unions for mutually exclusive fields.
```ts
// ✅ Good
type Config = { throttle: string | null }
// ❌ Bad
type Config = { throttle?: string }
```
## Error Handling
- `Result<T, E>` for expected failures
- `throw` only for programmer errors (bugs)
- No try-catch for flow control
## Naming
| Type | Style |
|------|-------|
| Files | `kebab-case.ts` |
| Types | `PascalCase` |
| Functions/vars | `camelCase` |
| Constants | `UPPER_SNAKE` |
## Exports
- Always named exports, never default
- One module = one responsibility
## Async
- Always `async/await`, never `.then()` chains
## No Dynamic Import
Static `import` only. Exceptions: `sense-runtime.ts`, `workflow-worker.ts` (runtime module paths).
## Toolchain
pnpm + TypeScript (strict) + Biome (lint/format) + Vitest (test)
```bash
pnpm run check # biome check
pnpm test # vitest
pnpm run build # full build
```
+38
View File
@@ -0,0 +1,38 @@
# Knowledge Layer (RFC-003 Phase 6)
Local-first, repo-scoped knowledge base for project context.
## Files
- `knowledge.yaml` — repo root, defines include/exclude globs
- `knowledge.db` — SQLite, stores chunks + embeddings
- `.knowledge/` — curated knowledge cards (indexed by sync)
## Commands
```bash
nerve knowledge sync # chunk files, compute embeddings, write to knowledge.db
nerve knowledge query "query" # search by cosine similarity (or word overlap fallback)
nerve knowledge query -g "query" # global search across all indexed repos
nerve knowledge query --repo /path "query" # search specific repo
```
## Embedding
- Remote service: `embed.shazhou.workers.dev` (Cloudflare Worker + KV cache)
- Model: Dashscope text-embedding-v3 (1024 dims)
- Cache: content-addressable (sha256 of model+text), never expires
- Fallback: word-overlap scoring when embed service not configured
## Chunking
- Markdown: split by headings, large sections split further by paragraphs (max 24)
- TypeScript/JS: split by function declarations, fallback to paragraphs
- Other files: single chunk
## Env Config
```
EMBED_SERVICE_URL=https://embed.shazhou.workers.dev
EMBED_AUTH_TOKEN=<token>
```
+24
View File
@@ -0,0 +1,24 @@
# Nerve Monorepo Structure
```
nerve/
packages/
core/ # @uncaged/nerve-core — shared types, config parser, Result, spawn-safe
cli/ # @uncaged/nerve-cli — CLI (init, validate, dev, daemon, knowledge)
daemon/ # @uncaged/nerve-daemon — kernel, workers, signal bus, scheduler
store/ # @uncaged/nerve-store — append-only log, SQLite, CAS blob store
workflow-utils/ # @uncaged/nerve-workflow-utils — role factories, extract, LLM helpers
adapter-cursor/ # @uncaged/nerve-adapter-cursor — cursor-agent CLI adapter
adapter-hermes/ # @uncaged/nerve-adapter-hermes — hermes chat CLI adapter
khala/ # Khala — Sense marketplace (future)
skills/ # nerve-managed skills
docs/ # RFCs, conventions
.knowledge/ # curated knowledge cards (this directory)
```
## Dependency Rules
- `core` is the shared layer — everyone depends on it
- `cli` and `daemon` must NOT depend on each other
- Adapter packages depend only on `core`
- `workflow-utils` depends on `core` and adapter packages
+29
View File
@@ -0,0 +1,29 @@
# Sense
A `compute()` function that samples or derives external data. The only first-class citizen in nerve.
## Behavior
- Returns `T | null` — non-null emits a Signal, null is silent (no storage write, no signal, no downstream trigger)
- Each Sense has its own **independent SQLite database**
- Cross-sense reads are read-only via `peers` parameter
- Schema defined with Drizzle ORM (`schema.ts` is single source of truth)
## Sense → Workflow
If `compute()` returns an object with `workflow: "name|maxRounds|prompt"`, the engine starts that workflow and does **not** emit a Signal. `workflow: null` or `""` means emit signal normally.
See `routeSenseComputeOutput` / `parseSenseWorkflowDirective` in `@uncaged/nerve-core`.
## Config (nerve.yaml)
```yaml
senses:
cpu-usage:
group: system # senses in same group share a worker
throttle: 10s # min interval between computes
timeout: 30s # max compute duration
grace_period: 5s # wait before first compute
interval: 30s # periodic trigger (optional)
on: [disk-pressure] # trigger on signals from other senses (optional)
```
+50
View File
@@ -0,0 +1,50 @@
# Workflow Engine
Stateful multi-step execution driven by Roles and a Moderator.
## Core Concepts
- **Workflow** — definition with concurrency strategy
- **Thread** — one execution instance, unique `runId`
- **Role** — executes actions (has side effects). `(start, messages) → { content, meta }`
- **Moderator** — pure routing function. `(context) → next role | END`
## Thread Lifecycle
```
trigger → queued → started → step_complete ↺ → completed
failed / crashed
```
## Concurrency Config (nerve.yaml)
```yaml
workflows:
cleanup:
concurrency: 1
overflow: drop # discard if already running
code-review:
concurrency: 3
overflow: queue
max_queue: 20 # queue limit, oldest discarded
```
## WorkflowSpec (RFC-003)
User-facing authoring format that compiles to runtime `WorkflowDefinition`:
```ts
const workflow: WorkflowSpec<MyMeta> = {
name: "develop",
roles: {
coder: { adapter: cursorAdapter, prompt: "...", meta: schema },
reviewer: { adapter: hermesAdapter, prompt: reviewFn, meta: schema },
},
moderator,
};
```
- `adapter: AgentFn` — direct function reference, no registry
- `prompt: string | ((start, messages) => Promise<string>)` — static or dynamic
- `meta: Schema<T>` — extract schema for typed output
+4
View File
@@ -0,0 +1,4 @@
include:
- ".knowledge/**/*.md"
exclude: []