coprogrammer 0.1.0__py3-none-any.whl

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,371 @@
1
+ """Zero-dependency MCP (Model Context Protocol) stdio server.
2
+
3
+ Exposes the CoProgrammer Manager Plane and digest tooling as MCP tools so any
4
+ MCP client (Claude Code, Codex, Cursor, Cowork, ...) can coordinate
5
+ multi-agent work without shelling out to the CLI.
6
+
7
+ Transport: newline-delimited JSON-RPC 2.0 over stdio, per the MCP spec.
8
+ No third-party dependencies; reuses cli.py internals.
9
+
10
+ Run:
11
+ python -m coprogrammer mcp serve [--cwd .] [--state-dir .coprogrammer]
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import sys
18
+ from pathlib import Path
19
+ from typing import Any
20
+
21
+ from . import cli
22
+
23
+ PROTOCOL_VERSION = "2025-06-18"
24
+ SERVER_INFO = {"name": "coprogrammer", "version": "0.1.0"}
25
+
26
+ TOOLS: list[dict[str, Any]] = [
27
+ {
28
+ "name": "digest_branch",
29
+ "description": (
30
+ "Generate a CoProgrammer branch digest (intent, changed files, "
31
+ "commits, contract/architecture risk signals, protected-path "
32
+ "matches, risk level) for a base..head range or the working tree."
33
+ ),
34
+ "inputSchema": {
35
+ "type": "object",
36
+ "properties": {
37
+ "base": {"type": "string", "default": "origin/main"},
38
+ "head": {"type": "string", "default": "HEAD"},
39
+ "working_tree": {"type": "boolean", "default": False},
40
+ "language": {"type": "string", "enum": ["en", "zh-CN"]},
41
+ },
42
+ },
43
+ },
44
+ {
45
+ "name": "manager_status",
46
+ "description": (
47
+ "Show reconstructed Manager Plane state: active leases, open "
48
+ "decisions, contract changes, and latest agent heartbeats."
49
+ ),
50
+ "inputSchema": {"type": "object", "properties": {}},
51
+ },
52
+ {
53
+ "name": "manager_forecast",
54
+ "description": (
55
+ "Forecast conflicts before PR time: overlapping agent leases, "
56
+ "breaking/unknown contract proposals, protected-path pressure, "
57
+ "and optionally which changed files collide with other agents."
58
+ ),
59
+ "inputSchema": {
60
+ "type": "object",
61
+ "properties": {
62
+ "changed_files": {
63
+ "type": "array",
64
+ "items": {"type": "string"},
65
+ "description": "Changed file paths to check.",
66
+ }
67
+ },
68
+ },
69
+ },
70
+ {
71
+ "name": "lease_request",
72
+ "description": (
73
+ "Request an advisory workspace lease for path patterns before "
74
+ "editing. Overlapping leases automatically open a decision."
75
+ ),
76
+ "inputSchema": {
77
+ "type": "object",
78
+ "properties": {
79
+ "holder": {"type": "string"},
80
+ "patterns": {"type": "array", "items": {"type": "string"}},
81
+ "kind": {
82
+ "type": "string",
83
+ "enum": list(cli.LEASE_KINDS),
84
+ "default": "path",
85
+ },
86
+ "task": {"type": "string", "default": ""},
87
+ },
88
+ "required": ["holder", "patterns"],
89
+ },
90
+ },
91
+ {
92
+ "name": "heartbeat",
93
+ "description": "Publish an agent heartbeat (current task and status).",
94
+ "inputSchema": {
95
+ "type": "object",
96
+ "properties": {
97
+ "agent": {"type": "string"},
98
+ "task": {"type": "string"},
99
+ },
100
+ "required": ["agent", "task"],
101
+ },
102
+ },
103
+ {
104
+ "name": "contract_propose",
105
+ "description": (
106
+ "Propose a shared contract change (api/schema/database/...) so "
107
+ "other agents see it before merge time. Breaking changes open a "
108
+ "human decision automatically."
109
+ ),
110
+ "inputSchema": {
111
+ "type": "object",
112
+ "properties": {
113
+ "proposer": {"type": "string"},
114
+ "kind": {"type": "string", "enum": list(cli.CONTRACT_KINDS)},
115
+ "name": {"type": "string"},
116
+ "summary": {"type": "string"},
117
+ "compatibility": {
118
+ "type": "string",
119
+ "enum": list(cli.CONTRACT_COMPATIBILITY),
120
+ "default": "unknown",
121
+ },
122
+ },
123
+ "required": ["proposer", "kind", "name", "summary"],
124
+ },
125
+ },
126
+ ]
127
+
128
+
129
+ class ManagerContext:
130
+ def __init__(self, cwd: Path, state_dir: str):
131
+ self.cwd = cwd
132
+ self.state_dir = state_dir
133
+
134
+ @property
135
+ def log_path(self) -> Path:
136
+ return cli.event_log_path(self.cwd, self.state_dir)
137
+
138
+ def events(self) -> list[dict[str, Any]]:
139
+ return cli.load_events(self.log_path)
140
+
141
+ def config(self) -> dict[str, Any]:
142
+ return cli.load_config(self.cwd)
143
+
144
+
145
+ def tool_digest_branch(ctx: ManagerContext, args: dict[str, Any]) -> str:
146
+ base = args.get("base", "origin/main")
147
+ head = args.get("head", "HEAD")
148
+ if args.get("working_tree"):
149
+ files = cli.get_working_tree_changed_files(base, ctx.cwd)
150
+ commits: list[str] = []
151
+ head_label = "working-tree"
152
+ else:
153
+ files = cli.get_changed_files(base, head, ctx.cwd)
154
+ commits = cli.get_commits(base, head, ctx.cwd)
155
+ head_label = head
156
+ config = ctx.config()
157
+ language = cli.resolve_language(args.get("language") or config.get("language"))
158
+ return cli.render_digest(
159
+ base=base,
160
+ head=head_label,
161
+ files=files,
162
+ commits=commits,
163
+ language=language,
164
+ config=config,
165
+ )
166
+
167
+
168
+ def tool_manager_status(ctx: ManagerContext, args: dict[str, Any]) -> str:
169
+ events = ctx.events()
170
+ return json.dumps(
171
+ {
172
+ "event_count": len(events),
173
+ "active_leases": list(cli.active_leases(events).values()),
174
+ "open_decisions": list(cli.open_decisions(events).values()),
175
+ "contract_changes": list(cli.contract_changes(events).values()),
176
+ "latest_heartbeats": cli.latest_heartbeats(events),
177
+ },
178
+ indent=2,
179
+ ensure_ascii=False,
180
+ )
181
+
182
+
183
+ def tool_manager_forecast(ctx: ManagerContext, args: dict[str, Any]) -> str:
184
+ report = cli.forecast_report(
185
+ ctx.events(), ctx.config(), args.get("changed_files")
186
+ )
187
+ return json.dumps(report, indent=2, ensure_ascii=False)
188
+
189
+
190
+ def tool_lease_request(ctx: ManagerContext, args: dict[str, Any]) -> str:
191
+ path = ctx.log_path
192
+ events = ctx.events()
193
+ lease = cli.new_lease(
194
+ args["holder"],
195
+ args.get("kind", "path"),
196
+ list(args["patterns"]),
197
+ args.get("task", ""),
198
+ )
199
+ cli.append_event(
200
+ path,
201
+ cli.make_event("lease.requested", args["holder"], "repo:mcp", {"lease": lease}),
202
+ )
203
+ conflicts = cli.find_lease_conflicts(lease, cli.active_leases(events))
204
+ if conflicts:
205
+ decision = cli.new_decision(
206
+ question=(
207
+ f"Should {args['holder']} proceed with "
208
+ f"{', '.join(args['patterns'])} despite active lease overlap?"
209
+ ),
210
+ context=json.dumps(
211
+ {"requested_lease": lease, "conflicting_leases": conflicts},
212
+ ensure_ascii=False,
213
+ sort_keys=True,
214
+ ),
215
+ related_artifacts=[lease["id"], *[c["id"] for c in conflicts]],
216
+ )
217
+ cli.append_event(
218
+ path,
219
+ cli.make_event(
220
+ "decision.requested", "manager", "repo:mcp", {"decision": decision}
221
+ ),
222
+ )
223
+ return json.dumps(
224
+ {
225
+ "granted": False,
226
+ "lease": lease,
227
+ "conflicts": conflicts,
228
+ "decision_requested": decision["id"],
229
+ },
230
+ indent=2,
231
+ ensure_ascii=False,
232
+ )
233
+ lease["status"] = "active"
234
+ cli.append_event(
235
+ path,
236
+ cli.make_event("lease.granted", "manager", "repo:mcp", {"lease": lease}),
237
+ )
238
+ return json.dumps({"granted": True, "lease": lease}, indent=2, ensure_ascii=False)
239
+
240
+
241
+ def tool_heartbeat(ctx: ManagerContext, args: dict[str, Any]) -> str:
242
+ heartbeat = cli.new_heartbeat(args["agent"], args["task"])
243
+ cli.append_event(
244
+ ctx.log_path,
245
+ cli.make_event(
246
+ "agent.heartbeat", args["agent"], "repo:mcp", {"heartbeat": heartbeat}
247
+ ),
248
+ )
249
+ return json.dumps(heartbeat, indent=2, ensure_ascii=False)
250
+
251
+
252
+ def tool_contract_propose(ctx: ManagerContext, args: dict[str, Any]) -> str:
253
+ path = ctx.log_path
254
+ change = cli.new_contract_change(
255
+ proposer=args["proposer"],
256
+ kind=args["kind"],
257
+ name=args["name"],
258
+ summary=args["summary"],
259
+ compatibility=args.get("compatibility", "unknown"),
260
+ )
261
+ cli.append_event(
262
+ path,
263
+ cli.make_event(
264
+ "contract.change.proposed",
265
+ args["proposer"],
266
+ "repo:mcp",
267
+ {"contract_change": change},
268
+ ),
269
+ )
270
+ result: dict[str, Any] = {"contract_change": change}
271
+ if change["compatibility"] == "breaking":
272
+ decision = cli.new_decision(
273
+ question=f"Should breaking contract change proceed: {args['name']}?",
274
+ context=json.dumps(change, ensure_ascii=False, sort_keys=True),
275
+ related_artifacts=[change["id"]],
276
+ risk="high",
277
+ )
278
+ cli.append_event(
279
+ path,
280
+ cli.make_event(
281
+ "decision.requested", "manager", "repo:mcp", {"decision": decision}
282
+ ),
283
+ )
284
+ result["decision_requested"] = decision["id"]
285
+ return json.dumps(result, indent=2, ensure_ascii=False)
286
+
287
+
288
+ TOOL_HANDLERS = {
289
+ "digest_branch": tool_digest_branch,
290
+ "manager_status": tool_manager_status,
291
+ "manager_forecast": tool_manager_forecast,
292
+ "lease_request": tool_lease_request,
293
+ "heartbeat": tool_heartbeat,
294
+ "contract_propose": tool_contract_propose,
295
+ }
296
+
297
+
298
+ def handle_request(ctx: ManagerContext, request: dict[str, Any]) -> dict[str, Any] | None:
299
+ method = request.get("method")
300
+ request_id = request.get("id")
301
+
302
+ if method == "initialize":
303
+ return {
304
+ "jsonrpc": "2.0",
305
+ "id": request_id,
306
+ "result": {
307
+ "protocolVersion": PROTOCOL_VERSION,
308
+ "capabilities": {"tools": {}},
309
+ "serverInfo": SERVER_INFO,
310
+ },
311
+ }
312
+ if method in ("notifications/initialized", "notifications/cancelled"):
313
+ return None
314
+ if method == "ping":
315
+ return {"jsonrpc": "2.0", "id": request_id, "result": {}}
316
+ if method == "tools/list":
317
+ return {"jsonrpc": "2.0", "id": request_id, "result": {"tools": TOOLS}}
318
+ if method == "tools/call":
319
+ params = request.get("params", {})
320
+ name = params.get("name")
321
+ handler = TOOL_HANDLERS.get(name)
322
+ if handler is None:
323
+ return {
324
+ "jsonrpc": "2.0",
325
+ "id": request_id,
326
+ "error": {"code": -32602, "message": f"unknown tool: {name}"},
327
+ }
328
+ try:
329
+ text = handler(ctx, params.get("arguments") or {})
330
+ result = {"content": [{"type": "text", "text": text}], "isError": False}
331
+ except Exception as exc: # noqa: BLE001 - report tool failure to client
332
+ result = {
333
+ "content": [{"type": "text", "text": f"error: {exc}"}],
334
+ "isError": True,
335
+ }
336
+ return {"jsonrpc": "2.0", "id": request_id, "result": result}
337
+
338
+ if request_id is not None:
339
+ return {
340
+ "jsonrpc": "2.0",
341
+ "id": request_id,
342
+ "error": {"code": -32601, "message": f"method not found: {method}"},
343
+ }
344
+ return None
345
+
346
+
347
+ def serve(cwd: Path, state_dir: str, stdin=None, stdout=None) -> int:
348
+ """Serve newline-delimited JSON-RPC over stdio until EOF."""
349
+ stdin = stdin or sys.stdin
350
+ stdout = stdout or sys.stdout
351
+ ctx = ManagerContext(cwd, state_dir)
352
+ for line in stdin:
353
+ line = line.strip()
354
+ if not line:
355
+ continue
356
+ try:
357
+ request = json.loads(line)
358
+ except json.JSONDecodeError:
359
+ response = {
360
+ "jsonrpc": "2.0",
361
+ "id": None,
362
+ "error": {"code": -32700, "message": "parse error"},
363
+ }
364
+ stdout.write(json.dumps(response) + "\n")
365
+ stdout.flush()
366
+ continue
367
+ response = handle_request(ctx, request)
368
+ if response is not None:
369
+ stdout.write(json.dumps(response, ensure_ascii=False) + "\n")
370
+ stdout.flush()
371
+ return 0
@@ -0,0 +1,250 @@
1
+ Metadata-Version: 2.4
2
+ Name: coprogrammer
3
+ Version: 0.1.0
4
+ Summary: Open protocol and toolkit for semantic integration in multi-agent software development.
5
+ Author: Qiu Guanzong
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Qiu Guanzong
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
+
28
+ Project-URL: Homepage, https://github.com/QIU-Guanzong/CoProgrammer
29
+ Project-URL: Repository, https://github.com/QIU-Guanzong/CoProgrammer
30
+ Project-URL: Issues, https://github.com/QIU-Guanzong/CoProgrammer/issues
31
+ Keywords: ai,software-development,multi-agent,merge,code-review
32
+ Classifier: Development Status :: 2 - Pre-Alpha
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3 :: Only
37
+ Requires-Python: >=3.10
38
+ Description-Content-Type: text/markdown
39
+ License-File: LICENSE
40
+ Dynamic: license-file
41
+
42
+ # CoProgrammer
43
+
44
+ CoProgrammer is an open protocol and toolkit for multi-agent software
45
+ development in the AI coding era.
46
+
47
+ CoProgrammer 同时支持中文团队协作场景:PR 分支消化报告可以用
48
+ `zh-CN` 输出,也可以通过仓库变量切回英文。
49
+
50
+ The project starts from one practical belief:
51
+
52
+ > AI-era merging is not only a text conflict problem. It is a semantic
53
+ > integration problem.
54
+
55
+ When several humans and AI agents work in parallel, the hard part is no longer
56
+ choosing one side of a merge conflict. The hard part is understanding what each
57
+ branch learned, preserving the useful insight, discarding noise, and rebuilding
58
+ the smallest safe patch on top of the current main branch.
59
+
60
+ ## Where CoProgrammer Sits
61
+
62
+ CoProgrammer is **not** another parallel-agent orchestrator. It is the missing
63
+ layer between orchestrators and the merge queue:
64
+
65
+ ```text
66
+ UPSTREAM agent runtimes & orchestrators
67
+ (Conductor, Sculptor, Vibe Kanban, Claude Squad,
68
+ Codex, Copilot Cloud Agent, OpenHands, ...)
69
+ → produce parallel branches
70
+ │
71
+ COPROGRAMMER integration & governance layer
72
+ protocol → telemetry → conflict forecast →
73
+ branch digest → integration plan →
74
+ minimal patch → integration record → policy update
75
+ │
76
+ DOWNSTREAM landing infrastructure
77
+ (Merge Queue / Merge Trains / Mergify / Graphite,
78
+ CI, CODEOWNERS, branch protection)
79
+ ```
80
+
81
+ Orchestrators solve "run N agents in parallel without stepping on each other."
82
+ CoProgrammer solves "when N branches come back, decide what deserves to reach
83
+ `main`, and rebuild it safely under main-branch constraints." See
84
+ `docs/ORCHESTRATOR_INTEGRATION.md` for concrete hookup recipes.
85
+
86
+ ## Core Loop
87
+
88
+ CoProgrammer organizes collaboration as a continuous loop:
89
+
90
+ 1. **Protocol before coding**: define main-branch principles, module
91
+ boundaries, shared contracts, protected files, and agent permissions.
92
+ 2. **Telemetry during coding**: agents publish heartbeats, contract changes,
93
+ current file ownership, experiments, and blockers.
94
+ 3. **Digest after coding**: a feature branch is summarized by intent, core
95
+ contribution, noise, contract changes, risks, and integration plan.
96
+ 4. **Semantic integration**: instead of directly merging a large AI branch, an
97
+ integration patch is rebuilt from latest `main` under main-branch
98
+ constraints.
99
+ 5. **Validation and feedback**: tests, contract checks, owner review, and merge
100
+ records update the protocol for the next cycle.
101
+
102
+ ## Repository Map
103
+
104
+ ```text
105
+ .
106
+ ├── docs/ Research route, framework, and MVP design
107
+ ├── protocols/ Human-readable collaboration protocols
108
+ ├── research/ Structured research leads and prior-art data
109
+ ├── schemas/ JSON schemas for machine-readable agent artifacts
110
+ ├── templates/ Task, heartbeat, digest, and integration templates
111
+ ├── src/coprogrammer/ First CLI scaffold
112
+ ├── tests/ Unit tests for the CLI scaffold
113
+ ├── AGENTS.md Minimal stable instructions for coding agents
114
+ ├── .coprogrammer.json Project policy config
115
+ └── .github/ PR template, issue templates, CI, and PR digest workflow
116
+ ```
117
+
118
+ Start with:
119
+
120
+ - `docs/COORDINATION_LIFECYCLE.md` for the before/during/after collaboration
121
+ loop: project covenant, Manager Plane synchronization, and post-PR semantic
122
+ integration;
123
+ - `docs/ECOSYSTEM_EXTENSION_STRATEGY.md` for the research method and MCP,
124
+ skill, plugin, GitHub automation, and open-source library integration plan;
125
+ - `docs/PLUGIN_QUICKSTART.md` for installing and using the repo-local
126
+ CoProgrammer Codex plugin;
127
+ - `docs/COMPREHENSIVE_RESEARCH_PLAN.md` for the research program and six-week sprint;
128
+ - `docs/RESEARCH_UPDATE_2026-05-25.md` for the latest Manager Plane evidence update;
129
+ - `docs/RESEARCH_PROTOCOL.md` for how to capture and evaluate research leads;
130
+ - `docs/FAILURE_TAXONOMY.md` for the failure modes CoProgrammer targets;
131
+ - `docs/RESEARCH_LANDSCAPE.md` for current tool landscape and gaps;
132
+ - `docs/OPEN_SOURCE_SCAN.md` for adjacent open-source projects and reusable features;
133
+ - `docs/FEATURE_GAP_MATRIX.md` for product-level comparison;
134
+ - `docs/DISCUSSIONS.md` for discussion categories and research intake;
135
+ - `docs/ARCHITECTURE.md` for the system architecture;
136
+ - `docs/MANAGER_PLANE.md` for the cloud/self-hosted control plane hypothesis;
137
+ - `docs/MANAGER_API_SKETCH.md` for the first Manager API surface;
138
+ - `docs/EVENT_LOG_PROTOTYPE.md` for the local Manager Plane prototype;
139
+ - `docs/AGENT_RUNTIME_INTEROP.md` for integrating with Codex, Copilot, OpenHands, and other runtimes;
140
+ - `docs/CONTEXT_FILE_STRATEGY.md` for keeping `AGENTS.md` small and structured state separate;
141
+ - `docs/INTEGRATION_PATCH_DESIGN.md` for the minimal-patch reconstruction design;
142
+ - `docs/MODEL_ROUTING_POLICY.md` for routing simple work to `codex-5.3` and high-risk work to review;
143
+ - `docs/HIGH_STAR_PROJECT_SCAN_2026-05-26.md` for high-star project patterns to borrow;
144
+ - `docs/FRAMEWORK.md` for the research framework;
145
+ - `docs/ORCHESTRATOR_INTEGRATION.md` for feeding Conductor, Sculptor, Vibe
146
+ Kanban, and cloud-agent branches into CoProgrammer;
147
+ - `docs/STRATEGY_MEMO_2026-06-10.md` for the latest positioning and priority
148
+ decisions;
149
+ - `docs/EVAL_PLAN.md` for the AgenticFlict-based evaluation plan;
150
+ - `ACKNOWLEDGMENTS.md` for the projects we learn from and how we credit them.
151
+
152
+ ## Install (pick your surface)
153
+
154
+ CoProgrammer ships one core through several thin wrappers — use whichever
155
+ your stack already speaks (details: `docs/DISTRIBUTION_STRATEGY.md`):
156
+
157
+ **MCP server** (Claude Code, Codex, Cursor, any MCP client):
158
+
159
+ ```json
160
+ { "mcpServers": { "coprogrammer": {
161
+ "command": "uvx", "args": ["coprogrammer", "mcp", "serve"] } } }
162
+ ```
163
+
164
+ Tools exposed: `digest_branch`, `manager_status`, `manager_forecast`,
165
+ `lease_request`, `heartbeat`, `contract_propose`.
166
+
167
+ **Agent Skills** (SKILL.md open standard — Claude Code, Codex CLI, Gemini
168
+ CLI, Copilot, Cursor, 35+ tools): copy `plugins/coprogrammer/skills/*` into
169
+ your agent's skills directory.
170
+
171
+ **GitHub Action** (PR branch digest, zero setup):
172
+
173
+ ```yaml
174
+ - uses: actions/checkout@v4
175
+ with: { fetch-depth: 0 }
176
+ - uses: QIU-Guanzong/CoProgrammer@v0
177
+ with: { language: zh-CN }
178
+ ```
179
+
180
+ **CLI**: `pipx install coprogrammer` (or from source:
181
+ `python -m pip install -e .`).
182
+
183
+ **Codex plugin**: `codex plugin marketplace add <this repo>` — see
184
+ `docs/PLUGIN_QUICKSTART.md`.
185
+
186
+ ## First MVP
187
+
188
+ The first useful version is a **Branch Digest Bot**:
189
+
190
+ - reads a PR diff and commit history;
191
+ - detects contract-sensitive files and architecture risk signals;
192
+ - generates a branch digest draft;
193
+ - asks reviewers to approve an integration plan before merging;
194
+ - keeps direct AI-generated mega-branches out of `main`.
195
+
196
+ The first GitHub Actions version is included in
197
+ `.github/workflows/pr-digest.yml`. It generates `branch-digest.md`, uploads it
198
+ as an artifact, and updates a stable PR comment for same-repository PRs.
199
+
200
+ This repository already contains a minimal local CLI prototype:
201
+
202
+ ```bash
203
+ python -m coprogrammer digest --base origin/main --head HEAD --output branch-digest.md
204
+ python -m coprogrammer digest --base origin/main --head HEAD --language zh-CN
205
+ python -m coprogrammer digest --base origin/main --working-tree
206
+ python -m coprogrammer config validate
207
+ python -m coprogrammer agents check
208
+ python -m coprogrammer manifest validate templates/change-manifest.json
209
+ python -m coprogrammer integration-plan validate templates/integration-plan.json
210
+ python -m coprogrammer heartbeat new --agent agent-a --task "Implement login API"
211
+ python -m coprogrammer manager lease request --holder agent-a --pattern "src/api/**"
212
+ python -m coprogrammer manager contract propose --proposer agent-a --kind api --name "POST /login" --summary "Add login endpoint"
213
+ python -m coprogrammer manager forecast --base origin/main --fail-on-conflict
214
+ python -m coprogrammer manager status
215
+ ```
216
+
217
+ Language can also be controlled by `COPROGRAMMER_LANGUAGE=en|zh-CN`.
218
+
219
+ For local development:
220
+
221
+ ```bash
222
+ python -m pip install -e .
223
+ python -m unittest discover -s tests
224
+ ```
225
+
226
+ ## Project Goals
227
+
228
+ - Create an open protocol for AI-assisted multi-agent collaboration.
229
+ - Make branch intent, contracts, and insights first-class artifacts.
230
+ - Reduce merge conflicts by forecasting ownership and contract collisions early.
231
+ - Preserve useful experiments without merging noisy generated code.
232
+ - Help reviewers inspect integration plans instead of massive raw diffs.
233
+
234
+ ## Non-Goals
235
+
236
+ - CoProgrammer is not a replacement for Git, GitHub, GitLab, or CI.
237
+ - CoProgrammer does not blindly auto-merge AI output.
238
+ - CoProgrammer does not treat formatting churn, dependency upgrades, and feature
239
+ logic as the same kind of change.
240
+
241
+ ## Status
242
+
243
+ This is an early research and tooling scaffold. The current focus is:
244
+
245
+ 1. protocol design;
246
+ 2. branch digest format;
247
+ 3. lightweight CLI;
248
+ 4. GitHub Action integration;
249
+ 5. project policy and risk scoring;
250
+ 6. later: semantic integration bot and multi-agent orchestrator.
@@ -0,0 +1,10 @@
1
+ coprogrammer/__init__.py,sha256=-QXUKZ4e8_F-nGCLBYAmQcZ3ttTHLQ0m7tu5Uc1mY5A,87
2
+ coprogrammer/__main__.py,sha256=PSQ4rpL0dG6f-qH4N7H-gD9igQkdHzH4yVZDcW8lfZo,80
3
+ coprogrammer/cli.py,sha256=Bb46tmI-3A7ycOvPDv9c795KyZi_Q6u5OAoo4jVpTsA,63981
4
+ coprogrammer/mcp_server.py,sha256=6R5lVjZteF8O1jmcnIykBHOgROU4p4Fd2nCl9zbcsSc,12491
5
+ coprogrammer-0.1.0.dist-info/licenses/LICENSE,sha256=eIX-QyKEWaCSPjCtPSJJOqEwa6UyYpR25VL9YvNb9VY,1069
6
+ coprogrammer-0.1.0.dist-info/METADATA,sha256=tywyvQ51QqiR6oXTr0vFlCAs2VslvGsSBx7GnF5rOoM,11193
7
+ coprogrammer-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
8
+ coprogrammer-0.1.0.dist-info/entry_points.txt,sha256=y6O0mHB5Q-kNyN6fS6jNoOYZVWDQZhhSCxqInd67jU0,55
9
+ coprogrammer-0.1.0.dist-info/top_level.txt,sha256=Rv0-pipBsieJUXEoaIiPHHxVlqJtlrZCI-wp3JQ0-tg,13
10
+ coprogrammer-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ coprogrammer = coprogrammer.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Qiu Guanzong
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 @@
1
+ coprogrammer