Skip to content

Commit 4ab7218

Browse files
darw007dclaude
andauthored
feat: Phase 7 — swarph spawn <role> (v0.6.0) (#8)
* feat: Phase 7 — `swarph spawn <role>` (v0.6.0) Implements the operator-tooling layer of substrate-doc R7 §11.1.7 4-layer R2 mechanism stack (merged on hedge-fund-mcp main as a50d1a2 earlier today). Wraps `claude` with the three R5/R7 disambiguation flags so sibling-cell instances on shared peer-id are distinguishable at the session-resume layer. What ships: * `swarph spawn <role-or-path>` — exec-replaces with `claude --name <role> --session-id <uuid> --append-system-prompt <starter>` * `swarph_cli/cell.py` — cell.yaml v1 parser + Lineage shape + atomic sidecar UUID persistence to $XDG_STATE_HOME * cell.yaml schema FROZEN at `schema_version: "v1"` per drop-mother review #890 (C2) — v0.7 swarph-shared migration is symbol-relocation only, no field changes * lineage block (parent_peer_id + spawn_manifest_signature) parsed but not enforced — alpha #891 (D1) reserved shape for v2 cryptographic-lineage tier * `--onboarding mesh-gateway://...` URL form parsed but raises NotImplementedError — alpha #891 (D2) v0.6→v0.7 no-flag-change upgrade path * `./cell.yaml` auto-discovery in cwd — alpha #891 (D3) * atomic UUID write (tempfile + fsync + rename) — drop-mother (C1) load-bearing for R5 disambiguation; torn write would silently regenerate on next spawn and defeat the primitive * mitosis-cell ASCII banner per commander pick — explicitly nods to §1.22 mitosis primitive (R6/R7) Resolution precedence: 1. --onboarding <path-or-url> explicit override (alias: --cell) 2. positional ending .yaml/.yml literal path 3. positional plain role name $XDG_CONFIG_HOME/swarph/cells/<role>.yaml 4. no positional auto-discover ./cell.yaml in cwd 5. mesh-gateway://... v0.7+ NotImplementedError today Falsifiability gates (substrate-doc R7 F4/F5 applied): * F-spawn-1: swarph spawn <role> --dry-run --print-id idempotent across consecutive calls (R5 invariant) * F-spawn-2: cell.yaml-pinned session_id never touches sidecar * F-spawn-3: corrupted sidecar regenerates rather than crashing * F-spawn-4: dry-run output redacts long starter prompts * F-spawn-5: provider != "claude" rejected with "v0.7+ feature" hint Tests: 43 new tests pass, full suite 200 pass + 3 skipped (live-API gates unaffected). End-to-end smoke verified — auto-discovery + UUID mint + persist + reuse all working with real cell.yaml under /tmp. Deferred to v0.7+: * beta #892 (B1) auto-suffix on --name collision * beta #892 (B2) --new-instance flag for sibling-spawn * non-Claude provider spawn * swarph-shared cell.yaml relocation (symbol-only refactor) * SessionStart memory-injection hook (complementary to --append-system-prompt per R7 §11.1.7.1 #1) * S-G mesh-gateway:// URL implementation (substrate primitive) Pre-PR consumer review: * drop-mother #890 — C1-C5 production-context observer (CLEAN scope) * drop-on-meta-edge alpha #891 — D1-D3 spawn-target consumer * drop-on-meta-edge beta #892 — B1-B3 sibling-instance consumer * alpha #893 concurrence on beta + cross-refs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: known-limitations note — single-instance-per-role at v0.6 (beta #897) beta consumer-side review #897 surfaced the sibling-spawn case: alpha + beta co-existing on `drop-on-meta-edge` peer-id cannot be reproduced via v0.6 spawn because the sidecar resolution always reuses the first-minted UUID. Multi-instance sibling spawn requires v0.7's --new-instance flag (already deferred per §18.6). Manual sibling workflow (tmux + explicit --session-id pinning) still works unchanged — v0.6 does not regress that path, it just doesn't yet expose a CLI shape for it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 39cafee commit 4ab7218

8 files changed

Lines changed: 1295 additions & 11 deletions

File tree

README.md

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,71 @@ This is one of three repos in the v0.3.x architecture:
1717

1818
## Status
1919

20-
**v0.5.0 — Phase 2 one-shot + Phase 2.5 import + Phase 5 REPL + Phase 5.5 onboard/ratify + Phase 5.6 daemon.** Six verbs ship:
20+
**v0.6.0 — Phase 7 spawn ships.** Seven verbs total:
2121

2222
1. `swarph "prompt"` — Phase 2 one-shot mode (any of five providers)
2323
2. `swarph chat` — Phase 5 interactive REPL with multi-turn history + slash commands
24-
3. `swarph import <path>` — Phase 2.5 session import (Claude JSONL → swarph-native, with `--report-only` for honest pre-commit inspection)
25-
4. `swarph onboard <peer-name>` — Phase 5.5 mechanics-phase onboarding (PLAN.md §15.4)
26-
5. `swarph ratify <peer-name>` — Phase 5.5 witness ratification (PLAN.md §15.4a)
27-
6. `swarph daemon`**NEW** Phase 5.6 foreground inbox drain loop (PLAN.md §16); structurally retires the orphaned-tail-F class
24+
3. `swarph spawn <role>`**NEW** Phase 7 long-lived `claude` session as a named mesh cell (`--name`/`--session-id`/`--append-system-prompt` pinning per substrate-doc R7 §11.1.7 4-layer R2 stack)
25+
4. `swarph import <path>` — Phase 2.5 session import (Claude JSONL → swarph-native)
26+
5. `swarph onboard <peer-name>` — Phase 5.5 mechanics-phase onboarding (PLAN.md §15.4)
27+
6. `swarph ratify <peer-name>` — Phase 5.5 witness ratification (PLAN.md §15.4a)
28+
7. `swarph daemon` — Phase 5.6 foreground inbox drain (PLAN.md §16)
2829

29-
Subsequent phases extend the CLI surface (`--ask <peer>`, REPL drain coroutine + `/inbox` + `/reply` slash commands in 5.6b).
30+
Subsequent phases extend the CLI surface (`--ask <peer>`, REPL drain coroutine + `/inbox` + `/reply` slash commands in 5.6b; non-Claude `spawn` providers + S-G `mesh-gateway://` URL form in v0.7).
31+
32+
### `swarph spawn` (Phase 7 — v0.6.0)
33+
34+
Operator-tooling layer of substrate-doc R7 §11.1.7 4-layer R2 mechanism stack. Wraps `claude` with the three R5/R7 disambiguation flags:
35+
36+
* `--name <role>` — display name for `/resume` picker
37+
* `--session-id <uuid>` — pinned UUID, persisted to `$XDG_STATE_HOME/swarph/sessions/<role>.session-id` so re-spawns reuse the same session (the R5 fix at the operator-tooling layer)
38+
* `--append-system-prompt <text>` — starter prompt injected without manual paste (the R2 fix at the operator-tooling layer)
39+
40+
```bash
41+
# 1. Author a cell.yaml (one-time per role)
42+
$ cat ~/.config/swarph/cells/lab.yaml
43+
schema_version: v1
44+
name: lab-ovh
45+
role: lab
46+
cwd: /home/ubuntu
47+
starter_prompt_path: ~/.claude/session_start_reminder.txt
48+
provider: claude
49+
50+
# 2. Summon the cell (long-lived claude session, exec-replaced)
51+
$ swarph spawn lab
52+
╭───╮
53+
│ ◉ │
54+
╭──┴───┴──╮
55+
│ swarph │ v0.6.0
56+
╰──┬───┬──╯ spawn │ chat │ daemon
57+
│ ◉ │
58+
╰───╯
59+
[claude session takes over the terminal — same flags as `claude --name lab --session-id <uuid> --append-system-prompt <starter>`]
60+
61+
# 3. Resume the same cell after exit — same UUID, same session
62+
$ swarph spawn lab # picker shows ONE entry: "lab" (R5 disambiguation)
63+
```
64+
65+
Resolution order for `swarph spawn <role-or-path>`:
66+
67+
1. `--onboarding <path-or-url>` (alias: `--cell`) — explicit override
68+
2. Positional ending in `.yaml`/`.yml` or containing a path separator — literal path
69+
3. Plain role name — `$XDG_CONFIG_HOME/swarph/cells/<role>.yaml` (default `~/.config/swarph/cells/`)
70+
4. No positional given — auto-discover `./cell.yaml` in current directory
71+
72+
Useful flags:
73+
74+
| Flag | Effect |
75+
|---|---|
76+
| `--dry-run` | Print resolved `claude` command + cell summary; do not exec |
77+
| `--no-starter` | Skip starter-prompt injection even if cell.yaml sets one |
78+
| `--print-id` | Print resolved session-id to stdout (capture for shell scripts) |
79+
| `--no-banner` | Suppress the swarph banner on stderr |
80+
| `-- <claude-args>` | Pass remaining args through to claude unchanged |
81+
82+
cell.yaml schema is **frozen at `schema_version: "v1"`**. v0.7 migrates the parser to `swarph-shared` as a symbol-relocation only — v0.6 cell.yaml files keep working unchanged. Breaking changes require a `schema_version: "v2"` bump and parallel-supported-version window per `swarph-mesh` DEPRECATIONS discipline.
83+
84+
**Known limitations (v0.6).** Single-instance-per-role only. Re-running `swarph spawn <role>` reuses the persisted UUID (R5 fix), so sibling-spawn (alpha + beta co-existing on the same peer-id) requires v0.7's `--new-instance` flag. Manual sibling spawning via `tmux` + explicit `--session-id` pinning still works unchanged; v0.6 does not regress that path, it just doesn't yet expose a CLI shape for it.
3085

3186
### `swarph daemon` (Phase 5.6)
3287

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "swarph-cli"
7-
version = "0.5.0"
8-
description = "The `swarph` binary — multi-LLM CLI with mesh-gateway integration. v0.5.0 ships Phase 5.6 `swarph daemon` (foreground inbox drain — retires the orphaned-tail-F class) on top of Phase 2 one-shot + Phase 2.5 import + Phase 5 REPL + Phase 5.5 onboard/ratify (PLAN.md §13 / §16)."
7+
version = "0.6.0"
8+
description = "The `swarph` binary — multi-LLM CLI with mesh-gateway integration. v0.6.0 ships Phase 7 `swarph spawn <role>` (operator-tooling layer of substrate-doc R7 §11.1.7 4-layer R2 mechanism stack — pins claude --name/--session-id/--append-system-prompt for sibling-cell session-resume disambiguation) on top of Phase 5.6 daemon + Phase 5.5 onboard/ratify + Phase 5 REPL + Phase 2.5 import + Phase 2 one-shot."
99
readme = "README.md"
1010
license = { text = "MIT" }
1111
requires-python = ">=3.10"
@@ -33,6 +33,10 @@ dependencies = [
3333
# OpenAI + Grok availability in /provider switch.
3434
"swarph-mesh>=0.5.0",
3535
"swarph-shared>=0.2.0",
36+
# Phase 7 spawn — cell.yaml parser. PyYAML 6.x is the standard.
37+
# Migrates to swarph-shared in v0.7+ per cell.yaml format-home
38+
# decision (substrate-doc R7 §11.1.7.4).
39+
"PyYAML>=6.0",
3640
]
3741

3842
[project.urls]

src/swarph_cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616

1717
from __future__ import annotations
1818

19-
__version__ = "0.5.0"
19+
__version__ = "0.6.0"
2020

2121
__all__ = ["__version__"]

0 commit comments

Comments
 (0)