paircode 0.11.1__tar.gz → 0.11.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {paircode-0.11.1 → paircode-0.11.3}/.gitignore +3 -0
  2. paircode-0.11.3/PKG-INFO +154 -0
  3. paircode-0.11.3/README.md +126 -0
  4. {paircode-0.11.1 → paircode-0.11.3}/pyproject.toml +1 -1
  5. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/__init__.py +1 -1
  6. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/cli.py +1 -1
  7. paircode-0.11.1/src/paircode/seal.py → paircode-0.11.3/src/paircode/converge.py +8 -4
  8. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/installer.py +1 -10
  9. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/state.py +2 -10
  10. paircode-0.11.3/src/paircode/util.py +18 -0
  11. paircode-0.11.1/tests/test_seal.py → paircode-0.11.3/tests/test_converge.py +2 -2
  12. paircode-0.11.1/PKG-INFO +0 -160
  13. paircode-0.11.1/README.md +0 -132
  14. paircode-0.11.1/src/paircode/journey.py +0 -63
  15. {paircode-0.11.1 → paircode-0.11.3}/LICENSE +0 -0
  16. {paircode-0.11.1 → paircode-0.11.3}/diary/001-step-a-architecture.md +0 -0
  17. {paircode-0.11.1 → paircode-0.11.3}/diary/002-v0.10-release-pipeline.md +0 -0
  18. {paircode-0.11.1 → paircode-0.11.3}/diary/003-arch-b-pivot-grappling.md +0 -0
  19. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/__main__.py +0 -0
  20. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/detect.py +0 -0
  21. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/handshake.py +0 -0
  22. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/runner.py +0 -0
  23. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/templates/FOCUS.md +0 -0
  24. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/templates/JOURNEY.md +0 -0
  25. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/templates/claude/commands/paircode.md +0 -0
  26. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/templates/codex/commands/paircode.md +0 -0
  27. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/templates/gemini/commands/paircode.toml +0 -0
  28. {paircode-0.11.1 → paircode-0.11.3}/src/paircode/templates/peers.yaml +0 -0
  29. {paircode-0.11.1 → paircode-0.11.3}/tests/__init__.py +0 -0
  30. {paircode-0.11.1 → paircode-0.11.3}/tests/test_cli_smoke.py +0 -0
  31. {paircode-0.11.1 → paircode-0.11.3}/tests/test_smoke.py +0 -0
  32. {paircode-0.11.1 → paircode-0.11.3}/tests/test_state.py +0 -0
@@ -35,3 +35,6 @@ ENV/
35
35
  /tmp/
36
36
  scratch/
37
37
  dist/
38
+
39
+ # paircode runtime state (focuses, peer workspaces, etc.)
40
+ .paircode/
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.4
2
+ Name: paircode
3
+ Version: 0.11.3
4
+ Summary: Adversarial journey framework — orchestrate multiple LLM peers through research, plan, and execute stages with file-trace peer review.
5
+ Project-URL: Homepage, https://github.com/starshipagentic/paircode
6
+ Project-URL: Repository, https://github.com/starshipagentic/paircode
7
+ Project-URL: Issues, https://github.com/starshipagentic/paircode/issues
8
+ Author-email: Travis Somerville <travis.somerville@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,claude,codex,gemini,llm,multi-agent,ollama,orchestration,peer-review
12
+ Classifier: Development Status :: 2 - Pre-Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: click>=8.1
24
+ Requires-Dist: cliworker>=0.8.1
25
+ Requires-Dist: pyyaml>=6.0
26
+ Requires-Dist: rich>=13.0
27
+ Description-Content-Type: text/markdown
28
+
29
+ # paircode
30
+
31
+ **Multi-LLM peer review for your code, with file-traces on disk.** One primary LLM (alpha, usually Claude Code) + any number of peer LLMs (Codex, Gemini, Ollama, …) running research / plan / execute / ask cycles with structured cross-review rounds stored entirely as Markdown on disk.
32
+
33
+ > Born from 31 iterations of dual-LLM silent-agreement hunting on a real ML project. See `diary/001-step-a-architecture.md` for the origin story and `diary/003-arch-b-pivot-grappling.md` for the current (v0.11) team-lead architecture.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pipx install paircode # or: pip install --user paircode
39
+ paircode install # registers /paircode in every detected LLM CLI
40
+ ```
41
+
42
+ `paircode install` deploys `/paircode` into each LLM CLI it finds on your PATH:
43
+
44
+ | CLI | How it's installed | What you get |
45
+ |---|---|---|
46
+ | Claude Code | file-drop `~/.claude/commands/paircode.md` | `/paircode` slash command |
47
+ | Codex CLI | `codex marketplace add starshipagentic/paircode-codex` | `/paircode` slash command |
48
+ | Gemini CLI | `gemini extensions install github.com/starshipagentic/paircode-gemini --consent` | `/paircode` slash command |
49
+
50
+ In Gemini you may need `/commands reload` the first time. In Codex the marketplace fetches on first use.
51
+
52
+ paircode delegates LLM subprocess invocation to [`cliworker`](https://pypi.org/project/cliworker/) — that's where speed flags, MCP strip tricks, skip-cache, and subscription-first fallback live. paircode adds the peer-review orchestration on top (file-traces, stages, rosters, convergence).
53
+
54
+ ## Use it
55
+
56
+ Inside any LLM CLI that has `/paircode` installed, just type:
57
+
58
+ ```
59
+ /paircode "build a KISS PHQ-9 depression risk engine"
60
+ ```
61
+
62
+ or
63
+
64
+ ```
65
+ /paircode "review my auth middleware approach at src/auth/"
66
+ /paircode "plan the refactor" --peers codex,gemini
67
+ /paircode "get a second opinion on this PR" --peer gemini
68
+ ```
69
+
70
+ The slash command's team-lead prompt (the LLM you're inside) reads your prompt, picks a stage (`research | plan | execute | ask`), fires peers, collects their markdown, iterates through review rounds until convergence, and writes `consensus.md` at the end. Everything lands under `.paircode/` in your current project.
71
+
72
+ ## What ends up on disk
73
+
74
+ ```
75
+ your-project/
76
+ .paircode/
77
+ JOURNEY.md # fleet log
78
+ peers.yaml # roster: who's on the team
79
+ peers/
80
+ peer-a-codex/ # codex's persistent sandbox (code goes here)
81
+ peer-b-gemini/ # gemini's persistent sandbox
82
+ focus-01-<slug>/
83
+ FOCUS.md # this focus's prompt + metadata
84
+ research/
85
+ alpha-v1.md ... alpha-vN.md
86
+ peer-a-codex-v1.md ...
87
+ reviews/round-01-peer-a-codex-critiques-alpha.md
88
+ alpha-FINAL.md
89
+ peer-a-codex-FINAL.md
90
+ consensus.md # team-lead synthesis (last thing written)
91
+ plan/ (same shape)
92
+ execute/ (same shape)
93
+ ask/ (same shape)
94
+ focus-02-<slug>/
95
+ ...
96
+ ```
97
+
98
+ **Code vs. reports.** Files inside `focus-*/` are markdown *reports* (opinions, plans, critiques, summaries of work). Actual code lives elsewhere:
99
+
100
+ - **Peers** code in their sandboxed workspaces at `.paircode/peers/<peer-id>/` — persistent across focuses.
101
+ - **Alpha** codes directly in the project root (the real repo) — alpha *is* the project.
102
+
103
+ ## Stages
104
+
105
+ Stage is picked by the team-lead LLM based on the prompt:
106
+
107
+ | Stage | When | Typical prompt |
108
+ |---|---|---|
109
+ | `research` | Explore new ground | "build X", "find the right Y", "how should we approach Z" |
110
+ | `plan` | Concrete implementation plan from prior research | "plan the refactor based on focus-02" |
111
+ | `execute` | Do the work from an existing plan | "execute the plan at focus-02" |
112
+ | `ask` | Get opinions on existing work | "what does codex think of this PR", "review my approach at <path>" |
113
+
114
+ The team lead can chain stages in one invocation: `research → plan → execute → done`. No hard round cap — the team lead converges when peers stop surfacing new signal.
115
+
116
+ ## Commands (the helper CLI)
117
+
118
+ Most users will only ever type `paircode install` and then use `/paircode` inside their LLM CLI. The binary's other commands are helpers the team-lead slash command calls on your behalf:
119
+
120
+ ```
121
+ paircode print current .paircode/ state
122
+ paircode install register /paircode in every detected LLM CLI
123
+ paircode uninstall remove /paircode from LLM CLIs (idempotent)
124
+ paircode ensure-scaffold idempotent .paircode/ init + handshake (silent)
125
+ paircode focus new <slug> create a new focus dir, print its path
126
+ paircode focus active print the active focus path
127
+ paircode roster [--alpha <cli>] [--peer <id>] [--peers <id,id>]
128
+ print peer ids, best-effort, never errors
129
+ paircode invoke <peer-id> "<prompt>" --out <path>
130
+ fire one peer, write file-trace to --out
131
+ paircode converge <stage> copy each participant's latest vN to *-FINAL.md
132
+ ```
133
+
134
+ ## Model compatibility
135
+
136
+ | CLI | `/paircode` slash command | Peer invocation | Parallel peers? | Status |
137
+ |---|---|---|---|---|
138
+ | Claude Code (`claude`) | ✓ file-drop at `~/.claude/commands/paircode.md` | ✓ `claude -p <prompt>` | ✓ via Agent tool + `run_in_background=true` | stable |
139
+ | Codex (`codex`) | ✓ via `codex marketplace add` | ✓ `codex exec <prompt>` | ✗ serial-only (codex constraint) | stable |
140
+ | Gemini (`gemini`) | ✓ via `gemini extensions install` | ✓ `gemini -p <prompt>` | ✗ serial-only (gemini constraint) | stable |
141
+ | Ollama (`ollama`) | — (local models, no slash-cmd host) | ✓ `ollama run <model> <prompt>` | n/a | peer-only |
142
+ | Aider / others | — | best-effort, PRs welcome | — | planned |
143
+
144
+ Peer roster is auto-detected at first install via `paircode handshake` (silent, called by `ensure-scaffold`). Edit `.paircode/peers.yaml` to customize.
145
+
146
+ ## Why this exists
147
+
148
+ See [`diary/001-step-a-architecture.md`](diary/001-step-a-architecture.md). Short version: running two LLMs adversarially surfaces silent-agreement bug classes that neither engine alone catches — cross-engine agreement is not the same as correctness when both engines share a blind spot.
149
+
150
+ See [`diary/003-arch-b-pivot-grappling.md`](diary/003-arch-b-pivot-grappling.md) for why v0.11 moved orchestration out of a Python driver and into the slash-command's team-lead LLM.
151
+
152
+ ## License
153
+
154
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,126 @@
1
+ # paircode
2
+
3
+ **Multi-LLM peer review for your code, with file-traces on disk.** One primary LLM (alpha, usually Claude Code) + any number of peer LLMs (Codex, Gemini, Ollama, …) running research / plan / execute / ask cycles with structured cross-review rounds stored entirely as Markdown on disk.
4
+
5
+ > Born from 31 iterations of dual-LLM silent-agreement hunting on a real ML project. See `diary/001-step-a-architecture.md` for the origin story and `diary/003-arch-b-pivot-grappling.md` for the current (v0.11) team-lead architecture.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pipx install paircode # or: pip install --user paircode
11
+ paircode install # registers /paircode in every detected LLM CLI
12
+ ```
13
+
14
+ `paircode install` deploys `/paircode` into each LLM CLI it finds on your PATH:
15
+
16
+ | CLI | How it's installed | What you get |
17
+ |---|---|---|
18
+ | Claude Code | file-drop `~/.claude/commands/paircode.md` | `/paircode` slash command |
19
+ | Codex CLI | `codex marketplace add starshipagentic/paircode-codex` | `/paircode` slash command |
20
+ | Gemini CLI | `gemini extensions install github.com/starshipagentic/paircode-gemini --consent` | `/paircode` slash command |
21
+
22
+ In Gemini you may need `/commands reload` the first time. In Codex the marketplace fetches on first use.
23
+
24
+ paircode delegates LLM subprocess invocation to [`cliworker`](https://pypi.org/project/cliworker/) — that's where speed flags, MCP strip tricks, skip-cache, and subscription-first fallback live. paircode adds the peer-review orchestration on top (file-traces, stages, rosters, convergence).
25
+
26
+ ## Use it
27
+
28
+ Inside any LLM CLI that has `/paircode` installed, just type:
29
+
30
+ ```
31
+ /paircode "build a KISS PHQ-9 depression risk engine"
32
+ ```
33
+
34
+ or
35
+
36
+ ```
37
+ /paircode "review my auth middleware approach at src/auth/"
38
+ /paircode "plan the refactor" --peers codex,gemini
39
+ /paircode "get a second opinion on this PR" --peer gemini
40
+ ```
41
+
42
+ The slash command's team-lead prompt (the LLM you're inside) reads your prompt, picks a stage (`research | plan | execute | ask`), fires peers, collects their markdown, iterates through review rounds until convergence, and writes `consensus.md` at the end. Everything lands under `.paircode/` in your current project.
43
+
44
+ ## What ends up on disk
45
+
46
+ ```
47
+ your-project/
48
+ .paircode/
49
+ JOURNEY.md # fleet log
50
+ peers.yaml # roster: who's on the team
51
+ peers/
52
+ peer-a-codex/ # codex's persistent sandbox (code goes here)
53
+ peer-b-gemini/ # gemini's persistent sandbox
54
+ focus-01-<slug>/
55
+ FOCUS.md # this focus's prompt + metadata
56
+ research/
57
+ alpha-v1.md ... alpha-vN.md
58
+ peer-a-codex-v1.md ...
59
+ reviews/round-01-peer-a-codex-critiques-alpha.md
60
+ alpha-FINAL.md
61
+ peer-a-codex-FINAL.md
62
+ consensus.md # team-lead synthesis (last thing written)
63
+ plan/ (same shape)
64
+ execute/ (same shape)
65
+ ask/ (same shape)
66
+ focus-02-<slug>/
67
+ ...
68
+ ```
69
+
70
+ **Code vs. reports.** Files inside `focus-*/` are markdown *reports* (opinions, plans, critiques, summaries of work). Actual code lives elsewhere:
71
+
72
+ - **Peers** code in their sandboxed workspaces at `.paircode/peers/<peer-id>/` — persistent across focuses.
73
+ - **Alpha** codes directly in the project root (the real repo) — alpha *is* the project.
74
+
75
+ ## Stages
76
+
77
+ Stage is picked by the team-lead LLM based on the prompt:
78
+
79
+ | Stage | When | Typical prompt |
80
+ |---|---|---|
81
+ | `research` | Explore new ground | "build X", "find the right Y", "how should we approach Z" |
82
+ | `plan` | Concrete implementation plan from prior research | "plan the refactor based on focus-02" |
83
+ | `execute` | Do the work from an existing plan | "execute the plan at focus-02" |
84
+ | `ask` | Get opinions on existing work | "what does codex think of this PR", "review my approach at <path>" |
85
+
86
+ The team lead can chain stages in one invocation: `research → plan → execute → done`. No hard round cap — the team lead converges when peers stop surfacing new signal.
87
+
88
+ ## Commands (the helper CLI)
89
+
90
+ Most users will only ever type `paircode install` and then use `/paircode` inside their LLM CLI. The binary's other commands are helpers the team-lead slash command calls on your behalf:
91
+
92
+ ```
93
+ paircode print current .paircode/ state
94
+ paircode install register /paircode in every detected LLM CLI
95
+ paircode uninstall remove /paircode from LLM CLIs (idempotent)
96
+ paircode ensure-scaffold idempotent .paircode/ init + handshake (silent)
97
+ paircode focus new <slug> create a new focus dir, print its path
98
+ paircode focus active print the active focus path
99
+ paircode roster [--alpha <cli>] [--peer <id>] [--peers <id,id>]
100
+ print peer ids, best-effort, never errors
101
+ paircode invoke <peer-id> "<prompt>" --out <path>
102
+ fire one peer, write file-trace to --out
103
+ paircode converge <stage> copy each participant's latest vN to *-FINAL.md
104
+ ```
105
+
106
+ ## Model compatibility
107
+
108
+ | CLI | `/paircode` slash command | Peer invocation | Parallel peers? | Status |
109
+ |---|---|---|---|---|
110
+ | Claude Code (`claude`) | ✓ file-drop at `~/.claude/commands/paircode.md` | ✓ `claude -p <prompt>` | ✓ via Agent tool + `run_in_background=true` | stable |
111
+ | Codex (`codex`) | ✓ via `codex marketplace add` | ✓ `codex exec <prompt>` | ✗ serial-only (codex constraint) | stable |
112
+ | Gemini (`gemini`) | ✓ via `gemini extensions install` | ✓ `gemini -p <prompt>` | ✗ serial-only (gemini constraint) | stable |
113
+ | Ollama (`ollama`) | — (local models, no slash-cmd host) | ✓ `ollama run <model> <prompt>` | n/a | peer-only |
114
+ | Aider / others | — | best-effort, PRs welcome | — | planned |
115
+
116
+ Peer roster is auto-detected at first install via `paircode handshake` (silent, called by `ensure-scaffold`). Edit `.paircode/peers.yaml` to customize.
117
+
118
+ ## Why this exists
119
+
120
+ See [`diary/001-step-a-architecture.md`](diary/001-step-a-architecture.md). Short version: running two LLMs adversarially surfaces silent-agreement bug classes that neither engine alone catches — cross-engine agreement is not the same as correctness when both engines share a blind spot.
121
+
122
+ See [`diary/003-arch-b-pivot-grappling.md`](diary/003-arch-b-pivot-grappling.md) for why v0.11 moved orchestration out of a Python driver and into the slash-command's team-lead LLM.
123
+
124
+ ## License
125
+
126
+ MIT. See [LICENSE](LICENSE).
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "paircode"
7
- version = "0.11.1"
7
+ version = "0.11.3"
8
8
  description = "Adversarial journey framework — orchestrate multiple LLM peers through research, plan, and execute stages with file-trace peer review."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -2,4 +2,4 @@
2
2
 
3
3
  See README.md and diary/001-step-a-architecture.md for the full design.
4
4
  """
5
- __version__ = "0.11.0"
5
+ __version__ = "0.11.2"
@@ -243,7 +243,7 @@ def converge(stage: str) -> None:
243
243
  Runs on the active focus. Mechanical file-copy only; the slash command
244
244
  writes `consensus.md` afterward from the FINAL files.
245
245
  """
246
- from paircode.seal import seal_stage
246
+ from paircode.converge import seal_stage
247
247
 
248
248
  state = find_paircode()
249
249
  if state is None or state.active_focus is None:
@@ -1,8 +1,12 @@
1
- """Seal a stage — copy the latest version per peer to {peer}-FINAL.md.
1
+ """Converge a stage — copy the latest version per peer to {peer}-FINAL.md.
2
2
 
3
- Sealing is the declarative exit signal for a stage. Once alpha-FINAL.md and
4
- each peer's *-FINAL.md exist, the stage is considered complete and the next
5
- stage can consume its outputs.
3
+ Convergence is the declarative exit signal for a stage. Once alpha-FINAL.md
4
+ and each peer's *-FINAL.md exist, the stage is considered complete and the
5
+ next stage can consume its outputs.
6
+
7
+ Renamed from `seal.py` in v0.11.1 to match the user-facing CLI verb
8
+ (`paircode converge <stage>`). The public function name stayed `seal_stage`
9
+ because it describes a file-copy primitive, not the user-level action.
6
10
  """
7
11
  from __future__ import annotations
8
12
 
@@ -22,12 +22,12 @@ Also cleans up legacy files from pre-v0.10 paircode versions on every install.
22
22
  from __future__ import annotations
23
23
 
24
24
  from dataclasses import dataclass
25
- from importlib import resources
26
25
  from pathlib import Path
27
26
 
28
27
  from cliworker import invoke
29
28
 
30
29
  from paircode.detect import detect_all, CliInfo
30
+ from paircode.util import read_template as _read_template
31
31
 
32
32
 
33
33
  # Satellite repo coordinates — update here when repos move.
@@ -46,15 +46,6 @@ class InstallResult:
46
46
  message: str
47
47
 
48
48
 
49
- def _read_template(relative_path: str) -> str:
50
- """Read a file under `paircode/templates/` by relative path.
51
-
52
- Host templates live at `<host>/commands/...`, host-agnostic scaffold
53
- templates at the root (`FOCUS.md`, `JOURNEY.md`, `peers.yaml`).
54
- """
55
- return resources.files("paircode.templates").joinpath(relative_path).read_text(encoding="utf-8")
56
-
57
-
58
49
  # ---------------------------------------------------------------------------
59
50
  # Per-CLI installers
60
51
  # ---------------------------------------------------------------------------
@@ -18,12 +18,13 @@ from __future__ import annotations
18
18
  import datetime as _dt
19
19
  import re
20
20
  from dataclasses import dataclass
21
- from importlib import resources
22
21
  from pathlib import Path
23
22
  from typing import Iterable
24
23
 
25
24
  import yaml
26
25
 
26
+ from paircode.util import read_template as _read_template
27
+
27
28
 
28
29
  PAIRCODE_DIRNAME = ".paircode"
29
30
  PEERS_FILE = "peers.yaml"
@@ -35,15 +36,6 @@ def _now_iso() -> str:
35
36
  return _dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
36
37
 
37
38
 
38
- def _read_template(relative_path: str) -> str:
39
- """Read a file under `paircode/templates/` by relative path.
40
-
41
- Examples: `_read_template("FOCUS.md")` or
42
- `_read_template("claude/commands/paircode.md")`.
43
- """
44
- return resources.files("paircode.templates").joinpath(relative_path).read_text(encoding="utf-8")
45
-
46
-
47
39
  def _render(template: str, vars: dict[str, str]) -> str:
48
40
  out = template
49
41
  for k, v in vars.items():
@@ -0,0 +1,18 @@
1
+ """Small shared helpers for paircode internals."""
2
+ from __future__ import annotations
3
+
4
+ from importlib import resources
5
+
6
+
7
+ def read_template(relative_path: str) -> str:
8
+ """Read a file under `paircode/templates/` by relative path.
9
+
10
+ Examples:
11
+ read_template("FOCUS.md")
12
+ read_template("claude/commands/paircode.md")
13
+ """
14
+ return (
15
+ resources.files("paircode.templates")
16
+ .joinpath(relative_path)
17
+ .read_text(encoding="utf-8")
18
+ )
@@ -1,9 +1,9 @@
1
- """Tests for stage sealing."""
1
+ """Tests for stage convergence — copying latest vN to *-FINAL.md."""
2
2
  from __future__ import annotations
3
3
 
4
4
  from pathlib import Path
5
5
 
6
- from paircode.seal import discover_latest_versions, seal_stage
6
+ from paircode.converge import discover_latest_versions, seal_stage
7
7
 
8
8
 
9
9
  def test_discover_latest_versions_picks_highest_per_peer(tmp_path: Path):
paircode-0.11.1/PKG-INFO DELETED
@@ -1,160 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: paircode
3
- Version: 0.11.1
4
- Summary: Adversarial journey framework — orchestrate multiple LLM peers through research, plan, and execute stages with file-trace peer review.
5
- Project-URL: Homepage, https://github.com/starshipagentic/paircode
6
- Project-URL: Repository, https://github.com/starshipagentic/paircode
7
- Project-URL: Issues, https://github.com/starshipagentic/paircode/issues
8
- Author-email: Travis Somerville <travis.somerville@gmail.com>
9
- License: MIT
10
- License-File: LICENSE
11
- Keywords: agents,claude,codex,gemini,llm,multi-agent,ollama,orchestration,peer-review
12
- Classifier: Development Status :: 2 - Pre-Alpha
13
- Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: MIT License
15
- Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Programming Language :: Python :: 3.13
21
- Classifier: Topic :: Software Development
22
- Requires-Python: >=3.10
23
- Requires-Dist: click>=8.1
24
- Requires-Dist: cliworker>=0.8.1
25
- Requires-Dist: pyyaml>=6.0
26
- Requires-Dist: rich>=13.0
27
- Description-Content-Type: text/markdown
28
-
29
- # paircode
30
-
31
- **Multi-LLM peer review for your code, with file-traces on disk.** One primary LLM (alpha) + any number of peer LLMs (Codex, Gemini, Ollama, …) running independent research, plans, and code, with structured cross-review rounds stored entirely as Markdown on disk.
32
-
33
- > Born from 31 iterations of dual-LLM silent-agreement hunting on a real ML project. See `diary/001-step-a-architecture.md` for the full design rationale.
34
-
35
- ## Install
36
-
37
- ```bash
38
- pipx install paircode # or: pip install --user paircode
39
- paircode install # registers /paircode in every detected LLM CLI
40
- ```
41
-
42
- After install, `/paircode` is available in all three:
43
-
44
- | CLI | File installed |
45
- |---|---|
46
- | Claude Code | `~/.claude/commands/paircode.md` |
47
- | Codex CLI | `~/.codex/prompts/paircode.md` |
48
- | Gemini CLI | `~/.gemini/commands/paircode.toml` |
49
-
50
- Open any of them and type `/paircode`. In Gemini, you may need `/commands reload` the first time.
51
-
52
- As of v0.8.0, paircode delegates all CLI invocation to [`cliworker`](https://pypi.org/project/cliworker/) — one place to own
53
- the speed flags, MCP strip tricks, skip-cache, and subscription-first fallback
54
- logic. paircode adds the peer-review orchestration on top (file-traces, stages,
55
- gates, journey).
56
-
57
- ## Use it — three entry points
58
-
59
- ### 1. From Claude Code (or any supported LLM) as a slash command
60
-
61
- Inside a Claude Code session:
62
-
63
- ```
64
- /paircode drive "build a KISS PHQ-9 depression risk engine"
65
- ```
66
-
67
- Claude relays that to the CLI. paircode opens a focus, runs research → plan → execute with peer-reviewed rounds, writes everything to `.paircode/` as Markdown.
68
-
69
- ### 2. From the shell directly
70
-
71
- ```bash
72
- paircode init # bootstrap .paircode/ in cwd
73
- paircode handshake --write # detect CLIs + write peer roster
74
- paircode drive "refactor the auth middleware" # full loop
75
- paircode status # see where you are
76
- ```
77
-
78
- ### 3. Piece by piece
79
-
80
- ```bash
81
- paircode focus "try GitHub Actions migration"
82
- paircode stage research --rounds 2 # cold v1 + one review/revise round
83
- paircode seal research # mark research FINAL
84
- paircode stage plan --rounds 3
85
- paircode seal plan
86
- paircode stage execute
87
- paircode seal execute
88
- ```
89
-
90
- ## What ends up on disk
91
-
92
- ```
93
- your-project/
94
- .paircode/
95
- JOURNEY.md # fleet log (auto-updated)
96
- peers.yaml # who's on the team
97
- peers/
98
- peer-a-codex/ # peer's profile (and code if full-fork mode)
99
- focus-01-<slug>/
100
- FOCUS.md # this focus's goal, roster override, gate config
101
- research/
102
- alpha-v1.md ... alpha-vN.md
103
- peer-a-codex-v1.md ...
104
- reviews/round-01-peer-a-codex-critiques-alpha.md
105
- alpha-FINAL.md # sealed exit artifact
106
- peer-a-codex-FINAL.md
107
- plan/
108
- (same shape)
109
- execute/
110
- (same shape)
111
- focus-02-<slug>/
112
- ...
113
- ```
114
-
115
- Every LLM's every thought lands as a Markdown file. That's how heterogeneous LLM tools communicate reliably across vendors, sessions, and days.
116
-
117
- ## Three peer modes
118
-
119
- | Mode | What the peer does | When to use |
120
- |---|---|---|
121
- | **full-fork** | Writes its own cold codebase + markdown artifacts | Silent-agreement hunting, safety-critical code |
122
- | **pair-code** | Contributes directly to alpha's codebase via patches + reviews | Feature work, regular dev |
123
- | **opinion-only** | Reads alpha's work, writes reviews, never touches code | Budget peers, quick sanity checks |
124
-
125
- Configured per peer in `.paircode/peers.yaml`.
126
-
127
- ## Model compatibility
128
-
129
- | CLI | Slash command | Subprocess driver | Status |
130
- |---|---|---|---|
131
- | Claude Code (`claude`) | ✓ `/paircode` via `~/.claude/commands/paircode.md` | ✓ `claude -p <prompt>` | stable |
132
- | Codex (`codex`) | ✓ context rule via `~/.codex/rules/paircode.rules` | ✓ `codex exec <prompt>` | stable |
133
- | Gemini CLI (`gemini`) | ✓ reference file at `~/.gemini/paircode.md` | ✓ `gemini -p <prompt>` | stable |
134
- | Ollama (`ollama`) | — (local models, no slash-cmd primitive) | ✓ `ollama run <model> <prompt>` | stable |
135
- | Aider / others | — | best-effort, PRs welcome | planned |
136
-
137
- ## Commands
138
-
139
- ```
140
- paircode --help full command list
141
- paircode install register /paircode in all detected LLM CLIs
142
- paircode uninstall remove /paircode from LLM CLIs (idempotent)
143
- paircode handshake detect CLIs, propose peer roster
144
- paircode handshake --write save roster to .paircode/peers.yaml
145
- paircode init bootstrap .paircode/ in cwd
146
- paircode status summarize current state
147
- paircode focus <name> open a new focus
148
- paircode focus list existing focuses
149
- paircode stage <name> run one stage N rounds on active focus
150
- paircode seal <stage> seal stage — copy each peer's latest vN to {peer}-FINAL.md
151
- paircode drive <topic> full loop: research → plan → execute
152
- ```
153
-
154
- ## Why this exists
155
-
156
- See [`diary/001-step-a-architecture.md`](diary/001-step-a-architecture.md) for the full backstory. The short version: running two LLMs adversarially surfaces silent-agreement bug classes that neither engine alone can catch, because cross-engine agreement is not the same as correctness when both share the same blind spot.
157
-
158
- ## License
159
-
160
- MIT. See [LICENSE](LICENSE).
paircode-0.11.1/README.md DELETED
@@ -1,132 +0,0 @@
1
- # paircode
2
-
3
- **Multi-LLM peer review for your code, with file-traces on disk.** One primary LLM (alpha) + any number of peer LLMs (Codex, Gemini, Ollama, …) running independent research, plans, and code, with structured cross-review rounds stored entirely as Markdown on disk.
4
-
5
- > Born from 31 iterations of dual-LLM silent-agreement hunting on a real ML project. See `diary/001-step-a-architecture.md` for the full design rationale.
6
-
7
- ## Install
8
-
9
- ```bash
10
- pipx install paircode # or: pip install --user paircode
11
- paircode install # registers /paircode in every detected LLM CLI
12
- ```
13
-
14
- After install, `/paircode` is available in all three:
15
-
16
- | CLI | File installed |
17
- |---|---|
18
- | Claude Code | `~/.claude/commands/paircode.md` |
19
- | Codex CLI | `~/.codex/prompts/paircode.md` |
20
- | Gemini CLI | `~/.gemini/commands/paircode.toml` |
21
-
22
- Open any of them and type `/paircode`. In Gemini, you may need `/commands reload` the first time.
23
-
24
- As of v0.8.0, paircode delegates all CLI invocation to [`cliworker`](https://pypi.org/project/cliworker/) — one place to own
25
- the speed flags, MCP strip tricks, skip-cache, and subscription-first fallback
26
- logic. paircode adds the peer-review orchestration on top (file-traces, stages,
27
- gates, journey).
28
-
29
- ## Use it — three entry points
30
-
31
- ### 1. From Claude Code (or any supported LLM) as a slash command
32
-
33
- Inside a Claude Code session:
34
-
35
- ```
36
- /paircode drive "build a KISS PHQ-9 depression risk engine"
37
- ```
38
-
39
- Claude relays that to the CLI. paircode opens a focus, runs research → plan → execute with peer-reviewed rounds, writes everything to `.paircode/` as Markdown.
40
-
41
- ### 2. From the shell directly
42
-
43
- ```bash
44
- paircode init # bootstrap .paircode/ in cwd
45
- paircode handshake --write # detect CLIs + write peer roster
46
- paircode drive "refactor the auth middleware" # full loop
47
- paircode status # see where you are
48
- ```
49
-
50
- ### 3. Piece by piece
51
-
52
- ```bash
53
- paircode focus "try GitHub Actions migration"
54
- paircode stage research --rounds 2 # cold v1 + one review/revise round
55
- paircode seal research # mark research FINAL
56
- paircode stage plan --rounds 3
57
- paircode seal plan
58
- paircode stage execute
59
- paircode seal execute
60
- ```
61
-
62
- ## What ends up on disk
63
-
64
- ```
65
- your-project/
66
- .paircode/
67
- JOURNEY.md # fleet log (auto-updated)
68
- peers.yaml # who's on the team
69
- peers/
70
- peer-a-codex/ # peer's profile (and code if full-fork mode)
71
- focus-01-<slug>/
72
- FOCUS.md # this focus's goal, roster override, gate config
73
- research/
74
- alpha-v1.md ... alpha-vN.md
75
- peer-a-codex-v1.md ...
76
- reviews/round-01-peer-a-codex-critiques-alpha.md
77
- alpha-FINAL.md # sealed exit artifact
78
- peer-a-codex-FINAL.md
79
- plan/
80
- (same shape)
81
- execute/
82
- (same shape)
83
- focus-02-<slug>/
84
- ...
85
- ```
86
-
87
- Every LLM's every thought lands as a Markdown file. That's how heterogeneous LLM tools communicate reliably across vendors, sessions, and days.
88
-
89
- ## Three peer modes
90
-
91
- | Mode | What the peer does | When to use |
92
- |---|---|---|
93
- | **full-fork** | Writes its own cold codebase + markdown artifacts | Silent-agreement hunting, safety-critical code |
94
- | **pair-code** | Contributes directly to alpha's codebase via patches + reviews | Feature work, regular dev |
95
- | **opinion-only** | Reads alpha's work, writes reviews, never touches code | Budget peers, quick sanity checks |
96
-
97
- Configured per peer in `.paircode/peers.yaml`.
98
-
99
- ## Model compatibility
100
-
101
- | CLI | Slash command | Subprocess driver | Status |
102
- |---|---|---|---|
103
- | Claude Code (`claude`) | ✓ `/paircode` via `~/.claude/commands/paircode.md` | ✓ `claude -p <prompt>` | stable |
104
- | Codex (`codex`) | ✓ context rule via `~/.codex/rules/paircode.rules` | ✓ `codex exec <prompt>` | stable |
105
- | Gemini CLI (`gemini`) | ✓ reference file at `~/.gemini/paircode.md` | ✓ `gemini -p <prompt>` | stable |
106
- | Ollama (`ollama`) | — (local models, no slash-cmd primitive) | ✓ `ollama run <model> <prompt>` | stable |
107
- | Aider / others | — | best-effort, PRs welcome | planned |
108
-
109
- ## Commands
110
-
111
- ```
112
- paircode --help full command list
113
- paircode install register /paircode in all detected LLM CLIs
114
- paircode uninstall remove /paircode from LLM CLIs (idempotent)
115
- paircode handshake detect CLIs, propose peer roster
116
- paircode handshake --write save roster to .paircode/peers.yaml
117
- paircode init bootstrap .paircode/ in cwd
118
- paircode status summarize current state
119
- paircode focus <name> open a new focus
120
- paircode focus list existing focuses
121
- paircode stage <name> run one stage N rounds on active focus
122
- paircode seal <stage> seal stage — copy each peer's latest vN to {peer}-FINAL.md
123
- paircode drive <topic> full loop: research → plan → execute
124
- ```
125
-
126
- ## Why this exists
127
-
128
- See [`diary/001-step-a-architecture.md`](diary/001-step-a-architecture.md) for the full backstory. The short version: running two LLMs adversarially surfaces silent-agreement bug classes that neither engine alone can catch, because cross-engine agreement is not the same as correctness when both share the same blind spot.
129
-
130
- ## License
131
-
132
- MIT. See [LICENSE](LICENSE).
@@ -1,63 +0,0 @@
1
- """Update JOURNEY.md as focuses open/close."""
2
- from __future__ import annotations
3
-
4
- import datetime as _dt
5
- import re
6
- from pathlib import Path
7
-
8
- from paircode.state import PaircodeState
9
-
10
-
11
- _HISTORY_HEADER_RE = re.compile(r"^## History\s*$", re.MULTILINE)
12
- _HISTORY_TABLE_RE = re.compile(
13
- r"\| # \| Focus \| Opened \| Closed \| Iterations \| Result \|\n\|[-|\s]+\|\n"
14
- )
15
- _ACTIVE_FOCUS_RE = re.compile(
16
- r"## Active focus\s*\n\n(.+?)\n\n##", re.DOTALL
17
- )
18
-
19
-
20
- def _now() -> str:
21
- return _dt.datetime.now().strftime("%Y-%m-%d %H:%M")
22
-
23
-
24
- def note_focus_opened(state: PaircodeState, focus_name: str) -> None:
25
- """Update JOURNEY.md: set active focus, append history row."""
26
- j = state.journey_path
27
- if not j.exists():
28
- return
29
- text = j.read_text(encoding="utf-8")
30
-
31
- # Replace the "Active focus" section
32
- new_active = f"## Active focus\n\n**{focus_name}** — opened {_now()}\n\n##"
33
- text = _ACTIVE_FOCUS_RE.sub(new_active, text, count=1)
34
-
35
- # Append to history table
36
- history_match = _HISTORY_TABLE_RE.search(text)
37
- if history_match:
38
- # Count existing rows in history table
39
- rest = text[history_match.end():]
40
- existing_rows = rest.split("\n\n")[0]
41
- row_count = len([r for r in existing_rows.split("\n") if r.startswith("|")])
42
- new_row = f"| {row_count + 1} | {focus_name} | {_now()} | — | 0 | — |\n"
43
- text = text[:history_match.end()] + new_row + text[history_match.end():]
44
-
45
- j.write_text(text, encoding="utf-8")
46
-
47
-
48
- def note_focus_closed(state: PaircodeState, focus_name: str, iterations: int, result: str) -> None:
49
- """Update JOURNEY.md: mark the focus row as closed with iteration count + result."""
50
- j = state.journey_path
51
- if not j.exists():
52
- return
53
- text = j.read_text(encoding="utf-8")
54
- # Find row for this focus and update its Closed/Iterations/Result columns
55
- pattern = re.compile(
56
- rf"(\| \d+ \| {re.escape(focus_name)} \| [^|]+\| )—( \| )0( \| )—( \|)"
57
- )
58
- text = pattern.sub(
59
- rf"\g<1>{_now()}\g<2>{iterations}\g<3>{result}\g<4>",
60
- text,
61
- count=1,
62
- )
63
- j.write_text(text, encoding="utf-8")
File without changes
File without changes
File without changes
File without changes