paircode 0.11.5__tar.gz → 0.11.7__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.
- {paircode-0.11.5 → paircode-0.11.7}/PKG-INFO +1 -1
- {paircode-0.11.5 → paircode-0.11.7}/pyproject.toml +1 -1
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/__init__.py +1 -1
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/cli.py +7 -1
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/templates/claude/commands/paircode.md +1 -0
- {paircode-0.11.5 → paircode-0.11.7}/tests/test_cli_smoke.py +37 -0
- {paircode-0.11.5 → paircode-0.11.7}/.gitignore +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/LICENSE +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/README.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/diary/001-step-a-architecture.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/diary/002-v0.10-release-pipeline.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/diary/003-arch-b-pivot-grappling.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/__main__.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/converge.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/detect.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/handshake.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/installer.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/runner.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/state.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/templates/FOCUS.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/templates/JOURNEY.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/templates/codex/commands/paircode.md +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/templates/gemini/commands/paircode.toml +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/templates/peers.yaml +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/src/paircode/util.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/tests/__init__.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/tests/test_converge.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/tests/test_smoke.py +0 -0
- {paircode-0.11.5 → paircode-0.11.7}/tests/test_state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: paircode
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.7
|
|
4
4
|
Summary: Adversarial journey framework — orchestrate multiple LLM peers through research, plan, and execute stages with file-trace peer review.
|
|
5
5
|
Project-URL: Homepage, https://github.com/starshipagentic/paircode
|
|
6
6
|
Project-URL: Repository, https://github.com/starshipagentic/paircode
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "paircode"
|
|
7
|
-
version = "0.11.
|
|
7
|
+
version = "0.11.7"
|
|
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" }
|
|
@@ -115,9 +115,15 @@ def ensure_scaffold() -> None:
|
|
|
115
115
|
proposed = propose_roster()
|
|
116
116
|
if proposed:
|
|
117
117
|
write_peers(state, proposed_as_yaml_dicts(proposed))
|
|
118
|
-
|
|
118
|
+
peers = proposed_as_yaml_dicts(proposed)
|
|
119
119
|
proposed_count = len(proposed)
|
|
120
120
|
|
|
121
|
+
# Always reconcile sandbox dirs with the roster-of-record (peers.yaml).
|
|
122
|
+
# Idempotent via mkdir(exist_ok=True); recreates any missing peer sandbox.
|
|
123
|
+
# Without this, roster peers added after first init (or dropped by a rename)
|
|
124
|
+
# never get their sandbox dir back.
|
|
125
|
+
ensure_peer_dirs(state, peers)
|
|
126
|
+
|
|
121
127
|
if did_init:
|
|
122
128
|
click.echo(f"init {state.root}")
|
|
123
129
|
if proposed_count:
|
|
@@ -165,6 +165,7 @@ Keep it under 200 words. Brief, honest, actionable.
|
|
|
165
165
|
- **Never skip Step 1.** The focus and roster helpers do the work Python is better at.
|
|
166
166
|
- **Never invent peer commands.** Always route through `paircode invoke <id> "..." --out <path>` — that's how cliworker's speed flags, MCP strip, and output tracing work.
|
|
167
167
|
- **Never pass the interactive Claude session as a peer by mistake.** `paircode roster --alpha claude` handles that for you.
|
|
168
|
+
- **Fire every peer in `paircode roster`** unless the user's prompt explicitly passes `--peer`/`--peers`. don't quarantine on prior failures.
|
|
168
169
|
- **Peer sandboxes are always available, never required.** Use them when it materially sharpens your answer, not by default.
|
|
169
170
|
- **The user's prompt is implicit go-ahead for the whole `{flow}`.** Do not pause for permission between stages. If you must stop early, say so explicitly in the final report with the reason.
|
|
170
171
|
- **No AI attribution** in any artifact you write (consensus.md, alpha-*.md). See the maintainer's CLAUDE.md.
|
|
@@ -126,6 +126,43 @@ def test_ensure_scaffold_is_idempotent(tmp_path, monkeypatch):
|
|
|
126
126
|
assert second.output.strip() == ""
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
def test_ensure_scaffold_recreates_missing_peer_sandbox(tmp_path, monkeypatch):
|
|
130
|
+
"""Roster-of-record wins. If peers.yaml has a peer but its sandbox dir
|
|
131
|
+
went missing (rename, manual rm, whatever), ensure-scaffold must recreate
|
|
132
|
+
it on next run — idempotently."""
|
|
133
|
+
import shutil
|
|
134
|
+
|
|
135
|
+
from paircode.handshake import ProposedPeer
|
|
136
|
+
|
|
137
|
+
monkeypatch.chdir(tmp_path)
|
|
138
|
+
peers = [
|
|
139
|
+
ProposedPeer(id="peer-a-codex", cli="codex", priority="high", notes=""),
|
|
140
|
+
ProposedPeer(id="peer-b-gemini", cli="gemini", priority="low", notes=""),
|
|
141
|
+
]
|
|
142
|
+
monkeypatch.setattr("paircode.cli.propose_roster", lambda: peers)
|
|
143
|
+
runner = CliRunner()
|
|
144
|
+
runner.invoke(main, ["ensure-scaffold"])
|
|
145
|
+
|
|
146
|
+
sandbox = tmp_path / ".paircode" / "sandbox"
|
|
147
|
+
assert (sandbox / "peer-a-codex").is_dir()
|
|
148
|
+
assert (sandbox / "peer-b-gemini").is_dir()
|
|
149
|
+
|
|
150
|
+
# Simulate the real-world drift: gemini's sandbox gets deleted.
|
|
151
|
+
shutil.rmtree(sandbox / "peer-b-gemini")
|
|
152
|
+
assert not (sandbox / "peer-b-gemini").exists()
|
|
153
|
+
|
|
154
|
+
# Re-running ensure-scaffold must put it back. Roster (peers.yaml) is
|
|
155
|
+
# the source of truth — propose_roster() returning the same list should
|
|
156
|
+
# NOT be required for reconciliation.
|
|
157
|
+
monkeypatch.setattr("paircode.cli.propose_roster", lambda: [])
|
|
158
|
+
result = runner.invoke(main, ["ensure-scaffold"])
|
|
159
|
+
assert result.exit_code == 0, result.output
|
|
160
|
+
assert (sandbox / "peer-b-gemini").is_dir(), (
|
|
161
|
+
"ensure-scaffold should reconcile sandbox dirs against peers.yaml, "
|
|
162
|
+
"not just on fresh handshake"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
129
166
|
# ---------------------------------------------------------------------------
|
|
130
167
|
# focus new / focus active
|
|
131
168
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|