diff --git a/OPS-RUNBOOK.md b/OPS-RUNBOOK.md new file mode 100644 index 0000000..0a96920 --- /dev/null +++ b/OPS-RUNBOOK.md @@ -0,0 +1,127 @@ +# CRK-1 Operational Piping Runbook (Local Governed Inference) + +## Objective + +Establish a fully governed, end-to-end local inference path using CRK-1: + +- All governed calls flow through a single adapter. +- Invariants (K0–K12) are enforced pre/post. +- CE-1 / CRR-1 / CLG-1 are invoked as designed. +- Receipts + lineage are emitted for every run. +- No side-door / raw model calls from the operator path. + +--- + +## Target Artifacts + +| Role | Path | +|------|------| +| Core adapter | `src/runtime/governedPredict.ts` | +| Local model client | `src/model/localClient.ts` | +| Invariants | `src/governance/invariants.ts` | +| Receipts | `src/governance/receipts.ts` | +| Lineage | `src/governance/lineage.ts` | +| CLI entrypoint | `bin/run_local_governed.ts` | +| Config | `config/local-governed.yaml` | +| Smoke test | `tests/local_governed_smoke.test.ts` | + +--- + +## A. Operator Kernel Health + +### A1. Operator identity + +**Requirement:** every governed call carries a stable operator id. + +- Field: `operator_id: string` +- Source: config (`config/local-governed.yaml`) or env (`OPERATOR_ID`). +- Must appear in: `GovernedContext`, receipts, lineage root. + +### A2. Receipts + +**Requirement:** every governed call emits a receipt. + +Minimum fields: + +- `call_id` +- `operator_id` +- `timestamp` +- `invariant_set_version` +- `mode` (predict / observe / correct) +- `invariants_passed: boolean` + +Implementation: `src/governance/receipts.ts` + +--- + +## B. AAIS Local Inference Path + +### B1. Local-only model client + +File: `src/model/localClient.ts` + +```ts +export async function localPredict(input: string, opts: LocalModelOptions): Promise; +``` + +Uses local weights only (no remote calls). `localPredict` must only be called from `governedPredict`. + +### B2. Governed adapter + +File: `src/runtime/governedPredict.ts` + +```ts +export async function governedPredict( + input: string, + context: GovernedContext +): Promise; +``` + +Responsibilities: + +1. Load invariants (K0–K12) and `invariant_set_version`. +2. Run pre-call admissibility checks. +3. Call `localPredict(...)`. +4. Run CE-1 / CRR-1 / CLG-1 post-call hooks. +5. Emit receipt + lineage entry. + +--- + +## C. End-to-End Governed Pipeline + +### C1. CLI — `bin/run_local_governed.ts` + +1. Load `config/local-governed.yaml`. +2. Construct `GovernedContext`. +3. Call `governedPredict(prompt, context)`. +4. Print model output, receipt summary, lineage root id. + +### C2. Config — `config/local-governed.yaml` + +```yaml +model_path: "./models/local-llm" +operator_id: "local-operator-001" +invariant_set_version: "K0-K12-v1" +log_receipts: true +log_lineage: true +``` + +--- + +## D. Tests + +### D1. Smoke test — `tests/local_governed_smoke.test.ts` + +Happy path: `governedPredict` returns output, receipt with `invariants_passed: true`, lineage `root_id`. + +Refusal path (optional v0.2): prompt that triggers invariant failure. + +--- + +## E. Success Criteria + +- [ ] `bin/run_local_governed.ts` runs using local weights only +- [ ] All calls go through `governedPredict` +- [ ] Receipts + lineage are emitted +- [ ] `tests/local_governed_smoke.test.ts` passes +- [ ] No direct/raw model calls from operator-facing code diff --git a/README.md b/README.md index 7025537..08450e4 100644 --- a/README.md +++ b/README.md @@ -1,191 +1,245 @@ -# Agentic Coding Agent — Nova Mission #002 +# Nova: The Constitutional Agentic Coding System **Repository:** [warheart1984-ctrl/agentic-coding-agent](https://github.com/warheart1984-ctrl/agentic-coding-agent) -Founder-independent reproduction bundle for **Nova × CRK-2** constitutional agentic coding. Mission #002 proves that an external observer can build, run, and verify a governed coding agent — with receipts, invariant enforcement, continuity snapshots, multi-agent orchestration, and a live cockpit — using only this repository. - [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) +[![Mission](https://img.shields.io/badge/Mission-%23002-blue.svg)](MISSION-002.md) +[![CRK-2](https://img.shields.io/badge/Kernel-CRK--2-8B4513.svg)](docs/CRK-2-SPEC.md) ---- - -## What Mission #002 Proves +Nova is a **governed agentic coding system** built on the **Constitutional Runtime Kernel (CRK-2)** — a lawful substrate for autonomous reasoning, execution, and verification. -| Component | Role | -|-----------|------| -| **CRK-2** | Constitutional Runtime Kernel v2 — dLAP constraints, PIT engine, MACC clustering, hash-chained ledger | -| **Agent SDK** (`agent/`) | `AgentRuntime` — validate → execute → receipt → `ledger.append` for every action | -| **Control Tower** | Multi-agent orchestration, consensus, drift detection, cluster replay | -| **Backend** | Unified service layer + WebSocket events gateway for the cockpit | -| **Cockpit** | React flight deck — plans, receipts, invariants, continuity matrix, drift map | -| **Observer bundle** | Frozen reproduction artifact with independent verification protocol | - -An observer clones this repo, runs `npm install && npm run build`, executes the reproduction protocol, and signs off — no founder guidance required. +Every action is lawful. +Every change is accountable. +Every outcome serves the Constitution. --- -## Repository Layout - -``` -agentic-coding-agent/ -├── README.md # This file -├── MISSION-002.md # Mission brief + reproduction protocol -├── RELEASE.md # Release notes + observer bundle attestation -├── observer-bundle-mission-002.zip -│ -├── agent/ # Nova Agent SDK (AgentRuntime + governance) -│ ├── runtime/agent-runtime.ts # Primary API entry point -│ ├── governance/ # validate, receipt, ledger, invariants -│ ├── core/ # Planner, executor, code generation -│ ├── continuity/ # Snapshots, substrate, replay -│ └── cli.ts # `nova` CLI -│ -├── crk2/ # CRK-2 constitutional kernel -│ ├── kernel/ # dLAP, PIT, panic handler -│ ├── invariants/ # Invariant engine -│ ├── continuity/ # CRP, substrate, replay -│ ├── ledger/ # Ledger v2 -│ └── cluster/ # MACC multi-agent continuity -│ -├── control-tower/ # Orchestration layer -│ ├── orchestrator/ # Cluster manager, consensus, drift detector -│ ├── replay/ # Cluster replay -│ └── drift/ # Drift simulation -│ -├── backend/ # Service adapters -│ ├── crk2-service.ts -│ ├── control-tower-service.ts -│ ├── nova-adapter.ts -│ └── events-gateway.ts -│ -├── cockpit/ # React UI (NovaShell + Flight Deck) -│ -├── observer/ # Independent verification -│ ├── REPRO_PROTOCOL.md -│ ├── CHECKLIST.md -│ └── EXPECTED_OUTPUT.md -│ -├── config/ # Mission invariants (nova.config.ts) -├── docs/ # Specs, operator certification, integrity suites -├── examples/ # Governed project templates -├── tools/fuzz/ # Kernel fuzz harness -├── web/ # Marketing site -│ -└── shell/ # Lawful Nova dev shell (bootstrap, separate concern) - ├── setup/ # bootstrap.sh / bootstrap.ps1 - ├── config/ # .zshrc, profile.ps1, novarc templates - ├── skills/ - └── AGENTS.md +## Overview + +Nova wraps agentic coding in a constitutional loop: plans and executions pass through **dLAP** legality checks, **invariant** enforcement, **continuity** preservation, and an immutable **ledger** before they touch your codebase. + +| Layer | What it does | +|-------|----------------| +| **CRK-2** | Kernel — legality, invariants, continuity, ledger | +| **Nova SDK** (`agent/`) | `AgentRuntime` — plan, validate, execute, receipt | +| **Control Tower** | Multi-agent orchestration, consensus, drift detection | +| **Cockpit** | Operator flight deck — receipts, invariants, continuity matrix | + +Mission **#002** ships a founder-independent reproduction bundle so any observer can rebuild, run, and verify the runtime without privileged access. + +### Constitutional layers + +Nova separates **law**, **execution**, **oversight**, and **verification** so governance cannot be bypassed by accident or convenience. + +| Layer | Path | Role | +|-------|------|------| +| **Law** | `crk2/` | Invariants, constraints, receipts, continuity substrate, ledger — defines what is lawful | +| **Execution** | `agent/` | `AgentRuntime` — plans and executes under CRK-2; applies governance, never defines it | +| **Oversight** | `control-tower/` | Multi-agent orchestration, consensus, drift detection | +| **Judicial** | `observer/` | Founder-independent reproduction and drift-free verification | + +This mirrors the constitutional stack: **Reality → Evidence → Judgment → Stewardship → Continuity**. See [`docs/WHAT-MY-AGENTIC-CODING-AGENT-DOES.md`](docs/WHAT-MY-AGENTIC-CODING-AGENT-DOES.md) for the full layered diagram. + +```mermaid +flowchart TB + subgraph law [LawLayer] + crk2[crk2_dLAP_Invariants_Ledger] + end + subgraph exec [ExecutionLayer] + sdk[agent_AgentRuntime] + end + subgraph oversight [OversightLayer] + tower[control_tower] + cockpit[cockpit_UI] + end + subgraph judicial [JudicialLayer] + observer[observer_Mission002] + end + crk2 --> sdk + sdk --> tower + tower --> cockpit + observer --> crk2 + observer --> sdk ``` -> **Note:** `shell/` is the self-bootstrapping Nova dev environment (macOS/Linux/Windows). It is intentionally separate from Mission #002 runtime code. See [`shell/README.md`](shell/README.md). +> **Roadmap:** `packages/` (crk2, nova-sdk, control-tower, types), `apps/` (cockpit, shell, backend), and `missions/mission-002/` will formalize this layout as the monorepo grows. Today, paths above are at repository root for Mission #002. --- -## Quick Start +## The Constitutional Runtime (CRK-2) -### Prerequisites +CRK-2 is the **lawful substrate** that governs all agentic behavior in this repository. -- Node.js 18+ -- Git +| Component | Role | +|-----------|------| +| **Lawful Action Predicate (dLAP)** | Determines legality of actions before execution | +| **Invariant Engine** | Maintains constitutional invariants at runtime | +| **Constraint Engine** | Enforces boundaries on plans and tool use | +| **Continuity Substrate v2** | Preserves identity, state, and replayable snapshots | +| **Ledger v2** | Hash-chained immutable audit trail | +| **Constitutional Amendments v2 (CA-2)** | Lawful evolution of the rule set | -### Install & Build +CRK-2 is the kernel of **truth**, **continuity**, and **accountability**. -```bash -git clone https://github.com/warheart1984-ctrl/agentic-coding-agent.git -cd agentic-coding-agent -npm install -npm run build -``` +→ Full spec: [`docs/CRK-2-SPEC.md`](docs/CRK-2-SPEC.md) + +--- -### 30-Second Agent Example +## The Agentic SDK + +The **Nova SDK** (`agent/`) exposes constitutional primitives for building governed agents. ```typescript import { AgentRuntime, governance } from "./agent"; import { invariants } from "./config/nova.config"; -// Register constitutional invariants for (const inv of invariants) { await governance.requireInvariant(inv); } const runtime = new AgentRuntime(); -// Governed code generation — validate → receipt → ledger.append +// Governed execution — validate → receipt → ledger.append const result = await runtime.generateCode({ - prompt: "Write a TypeScript function to compute Fibonacci numbers.", + prompt: "Add pagination to the API", }); console.log(result.code); console.log(result.receipts[0].ledgerHash); ``` -### CLI +Agents operate under CRK-2 governance — every plan, execution, and output is **verifiable**. ```bash -npx nova generate "Write a factorial function in TypeScript." npx nova plan "Refactor the data access layer" -npx nova continuity +npx nova generate "Write a factorial function in TypeScript." npx nova receipts +npx nova continuity ``` -### Cockpit (Flight Deck UI) +--- -```bash -npm run cockpit -``` +## Mission #002: Founder-Independent Reproduction -Opens the React cockpit at `http://localhost:5173` with kernel status, receipts, continuity matrix, and drift visualization. +Mission #002 proves that Nova's governed runtime can be **reproduced and verified independently**. ---- +| Goal | Rebuild the system from the observer bundle and confirm drift-free behavior | +|------|-------------------------------------------------------------------------------| + +**Includes** + +| Path | Contents | +|------|----------| +| [`observer/`](observer/) | Verification tools, checklist, expected output | +| [`docs/`](docs/) | Architecture, CRK-2 spec, operator certification | +| [`observer-bundle-mission-002.zip`](observer-bundle-mission-002.zip) | Immutable reference bundle | + +**Verification steps** + +1. Prepare a clean machine (Node.js 18+, Git) +2. Clone, `npm install`, `npm run build` +3. Rebuild CRK-2 and Nova SDK artifacts +4. Run the agent (`npx nova …` or `AgentRuntime`) +5. Verify receipts, ledger entries, and PIT transitions +6. Sign off via [`observer/CHECKLIST.md`](observer/CHECKLIST.md) -## Observer Bundle +→ Protocol: [`observer/REPRO_PROTOCOL.md`](observer/REPRO_PROTOCOL.md) · Brief: [`MISSION-002.md`](MISSION-002.md) -Mission #002 ships a frozen observer bundle for independent verification: +**Bundle attestation** | Property | Value | |----------|-------| -| File | [`observer-bundle-mission-002.zip`](observer-bundle-mission-002.zip) | +| File | `observer-bundle-mission-002.zip` | | SHA-256 | `5FFDF5B95095E9FA2C4331EE71739850C335D3F0FF7EBBC3F0E3C1BAB020BD82` | -| Size | 151,078 bytes | -Verify: +--- + +## Quick Start ```bash -# macOS / Linux -shasum -a 256 observer-bundle-mission-002.zip +git clone https://github.com/warheart1984-ctrl/agentic-coding-agent.git +cd agentic-coding-agent +npm install +npm run build +``` + +**Cockpit (operator UI)** + +```bash +npm run cockpit +``` + +Opens the React flight deck at `http://localhost:5173`. + +--- + +## Project Structure -# Windows PowerShell -Get-FileHash -Algorithm SHA256 observer-bundle-mission-002.zip +``` +agentic-coding-agent/ +├── agent/ # Nova Agent SDK (AgentRuntime + governance) +├── crk2/ # Constitutional Runtime Kernel v2 +├── control-tower/ # Multi-agent orchestration +├── backend/ # Service layer + WebSocket events gateway +├── cockpit/ # Operator UI (NovaShell + Flight Deck) +├── observer/ # Mission #002 verification protocol +├── config/ # Mission invariants (nova.config.ts) +├── docs/ # Architecture & specs +├── examples/ # Governed project templates +├── tools/fuzz/ # Kernel fuzz harness +└── shell/ # Lawful Nova dev shell (bootstrap; separate concern) ``` -Follow [`observer/REPRO_PROTOCOL.md`](observer/REPRO_PROTOCOL.md) and sign off with [`observer/CHECKLIST.md`](observer/CHECKLIST.md). +> `shell/` is the self-bootstrapping Nova dev environment (macOS / Linux / Windows). It is intentionally separate from Mission #002 runtime code. See [`shell/README.md`](shell/README.md). --- -## SDK API Surface +## For Developers + +Build governed agents using the Nova SDK and CRK-2 kernel primitives. -**Primary:** `AgentRuntime` +| Resource | Link | +|----------|------| +| Architecture | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | +| CRK-2 spec | [`docs/CRK-2-SPEC.md`](docs/CRK-2-SPEC.md) | +| Control Tower | [`docs/NOVA-CONTROL-TOWER.md`](docs/NOVA-CONTROL-TOWER.md) | +| SDK entry | [`agent/runtime/agent-runtime.ts`](agent/runtime/agent-runtime.ts) | + +**Primary API** ```typescript const runtime = new AgentRuntime(); -await runtime.validate(action); // Pre-flight invariant check -await runtime.receipt(action, invIds); // Record + hash-chain -runtime.ledger.append(receipt); // Direct ledger access -runtime.ledger.tailHash(); // Chain tip +await runtime.validate(action); +await runtime.receipt(action, invIds); +runtime.ledger.append(receipt); +runtime.ledger.tailHash(); ``` -**Governance namespace:** +--- -```typescript -import { governance } from "./agent"; +## For Verifiers -await governance.validate(action); -await governance.receipt(action, ["no-dangerous-shell"]); -governance.ledger.append(receipt); -``` +Use Mission #002 to independently reproduce and validate the runtime. -Legacy `nova.*` and `runtime.*` namespaces remain exported for backward compatibility but are deprecated. +1. Verify bundle hash (see table above) +2. Follow [`observer/REPRO_PROTOCOL.md`](observer/REPRO_PROTOCOL.md) +3. Compare output to [`observer/EXPECTED_OUTPUT.md`](observer/EXPECTED_OUTPUT.md) +4. Complete [`observer/CHECKLIST.md`](observer/CHECKLIST.md) + +Release notes and attestation: [`RELEASE.md`](RELEASE.md) + +--- + +## Architecture overview + +| Concern | Document | +|---------|----------| +| System layers and data flow | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | +| CRK-2 dual-stack (CRK-1 → CRK-2) | [`docs/CRK-2-SPEC.md`](docs/CRK-2-SPEC.md) · [`docs/CRK-1-TO-CRK-2-MIGRATION-PLAN.md`](docs/CRK-1-TO-CRK-2-MIGRATION-PLAN.md) | +| Figma-ready layer diagram | [`docs/WHAT-MY-AGENTIC-CODING-AGENT-DOES.md`](docs/WHAT-MY-AGENTIC-CODING-AGENT-DOES.md) | +| SDK and governance API | [`docs/api/governance.md`](docs/api/governance.md) · [`docs/api/nova.md`](docs/api/nova.md) | +| Mission #002 reproduction | [`MISSION-002.md`](MISSION-002.md) · [`observer/REPRO_PROTOCOL.md`](observer/REPRO_PROTOCOL.md) | --- @@ -194,11 +248,18 @@ Legacy `nova.*` and `runtime.*` namespaces remain exported for backward compatib | Doc | Purpose | |-----|---------| | [MISSION-002.md](MISSION-002.md) | Mission brief + reproduction protocol | -| [RELEASE.md](RELEASE.md) | Release notes + bundle attestation | -| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | System architecture | -| [docs/CRK-2-SPEC.md](docs/CRK-2-SPEC.md) | CRK-2 constitutional kernel spec | -| [docs/NOVA-CONTROL-TOWER.md](docs/NOVA-CONTROL-TOWER.md) | Control Tower orchestration | -| [observer/REPRO_PROTOCOL.md](observer/REPRO_PROTOCOL.md) | Observer reproduction steps | +| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Constitutional runtime architecture | +| [docs/CRK-2-SPEC.md](docs/CRK-2-SPEC.md) | CRK-2 kernel specification | +| [docs/NOVA-CONTROL-TOWER.md](docs/NOVA-CONTROL-TOWER.md) | Multi-agent orchestration | +| [docs/index.md](docs/index.md) | Documentation hub | + +--- + +## Core Principle + +**Lawfulness. Accountability. Continuity.** + +Nova transforms ideas into infrastructure — one invariant at a time. --- diff --git a/bin/run_local_governed.ts b/bin/run_local_governed.ts new file mode 100644 index 0000000..782dce5 --- /dev/null +++ b/bin/run_local_governed.ts @@ -0,0 +1,80 @@ +#!/usr/bin/env node +import { readFileSync } from "fs"; +import { resolve } from "path"; +import { governedPredict } from "../src/runtime/governedPredict"; +import type { GovernedContext } from "../src/runtime/types"; + +interface LocalGovernedConfig { + model_path: string; + operator_id: string; + invariant_set_version: string; + log_receipts: boolean; + log_lineage: boolean; +} + +function loadYamlConfig(filePath: string): LocalGovernedConfig { + const text = readFileSync(filePath, "utf8"); + const raw: Record = {}; + for (const line of text.split("\n")) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + const idx = trimmed.indexOf(":"); + if (idx === -1) continue; + const key = trimmed.slice(0, idx).trim(); + let value = trimmed.slice(idx + 1).trim(); + if ( + (value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'")) + ) { + value = value.slice(1, -1); + } + raw[key] = value; + } + return { + model_path: raw.model_path ?? "./models/local-llm", + operator_id: process.env.OPERATOR_ID ?? raw.operator_id ?? "local-operator-001", + invariant_set_version: raw.invariant_set_version ?? "K0-K12-v1", + log_receipts: raw.log_receipts !== "false", + log_lineage: raw.log_lineage !== "false", + }; +} + +async function main(): Promise { + const configPath = resolve(process.cwd(), "config/local-governed.yaml"); + const config = loadYamlConfig(configPath); + const prompt = process.argv.slice(2).join(" ") || "Say hello, but do not violate any invariants."; + + const context: GovernedContext = { + operator_id: config.operator_id, + mode: "predict", + invariant_set_version: config.invariant_set_version, + model_path: config.model_path, + }; + + const result = await governedPredict(prompt, context); + + console.log("--- Model output ---"); + console.log(result.output); + console.log("\n--- Receipt ---"); + console.log( + JSON.stringify( + { + call_id: result.receipt.call_id, + operator_id: result.receipt.operator_id, + invariants_passed: result.receipt.invariants_passed, + mode: result.receipt.mode, + invariant_set_version: result.receipt.invariant_set_version, + }, + null, + 2 + ) + ); + console.log("\n--- Lineage ---"); + console.log(`root_id: ${result.lineage.root_id}`); + console.log(`entry_id: ${result.lineage.entry_id}`); +} + +main().catch((err: unknown) => { + console.error(err instanceof Error ? err.message : err); + process.exit(1); +}); diff --git a/cockpit/src/bridge/nova-sdk-browser.ts b/cockpit/src/bridge/nova-sdk-browser.ts new file mode 100644 index 0000000..a1ad7bc --- /dev/null +++ b/cockpit/src/bridge/nova-sdk-browser.ts @@ -0,0 +1,235 @@ +export type AgentAction = { + type: string; + payload?: unknown; +}; + +export interface PlanStep { + id: string; + description: string; + action: AgentAction; +} + +export interface Plan { + id: string; + steps: PlanStep[]; + justification: string; + receipts: GovernanceReceipt[]; +} + +export type InvariantSeverity = "error" | "warn"; + +export interface InvariantState { + action?: AgentAction; + diff?: string; + code?: string; + prompt?: string; + runTests?: () => Promise<{ failures: number }>; +} + +export interface Invariant { + id: string; + description: string; + severity: InvariantSeverity; + check: (state: InvariantState) => boolean | Promise; +} + +export interface InvariantViolation { + id: string; + invariantId: string; + description: string; + message: string; + severity: InvariantSeverity; + action: AgentAction; +} + +export interface GovernanceReceipt { + id: string; + timestamp: number; + action: AgentAction; + invariantsChecked: string[]; + continuityHash: string; + ledgerHash: string; + blocked?: boolean; + blockReason?: string; +} + +export interface KernelStatus { + invariantEngine: "ok" | "warn" | "error"; + ledger: "ok" | "warn" | "error"; + continuity: "ok" | "warn" | "error"; + violationsLastMinute: number; + receiptCount: number; + snapshotCount: number; + activeInvariants: number; +} + +export type KernelHeartbeat = KernelStatus & { + kernelId: string; + ts: number; +}; + +export interface Snapshot { + id: string; + timestamp: number; + stateHash: string; +} + +type Listener = (value: T) => void; + +const invariants: Invariant[] = []; +const receipts: GovernanceReceipt[] = []; +const snapshots: Snapshot[] = []; +const listeners = { + plan: [] as Listener[], + action: [] as Listener[], + receipt: [] as Listener[], + violation: [] as Listener[], + kernelHeartbeat: [] as Listener[], +}; + +const workspaceContext = { + root: "/workspace", + files: ["agent/index.ts", "package.json", "config/nova.config.ts"], +}; + +function browserHash(input: string): string { + let hash = 2166136261; + for (let i = 0; i < input.length; i += 1) { + hash ^= input.charCodeAt(i); + hash = Math.imul(hash, 16777619); + } + return `browser-${(hash >>> 0).toString(16).padStart(8, "0")}`; +} + +function emitReceipt(action: AgentAction, blocked = false): GovernanceReceipt { + const receipt: GovernanceReceipt = { + id: crypto.randomUUID(), + timestamp: Date.now(), + action, + invariantsChecked: invariants.map((invariant) => invariant.id), + continuityHash: browserHash(`continuity:${Date.now()}:${receipts.length}`), + ledgerHash: browserHash(`ledger:${Date.now()}:${receipts.length}`), + blocked, + }; + receipts.unshift(receipt); + listeners.receipt.forEach((listener) => listener(receipt)); + return receipt; +} + +async function kernelStatus(): Promise { + return { + invariantEngine: invariants.length > 0 ? "ok" : "warn", + ledger: "ok", + continuity: "ok", + violationsLastMinute: 0, + receiptCount: receipts.length, + snapshotCount: snapshots.length, + activeInvariants: invariants.length, + }; +} + +async function emitKernelHeartbeat(): Promise { + const heartbeat: KernelHeartbeat = { + ...(await kernelStatus()), + kernelId: "cockpit-browser", + ts: Date.now(), + }; + listeners.kernelHeartbeat.forEach((listener) => listener(heartbeat)); + return heartbeat; +} + +export const events = { + onPlan(listener: Listener): void { + listeners.plan.push(listener); + }, + onAction(listener: Listener): void { + listeners.action.push(listener); + }, + onReceipt(listener: Listener): void { + listeners.receipt.push(listener); + }, + onViolation(listener: Listener): void { + listeners.violation.push(listener); + }, + onKernelHeartbeat(listener: Listener): void { + listeners.kernelHeartbeat.push(listener); + }, +}; + +export const governance = { + async requireInvariant(invariant: Invariant): Promise { + if (!invariants.some((existing) => existing.id === invariant.id)) { + invariants.push(invariant); + } + }, + getInvariants(): Invariant[] { + return [...invariants]; + }, + async kernelStatus(): Promise { + return kernelStatus(); + }, + async emitKernelHeartbeat(): Promise { + return emitKernelHeartbeat(); + }, +}; + +export const continuity = { + async snapshot(): Promise { + const snapshot = { + id: crypto.randomUUID(), + timestamp: Date.now(), + stateHash: browserHash(`${Date.now()}:${receipts.length}:${snapshots.length}`), + }; + snapshots.push(snapshot); + return snapshot; + }, + getSnapshots(): readonly Snapshot[] { + return snapshots; + }, + async replay(id: string): Promise<{ snapshot: Snapshot | null; receipts: GovernanceReceipt[] }> { + return { + snapshot: snapshots.find((snapshot) => snapshot.id === id) ?? null, + receipts: [...receipts], + }; + }, +}; + +export const runtime = { + async getContext(): Promise { + return workspaceContext; + }, +}; + +export const nova = { + async plan(input: { goal: string; context?: unknown }): Promise { + const plan: Plan = { + id: crypto.randomUUID(), + justification: "Browser cockpit plan preview", + receipts: [], + steps: [ + { + id: "step-1", + description: `Analyze goal: ${input.goal}`, + action: { type: "plan", payload: input }, + }, + { + id: "step-2", + description: "Route through governed runtime before execution", + action: { type: "plan", payload: { phase: "governance" } }, + }, + ], + }; + listeners.plan.forEach((listener) => listener(plan)); + return plan; + }, + async generateCode(input: { prompt: string }): Promise<{ code: string; receipts: GovernanceReceipt[] }> { + const action = { type: "generate", payload: input }; + const code = `// Generated cockpit preview\n// ${input.prompt}\n`; + const receipt = emitReceipt(action); + listeners.action.forEach((listener) => listener(action)); + return { code, receipts: [receipt] }; + }, + async applyPatch(input: { diff: string; reason: string }): Promise<{ receipt: GovernanceReceipt }> { + return { receipt: emitReceipt({ type: "apply_patch", payload: input }) }; + }, +}; diff --git a/cockpit/src/panels/DiffInspector.tsx b/cockpit/src/panels/DiffInspector.tsx index 18348e0..b80efd4 100644 --- a/cockpit/src/panels/DiffInspector.tsx +++ b/cockpit/src/panels/DiffInspector.tsx @@ -18,7 +18,7 @@ export function DiffInspector() { if (!diff) { return ( -
No diff selected — generate code or refactor to inspect.
+
No diff selected - generate code or refactor to inspect.
); } @@ -26,14 +26,14 @@ export function DiffInspector() { return (
-
— before —
+
- before -
{diff.text}
Action: {diff.metadata.action}
Invariants: [{diff.metadata.invariantsChecked.join(", ")}]
Continuity Hash: {diff.metadata.continuityHash}
-
Receipt: {diff.metadata.receiptId ?? "—"}
+
Receipt: {diff.metadata.receiptId ?? "-"}