Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
b17f918
test: guard harness R1 package boundaries
Grivn Jun 23, 2026
5fb4b17
feat: add R1 teamwork capability schemas
Grivn Jun 23, 2026
291b990
feat: add R1 render cue endpoint
Grivn Jun 23, 2026
081719f
feat: add R1 thin render shim
Grivn Jun 23, 2026
1aeb5b8
feat: gate R1 thin shim projection
Grivn Jun 23, 2026
15a453c
test: cover R1 teamwork cue loop
Grivn Jun 23, 2026
2fc270e
test: align R1 harness e2e assignments
Grivn Jun 23, 2026
5d0b593
refactor: prune codex team demo command
Grivn Jun 23, 2026
fe004dc
refactor: prune loopdef dynamic vocabulary
Grivn Jun 23, 2026
8b27c88
refactor: default setup to R1 thin hooks
Grivn Jun 23, 2026
09b3fae
refactor: route runtime context through render
Grivn Jun 23, 2026
a33de53
feat: install R1 standard host shim
Grivn Jun 23, 2026
70b4086
refactor: make setup use the R1 host shim
Grivn Jun 23, 2026
fc88ca5
refactor: prune legacy loop projection
Grivn Jun 23, 2026
89e6d5a
feat: add R1 Codex acceptance runner
Grivn Jun 23, 2026
5f1d494
feat: cover R1 Codex sync acceptance
Grivn Jun 23, 2026
ac8a2d3
refactor: derive hostagent events before cue text
Grivn Jun 24, 2026
84ee2ac
refactor(harness): normalize event substrate internals
Grivn Jun 24, 2026
bf6405d
refactor(harness): exchange synced events through mnemonhub
Grivn Jun 24, 2026
6a49ab4
refactor(harness): present derived events as event views
Grivn Jun 24, 2026
b87ee8b
test(harness): add production-like event acceptance
Grivn Jun 24, 2026
3910346
chore(harness): remove unreachable helper code
Grivn Jun 24, 2026
225d5f1
chore(harness): consolidate acceptance observation command
Grivn Jun 24, 2026
379b901
test(harness): guard main-axis package ownership
Grivn Jun 24, 2026
bc6f922
refactor(harness): move remote sync under mnemonhub exchange
Grivn Jun 24, 2026
b457505
refactor(harness): move render under mnemond presentation
Grivn Jun 24, 2026
7a6782d
refactor(harness): rename host surface package to hostagent
Grivn Jun 24, 2026
44a8c90
refactor(harness): move capability semantics under mnemond policy
Grivn Jun 24, 2026
03263f9
refactor(harness): move channel under mnemond access
Grivn Jun 24, 2026
693a26e
refactor(harness): move event view under mnemond presentation
Grivn Jun 24, 2026
eb9fe33
refactor(harness): group admission rules under mnemond
Grivn Jun 24, 2026
c3e7e54
refactor(harness): group state store under mnemond
Grivn Jun 24, 2026
7d76b56
refactor(harness): rename state materializer API
Grivn Jun 24, 2026
275f46a
refactor(harness): rename presentation view access
Grivn Jun 24, 2026
d7b4957
refactor(harness): introduce presentation presenters
Grivn Jun 24, 2026
6281ae3
test(harness): guard presentation dataflow boundary
Grivn Jun 24, 2026
873ab7a
test(harness): prove memory dataflow presentation
Grivn Jun 24, 2026
ffc5698
refactor(harness): remove memory skill embedded capabilities
Grivn Jun 24, 2026
8ca676a
docs(harness): align docs with event package purity
Grivn Jun 24, 2026
f2f1f77
refactor(harness): converge event package registry
Grivn Jun 24, 2026
9a32325
refactor(harness): make host hooks guide-driven
Grivn Jun 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ unit: ## Run Go unit tests
vet: ## Run go vet static analysis
go vet ./...

harness-validate: ## Validate harness loop manifests and declared asset paths
harness-validate: ## Validate harness event packages
bash scripts/validate_harness_loops.sh

harness-docs-check: ## Check bilingual harness doc heading sync
Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,7 @@ Different agents/processes can use different stores via the `MNEMON_STORE` envir

**How do I customize the behavior?**
Edit the generated guideline (`~/.mnemon/prompt/guide.md` in current setup
flows) or use the installable [memory loop GUIDE](harness/internal/assets/loops/memory/GUIDE.md)
as the source. The skill file should stay focused on command syntax.
flows). Skill files should stay focused on command syntax.

**What is sub-agent delegation?**
Sub-agent delegation is optional. When a runtime supports it, the main agent can
Expand Down Expand Up @@ -396,8 +395,6 @@ See [Development and Deployment](docs/DEPLOYMENT.md) for Docker, Compose, Ollama
## Documentation

- [Mnemon Harness Beta](harness/README.md) — experimental host-agent lifecycle state
- [Memory Loop Harness](harness/internal/assets/loops/memory/README.md) — installable memory loop assets
- [Skill Loop Harness](harness/internal/assets/loops/skill/README.md) — installable skill loop assets
- [Design & Architecture](docs/DESIGN.md) — current engine architecture, algorithms, integration design
- [Usage & Reference](docs/USAGE.md) — CLI commands, embedding support, architecture overview
- [Memory Import Guide](docs/IMPORT.md) — schema and LLM prompt for importing historical chats
Expand Down
2 changes: 1 addition & 1 deletion docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Markdown-installable runtime integration: `SKILL.md`, `INSTALL.md`, `GUIDELINE.m

### [Self-Evolution Harness](harness/README.md)

The formal modular harness docs for agent-agnostic installation, memory loop, skill loop, and future attachable evolution modules.
The formal modular harness docs for agent-agnostic installation, Agent Integration, event packages, and future attachable evolution modules.

### [8. Design Decisions & Future Direction](design/08-decisions.md)

Expand Down
14 changes: 7 additions & 7 deletions docs/harness/QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Goal: stand up Local Mnemon, observe one candidate, and see it admitted as a
governed decision on the Control Tower.

```sh
# 1. install the integration for your host + a memory loop
mnemon-harness setup --host codex --loop memory \
# 1. install the integration for your host
mnemon-harness setup --host codex \
--principal codex@project --control-url http://127.0.0.1:8801

# 2. start Local Mnemon (the local governance daemon)
Expand All @@ -25,8 +25,8 @@ mnemon-harness local run &
mnemon-harness control observe \
--addr http://127.0.0.1:8801 --principal codex@project \
--token-file .mnemon/harness/channel/credentials/codex-project.token \
--type memory.write_candidate.observed --external-id q1 \
--payload '{"content":"my first governed memory","source":"user","confidence":"high"}'
--type progress_digest.write_candidate.observed --external-id q1 \
--payload '{"summary":"my first governed event"}'
# -> observed seq=1 dup=false ticked=true

# 4. stop the daemon, then read the Control Tower (it needs exclusive store access)
Expand All @@ -39,7 +39,7 @@ to its proposer:

```
# LEDGER
dec_… by codex@project -> memory
dec_… by codex@project -> progress_digest
```

That is the whole point: a candidate became a **governed, attributed decision**
Expand All @@ -53,7 +53,7 @@ Goal: declare a new event kind as a loop package and watch it govern, with no
code — a capability is **data that SELECTS from a closed catalog** of validators
and renderers, never new behavior.

Start from a working install (Path A, or `setup --host codex --loop memory …`).
Start from a working install (Path A, or `setup --host codex …`).

```sh
# 1. drop a loop package: .mnemon/loops/<name>/capability.json
Expand Down Expand Up @@ -81,7 +81,7 @@ JSON
# allowed_observed_types: "note.write_candidate.observed"
# subscription_scope: {"kind":"note","id":"project"}

# 3. run + observe your new kind — it governs through the SAME path as the built-ins
# 3. run + observe your new kind — it governs through the SAME path as embedded descriptors
mnemon-harness local run &
mnemon-harness control observe \
--addr http://127.0.0.1:8803 --principal codex@project \
Expand Down
16 changes: 8 additions & 8 deletions docs/harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
assets and connecting them to a local Mnemon service.

Stable Mnemon remains the memory CLI. The harness is source-build only, has no
compatibility guarantee, and is currently scoped to memory and skill
integration.
compatibility guarantee, and is currently scoped to Agent Integration, Local
Mnemon, standard event packages, and Remote Workspace sync.

## 1. Product Surface

The user-facing command surface is intentionally small:

- `setup`: install memory and skill Agent Integration assets.
- `setup`: install Agent Integration shim assets.
- `local`: run or inspect Local Mnemon.
- `status`: show Agent Integration, Local Mnemon, and Remote Workspace state.
- `sync`: connect Local Mnemon to a Remote Workspace.
Expand All @@ -21,9 +21,9 @@ contract.

## 2. Current Scope

The beta supports Codex and Claude Code projections for the memory and skill
loops. Projected host directories such as `.codex/` and `.claude/` are generated
surfaces. Local state lives under `.mnemon/harness/`.
The beta supports Codex and Claude Code projections. Projected host directories
such as `.codex/` and `.claude/` are generated surfaces. Local state lives under
`.mnemon/harness/`.

The current beta does not promise production readiness, automatic apply,
multi-agent governance, broad organization scope, or a general evaluation
Expand All @@ -45,10 +45,10 @@ go build -o mnemon .
go build -o mnemon-harness ./harness/cmd/mnemon-harness
```

Install memory and skill integration for a project:
Install Agent Integration for a project:

```sh
./mnemon-harness setup --host codex --loop memory --loop skill --project-root .
./mnemon-harness setup --host codex --project-root .
./mnemon-harness local run
./mnemon-harness status
```
Expand Down
8 changes: 4 additions & 4 deletions docs/harness/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ go build -o mnemon-harness ./harness/cmd/mnemon-harness

## 1. Install Agent Integration

Install memory and skill integration into the current project:
Install Agent Integration into the current project:

```sh
./mnemon-harness setup --host codex --loop memory --loop skill --project-root .
./mnemon-harness setup --host codex --project-root .
```

Use `--dry-run` to preview file changes:

```sh
./mnemon-harness setup --host codex --loop memory --loop skill --project-root . --dry-run
./mnemon-harness setup --host codex --project-root . --dry-run
```

## 2. Run Local Mnemon

Start the local service used by the projected host skills:
Start the local service used by the host integration:

```sh
./mnemon-harness local run
Expand Down
12 changes: 6 additions & 6 deletions docs/harness/capability-spec-v1.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Capability Spec v1 (frozen)

> Superseded by `capability-spec-v2.md` (P2, 2026-06-12). v2 formalizes the type grammar as a
> closed table (reserving the system-derived `<kind>.remote_commit.observed` form), defines how a
> closed table (reserving the system-derived `<kind>.remote_synced_event.observed` form), defines how a
> declared kind's required fields derive, and — per the R1 no-forward-compat revision channel —
> moves the KindCatalog membership check to the assembly-time declared set. This document remains
> the v1 record; the live compile path follows v2.
Expand Down Expand Up @@ -55,7 +55,7 @@ directory ≡ name ≡ kind as well, so the package directory IS the event famil
| member | params | deny message |
|---|---|---|
| `required` | `missing_style: empty\|missing` | `empty <field>` / `missing <field>` |
| `format:skill-id` | — | `invalid <field>` (lowercase a-z0-9 dash) |
| `format:identifier` | — | `invalid <field>` (lowercase a-z0-9 dash) |
| `enum` | `values: a\|b\|c`, `message` | `<message>` |
| `default` | `value` | — (fills trimmed-empty) |
| `default-from` | `field` (declared EARLIER) | — (fills from processed field) |
Expand All @@ -68,7 +68,7 @@ directory ≡ name ≡ kind as well, so the package directory IS the event famil

| member | params | output |
|---|---|---|
| `memory-entry-list` | — | `content` = the memory entry-list markdown |
| `entry-list` | — | `content` = the generic entry-list markdown |
| `bullet-list` | `title`, `field` (declared) | `content` = title + `"- "+item[field]` lines |

`static` is a literal field map. A member that evaluates user content as a template is FORBIDDEN
Expand All @@ -77,7 +77,7 @@ vocabulary — item values are joined, never executed. Render-produced keys must

## FromSpec fail-closed checks

schema_version == 1 · non-empty core fields · resource_kind ∈ KindCatalog · no duplicate fields ·
schema_version == 1 · non-empty core fields · resource_kind not reserved · no duplicate fields ·
member existence · exact param key sets (missing/unknown params rejected) · `default-from` only
backward references · `list:strings` exclusivity · render collision guards. Cross-spec (loader):
duplicate capability names / observed types / proposed types rejected.
Expand All @@ -94,8 +94,8 @@ package path) refuses Local Mnemon boot. Two deliberate differences from embedde
messages, `default` validator values — free prose that lands verbatim in items when the host
omits the field — render `static` values, and the bullet-list `title`) are scanned by the
secret/prompt-injection scanners; IDENTIFIERS (field names, `items_field`, render `static` keys)
are pattern-locked to `^[a-z][a-z0-9_-]*$` (underscore allowed — the builtin `skill_id` and
`items_field` shapes carry it); the spec `name` is pattern-locked via directory == name (== kind)
are pattern-locked to `^[a-z][a-z0-9_-]*$` (underscore allowed for descriptor field names such as
`items_field`); the spec `name` is pattern-locked via directory == name (== kind)
— because embedded spec text is reviewed code pinned by golden parity (TestSpecGoldens) while
external spec text is untrusted input; (b) the merge rejects shadowing on FOUR axes (name,
observed type, proposed type, resource kind) — an external spec can never displace or impersonate
Expand Down
19 changes: 9 additions & 10 deletions docs/harness/capability-spec-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
> assembled one). See `loop-package-v2.md` and the PD2 declared-kind mechanism.

The DATA form of a capability: `<name>/capability.json` (external) or
`assets/capabilities/<name>.json` (first-party), compiled by `capability.FromSpec` against the
`assets/capabilities/<name>.json` (embedded), compiled by `capability.FromSpec` against the
CLOSED validator and render catalogs. A spec only ever SELECTS compiled members and COMPOSES
closed validators — it never defines behavior (define≠select); everything unknown fails closed.

Expand All @@ -34,12 +34,12 @@ just free text).
|---|---|---|
| `<kind>.write_candidate.observed` | `observed_type` — the host's write candidate | yes |
| `<kind>.write.proposed` | `proposed_type` — the rule's proposal (reconciler consumes only `*.proposed`) | yes |
| `<kind>.remote_commit.observed` | sync-import observation the platform mints | **no — system-derived** |
| `<kind>.remote_synced_event.observed` | sync-import observation the platform mints | **no — system-derived** |

A spec that declares a system-derived form is rejected by name ("system-derived, not
spec-declarable"). New event families are added as a table ROW, not by reshaping the compile path
— this is the G7 extension point that lets P3's coordination/model-event families exist without
the grammar fighting them. The `remote_commit` form is the sync-import wire (`sync-abi-v2.md` §6);
the grammar fighting them. The `remote_synced_event` form is the sync-import wire (`sync-abi-v2.md` §6);
its rule and producer landed in PD6 (descriptor-derived import dispatch + the produce surface).

## Declared kind + required fields
Expand All @@ -55,11 +55,10 @@ kind's kernel-required fields DERIVE from the spec rather than a parallel hand-w
> fields are selected from — a kind can never require a field its writes do not carry. A spec's
> optional `required` array SELECTS a subset of those produced keys; omitted, every produced key is
> required. Because the capability emits its full header on every propose, the produced keys are
> exactly the fields every write carries, so the default reproduces the v1 hand-written
> `DefaultSchemaGuard` lines (memory render content → `{content}`; skill render static
> `{"name":"project"}` → `{name}`), and `required` narrows it where v1 hand-picked a subset (goal
> renders `{content, statement}` but required only `{statement}` → declares `"required":
> ["statement"]`). FromSpec rejects a `required` entry the render does not produce. The lockstep
> exactly the fields every write carries. `required` narrows that set where a spec renders multiple
> header fields but only some should be kernel-required (for example a kind rendering
> `{content, statement}` but declaring `"required": ["statement"]`). FromSpec rejects a `required`
> entry the render does not produce. The lockstep
> test becomes: governance kinds stay bidirectionally pinned in code; user kinds have a single
> source — the capability spec, read through the assembled catalog.

Expand All @@ -72,8 +71,8 @@ the wiring is in the runtime.

A declared kind may NOT: be a governance kind (`lease`/`budget`/`receipt`/`coordination`); be in the
reserved `mnemon` namespace (the exact kind `mnemon` or a `mnemon_` prefix — the kind grammar
`^[a-z][a-z0-9_]*$` admits no dot, so the namespace separator is `_`); collide with a first-party
event family whose diagnostics share a domain (`sync`, `session`, `remote`); or shadow any
`^[a-z][a-z0-9_]*$` admits no dot, so the namespace separator is `_`); collide with a reserved
system event family whose diagnostics share a domain (`sync`, `session`, `remote`); or shadow any
already-loaded capability on the four axes (name, observed type, proposed type, resource kind). External package text remains untrusted input —
values scanned by the secret/prompt-injection scanners, identifiers pattern-locked — exactly as in
v1's external-loader section.
Expand Down
10 changes: 5 additions & 5 deletions docs/harness/loop-package-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,17 @@ document maps to an enforcing fault class:
| strict spec decode | class ① bad JSON / trailing data / unknown keys (decodeSpec); ② unknown vocabulary, ③ kind outside KindCatalog (FromSpec) |
| no shadowing | class ④ four-axis merge rejection — name, observed type, proposed type, resource kind — external may not claim what embedded claims; ⑤ two externals may not collide either (incl. sharing a kind) |
| kernel-satisfiable | class ⑦ load-time SchemaGuard lockstep: statically derived header keys (static ∪ content ∪ items_field ∪ updated_by) must cover the kind's required fields |
| untrusted spec surfaces | class ⑧, EXTERNAL ONLY, two halves. VALUES → scanned by the secret + prompt-injection scanners: enum deny messages, `default` validator values, render static values, the bullet-list title. IDENTIFIERS → pattern-locked to `^[a-z][a-z0-9_-]*$` (underscore allowed; the builtin `skill_id`/`items_field` shapes carry it): field names, `items_field`, render static keys. The spec `name` is pattern-locked via directory == name (class ⑨) and scanned as belt-and-braces |
| untrusted spec surfaces | class ⑧, EXTERNAL ONLY, two halves. VALUES → scanned by the secret + prompt-injection scanners: enum deny messages, `default` validator values, render static values, the bullet-list title. IDENTIFIERS → pattern-locked to `^[a-z][a-z0-9_-]*$` (underscore allowed for descriptor field names such as `items_field`): field names, `items_field`, render static keys. The spec `name` is pattern-locked via directory == name (class ⑨) and scanned as belt-and-braces |
| no kernel-internal kinds | class ⑪: `lease`/`budget`/`receipt`/`coordination` are deny-listed for external claim |
| no symlinks | class ⑩: a symlinked external root, package dir, or capability.json is rejected by ResolveCatalog's lstat screening on the real path |

A bad package REFUSES `local run` boot — the directory's presence is a contract, not a hint;
`local run --ignore-external` is the operator escape hatch (embedded-only catalog, each ignored
package named on stderr). `loop validate` reports each loadable package as
`external capability <name>: OK` and goes red on any loader failure. Sync-import stays
memory/skill-only — narrower than Builtins: pushes are kind-agnostic, but the puller imports only
memory and skill commits and drops every other kind; external capabilities have no remote
producer in v1.
`external capability <name>: OK` and goes red on any loader failure. In v1, sync-import stayed
limited to a fixed embedded set — narrower than the catalog: pushes were kind-agnostic, but the
puller imported only that fixed set and dropped every other kind; external capabilities had no
remote producer in v1. This is superseded by `sync-abi-v2.md`.

## Migration provenance

Expand Down
2 changes: 1 addition & 1 deletion docs/harness/loop-package-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
> path-miss).
> 3. Prose assets (GUIDE.md, SKILL.md) carry a documentation-grade injection scan, not the
> content-grade secret scan (a legitimate GUIDE may honestly discuss "private keys").
> 4. The v1 "sync-import stays memory/skill-only … external capabilities have no remote producer"
> 4. The v1 "sync-import stays fixed-embedded-only … external capabilities have no remote producer"
> sentence is superseded by `sync-abi-v2.md` (PD6, descriptor-derived sync).

## Package contents (external packages, v2)
Expand Down
Loading
Loading