Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
322392a
feat(agentic-org): observe.ts run-state keystone + ZetaId/git-sync + …
maximdolphin May 30, 2026
e4e1014
feat(agentic-org): git-as-database-and-event-store via frontmatter + …
maximdolphin May 30, 2026
53c0e34
feat(agentic-org): frontmatter YAML codec, schema<->SQL + git<->cockr…
maximdolphin May 30, 2026
8f36fee
feat(agentic-org): git/cockroach sync adapters + reconcile worker; qu…
maximdolphin May 30, 2026
55eedcd
feat(agentic-org): slice 1 — state reconciliation table (North Star p…
maximdolphin May 30, 2026
fe42b61
feat(agentic-org): slice 2 — supervisor triage action resolver (North…
maximdolphin May 30, 2026
2c2e0f9
feat(agentic-org): slice 3 — agent-native knowledge graph projection …
maximdolphin May 30, 2026
61ddf57
feat(agentic-org): slice 4 — wire observe.ts to real work-item state
maximdolphin May 30, 2026
06e3cdf
feat(agentic-org): slice 5 — review board as a real gate
maximdolphin May 30, 2026
e2c1e4a
docs(agentic-org): slice 6 — doc coherence (status frontmatter + Nort…
maximdolphin May 30, 2026
fe8128b
fix(agentic-org): MD018 reflow in NORTH_STAR_ALIGNMENT_CHECKPOINT
claude May 30, 2026
7568d23
fix(agentic-org): install @nats-io v3 + pg deps — unblocks workers te…
maximdolphin May 30, 2026
d454c1f
feat(agentic-org): Phase 3 — deterministic keep-alive (org + agent li…
maximdolphin May 30, 2026
e19a8de
feat(agentic-org): Phase 4 — Hermes runtime + Hindsight memory + orch…
maximdolphin May 30, 2026
33e40d0
feat(agentic-org): Phase 5 — bootable process host + container substr…
maximdolphin May 30, 2026
c019a1d
feat(agentic-org): wire deterministic keep-alive as a third worker-ru…
maximdolphin May 30, 2026
d9c5a97
feat(agentic-org): make the deterministic keep-alive real — Cockroach…
maximdolphin May 30, 2026
4ac430c
docs(agentic-org): checkpoint — deterministic keep-alive control plan…
maximdolphin May 30, 2026
3733717
feat(agentic-org): k8s deploy substrate — cockroach + nats + worker m…
maximdolphin May 30, 2026
2856bc5
feat(agentic-org): k8s deadline tuning + spin-up-task publisher
maximdolphin May 30, 2026
cdf945d
docs(agentic-org): Phase 6 checkpoint — running in kubernetes-in-dock…
maximdolphin May 30, 2026
82c3d06
feat(agentic-org): agent liveness is real — second half of keep-alive…
maximdolphin May 30, 2026
c934313
docs(agentic-org): Phase 7 checkpoint — agent liveness real, both hal…
maximdolphin May 30, 2026
02e5c83
feat(agentic-org): wire the orchestration's Hermes heartbeat to the a…
maximdolphin May 30, 2026
22efcd8
docs(agentic-org): consolidation + honest status — keep-alive tenet #…
maximdolphin May 30, 2026
65b9170
feat(agentic-org): integrate the Hermes data plane into the deployed …
maximdolphin May 30, 2026
7ba4507
docs(agentic-org): Phase 9 capstone — autonomous data plane runs end-…
maximdolphin May 30, 2026
2e8c435
docs(agentic-org): the full watch loop closes in k8s — keep-alive cau…
maximdolphin May 30, 2026
2e1e984
fix(lint): MD032 blanks-around-lists in NORTH_STAR_ALIGNMENT_CHECKPOI…
claude May 30, 2026
f6d1d12
feat(agentic-org): independent fast keep-alive loop — decouple the he…
maximdolphin May 30, 2026
711b7f5
docs(agentic-org): independent keep-alive loop proven in k8s — heartb…
maximdolphin May 30, 2026
7bbb9d3
feat(agentic-org): durable Cockroach-backed Hindsight memory, wired i…
maximdolphin May 30, 2026
ac0d040
feat(agentic-org): durable Cockroach-backed Hermes runs, wired into t…
maximdolphin May 30, 2026
4bed8cc
fix(agentic-org): durable Hermes/memory id-collision + JSONB cast (ca…
maximdolphin May 30, 2026
286cbc0
docs(agentic-org): durable data plane runs to completion in k8s; live…
maximdolphin May 30, 2026
81c3df6
fix(markdownlint): MD032 blank lines around two lists in NORTH_STAR c…
claude May 30, 2026
3383ebe
feat(agentic-org): composed organization reaction-plan executor (agen…
maximdolphin May 30, 2026
4d838db
feat(workers): produce durable org artifacts in deployed worker
maximdolphin May 30, 2026
697059b
docs: record Phase 12 org-artifact command pipeline proven in-cluster
maximdolphin May 30, 2026
968147f
feat(application): agent decisions computed by the deterministic kernel
maximdolphin May 30, 2026
6f3a3a8
docs: record Phase 13 computed agent decision proven in-cluster
maximdolphin May 30, 2026
5a2f908
docs: record operator tenet #1 holistic keep-alive proof (org v594, 1…
maximdolphin May 30, 2026
f1055f2
feat: live LLM decision backend + real sandboxed tool execution
maximdolphin May 30, 2026
c2dd159
docs: record Phase 14 live LLM + sandboxed-tool backend proven in-clu…
maximdolphin May 30, 2026
bcace47
fix(lint): clear markdownlint MD032/MD026 in NORTH_STAR_ALIGNMENT_CHE…
claude May 30, 2026
b8fa461
fix(review): resolve all 7 Copilot review findings on PR #6071
maximdolphin May 30, 2026
711536e
feat(org): P0 blueprint + P1 org structure as data (16 depts + ~115 h…
maximdolphin May 30, 2026
808d3cb
feat(org): P2 hat binding lifecycle + expiry + succession + OrgEvent …
maximdolphin May 30, 2026
26ae95b
feat(org): P3 prioritization (directors/TPMs) + RMO hat-supply voting
maximdolphin May 30, 2026
960d6da
feat(org): P4 assignment engine (rank by reputation, assign within su…
maximdolphin May 30, 2026
82e9fd1
feat(org): P5 work pipeline driver (customer discovery -> release)
maximdolphin May 30, 2026
5682fa5
feat(org): P6 observability — org snapshot + Cockroach org_events/hat…
maximdolphin May 30, 2026
5fe5c83
feat(org): P7a org runtime — full end-to-end cycle ties all layers
maximdolphin May 30, 2026
2c363b1
feat(org): P7 end-to-end org cycle proven in kind — full hierarchy to…
maximdolphin May 30, 2026
7e77842
docs: record P7 — full hat+department org proven end-to-end in kind (…
maximdolphin May 30, 2026
e707441
fix(lint): clear markdownlint MD022 on P7 checkpoint heading
maximdolphin May 30, 2026
d469f5c
docs: design the dynamic memory system (hat+agent+work memory, weight…
maximdolphin May 30, 2026
6c0dec1
fix(agentic-org): unblock markdownlint — reflow line-leading `+` in O…
claude May 30, 2026
4bfb99c
docs(memory): add retrieval/storage reliability model + Hindsight int…
maximdolphin May 30, 2026
12597af
docs(memory): close 5 design gaps + ground Hindsight integration in i…
maximdolphin May 30, 2026
f8cce07
docs(work-os): W0 — gap audit + overhaul design for a true agentic Wo…
maximdolphin May 30, 2026
8a72a46
fix(agentic-org): close 2 Copilot P1 review findings on #6071
May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions agentic-organization/docs/DOC_FRONTMATTER_CONVENTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
title: Doc Frontmatter Convention
canonical_name: Agentic Organization
status: design
ideas: [3]
extends: [README.md]
composes_with:
- ./OBSERVE_COMPOSER_AND_RUN_STATE.md
- ./GIT_COCKROACH_SYNC_AND_ZETAID_ADDRESSING.md
code_anchors: []
supersedes: []
---

# Doc Frontmatter Convention

Operator idea 3: every design document in `agentic-organization/docs/` carries
YAML frontmatter with pointers to the documents and code it relates to, so the
doc set is a navigable graph rather than a flat list. The frontmatter is the
machine-readable edge layer; the prose is the node.

## Schema

```yaml
---
title: <human title, matches the H1>
canonical_name: Agentic Organization # always; never "Hermes"/"Work OS" at platform scope
status: design | v0 | implemented # lifecycle of the doc's content
ideas: [<operator idea numbers this doc covers>]
extends: [<doc filenames this builds directly on>]
composes_with: # related docs (bidirectional intent)
- ./<doc>.md
code_anchors: # real code paths the doc describes
- ../packages/<pkg>/src/<file>.ts
supersedes: [<doc filenames this replaces, if any>]
---
```

### Key semantics

- **`canonical_name`** — enforces the naming discipline from the README:
"Agentic Organization" is the platform; "Hermes" is *only* the agent runtime;
"Organization Work OS" is *only* the work-management subsystem. Docs whose
scope is one of those subsystems may still set `canonical_name: Agentic
Organization` and name the subsystem in the body.
- **`status`** — `design` (reference substrate), `v0` (smallest end-to-end
slice in flight), `implemented` (code exists and is tested). A doc moves
`design → v0 → implemented` as its `code_anchors` become real and green.
- **`extends` vs `composes_with`** — `extends` is the parent(s) a reader should
read first; `composes_with` is the lateral graph. Both are pointers, not
copies (substrate-or-it-didn't-happen: the pointed-at doc is the source of
truth).
- **`code_anchors`** — relative paths from the doc to real code. When a doc
claims a contract, the anchor proves it exists. Empty is allowed for
pure-design docs.
- **`supersedes`** — retraction-native: a superseding doc names what it
replaces; the replaced doc stays in git history (never deleted silently).

## Why pointers, not a central index

The README remains the human entry list, but it is hand-maintained and drifts.
Frontmatter pointers let a tool (or an agent) reconstruct the doc graph from the
files themselves — the same way `composes_with:` edges work in the backlog. The
graph is derivable, so it cannot rot out of sync with the docs.

## Two roles, one mechanism

Frontmatter plays two roles in the Agentic Organization, and they are the same
mechanism at two scopes:

1. **Doc-graph metadata** (this doc) — `title`/`status`/`extends`/`composes_with`/
`code_anchors` make the design docs a navigable graph.
2. **Database rows + schema** (`GIT_COCKROACH_SYNC_AND_ZETAID_ADDRESSING.md`) —
a `.md` file is a row, its frontmatter is the typed columns, and `fk`/`fk_array`
columns are graph edges resolved exactly like `composes_with`.

A doc's `composes_with` list *is* an `fk_array` over the docs "table"; a task row's
`depends_on` is an `fk_array` over the task table. The traversal code
(`packages/frontmatter-db/src/traverse.ts`) is therefore reusable for both: the
doc graph and the data graph are one graph with different schemas.

## Adoption

New docs MUST carry the frontmatter. Existing docs adopt it opportunistically as
they are edited (no big-bang rewrite). The two docs landed alongside this one
(`OBSERVE_COMPOSER_AND_RUN_STATE.md`, `GIT_COCKROACH_SYNC_AND_ZETAID_ADDRESSING.md`)
are the first adopters and the reference examples.

## Future: derive the graph

A small tool under `agentic-organization` (or the repo's `tools/`) can parse
frontmatter across `docs/*.md`, validate that every `extends`/`composes_with`
target exists, that `canonical_name` is set, and that `code_anchors` resolve to
real files — then emit the doc graph for the UI (composes with
`UI_AND_OBSERVABILITY_CONCEPTS.md`). That validator is the natural next slice for
this convention; until it lands, the discipline is enforced in review.
175 changes: 175 additions & 0 deletions agentic-organization/docs/GIT_COCKROACH_SYNC_AND_ZETAID_ADDRESSING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
title: Git as Database and Event Store (Frontmatter + ZetaId CRDT)
canonical_name: Agentic Organization
status: v0
ideas: [1, 2, 3, 7, 8]
extends:
- CLUSTER_EXECUTION_AND_MEMORY_SUBSTRATE.md
- V0_SCHEMA_AND_COMMANDS.md
composes_with:
- ./TECHNICAL_CA_PACKAGE_ARCHITECTURE.md
- ./OBSERVE_COMPOSER_AND_RUN_STATE.md
- ./DOC_FRONTMATTER_CONVENTION.md
code_anchors:
- ../packages/frontmatter-db/src/schema.ts
- ../packages/frontmatter-db/src/event.ts
- ../packages/frontmatter-db/src/crdt-log.ts
- ../packages/frontmatter-db/src/project.ts
- ../packages/frontmatter-db/src/sql-to-schema.ts
- ../packages/frontmatter-db/src/schema-to-sql.ts
- ../packages/frontmatter-db/src/frontmatter-codec.ts
- ../packages/frontmatter-db/src/event-codec.ts
- ../packages/frontmatter-db/src/sync.ts
- ../packages/frontmatter-db/src/git-fs-adapter.ts
- ../packages/frontmatter-db/src/cockroach-row-sink.ts
- ../packages/frontmatter-db/src/reconcile-worker.ts
- ../packages/frontmatter-db/src/traverse.ts
- ../packages/frontmatter-db/src/validate.ts
- ../../src/Core.TypeScript/zeta-id/zeta-id.ts
supersedes: []
---

# Git as Database and Event Store (Frontmatter + ZetaId CRDT)

The persistence and addressing layer. Operator vision (2026-05-29): **git is the
database and the event store**. A markdown file is a row; its YAML frontmatter is
the typed schema/columns; foreign-key columns are graph edges; events are
unique-id files that merge conflict-free as a CRDT; and the schema converts
to/from SQL. CockroachDB demotes to a rebuildable query index. Covers operator
ideas 1 (git<->cockroach converter), 2 (explicit DUs), 3 (frontmatter graph), 7
(no-collision ids), 8 (ZetaId decimal index).

> **Why this is git's native shape.** Linus Torvalds built git as a
> content-addressable object database (a "stupid content tracker"): `git
> hash-object` writes a blob keyed by its SHA, `git cat-file` reads it back;
> trees and commits are just objects on top. Git-as-db is not a hack — it is
> git used for what it fundamentally is. The one thing we add is a *stable,
> semantic, time-ordered* key (ZetaId) because a content SHA changes whenever
> content changes and therefore cannot be a primary key or a foreign-key target.

## The stack

```text
git object DB (durability + conflict-free merge)
└─ events/<table>/<ZetaIdDecimal>.md append-only event files ── G-Set CRDT
│ (frontmatter = op + aggregateId + field values + schema_version)
▼ fold in (timestamp, id) order ── retraction-native (Z-set)
<table>/<ZetaIdDecimal>.md materialized rows (current state)
│ (frontmatter = typed columns; fk columns = graph edges; body = doc)
▼ derive
CockroachDB rebuildable query / index projection
```

One **frontmatter schema** (derived from SQL) governs all four layers.

## Layer 1 — the schema is frontmatter, derived from SQL (ideas 2, 3)

`packages/frontmatter-db/src/schema.ts` defines the column model as an explicit
discriminated union (`ColumnType`: zeta_id, text, int, bool, timestamp, enum, fk,
fk_array). Payload-bearing kinds carry their payload as an explicit variant —
`enum` carries `values`, `fk`/`fk_array` carry `references` — never buried in
optional fields (repo rule: IMPLICIT-NOT-EXPLICIT is class error).

`sql-to-schema.ts` converts a `CREATE TABLE` into that schema:

| SQL | frontmatter column |
|-----|--------------------|
| `id TEXT PRIMARY KEY` | `{ type: zeta_id, pk: true, required: true }` |
| `status TEXT NOT NULL CHECK (status IN ('a','b'))` | `{ type: enum, required: true, values: [a, b] }` |
| `project_id TEXT REFERENCES project(id)` | `{ type: fk, references: project }` |
| `reviewer_ids TEXT[] REFERENCES hat_assignment(id)` | `{ type: fk_array, references: hat_assignment }` |
| `estimate INTEGER` / `created_at TIMESTAMPTZ NOT NULL` | `{ type: int }` / `{ type: timestamp, required: true }` |

The reverse (schema → `CREATE TABLE`) feeds the Cockroach projection, so the
schema is the single source both sides derive from — the existing
`state-cockroach/migrations` become derivable rather than hand-authored.

## Layer 2 — events are a ZetaId-keyed G-Set CRDT (ideas 7, 1)

`event.ts` + `crdt-log.ts`. Each event is one file named by its ZetaId decimal.
Because ZetaIds are globally unique (32-bit crypto-random field), two agents
writing concurrently produce **different filenames** — a git merge is a pure
union, never a content conflict. The log is therefore a **grow-only set keyed by
unique id**; `mergeLogs` is union, which is:

- **commutative** — `merge(a,b)` and `merge(b,a)` have the same ids
- **associative** — grouping does not matter
- **idempotent** — re-merging the same log changes nothing

(All three proven in `test/crdt-log.test.ts`.) These are the CRDT join laws, so
branches converge in any merge order. Collision policy is "minted once with
crypto randomness, addressed by decimal everywhere" — one id scheme, no
reconciliation.

## Layer 3 — state is a timestamp-ordered fold (ideas 8, 2)

`project.ts`. ZetaId embeds a 48-bit timestamp, so the event log is
self-ordering — `timestampMsFromZetaId` reads it straight out of the id. `project`
folds a table's events in `(timestamp, id)` order:

- `upsert` merges field values (last-writer-wins by timestamp)
- `retract` tombstones the aggregate (retraction-native, Z-set style; a later
upsert revives it)

Because the order is derived from the ids (not from insertion or merge order),
`project(merge(a,b)) === project(merge(b,a))` — the convergence property, proven
in `test/project.test.ts`. The resulting `FrontmatterRow`s are the materialized
rows of Layer 1; they are fully rebuildable from the event log (DST-replayable).

## Layer 4 — frontmatter is graph-traversed (idea 3)

`traverse.ts`. `fk` and `fk_array` columns are edges; `edgesOf(row, schema)`
yields them and `neighbors(row, schema, column, store)` resolves them against a
row store keyed by `ZetaIdDecimal`. This is the same edge mechanism the doc graph
uses (`composes_with` in `DOC_FRONTMATTER_CONVENTION.md`) — docs and data rows
share one traversal model.

## Layer 5 — Cockroach is the index, and the converter is generic (idea 1)

CockroachDB is the low-latency query projection (`WHERE status='ready' ORDER BY
created_at` over thousands of `.md` files is not viable; the index is). The
generic converter (`sync.ts`) is keyed by the schema and driven entirely through
injected ports (`GitEventSource`, `IndexRowSink`, `IndexRowSource`,
`GitEventSink`, `IdGenerator`), so the pure core has no git/db dependency and is
fully testable with in-memory fakes:

- **git → cockroach** (`syncGitToIndex`): fold the event log to rows via
`project`, upsert each into the index, and `deleteRow` any index id no longer
in the projection (tombstoned aggregates drop out) — returns
`{ applied: { upserted, deleted } }`
- **cockroach → git** (`syncIndexToGit`): emit one `Upsert` event per changed
row (id from `IdGenerator`, aggregateId from the row's pk); a row missing its
pk returns `row_missing_id` feedback rather than emitting a malformed event
- a committed command's event file rides the existing `messaging-nats` outbox;
a periodic full reconcile (`ALWAYS_ON_ORCHESTRATION_RUNTIME.md`) is the
recovery net

Conflicts cannot arise at the event layer (unique ids). At the *row* layer, two
upserts to the same aggregate are resolved deterministically by the timestamp
fold — there is no last-write-wins ambiguity to hand-resolve, because the id
*is* the clock.

## Status

Implemented and tested: `packages/frontmatter-db` — schema DUs, SQL→schema
(`sql-to-schema.ts`) and schema→SQL (`schema-to-sql.ts`, round-trip verified),
event/CRDT log, timestamp-ordered projection, validation, traversal, the on-disk
frontmatter YAML codec (`frontmatter-codec.ts`, lossless round-trip incl.
number-looking strings and arrays), and the port-based git↔cockroach sync core
(`sync.ts`). Full suite 318 green; real `tsc` clean for these files.

Also implemented and tested: the filesystem-backed Git adapter
(`git-fs-adapter.ts` + `event-codec.ts`, async load/flush over an in-memory
snapshot so the sync ports stay synchronous), the in-memory CockroachDB row sink
(`cockroach-row-sink.ts`, the rebuildable index, with a SQL-host `// TODO`), and
the periodic reconcile worker (`reconcile-worker.ts`, a `runOnce()` cycle
mirroring `worker-host.ts`). The reconcile cycle runs **index→git before
git→index** so a row written only to the index this cycle becomes an event before
the projection diff — otherwise git→index would tombstone-delete it as canonical.

Design/next: the real SQL-backed `CockroachRowSink` behind the port (the
`// TODO(cockroach-host)`), committing the adapter's written event files to git,
and wiring the reconcile worker onto the existing `messaging-nats` outbox +
scheduler. The ZetaId codec (ideas 7, 8) is the existing
cross-verified `src/Core.TypeScript/zeta-id`; `frontmatter-db` mirrors only its
timestamp-bit layout to stay self-contained.
114 changes: 114 additions & 0 deletions agentic-organization/docs/METRICS_AND_REVIEW_BOARD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: Metrics and the 3-Agent Review Board
canonical_name: Agentic Organization
status: v0
ideas: [2, 4]
extends:
- OBSERVABILITY_AND_SELF_HEALING.md
- BUSINESS_QUALITY_GATE_SYSTEM.md
composes_with:
- ./OBSERVE_COMPOSER_AND_RUN_STATE.md
- ./SUPERVISOR_CHAIN_COMMUNICATION.md
- ./DOC_FRONTMATTER_CONVENTION.md
code_anchors:
- ../packages/metrics/src/code-metrics.ts
- ../packages/metrics/src/review-board.ts
- ../packages/metrics/src/mcp-tools.ts
- ../packages/governance/src/constitution-gate.ts
supersedes: []
---

# Metrics and the 3-Agent Review Board

Operator idea 4, sharpened (2026-05-29): metrics have **two layers** — a
*quantitative* layer gathered mechanically like test coverage, and a
*qualitative* layer run by a board of reviewer agents who must **agree** before a
comment is published. The qualitative layer is the constitution gate (idea 2)
applied to review findings: ≥3 distinct reviewers, agreement required.

## Quantitative — "coverage for structure"

`packages/metrics/src/code-metrics.ts` measures source text the way a coverage
tool measures execution: deterministic, no judgment, just numbers.

| Metric (`CodeMetricKind`) | What it catches | Default warn / flag |
|---|---|---|
| `longest_function` | sprawling functions | 40 / 80 lines |
| `longest_class` | **god classes** | 200 / 400 lines |
| `file_length` | god files | 400 / 800 lines |
| `max_nesting_depth` | tangled control flow | 4 / 6 |

`analyzeSource(filePath, source, thresholds?)` returns a `CodeMetricsReport` with
the measured spans plus a list of `MetricFinding`s. Each finding is an explicit
DU on `metric` + `severity` (`ok`/`warn`/`flag`), so a "god class" finding is
structurally distinct from a "long file" finding — never collapsed into a generic
"too big" string. These are **heuristics that flag candidates**, not verdicts;
the verdict is the review board's.

## Qualitative — the 3-agent review board

`packages/metrics/src/review-board.ts`. A candidate finding becomes a published
comment only when a **quorum of distinct reviewer agents agree**. Reviewers vote
along explicit `ReviewDimension`s — `correctness`, `solid`,
`architecture_adherence`, `performance`, `testing` — the discussion axes the
operator named.

```text
CandidateFinding[] + ReviewerVote[] -> evaluateReviewBoard({ findings, votes, quorum? })
-> per finding: FindingDecision
```

`FindingDecision.state` is an explicit DU:

- **adopted** — ≥ quorum *distinct* reviewers agreed and fewer than quorum
disagreed; the comment is published
- **withheld** — too few distinct agreers; the comment is dropped (no
single reviewer can force a comment through)
- **contested** — quorum agreed *and* quorum disagreed; escalate rather than
silently pick a side

The board returns `feedback` (`too_few_reviewers`) if fewer than quorum distinct
reviewers participated at all — a 2-agent board cannot adopt anything when quorum
is 3.

### Why this is the constitution gate again

The agreement rule is identical in shape to
`governance/src/constitution-gate.ts`: **distinct** agreers (one agent voting
three times counts once — no self-amplification), quorum-gated, with disagreement
able to veto. The constitution gate ratifies *rule sets*; the review board
ratifies *review findings*. Same multi-oracle principle, two scopes. They live in
different packages (no cross-import across the boundary), so the logic is restated
rather than shared — but the semantics are deliberately the same, and both are
explicit DUs with no buried thresholds.

This is also why a review board sits naturally on the observe/compose keystone:
"publish this review comment" is exactly the kind of side effect that should pass
a gate before `decide()` lets a run act on it.

## MCP tool interface (hosting is a TODO)

`packages/metrics/src/mcp-tools.ts` exposes both layers as MCP tools — **the
interface only**. `METRICS_TOOL_DESCRIPTORS` advertises:

- `analyze_source` — gather quantitative metrics for one file
- `run_review_board` — run the ≥3-agent board over findings + votes

`dispatchMetricsTool(name, args)` is the pure in-process router an MCP server's
`call_tool` would delegate to; it returns an explicit `MetricsToolResult` DU
(`ok` with a typed payload per tool, or `feedback` for unknown-tool / bad-args).

The actual server **hosting is deliberately stubbed** (`// TODO(mcp-host)` in
`mcp-tools.ts`): advertise the descriptors via `list_tools`, map `call_tool` onto
`dispatchMetricsTool`, run over the cluster MCP gateway transport, and enforce
hat-token preflight before dispatch (metrics reads are low-risk; publishing review
comments is a scoped authority per `V0_POLICY_AND_RUNTIME_BOUNDARIES.md`). Per the
operator: build the tooling + the interface now, host the server later.

## Status

Implemented and tested: quantitative metrics, the qualitative review board, and
the MCP tool dispatch interface (`packages/metrics`, 15 tests; full suite 346
green). Design/next: the MCP server host behind `dispatchMetricsTool`; wiring
metric findings into the supervisor-chain so a `flag` becomes a triaged work
item; and persisting review decisions as evidence on the work item.
Loading
Loading