From 97840e25ab021bbbb7fe8b0c0ae2416282996201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=A2=A8?= Date: Wed, 29 Apr 2026 09:29:29 +0000 Subject: [PATCH] chore: add .knowledge/ cards + knowledge.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .knowledge/adapter.md | 45 +++++++++++++++++++++++++ .knowledge/architecture.md | 33 ++++++++++++++++++ .knowledge/coding-conventions.md | 57 ++++++++++++++++++++++++++++++++ .knowledge/knowledge-layer.md | 38 +++++++++++++++++++++ .knowledge/monorepo.md | 24 ++++++++++++++ .knowledge/sense.md | 29 ++++++++++++++++ .knowledge/workflow.md | 50 ++++++++++++++++++++++++++++ knowledge.yaml | 4 +++ 8 files changed, 280 insertions(+) create mode 100644 .knowledge/adapter.md create mode 100644 .knowledge/architecture.md create mode 100644 .knowledge/coding-conventions.md create mode 100644 .knowledge/knowledge-layer.md create mode 100644 .knowledge/monorepo.md create mode 100644 .knowledge/sense.md create mode 100644 .knowledge/workflow.md create mode 100644 knowledge.yaml diff --git a/.knowledge/adapter.md b/.knowledge/adapter.md new file mode 100644 index 0000000..975c37e --- /dev/null +++ b/.knowledge/adapter.md @@ -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 +``` + +- 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`. diff --git a/.knowledge/architecture.md b/.knowledge/architecture.md new file mode 100644 index 0000000..69ccefc --- /dev/null +++ b/.knowledge/architecture.md @@ -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 diff --git a/.knowledge/coding-conventions.md b/.knowledge/coding-conventions.md new file mode 100644 index 0000000..b14253b --- /dev/null +++ b/.knowledge/coding-conventions.md @@ -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`, `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` 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 +``` diff --git a/.knowledge/knowledge-layer.md b/.knowledge/knowledge-layer.md new file mode 100644 index 0000000..3d580e6 --- /dev/null +++ b/.knowledge/knowledge-layer.md @@ -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= +``` diff --git a/.knowledge/monorepo.md b/.knowledge/monorepo.md new file mode 100644 index 0000000..98ae350 --- /dev/null +++ b/.knowledge/monorepo.md @@ -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 diff --git a/.knowledge/sense.md b/.knowledge/sense.md new file mode 100644 index 0000000..52049e0 --- /dev/null +++ b/.knowledge/sense.md @@ -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) +``` diff --git a/.knowledge/workflow.md b/.knowledge/workflow.md new file mode 100644 index 0000000..f44def1 --- /dev/null +++ b/.knowledge/workflow.md @@ -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 = { + 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)` — static or dynamic +- `meta: Schema` — extract schema for typed output diff --git a/knowledge.yaml b/knowledge.yaml new file mode 100644 index 0000000..ab2ac2c --- /dev/null +++ b/knowledge.yaml @@ -0,0 +1,4 @@ +include: + - ".knowledge/**/*.md" + +exclude: []