Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7bb8e3d
feat(harness): add remote workspace sync seam
Grivn Jun 25, 2026
64e7747
test(harness): guard GitHub remote workspace boundaries
Grivn Jun 25, 2026
3e2c973
feat(harness): add directional remote plans
Grivn Jun 25, 2026
e9a92b1
fix(harness): stabilize acceptance run-root guard
Grivn Jun 25, 2026
fc71c41
feat(harness): ingest remote pull diagnostics
Grivn Jun 25, 2026
74d9c13
feat(harness): add publication store seam
Grivn Jun 25, 2026
8a408b1
feat(harness): add fake-tested github publication backend
Grivn Jun 25, 2026
8ba3346
feat(harness): add github remote config shape
Grivn Jun 25, 2026
2b3c49a
feat(harness): add github publication store adapter
Grivn Jun 25, 2026
6ff50c5
test(harness): cover five-node github publication mesh
Grivn Jun 25, 2026
b9734a4
feat(harness): scaffold github mesh acceptance
Grivn Jun 25, 2026
8e2ea60
feat(harness): wire github mesh natural scenarios
Grivn Jun 25, 2026
faea4ee
fix(harness): normalize github publication cursors
Grivn Jun 25, 2026
2f07a1e
test(harness): add gated github live round trip
Grivn Jun 25, 2026
a91cd81
test(harness): strengthen github mesh acceptance evidence
Grivn Jun 25, 2026
c69d9a4
test(harness): cover github mesh join leave reassignment
Grivn Jun 25, 2026
ef95b52
docs(harness): record github mesh implementation checkpoint
Grivn Jun 25, 2026
febd01a
docs(harness): describe github remote workspace backend
Grivn Jun 25, 2026
cbeb532
test(harness): require governed github mesh task evidence
Grivn Jun 25, 2026
42a7fdf
test(harness): exercise github mesh mnemond lifecycle
Grivn Jun 25, 2026
b584a15
docs(harness): record live github validation pass
Grivn Jun 25, 2026
09652c9
feat(harness): use explicit github publication paths
Grivn Jun 25, 2026
33ca593
feat(harness): isolate github mesh acceptance branches
Grivn Jun 25, 2026
13eadca
fix(harness): throttle github mesh acceptance sync
Grivn Jun 25, 2026
718f6a5
test(harness): summarize github mesh sync evidence
Grivn Jun 25, 2026
4842fb7
fix(harness): preserve github rate limit hints
Grivn Jun 25, 2026
40a1488
test(harness): exercise github mesh delayed join
Grivn Jun 25, 2026
d5555aa
test(harness): assert github mesh natural evidence
Grivn Jun 25, 2026
6285c04
fix(harness): name github mesh branches by mnemond id
Grivn Jun 25, 2026
abb7469
fix(harness): pace github mesh branch creation
Grivn Jun 25, 2026
89f9e61
fix(harness): tolerate github mesh mnemond shutdown
Grivn Jun 25, 2026
498c87f
test(harness): make github mesh scenarios team-shaped
Grivn Jun 25, 2026
ba79426
test(harness): advance github mesh natural handoff
Grivn Jun 25, 2026
2572c3b
test(harness): scale github mesh profile convergence
Grivn Jun 25, 2026
dab3695
chore(harness): keep mnemon dev notes local
Grivn Jun 26, 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
8 changes: 7 additions & 1 deletion docs/harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ The user-facing command surface is intentionally small:
- `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.
- `sync`: connect Local Mnemon to a Remote Workspace. `mnemon-hub` is the
first-party backend; GitHub publication branches are available as an
experimental repo-mediated backend.

Other implementation commands are internal and are not part of the beta product
contract.
Expand All @@ -29,6 +31,10 @@ The current beta does not promise production readiness, automatic apply,
multi-agent governance, broad organization scope, or a general evaluation
runtime.

The GitHub Remote Workspace backend is experimental. It uses explicitly
configured publication branches and does not implement P2P discovery, GitHub
Issues, GitHub PRs, or GitHub Actions as teamwork semantics.

## 3. Separation From Stable Mnemon

`mnemon-harness` is built from `./harness/cmd/mnemon-harness`.
Expand Down
25 changes: 23 additions & 2 deletions docs/harness/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,33 @@ Inspect local state:

## 3. Remote Workspace Sync

Connect a Remote Workspace:
Connect an HTTP `mnemon-hub` Remote Workspace:

```sh
./mnemon-harness sync connect my-workspace
./mnemon-harness sync connect my-workspace --remote-url https://mnemon-hub.example/sync --token-file ./hub.token
```

Experimental GitHub publication backend:

```sh
./mnemon-harness sync connect self \
--backend github \
--direction publish \
--github-repo mnemon-dev/mnemon-teamwork-example \
--github-branch mnemon/agent-a \
--token-file ~/.config/mnemon/github.token

./mnemon-harness sync connect agent-b \
--backend github \
--direction subscribe \
--github-repo mnemon-dev/mnemon-teamwork-example \
--github-branch mnemon/agent-b \
--token-file ~/.config/mnemon/github.token
```

The GitHub backend is repo-mediated publication, not P2P discovery. Configure the
branches you publish and subscribe to explicitly.

Run one push or pull:

```sh
Expand Down
42 changes: 40 additions & 2 deletions harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ The current product surface is intentionally small:
- `setup` installs Agent Integration shim assets into Codex or Claude Code.
- `local run` starts the project-local Mnemon service.
- `status` reports Agent Integration, Local Mnemon, and sync status.
- `sync` connects Local Mnemon to a Remote Workspace (`mnemon-hub`) and pushes/pulls
governed commits with attribution preserved.
- `sync` connects Local Mnemon to a Remote Workspace and pushes/pulls governed
commits with attribution preserved. The first-party backend is `mnemon-hub`;
the experimental GitHub backend uses repo-mediated publication branches.
- `loop validate` remains hidden and is used by `make harness-validate`.

Host directories such as `.codex` and `.claude` are projection surfaces. Runtime
Expand Down Expand Up @@ -48,3 +49,40 @@ Remove projected assets for a principal:
```

More command examples are in `docs/harness/USAGE.md`.

## Experimental GitHub Remote Workspace

GitHub can be used as a bootstrap Remote Workspace backend for a decentralized
publication mesh. Each Local Mnemon publishes accepted synced events to its own
configured branch and subscribes to explicitly configured peer branches.

This is not P2P networking or GitHub Issues/PR-based teamwork. GitHub is only the
publication substrate; every imported event still enters through the receiving
Local Mnemon's Event Intake.

Example shape:

```sh
./mnemon-harness sync connect self \
--backend github \
--direction publish \
--github-repo mnemon-dev/mnemon-teamwork-example \
--github-branch mnemon/agent-a \
--token-file ~/.config/mnemon/github.token

./mnemon-harness sync connect agent-b \
--backend github \
--direction subscribe \
--github-repo mnemon-dev/mnemon-teamwork-example \
--github-branch mnemon/agent-b \
--token-file ~/.config/mnemon/github.token
```

Live validation is opt-in:

```sh
MNEMON_GITHUB_LIVE=1 \
MNEMON_GITHUB_REPO=mnemon-dev/mnemon-teamwork-example \
MNEMON_GITHUB_TOKEN_FILE=~/.config/mnemon/github.token \
go test ./harness/internal/app -run TestGitHubLivePublishPullImport -count=1 -v
```
58 changes: 56 additions & 2 deletions harness/cmd/mnemon-harness/acceptance.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/mnemon-dev/mnemon/harness/internal/mnemond/presentation"
"github.com/mnemon-dev/mnemon/harness/internal/mnemond/state"
"github.com/mnemon-dev/mnemon/harness/internal/mnemonhub"
"github.com/mnemon-dev/mnemon/harness/internal/mnemonhub/exchange"
"github.com/mnemon-dev/mnemon/harness/internal/runtime"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -147,8 +148,23 @@ type r1CodexAgentReport struct {

type r1CodexSyncReport struct {
Status string `json:"status"`
Backend string `json:"backend,omitempty"`
Repo string `json:"repo,omitempty"`
TransportModel string `json:"transport_model,omitempty"`
RosterSource string `json:"roster_source,omitempty"`
NetworkDiscovery string `json:"network_discovery,omitempty"`
HubURL string `json:"hub_url"`
PublicationBranches []string `json:"publication_branches,omitempty"`
BranchByAgent map[string]string `json:"branch_by_agent,omitempty"`
RemotePlanPaths []string `json:"remote_plan_paths,omitempty"`
RuntimeWorkspaces []string `json:"runtime_workspace_paths,omitempty"`
LocalStorePaths []string `json:"local_mnemond_store_paths,omitempty"`
PublishedByBranch map[string]int `json:"published_events_by_branch,omitempty"`
ImportedByMnemond map[string]int `json:"imported_events_by_mnemond,omitempty"`
DiagnosticsByMnemond map[string]int `json:"diagnostics_by_mnemond,omitempty"`
ProfileByMnemond map[string]int `json:"profile_events_by_mnemond,omitempty"`
AllowedEventSubjects []string `json:"allowed_event_subjects"`
Lifecycle []r1SyncLifecycleReport `json:"lifecycle,omitempty"`
Source string `json:"source"`
Target string `json:"target"`
Agents []r1CodexAgentReport `json:"agents"`
Expand All @@ -158,6 +174,16 @@ type r1CodexSyncReport struct {
Artifacts map[string]string `json:"artifacts,omitempty"`
}

type r1SyncLifecycleReport struct {
At string `json:"at"`
Principal string `json:"principal"`
Action string `json:"action"`
Result string `json:"result"`
Branch string `json:"branch,omitempty"`
Detail string `json:"detail,omitempty"`
Ledger map[string]int `json:"ledger,omitempty"`
}

type r1AcceptanceAssertion struct {
Name string `json:"name"`
Passed bool `json:"passed"`
Expand Down Expand Up @@ -376,7 +402,11 @@ func installAcceptanceHarnessBinary(runRoot string) (string, error) {
}

func prepareR1AcceptanceRunRoot(runRoot string) error {
testdataRoot, err := filepath.Abs(".testdata")
testdataRoot, err := physicalAcceptancePath(".testdata")
if err != nil {
return err
}
runRoot, err = physicalAcceptancePath(runRoot)
if err != nil {
return err
}
Expand All @@ -401,6 +431,30 @@ func prepareR1AcceptanceRunRoot(runRoot string) error {
return nil
}

func physicalAcceptancePath(path string) (string, error) {
abs, err := filepath.Abs(path)
if err != nil {
return "", err
}
if resolved, err := filepath.EvalSymlinks(abs); err == nil {
return resolved, nil
}
var missing []string
for current := abs; ; current = filepath.Dir(current) {
if resolved, err := filepath.EvalSymlinks(current); err == nil {
for i := len(missing) - 1; i >= 0; i-- {
resolved = filepath.Join(resolved, missing[i])
}
return resolved, nil
}
parent := filepath.Dir(current)
if parent == current {
return abs, nil
}
missing = append(missing, filepath.Base(current))
}
}

func setupR1CodexAgents(runRoot, binDir, controlURL string, count int, sourceCodexHome string) ([]r1CodexAgent, access.LoadedBindings, error) {
var agents []r1CodexAgent
var loaded access.LoadedBindings
Expand Down Expand Up @@ -1081,7 +1135,7 @@ func setupR1CodexSyncAgents(ctx context.Context, runRoot, binDir string, hub r1S
if i-1 >= len(hub.Tokens) {
return nil, fmt.Errorf("hub token missing for agent %d", i)
}
if err := upsertSyncRemote(filepath.Join(workspace, ".mnemon", "harness", "sync", "remotes.json"), workspace, "hub", hub.URL, hub.Tokens[i-1], "", ""); err != nil {
if err := upsertSyncRemote(filepath.Join(workspace, ".mnemon", "harness", "sync", "remotes.json"), workspace, "hub", exchange.RemoteBackendHTTP, "", hub.URL, "", "", hub.Tokens[i-1], "", ""); err != nil {
return nil, err
}
loaded, err := access.LoadBindingFile(workspace, filepath.Join(workspace, access.DefaultBindingFile))
Expand Down
Loading
Loading