Skip to content

Commit 7b283bd

Browse files
authored
feat: v0.3.0 harness selection (two-axis depth+harnesses) (#5)
* docs(spec): v0.3.0 harness selection design Approved design for v0.3.0: split init into depth + harnesses axes, let users pick any combination of claude / codex / openclaw / hermes, introduce .solo-mise/config.json as the source of truth, keep legacy --profile working through v0.3.0 with deprecation note, remove in v0.4.0. Tracks issue #4. * docs(plan): v0.3.0 harness selection implementation plan 20-task implementation plan derived from the v0.3.0 design spec. Phases: foundation (Selection model, config.json, profile shim), template manifests (depth/harnesses/includes), install engine, CLI surface (flags + deprecation shim + interactive prompt), surrounding tools (doctor, ingester, reconfigure), and ship (docs, CHANGELOG, CI matrix, release). * feat(selection): add Selection model + owner-priority resolver * feat(config): add .solo-mise/config.json read/write * feat(selection): add profile_to_selection legacy shim * feat(templates): add depth manifests (repo, workspace) * feat(templates): add per-harness manifests + codex inbox template * feat(templates): add include manifests (publisher) * feat(install): add install_selection engine that composes manifests * feat(install): gitignore block adapts to selected writer harnesses * feat(cli): add --depth, --harnesses, --owner, --include flags * feat(cli): --profile becomes a deprecation shim translating to new flags * feat(prompt): zero-dep interactive harness/depth/include picker * feat(cli): route to interactive prompt when no selection flags given * feat(doctor): read config.json + per-writer inbox checks + orphan warnings * feat(ingest): scan all configured writer inboxes, not just .claude/ * feat(reconfigure): add subcommand to adjust selection on existing target * docs: reframe around two-axis depth + harnesses model * release: prepare v0.3.0 * ci: matrix replaces single profiles with depth+harnesses combos
1 parent db6eb78 commit 7b283bd

36 files changed

Lines changed: 4926 additions & 185 deletions

.github/workflows/ci.yml

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,25 @@ jobs:
5151
strategy:
5252
fail-fast: false
5353
matrix:
54-
profile: [repo, workspace, openclaw, hermes, generic, publisher]
54+
combo:
55+
- name: "repo+claude"
56+
flags: "--depth repo --harnesses claude"
57+
- name: "repo+codex"
58+
flags: "--depth repo --harnesses codex"
59+
- name: "workspace+claude+openclaw"
60+
flags: "--depth workspace --harnesses claude,openclaw"
61+
- name: "workspace+codex+openclaw"
62+
flags: "--depth workspace --harnesses codex,openclaw"
63+
- name: "kitchen-sink"
64+
flags: "--depth workspace --harnesses claude,codex,openclaw,hermes"
65+
- name: "workspace+none"
66+
flags: "--depth workspace --harnesses none"
67+
- name: "repo+claude+publisher"
68+
flags: "--depth repo --harnesses claude --include publisher"
69+
- name: "legacy-workspace"
70+
flags: "--profile workspace"
71+
- name: "legacy-openclaw"
72+
flags: "--profile openclaw"
5573
steps:
5674
- uses: actions/checkout@v4
5775
- uses: actions/setup-python@v5
@@ -64,17 +82,9 @@ jobs:
6482
solo-mise --version
6583
- name: Init + doctor
6684
run: |
67-
target="/tmp/ci-smoke-${{ matrix.profile }}"
85+
target="/tmp/sm-${{ matrix.combo.name }}"
6886
rm -rf "$target"
6987
mkdir -p "$target"
70-
# The 'repo' profile installs a pre-push hook; that wants a git repo.
71-
# Other profiles do not require one but it is harmless.
7288
git init -q -b main "$target"
73-
solo-mise init --target "$target" --profile ${{ matrix.profile }}
74-
# Doctor is harness-aware. Map the profile to the right --harness value.
75-
case "${{ matrix.profile }}" in
76-
openclaw) harness=openclaw ;;
77-
hermes) harness=hermes ;;
78-
*) harness=generic ;;
79-
esac
80-
solo-mise doctor --target "$target" --harness "$harness"
89+
solo-mise init --target "$target" ${{ matrix.combo.flags }}
90+
solo-mise doctor --target "$target"

CHANGELOG.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.3.0] - 2026-05-16
9+
10+
### Added
11+
- Two-axis selection model: `--depth {repo,workspace}` + `--harnesses {claude,codex,openclaw,hermes}` + `--include publisher`. Pick any combination of harnesses.
12+
- Interactive prompt on bare `solo-mise init` (no flags). Defaults to claude + repo + no includes.
13+
- `.solo-mise/config.json` is now the per-target source of truth for selection state. Read by `doctor`, `ingest`, and `reconfigure`.
14+
- `solo-mise reconfigure --target . [--prune]` adjusts an existing install to a new selection. `--prune` removes orphaned files for deselected harnesses.
15+
- Per-writer handoff inboxes: `.codex/memory-handoffs/` for Codex (in addition to existing `.claude/memory-handoffs/`).
16+
- Ingester now scans all configured writer inboxes.
17+
- Doctor reports apparent harness shape, checks per-writer inbox, warns on orphaned inbox dirs from unselected harnesses.
18+
19+
### Changed
20+
- README reframed around the two-axis model. New "Picking your harnesses" section walks through four common combos.
21+
- CONTRIBUTING.md "Adding a profile" replaced by "Adding a harness" + "Adding a depth" + "Adding an include".
22+
23+
### Deprecated
24+
- `solo-mise init --profile <x>` still works but prints a stderr deprecation note pointing at the new flags. Will be removed in v0.4.0.
25+
26+
### Migration
27+
28+
If you have v0.2.0 scripts using `--profile`:
29+
30+
| v0.2.0 | v0.3.0+ |
31+
|---|---|
32+
| `--profile repo` | `--depth repo --harnesses claude` |
33+
| `--profile workspace` | `--depth workspace --harnesses claude` |
34+
| `--profile openclaw` | `--depth workspace --harnesses claude,openclaw` |
35+
| `--profile hermes` | `--depth workspace --harnesses claude,hermes` |
36+
| `--profile generic` | `--depth workspace --harnesses none` |
37+
| `--profile publisher` | `--depth repo --harnesses claude --include publisher` |
38+
839
## [0.2.0] - 2026-05-16
940

1041
### Added
@@ -60,6 +91,7 @@ Initial release.
6091
- OpenClaw adapter fragments and harness-aware doctor checks.
6192
- Experimental Hermes adapter fragments.
6293

63-
[Unreleased]: https://github.com/solomonneas/solo-mise/compare/v0.2.0...HEAD
94+
[Unreleased]: https://github.com/solomonneas/solo-mise/compare/v0.3.0...HEAD
95+
[0.3.0]: https://github.com/solomonneas/solo-mise/compare/v0.2.0...v0.3.0
6496
[0.2.0]: https://github.com/solomonneas/solo-mise/compare/v0.1.0...v0.2.0
6597
[0.1.0]: https://github.com/solomonneas/solo-mise/releases/tag/v0.1.0

CONTRIBUTING.md

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ solo-mise is the installable kit behind [Solomon's Cookbook](https://github.com/
55
## What kinds of changes land easily
66

77
- **Bug fixes** for `solo-mise init`, `doctor`, `scrub`, or the ingester.
8-
- **Profile improvements**: new bootstrap content, sharper post-install notes, better defaults.
9-
- **New harness adapters** (with doctor checks) under `src/solo_mise/templates/<harness>/`.
8+
- **Harness / depth / include improvements**: new bootstrap content, sharper post-install notes, better defaults.
9+
- **New harness adapters** (with doctor checks) under `src/solo_mise/templates/harnesses/<id>.json`.
1010
- **Doctor checks** that catch real, observed failure modes.
1111
- **Test coverage** for any of the above.
1212

1313
## What needs a conversation first
1414

15-
- **A new top-level profile.** Open an issue first describing the user story. Profiles are the public surface and renaming or splitting them later is painful.
15+
- **A new top-level harness, depth, or include.** Open an issue first describing the user story. These are the public surface and renaming or splitting them later is painful.
1616
- **Breaking changes** to template paths, the handoff TEMPLATE.md fields, or the ingester routing rules.
1717
- **Anything that adds a runtime dependency.** solo-mise has zero runtime deps on purpose, and we want to keep it that way.
1818

@@ -32,25 +32,36 @@ pip install -e ".[dev]"
3232
pytest -q
3333
```
3434

35-
To smoke-test a profile end-to-end the same way CI does:
35+
To smoke-test an install end-to-end the same way CI does:
3636

3737
```bash
3838
target=/tmp/solo-mise-smoke
3939
rm -rf "$target" && mkdir -p "$target" && git init -q "$target"
40-
python -m solo_mise init --target "$target" --profile workspace
40+
python -m solo_mise init --target "$target" --depth workspace --harnesses claude,codex,openclaw
4141
python -m solo_mise doctor --target "$target"
4242
```
4343

44-
## Adding a profile
44+
## Adding a harness
4545

46-
A profile is a single JSON manifest in `src/solo_mise/templates/profiles/<id>.json` and any template files it references. Manifests support `extends` for inheritance. See `publisher.json` (extends `repo`) for the simplest example.
46+
A harness is a manifest under `src/solo_mise/templates/harnesses/<id>.json` plus any template files it references. The manifest declares `role: "writer"` (gets an inbox) or `role: "reader"` (gets adapter fragments).
4747

48-
When you add a profile:
48+
To add a harness:
4949

50-
1. Add it to the `choices=[...]` list in `src/solo_mise/cli.py` (the `--profile` flag).
51-
2. Add a row to the profile table in `README.md`.
52-
3. Add it to the matrix in `.github/workflows/ci.yml` so the smoke job exercises it.
53-
4. If it has post-install steps, list them in `post_install_notes`. They are printed at the end of `solo-mise init`.
50+
1. Create the manifest at `src/solo_mise/templates/harnesses/<id>.json`.
51+
2. Add template files under a harness-named directory (e.g. `src/solo_mise/templates/<id>/`).
52+
3. Add the harness id to `KNOWN_HARNESSES` in `src/solo_mise/selection.py`.
53+
4. Update `HARNESS_PRIORITY` if the new harness should be an owner candidate (readers usually want to land near OpenClaw/Hermes in the priority list).
54+
5. If it's a writer, add it to `_WRITER_INBOXES` in `src/solo_mise/install.py`, `src/solo_mise/doctor.py`, and `src/solo_mise/ingest.py`.
55+
6. Add the harness to the CI matrix in `.github/workflows/ci.yml`.
56+
7. Add a row to the harness table in `README.md`.
57+
58+
## Adding a depth
59+
60+
Depths live at `src/solo_mise/templates/depth/<id>.json` and may use `extends` to inherit from another depth. Add the id to `KNOWN_DEPTHS` in `selection.py` and to the `--depth` choices in `cli.py`.
61+
62+
## Adding an include
63+
64+
Includes live at `src/solo_mise/templates/includes/<id>.json`. Add the id to `KNOWN_INCLUDES` in `selection.py`.
5465

5566
## Adding a doctor check
5667

@@ -68,7 +79,7 @@ Open a PR with all three and we'll land it.
6879

6980
## Filing issues
7081

71-
Please use the templates under `.github/ISSUE_TEMPLATE/` - they exist to save you from re-typing the version and profile every time.
82+
Please use the templates under `.github/ISSUE_TEMPLATE/` - they exist to save you from re-typing the version and install shape every time.
7283

7384
The `ingester-misclassified` template is the most useful one to file early. If a handoff that should have promoted to a card got bounced (or vice versa), that is a real bug in the routing rules, not a corner case. We want to see it.
7485

QUICKSTART.md

Lines changed: 47 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,96 +15,82 @@ python3 -m pip install --user pipx
1515
python3 -m pipx ensurepath
1616
```
1717

18-
## 2. Pick a profile
18+
## First install
1919

20-
The default `repo` profile adds the handoff flow and a publish guard to an existing project.
20+
The fastest path is to run `solo-mise init` with no flags and answer the prompts:
2121

22-
The `workspace` profile creates a home-style agent workspace from scratch.
23-
24-
## 3. Initialize
22+
```bash
23+
$ solo-mise init --target ~/agent-kitchen
2524

26-
### Repo profile (lightest)
25+
Which harnesses do you use? (type numbers separated by space/comma to toggle, enter to confirm)
26+
[x] 1. Claude Code
27+
[ ] 2. Codex
28+
[ ] 3. OpenClaw
29+
[ ] 4. Hermes (experimental)
2730

28-
In a project you already work in:
31+
Depth? (type a number, enter for default)
32+
* 1. repo (handoff flow + publish guard)
33+
2. workspace (full home: MEMORY.md, TOOLS.md, USER.md, ...)
2934

30-
```bash
31-
cd ~/repos/your-project
32-
solo-mise init --target .
35+
Add-ons? (type numbers separated by space/comma to toggle, enter to confirm)
36+
[ ] 1. publisher (content-guard policies for blog/social/docs)
3337
```
3438

35-
This creates:
36-
37-
```text
38-
your-project/
39-
AGENTS.md
40-
CLAUDE.md
41-
.claude/memory-handoffs/
42-
TEMPLATE.md
43-
hooks/
44-
pre-push
45-
.gitignore # adds a managed solo-mise block (handoffs, daily logs, review inbox)
46-
```
39+
Defaults are claude harness, repo depth, no includes. Enter ships the install.
4740

48-
The `.gitignore` block is bounded by `# >>> solo-mise gitignore block >>>` markers so re-running `init` is idempotent and your hand-written rules outside the block are preserved. Pass `--no-gitignore` to skip the gitignore step.
41+
## CI / scripted install
4942

50-
Enable the pre-push hook once:
43+
Pass flags directly to skip the prompt:
5144

5245
```bash
53-
git config core.hooksPath hooks
54-
```
46+
# Claude Code + Codex + OpenClaw, full workspace
47+
solo-mise init --target ~/agent-kitchen \
48+
--depth workspace \
49+
--harnesses claude,codex,openclaw
5550

56-
### Workspace profile
51+
# Codex-only project, minimal install
52+
solo-mise init --target ./my-project --depth repo --harnesses codex
5753

58-
```bash
59-
solo-mise init --target ~/agent-kitchen --profile workspace
54+
# Generic layout, no harness-specific files
55+
solo-mise init --target ./my-project --harnesses none
6056
```
6157

62-
This creates the full bootstrap file set: `AGENTS.md`, `CLAUDE.md`, `SOUL.md`, `USER.md`, `TOOLS.md`, `MEMORY.md`, `IDENTITY.md`, `HEARTBEAT.md`, `SAFETY_RULES.md`, `INSTALL_FOR_AGENTS.md`, plus `memory/cards/` with starter cards, a `.claude/memory-handoffs/` inbox, and the publish hook.
58+
## Verifying
6359

64-
## 4. Verify
60+
After install, `solo-mise doctor --target <path>` reports the apparent harness shape and checks every configured inbox and adapter:
6561

66-
```bash
67-
solo-mise doctor --target ~/agent-kitchen
6862
```
69-
70-
The doctor checks that the bootstrap files exist, the handoff inbox is in place, and (if you chose `--profile openclaw`) the OpenClaw config can see your workspace. It prints `OK` or `MANUAL ACTION NEEDED` per check; it never edits your config.
71-
72-
## 5. Write your first handoff
73-
74-
```bash
75-
solo-mise handoff-template --target ~/agent-kitchen > \
76-
~/agent-kitchen/.claude/memory-handoffs/$(date -u +%Y-%m-%dT%H%MZ)-first-handoff.md
63+
solo-mise doctor: target /home/you/agent-kitchen
64+
harnesses: claude, codex, openclaw (owner=openclaw, depth=workspace)
65+
[ok] bootstrap: AGENTS.md /home/you/agent-kitchen/AGENTS.md
66+
[ok] handoff: claude inbox /home/you/agent-kitchen/.claude/memory-handoffs
67+
[ok] handoff: codex inbox /home/you/agent-kitchen/.codex/memory-handoffs
68+
[ok] openclaw: config /home/you/.openclaw/openclaw.json
69+
...
7770
```
7871

79-
Edit the file with whatever durable knowledge your agent just produced.
72+
A `[fail]` line means the install is incomplete; `[warn]` is informational; `[todo]` means the check needs your attention (e.g. Hermes is experimental).
8073

81-
## 6. Ingest
74+
## Reconfiguring
8275

83-
```bash
84-
solo-mise ingest --target ~/agent-kitchen --dry-run
85-
solo-mise ingest --target ~/agent-kitchen
86-
```
76+
To change which harnesses are installed on an existing target:
8777

88-
The ingester is conservative. Handoffs with `Recommended memory action: create-card` and a safe filename + frontmatter become memory cards. Handoffs that route to `TOOLS.md`, `USER.md`, `rules/*.md`, or `.learnings/*.md` get appended. Anything ambiguous lands in `memory/handoff-inbox/` for manual review.
89-
90-
If you administer multiple agent setups, keep one canonical owner and pull remote handoffs into staging directories before ingesting them. See `memory/cards/multi-workspace-handoff-admin.md`.
78+
```bash
79+
# Add a harness
80+
solo-mise reconfigure --target . --harnesses claude,codex
9181

92-
## 7. Scrub before publishing
82+
# Drop one (without removing its files)
83+
solo-mise reconfigure --target . --harnesses claude
9384

94-
```bash
95-
solo-mise scrub --target . --dry-run
85+
# Drop one and remove its files
86+
solo-mise reconfigure --target . --harnesses claude --prune
9687
```
9788

98-
If you have [content-guard](https://github.com/solomonneas/content-guard) installed, the pre-push hook will block pushes that contain private IPs, secrets, or AI attribution trailers. `solo-mise scrub` is the deterministic counterpart that runs the same scanner with the public-repo policy.
99-
100-
## 8. OpenClaw users
89+
## The handoff flow
10190

102-
```bash
103-
solo-mise doctor --target ~/.openclaw/workspace --harness openclaw
104-
solo-mise openclaw-fragments --out ./openclaw-fragments
105-
```
91+
The starter handoff template lives at `<inbox>/TEMPLATE.md`. Copy it to a new dated file (e.g. `2026-05-16-1430-fixed-X.md`), fill it in, and the ingester promotes safe card handoffs into `memory/cards/`, appends targeted updates to the right file, and kicks ambiguous material to the review inbox.
10692

107-
The fragments are JSON files you can inspect and merge into your `openclaw.json` by hand. `solo-mise` never mutates your live OpenClaw config.
93+
See the [Solo Cookbook](https://github.com/solomonneas/solos-cookbook) for the longer-form guidance on what makes a good handoff and when to use which routing.
10894

10995
## Next steps
11096

0 commit comments

Comments
 (0)