synod-council 0.1.0__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.
@@ -0,0 +1,3 @@
1
+ * text=auto eol=lf
2
+ *.png binary
3
+ *.jpg binary
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ matrix:
13
+ os: [ubuntu-latest]
14
+ python-version: ["3.11", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - name: Install
21
+ run: pip install -e .
22
+ - name: Test
23
+ run: python -m unittest discover -s tests -v
@@ -0,0 +1,49 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.12"
15
+ - run: pip install build
16
+ - run: python -m build
17
+ - uses: actions/upload-artifact@v4
18
+ with:
19
+ name: dist
20
+ path: dist/
21
+
22
+ pypi-publish:
23
+ needs: build
24
+ runs-on: ubuntu-latest
25
+ environment: pypi
26
+ permissions:
27
+ id-token: write # Trusted Publishing (OIDC) — no API token needed
28
+ steps:
29
+ - uses: actions/download-artifact@v4
30
+ with:
31
+ name: dist
32
+ path: dist/
33
+ - uses: pypa/gh-action-pypi-publish@release/v1
34
+
35
+ mcp-registry-publish:
36
+ needs: build
37
+ runs-on: ubuntu-latest
38
+ permissions:
39
+ id-token: write # GitHub OIDC proves ownership of naruminho/synod
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - name: Install mcp-publisher
43
+ run: |
44
+ curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz" | tar xz
45
+ sudo mv mcp-publisher /usr/local/bin/
46
+ - name: Publish to official MCP Registry
47
+ run: |
48
+ mcp-publisher login github-oidc
49
+ mcp-publisher publish
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ council.db
7
+ *.db-shm
8
+ *.db-wal
9
+ .env
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Narumi Abe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.5
2
+ Name: synod-council
3
+ Version: 0.1.0
4
+ Summary: Durable, symmetric deliberation between two AI agents — with isolated git worktrees, peer review, and approval workflow.
5
+ Author: Narumi Abe
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Narumi Abe
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Keywords: agents,ai,code-review,deliberation,mcp,multi-agent
29
+ Classifier: Development Status :: 4 - Beta
30
+ Classifier: Intended Audience :: Developers
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Programming Language :: Python :: 3.11
33
+ Classifier: Topic :: Software Development :: Quality Assurance
34
+ Requires-Python: >=3.11
35
+ Provides-Extra: mcp
36
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # Synod
40
+
41
+ **Durable, symmetric deliberation between two AI agents** — with isolated git worktrees,
42
+ peer review, automated validation, and an explicit approval workflow.
43
+
44
+ Synod started life as the "council" inside a personal AI infrastructure where two
45
+ autonomous agents (an orchestrator and an executor) needed to make *real* decisions and
46
+ *real* code changes together — without one of them silently becoming the other's rubber
47
+ stamp.
48
+
49
+ ## Why
50
+
51
+ Most multi-agent frameworks are orchestration theater: one agent calls another as a tool
52
+ and calls the output "collaboration". Synod is built around a different premise — two
53
+ agents that are **peers by construction**:
54
+
55
+ - **Symmetric protocol** — either agent can initiate; the protocol has no privileged side.
56
+ - **Identity contract** — every prompt re-establishes who the agent is, so a weak or
57
+ distracted model can't drift into answering *as* its peer.
58
+ - **Bias-resistant synthesis** — the synthesizer for each problem is chosen by hashing
59
+ the problem text, not by who spoke first.
60
+ - **Durable state** — every session lives in SQLite with explicit stages (`plan`,
61
+ `review`, `synthesize`, `ratify`, ...). A crashed run leaves an inspectable trail, not
62
+ a mystery.
63
+ - **Code changes land through worktrees** — each session gets its own git worktree and
64
+ branch. Agents never push to `main`; a human-facing approval step stands between
65
+ "looks done" and "published".
66
+ - **Validation with remediation** — checks run after implementation, failures go back to
67
+ the implementing agent with bounded retries before a human ever sees it.
68
+
69
+ ## Install
70
+
71
+ ```bash
72
+ pipx install synod-council
73
+ ```
74
+
75
+ Or from source:
76
+
77
+ ```bash
78
+ git clone https://github.com/naruminho/synod-council
79
+ cd synod && pip install .
80
+ ```
81
+
82
+ ## Usage
83
+
84
+ ### Library
85
+
86
+ ```python
87
+ from synod.deliberation import Deliberator, Store, HTTPAdapter
88
+
89
+ adapters = {
90
+ "Alice": HTTPAdapter("Alice", "http://127.0.0.1:9001/ask"),
91
+ "Bob": HTTPAdapter("Bob", "http://127.0.0.1:9002/ask"),
92
+ }
93
+ synod = Deliberator(adapters, Store("council.db"))
94
+ result = synod.run("Should we use SQLite or Postgres for this workload?", initiator="Alice")
95
+ print(result.decision, result.confidence, result.status) # consensus | reconciled
96
+ ```
97
+
98
+ ### MCP server
99
+
100
+ Synod ships an [MCP](https://modelcontextprotocol.io) server so any MCP-capable client
101
+ (Claude Desktop, Claude Code, Cursor, ...) can start a deliberation:
102
+
103
+ ```
104
+ synod-mcp # stdio transport
105
+ ```
106
+
107
+ Add it to your client config and ask your agents to *deliberate* instead of guessing.
108
+
109
+ ### HTTP server
110
+
111
+ ```bash
112
+ synod-server --port 8790
113
+ curl -X POST http://127.0.0.1:8790/run -d '{"problem": "...", "initiator": "Alice"}'
114
+ ```
115
+
116
+ ## How a deliberation flows
117
+
118
+ ```
119
+ plan (parallel) → cross-review (parallel) → synthesis → [ratification → reconciliation?]
120
+ ```
121
+
122
+ If reviewers raise unresolved blockers, or confidence lands below 0.7, the candidate
123
+ decision goes to ratification by the non-synthesizing peer; a rejection forces explicit
124
+ reconciliation instead of silent consensus.
125
+
126
+ ## Status
127
+
128
+ Extracted and battle-tested from a production personal infrastructure where it has been
129
+ deciding architecture and shipping code since 2026. The two-agent design is intentional;
130
+ N-participant support is on the roadmap.
131
+
132
+ ## License
133
+
134
+ [MIT](LICENSE)
@@ -0,0 +1,96 @@
1
+ # Synod
2
+
3
+ **Durable, symmetric deliberation between two AI agents** — with isolated git worktrees,
4
+ peer review, automated validation, and an explicit approval workflow.
5
+
6
+ Synod started life as the "council" inside a personal AI infrastructure where two
7
+ autonomous agents (an orchestrator and an executor) needed to make *real* decisions and
8
+ *real* code changes together — without one of them silently becoming the other's rubber
9
+ stamp.
10
+
11
+ ## Why
12
+
13
+ Most multi-agent frameworks are orchestration theater: one agent calls another as a tool
14
+ and calls the output "collaboration". Synod is built around a different premise — two
15
+ agents that are **peers by construction**:
16
+
17
+ - **Symmetric protocol** — either agent can initiate; the protocol has no privileged side.
18
+ - **Identity contract** — every prompt re-establishes who the agent is, so a weak or
19
+ distracted model can't drift into answering *as* its peer.
20
+ - **Bias-resistant synthesis** — the synthesizer for each problem is chosen by hashing
21
+ the problem text, not by who spoke first.
22
+ - **Durable state** — every session lives in SQLite with explicit stages (`plan`,
23
+ `review`, `synthesize`, `ratify`, ...). A crashed run leaves an inspectable trail, not
24
+ a mystery.
25
+ - **Code changes land through worktrees** — each session gets its own git worktree and
26
+ branch. Agents never push to `main`; a human-facing approval step stands between
27
+ "looks done" and "published".
28
+ - **Validation with remediation** — checks run after implementation, failures go back to
29
+ the implementing agent with bounded retries before a human ever sees it.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pipx install synod-council
35
+ ```
36
+
37
+ Or from source:
38
+
39
+ ```bash
40
+ git clone https://github.com/naruminho/synod-council
41
+ cd synod && pip install .
42
+ ```
43
+
44
+ ## Usage
45
+
46
+ ### Library
47
+
48
+ ```python
49
+ from synod.deliberation import Deliberator, Store, HTTPAdapter
50
+
51
+ adapters = {
52
+ "Alice": HTTPAdapter("Alice", "http://127.0.0.1:9001/ask"),
53
+ "Bob": HTTPAdapter("Bob", "http://127.0.0.1:9002/ask"),
54
+ }
55
+ synod = Deliberator(adapters, Store("council.db"))
56
+ result = synod.run("Should we use SQLite or Postgres for this workload?", initiator="Alice")
57
+ print(result.decision, result.confidence, result.status) # consensus | reconciled
58
+ ```
59
+
60
+ ### MCP server
61
+
62
+ Synod ships an [MCP](https://modelcontextprotocol.io) server so any MCP-capable client
63
+ (Claude Desktop, Claude Code, Cursor, ...) can start a deliberation:
64
+
65
+ ```
66
+ synod-mcp # stdio transport
67
+ ```
68
+
69
+ Add it to your client config and ask your agents to *deliberate* instead of guessing.
70
+
71
+ ### HTTP server
72
+
73
+ ```bash
74
+ synod-server --port 8790
75
+ curl -X POST http://127.0.0.1:8790/run -d '{"problem": "...", "initiator": "Alice"}'
76
+ ```
77
+
78
+ ## How a deliberation flows
79
+
80
+ ```
81
+ plan (parallel) → cross-review (parallel) → synthesis → [ratification → reconciliation?]
82
+ ```
83
+
84
+ If reviewers raise unresolved blockers, or confidence lands below 0.7, the candidate
85
+ decision goes to ratification by the non-synthesizing peer; a rejection forces explicit
86
+ reconciliation instead of silent consensus.
87
+
88
+ ## Status
89
+
90
+ Extracted and battle-tested from a production personal infrastructure where it has been
91
+ deciding architecture and shipping code since 2026. The two-agent design is intentional;
92
+ N-participant support is on the roadmap.
93
+
94
+ ## License
95
+
96
+ [MIT](LICENSE)
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "synod-council"
7
+ version = "0.1.0"
8
+ description = "Durable, symmetric deliberation between two AI agents — with isolated git worktrees, peer review, and approval workflow."
9
+ readme = "README.md"
10
+ license = { file = "LICENSE" }
11
+ authors = [{ name = "Narumi Abe" }]
12
+ requires-python = ">=3.11"
13
+ keywords = ["ai", "agents", "multi-agent", "deliberation", "mcp", "code-review"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Topic :: Software Development :: Quality Assurance",
20
+ ]
21
+ dependencies = []
22
+
23
+ [project.optional-dependencies]
24
+ mcp = ["mcp>=1.0"]
25
+
26
+ [project.scripts]
27
+ synod-server = "synod.server:main"
28
+
29
+ [tool.hatch.build.targets.wheel]
30
+ packages = ["src/synod"]
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
3
+ "name": "io.github.naruminho/synod-council",
4
+ "description": "Durable symmetric deliberation between two AI agents, with isolated worktrees and peer review.",
5
+ "version": "0.1.0",
6
+ "authors": [
7
+ {
8
+ "name": "Narumi Abe"
9
+ }
10
+ ],
11
+ "repository": {
12
+ "url": "https://github.com/naruminho/synod-council",
13
+ "source": "github"
14
+ },
15
+ "license": "MIT",
16
+ "keywords": [
17
+ "ai",
18
+ "agents",
19
+ "multi-agent",
20
+ "deliberation",
21
+ "peer-review",
22
+ "code-review",
23
+ "mcp"
24
+ ]
25
+ }
@@ -0,0 +1,6 @@
1
+ """Synod — durable, symmetric deliberation between two AI agents."""
2
+
3
+ from synod.deliberation import DeliberationResult, Deliberator, Store
4
+
5
+ __all__ = ["DeliberationResult", "Deliberator", "Store"]
6
+ __version__ = "0.1.0"