@hunyed15/codecgc 0.1.0

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 (128) hide show
  1. package/.claude/hooks/route-edit.ps1 +86 -0
  2. package/INSTALLATION.md +550 -0
  3. package/LICENSE +21 -0
  4. package/README.md +171 -0
  5. package/bin/cgc-build.js +4 -0
  6. package/bin/cgc-doctor.js +4 -0
  7. package/bin/cgc-entry.js +4 -0
  8. package/bin/cgc-external-audit.js +4 -0
  9. package/bin/cgc-fix.js +4 -0
  10. package/bin/cgc-history.js +4 -0
  11. package/bin/cgc-install.js +4 -0
  12. package/bin/cgc-lifecycle.js +4 -0
  13. package/bin/cgc-package-audit.js +4 -0
  14. package/bin/cgc-plan.js +4 -0
  15. package/bin/cgc-release-readiness.js +4 -0
  16. package/bin/cgc-review.js +4 -0
  17. package/bin/cgc-route.js +4 -0
  18. package/bin/cgc-status.js +4 -0
  19. package/bin/cgc-test.js +4 -0
  20. package/bin/cgc.js +4 -0
  21. package/bin/codecgc.js +1284 -0
  22. package/codecgc/cgc/SKILL.md +46 -0
  23. package/codecgc/cgc-arch/SKILL.md +61 -0
  24. package/codecgc/cgc-build/SKILL.md +53 -0
  25. package/codecgc/cgc-decide/SKILL.md +55 -0
  26. package/codecgc/cgc-fix/SKILL.md +47 -0
  27. package/codecgc/cgc-learn/SKILL.md +46 -0
  28. package/codecgc/cgc-onboard/SKILL.md +52 -0
  29. package/codecgc/cgc-plan/SKILL.md +48 -0
  30. package/codecgc/cgc-refactor/SKILL.md +46 -0
  31. package/codecgc/cgc-req/SKILL.md +61 -0
  32. package/codecgc/cgc-review/SKILL.md +57 -0
  33. package/codecgc/cgc-roadmap/SKILL.md +55 -0
  34. package/codecgc/cgc-test/SKILL.md +21 -0
  35. package/codecgc/reference/api-cgc-review-libdoc.md +13 -0
  36. package/codecgc/reference/artifact-class-policy.md +81 -0
  37. package/codecgc/reference/build-flow.md +95 -0
  38. package/codecgc/reference/checklist-contract.md +103 -0
  39. package/codecgc/reference/execution-audit.md +121 -0
  40. package/codecgc/reference/execution-model.md +118 -0
  41. package/codecgc/reference/execution-routing.md +130 -0
  42. package/codecgc/reference/executor-contract.md +87 -0
  43. package/codecgc/reference/external-capability-registry.json +104 -0
  44. package/codecgc/reference/fix-flow.md +94 -0
  45. package/codecgc/reference/fixture-governance.md +60 -0
  46. package/codecgc/reference/flow-execution.md +65 -0
  47. package/codecgc/reference/lifecycle-map.md +172 -0
  48. package/codecgc/reference/lifecycle-playbook.md +104 -0
  49. package/codecgc/reference/long-lived-artifacts.md +98 -0
  50. package/codecgc/reference/operation-guide.md +242 -0
  51. package/codecgc/reference/release-maintenance-playbook.md +150 -0
  52. package/codecgc/reference/review-writeback.md +141 -0
  53. package/codecgc/reference/role-model.md +128 -0
  54. package/codecgc/reference/runtime-boundary.md +72 -0
  55. package/codecgc/reference/shared-conventions.md +93 -0
  56. package/codecgc/reference/workflow-scaffold.md +57 -0
  57. package/codexmcp/LICENSE +21 -0
  58. package/codexmcp/README.md +294 -0
  59. package/codexmcp/pyproject.toml +37 -0
  60. package/codexmcp/src/codexmcp/__init__.py +4 -0
  61. package/codexmcp/src/codexmcp/cli.py +12 -0
  62. package/codexmcp/src/codexmcp/server.py +529 -0
  63. package/geminimcp/README.md +258 -0
  64. package/geminimcp/pyproject.toml +15 -0
  65. package/geminimcp/src/geminimcp/__init__.py +4 -0
  66. package/geminimcp/src/geminimcp/cli.py +12 -0
  67. package/geminimcp/src/geminimcp/server.py +465 -0
  68. package/model-routing.yaml +30 -0
  69. package/package.json +90 -0
  70. package/requirements.txt +1 -0
  71. package/scripts/README-codecgc-cli.md +89 -0
  72. package/scripts/audit_codecgc_external_capabilities.py +276 -0
  73. package/scripts/audit_codecgc_historical_audits.py +242 -0
  74. package/scripts/audit_codecgc_lifecycle.py +241 -0
  75. package/scripts/audit_codecgc_package_runtime.py +445 -0
  76. package/scripts/audit_codecgc_release_readiness.py +202 -0
  77. package/scripts/audit_codecgc_review_policy.py +82 -0
  78. package/scripts/audit_codecgc_workflow_history.py +317 -0
  79. package/scripts/build_codecgc_task.py +487 -0
  80. package/scripts/codecgc_artifact_roots.py +40 -0
  81. package/scripts/codecgc_cli.py +843 -0
  82. package/scripts/codecgc_command_surface.py +28 -0
  83. package/scripts/codecgc_console_io.py +45 -0
  84. package/scripts/codecgc_executor_registry.py +54 -0
  85. package/scripts/codecgc_file_evidence.py +349 -0
  86. package/scripts/codecgc_flow_control.py +233 -0
  87. package/scripts/codecgc_governance_dedupe.py +161 -0
  88. package/scripts/codecgc_plan_decision.py +103 -0
  89. package/scripts/codecgc_review_control.py +588 -0
  90. package/scripts/codecgc_roadmap_templates.py +149 -0
  91. package/scripts/codecgc_routing_paths.py +16 -0
  92. package/scripts/codecgc_routing_template.py +135 -0
  93. package/scripts/codecgc_runtime_paths.py +22 -0
  94. package/scripts/codecgc_session_recovery.py +44 -0
  95. package/scripts/codecgc_step_control.py +154 -0
  96. package/scripts/codecgc_workflow_runtime.py +63 -0
  97. package/scripts/codecgc_workflow_templates.py +437 -0
  98. package/scripts/entry_codecgc_workflow.py +3419 -0
  99. package/scripts/exercise_mcp_tools.py +109 -0
  100. package/scripts/expand_codecgc_roadmap.py +664 -0
  101. package/scripts/init_codecgc_roadmap.py +134 -0
  102. package/scripts/init_codecgc_workflow.py +207 -0
  103. package/scripts/install_codecgc.py +938 -0
  104. package/scripts/migrate_demo_workflows_to_fixtures.py +128 -0
  105. package/scripts/normalize_codecgc_audits.py +114 -0
  106. package/scripts/normalize_codecgc_governance_docs.py +79 -0
  107. package/scripts/normalize_codecgc_workflow_docs.py +269 -0
  108. package/scripts/plan_codecgc_workflow.py +970 -0
  109. package/scripts/refresh_codecgc_review_policy.py +223 -0
  110. package/scripts/review_codecgc_workflow.py +88 -0
  111. package/scripts/route_codecgc_workflow.py +671 -0
  112. package/scripts/run_codecgc_build.py +104 -0
  113. package/scripts/run_codecgc_fix.py +104 -0
  114. package/scripts/run_codecgc_flow_step.py +165 -0
  115. package/scripts/run_codecgc_task.py +410 -0
  116. package/scripts/run_codecgc_test.py +105 -0
  117. package/scripts/sync_codecgc_mcp_config.py +41 -0
  118. package/scripts/write_codecgc_architecture.py +78 -0
  119. package/scripts/write_codecgc_decision.py +83 -0
  120. package/scripts/write_codecgc_explore.py +118 -0
  121. package/scripts/write_codecgc_guide.py +141 -0
  122. package/scripts/write_codecgc_learning.py +87 -0
  123. package/scripts/write_codecgc_libdoc.py +140 -0
  124. package/scripts/write_codecgc_refactor.py +78 -0
  125. package/scripts/write_codecgc_requirement.py +78 -0
  126. package/scripts/write_codecgc_review.py +291 -0
  127. package/scripts/write_codecgc_roadmap.py +122 -0
  128. package/scripts/write_codecgc_trick.py +123 -0
@@ -0,0 +1,465 @@
1
+ """FastMCP server implementation for the Gemini MCP project."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import queue
8
+ import subprocess
9
+ import threading
10
+ import time
11
+ import uuid
12
+ from pathlib import Path
13
+ from typing import Annotated, Any, Dict, Generator, List, Optional
14
+
15
+ from mcp.server.fastmcp import FastMCP
16
+ from pydantic import BeforeValidator, Field
17
+ import shutil
18
+
19
+ mcp = FastMCP("Gemini MCP Server-from guda.studio")
20
+
21
+ # Mirror of model-routing.yaml backend_paths — keep these hints in sync with
22
+ # route-edit.ps1 and codexmcp/server.py FRONTEND_PATH_HINTS.
23
+ BACKEND_PATH_HINTS = (
24
+ "apps/api/",
25
+ "server/",
26
+ "src/server/",
27
+ "src/services/",
28
+ "src/repositories/",
29
+ "backend/",
30
+ )
31
+
32
+ BACKEND_FILE_HINTS = (
33
+ ".py",
34
+ ".go",
35
+ ".rs",
36
+ ".java",
37
+ ".kt",
38
+ ".cs",
39
+ ".rb",
40
+ ".php",
41
+ ".sql",
42
+ )
43
+
44
+
45
+ def _normalize_path_text(path_value: Path | str) -> str:
46
+ """Normalize a path-like value to a forward-slash string."""
47
+ return str(path_value).replace("\\", "/").strip()
48
+
49
+
50
+ def _is_probably_backend_path(path_value: Path | str) -> bool:
51
+ """Best-effort check to keep frontend-only Gemini tasks away from backend files."""
52
+ normalized = _normalize_path_text(path_value).lower().lstrip("./")
53
+ if any(hint in normalized for hint in BACKEND_PATH_HINTS):
54
+ return True
55
+
56
+ suffix = Path(normalized).suffix.lower()
57
+ if suffix in BACKEND_FILE_HINTS:
58
+ return True
59
+
60
+ return False
61
+
62
+
63
+ def _build_frontend_task_prompt(
64
+ task_summary: str,
65
+ target_paths: List[Path],
66
+ constraints: List[str],
67
+ acceptance_criteria: List[str],
68
+ ) -> str:
69
+ """Build a constrained prompt for frontend implementation tasks."""
70
+ lines = [
71
+ "You are implementing a frontend-only coding task.",
72
+ "Stay strictly within the provided target paths.",
73
+ "Do not edit backend files, API layers, repositories, or server logic.",
74
+ "Preserve the existing product structure unless the task explicitly requires otherwise.",
75
+ "Return a concise implementation summary, followed by risks if any remain.",
76
+ "",
77
+ "Task summary:",
78
+ task_summary.strip(),
79
+ "",
80
+ "Target paths:",
81
+ ]
82
+
83
+ lines.extend(f"- {_normalize_path_text(path)}" for path in target_paths)
84
+
85
+ if constraints:
86
+ lines.append("")
87
+ lines.append("Constraints:")
88
+ lines.extend(f"- {item.strip()}" for item in constraints if item.strip())
89
+
90
+ if acceptance_criteria:
91
+ lines.append("")
92
+ lines.append("Acceptance criteria:")
93
+ lines.extend(f"- {item.strip()}" for item in acceptance_criteria if item.strip())
94
+
95
+ return "\n".join(lines).strip()
96
+
97
+
98
+ def _validate_frontend_target_paths(target_paths: List[Path]) -> tuple[bool, List[str], str]:
99
+ """Validate frontend task target paths and return policy check notes."""
100
+ if not target_paths:
101
+ return False, [], "The `target_paths` field must contain at least one file or directory."
102
+
103
+ normalized_paths = [_normalize_path_text(path) for path in target_paths]
104
+ backend_hits = [
105
+ path_text
106
+ for path_text in normalized_paths
107
+ if _is_probably_backend_path(path_text)
108
+ ]
109
+
110
+ policy_checks = [
111
+ "target_paths_present",
112
+ "frontend_scope_requested",
113
+ ]
114
+
115
+ if backend_hits:
116
+ return (
117
+ False,
118
+ policy_checks,
119
+ "The frontend executor refused backend-like paths: "
120
+ + ", ".join(backend_hits),
121
+ )
122
+
123
+ policy_checks.append("backend_boundary_check_passed")
124
+ return True, policy_checks, ""
125
+
126
+
127
+ def run_shell_command(cmd: list[str], cwd: str | None = None) -> Generator[str, None, None]:
128
+ """Execute a command and stream its output line-by-line.
129
+
130
+ Args:
131
+ cmd: Command and arguments as a list (e.g., ["gemini", "-o", "stream-json", "--", "prompt"])
132
+ cwd: Working directory for the command
133
+
134
+ Yields:
135
+ Output lines from the command
136
+ """
137
+ popen_cmd = cmd
138
+
139
+ gemini_path = shutil.which("gemini") or cmd[0]
140
+ popen_cmd[0] = gemini_path
141
+
142
+ # if os.name == "nt" and gemini_path.lower().endswith((".cmd", ".bat")):
143
+ # from subprocess import list2cmdline
144
+ # popen_cmd = ["cmd.exe", "/s", "/c", list2cmdline(cmd)]
145
+
146
+ process = subprocess.Popen(
147
+ popen_cmd,
148
+ shell=False,
149
+ stdin=subprocess.DEVNULL,
150
+ stdout=subprocess.PIPE,
151
+ stderr=subprocess.STDOUT,
152
+ universal_newlines=True,
153
+ encoding='utf-8',
154
+ cwd=cwd,
155
+ )
156
+
157
+ output_queue: queue.Queue[str | None] = queue.Queue()
158
+ GRACEFUL_SHUTDOWN_DELAY = 0.3
159
+
160
+ def is_turn_completed(line: str) -> bool:
161
+ """Check if the line indicates turn completion via JSON parsing."""
162
+ try:
163
+ data = json.loads(line)
164
+ return data.get("type") in {"turn.completed", "result"}
165
+ except (json.JSONDecodeError, AttributeError, TypeError):
166
+ return False
167
+
168
+ def read_output() -> None:
169
+ """Read process output in a separate thread."""
170
+ if process.stdout:
171
+ for line in iter(process.stdout.readline, ""):
172
+ stripped = line.strip()
173
+ output_queue.put(stripped)
174
+ if is_turn_completed(stripped):
175
+ time.sleep(GRACEFUL_SHUTDOWN_DELAY)
176
+ process.terminate()
177
+ break
178
+ process.stdout.close()
179
+ output_queue.put(None)
180
+
181
+ thread = threading.Thread(target=read_output)
182
+ thread.start()
183
+
184
+ # Yield lines while process is running
185
+ while True:
186
+ try:
187
+ line = output_queue.get(timeout=0.5)
188
+ if line is None:
189
+ break
190
+ yield line
191
+ except queue.Empty:
192
+ if process.poll() is not None and not thread.is_alive():
193
+ break
194
+
195
+ try:
196
+ process.wait(timeout=5)
197
+ except subprocess.TimeoutExpired:
198
+ process.kill()
199
+ process.wait()
200
+ thread.join(timeout=5)
201
+
202
+ while not output_queue.empty():
203
+ try:
204
+ line = output_queue.get_nowait()
205
+ if line is not None:
206
+ yield line
207
+ except queue.Empty:
208
+ break
209
+
210
+
211
+ def _execute_gemini_session(
212
+ *,
213
+ prompt: str,
214
+ cd: Path,
215
+ sandbox: bool,
216
+ session_id: str,
217
+ return_all_messages: bool,
218
+ model: str,
219
+ ) -> Dict[str, Any]:
220
+ """Execute Gemini CLI and return the parsed MCP response payload."""
221
+ if not cd.exists():
222
+ return {
223
+ "success": False,
224
+ "error": f"The workspace root directory `{cd.absolute().as_posix()}` does not exist. Please check the path and try again.",
225
+ }
226
+
227
+ if os.name == "nt":
228
+ prompt = windows_escape(prompt)
229
+
230
+ cmd = ["gemini", "--skip-trust", "--prompt", prompt, "-o", "stream-json"]
231
+
232
+ if sandbox:
233
+ cmd.extend(["--sandbox"])
234
+
235
+ if model:
236
+ cmd.extend(["--model", model])
237
+
238
+ if session_id:
239
+ cmd.extend(["--resume", session_id])
240
+
241
+ all_messages = []
242
+ agent_messages = ""
243
+ success = True
244
+ err_message = ""
245
+ thread_id: Optional[str] = None
246
+
247
+ for line in run_shell_command(cmd, cwd=cd.absolute().as_posix()):
248
+ try:
249
+ line_dict = json.loads(line.strip())
250
+ all_messages.append(line_dict)
251
+ item_type = line_dict.get("type", "")
252
+ item_role = line_dict.get("role", "")
253
+ if item_type == "message" and item_role == "assistant":
254
+ if (
255
+ "The --prompt (-p) flag has been deprecated and will be removed in a future version. Please use a positional argument for your prompt. See gemini --help for more information.\n"
256
+ in line_dict.get("content", "")
257
+ ):
258
+ continue
259
+ agent_messages = agent_messages + line_dict.get("content", "")
260
+ if line_dict.get("session_id") is not None:
261
+ thread_id = line_dict.get("session_id")
262
+ except json.JSONDecodeError:
263
+ err_message += "\n\n[json decode error] " + line
264
+ continue
265
+ except Exception as error:
266
+ err_message += "\n\n[unexpected error] " + f"Unexpected error: {error}. Line: {line!r}"
267
+ break
268
+
269
+ if thread_id is None:
270
+ success = False
271
+ err_message = (
272
+ "Failed to get `SESSION_ID` from the gemini session. \n\n" + err_message
273
+ )
274
+
275
+ if success and len(agent_messages) == 0:
276
+ success = False
277
+ err_message = (
278
+ "Failed to retrieve `agent_messages` data from the Gemini session. This might be due to Gemini performing a tool call. You can continue using the `SESSION_ID` to proceed with the conversation. \n\n "
279
+ + err_message
280
+ )
281
+
282
+ if success:
283
+ result: Dict[str, Any] = {
284
+ "success": True,
285
+ "SESSION_ID": thread_id,
286
+ "agent_messages": agent_messages,
287
+ }
288
+ else:
289
+ result = {"success": False, "error": err_message}
290
+
291
+ if return_all_messages:
292
+ result["all_messages"] = all_messages
293
+
294
+ return result
295
+
296
+
297
+ def windows_escape(prompt):
298
+ """
299
+ Windows 风格的字符串转义函数。
300
+ 把常见特殊字符转义成 \\ 形式,适合命令行、JSON 或路径使用。
301
+ 比如:\n 变成 \\n," 变成 \\"。
302
+ """
303
+ # 先处理反斜杠,避免它干扰其他替换
304
+ result = prompt.replace("\\", "\\\\")
305
+ # 双引号,转义成 \",防止字符串边界乱套
306
+ result = result.replace('"', '\\"')
307
+ # 换行符,Windows 常用 \r\n,但我们分开转义
308
+ result = result.replace("\n", "\\n")
309
+ result = result.replace("\r", "\\r")
310
+ # 制表符,空格的“超级版”
311
+ result = result.replace("\t", "\\t")
312
+ # 其他常见:退格符(像按了后退键)、换页符(打印机跳页用)
313
+ result = result.replace("\b", "\\b")
314
+ result = result.replace("\f", "\\f")
315
+ # 如果有单引号,也转义下(不过 Windows 命令行不那么严格,但保险起见)
316
+ result = result.replace("'", "\\'")
317
+
318
+ return result
319
+
320
+
321
+ @mcp.tool(
322
+ name="gemini",
323
+ description="""
324
+ Invokes the Gemini CLI to execute AI-driven tasks, returning structured JSON events and a session identifier for conversation continuity.
325
+
326
+ **Return structure:**
327
+ - `success`: boolean indicating execution status
328
+ - `SESSION_ID`: unique identifier for resuming this conversation in future calls
329
+ - `agent_messages`: concatenated assistant response text
330
+ - `all_messages`: (optional) complete array of JSON events when `return_all_messages=True`
331
+ - `error`: error description when `success=False`
332
+
333
+ **Best practices:**
334
+ - Always capture and reuse `SESSION_ID` for multi-turn interactions
335
+ - Enable `sandbox` mode when file modifications should be isolated
336
+ - Use `return_all_messages` only when detailed execution traces are necessary (increases payload size)
337
+ - Only pass `model` when the user has explicitly requested a specific model
338
+ """,
339
+ meta={"version": "0.0.0", "author": "guda.studio"},
340
+ )
341
+ async def gemini(
342
+ PROMPT: Annotated[str, "Instruction for the task to send to gemini."],
343
+ cd: Annotated[Path, "Set the workspace root for gemini before executing the task."],
344
+ sandbox: Annotated[
345
+ bool,
346
+ Field(description="Run in sandbox mode. Defaults to `False`."),
347
+ ] = False,
348
+ SESSION_ID: Annotated[
349
+ str,
350
+ "Resume the specified session of the gemini. Defaults to empty string, start a new session.",
351
+ ] = "",
352
+ return_all_messages: Annotated[
353
+ bool,
354
+ "Return all messages (e.g. reasoning, tool calls, etc.) from the gemini session. Set to `False` by default, only the agent's final reply message is returned.",
355
+ ] = False,
356
+ model: Annotated[
357
+ str,
358
+ "The model to use for the gemini session. This parameter is strictly prohibited unless explicitly specified by the user.",
359
+ ] = "",
360
+ ) -> Dict[str, Any]:
361
+ """Execute a gemini CLI session and return the results."""
362
+ return _execute_gemini_session(
363
+ prompt=PROMPT,
364
+ cd=cd,
365
+ sandbox=sandbox,
366
+ session_id=SESSION_ID,
367
+ return_all_messages=return_all_messages,
368
+ model=model,
369
+ )
370
+
371
+
372
+ @mcp.tool(
373
+ name="implement_frontend_task",
374
+ description="""
375
+ Executes a frontend-only implementation task via Gemini with extra policy checks.
376
+ Use this tool when Claude has already completed planning/design and needs Gemini to
377
+ perform the actual frontend code changes inside a constrained path set.
378
+ """,
379
+ meta={"version": "0.1.0", "author": "CodeCGC"},
380
+ )
381
+ async def implement_frontend_task(
382
+ task_id: Annotated[str, "Stable task identifier for audit and review."],
383
+ task_summary: Annotated[str, "Frontend implementation summary prepared by the orchestrator."],
384
+ target_paths: Annotated[
385
+ List[Path],
386
+ Field(
387
+ description="Frontend paths Gemini is allowed to touch for this task.",
388
+ ),
389
+ ],
390
+ constraints: Annotated[
391
+ List[str],
392
+ Field(
393
+ description="Non-negotiable implementation constraints for this frontend task.",
394
+ ),
395
+ ] = [],
396
+ acceptance_criteria: Annotated[
397
+ List[str],
398
+ Field(
399
+ description="Acceptance criteria the implementation should satisfy.",
400
+ ),
401
+ ] = [],
402
+ cd: Annotated[Path, "Workspace root for the frontend task."] = Path("."),
403
+ SESSION_ID: Annotated[
404
+ str,
405
+ "Resume the specified Gemini session. Empty string starts a new session.",
406
+ ] = "",
407
+ sandbox: Annotated[
408
+ bool,
409
+ Field(description="Run Gemini in sandbox mode. Defaults to `False`."),
410
+ ] = False,
411
+ return_all_messages: Annotated[
412
+ bool,
413
+ "Return full Gemini event logs for debugging. Defaults to `False`.",
414
+ ] = False,
415
+ model: Annotated[
416
+ str,
417
+ "Optional model override. Only use when explicitly requested by the user.",
418
+ ] = "",
419
+ ) -> Dict[str, Any]:
420
+ """Execute a frontend-only Gemini task with CodeCGC policy checks."""
421
+ valid, policy_checks, validation_error = _validate_frontend_target_paths(target_paths)
422
+ if not valid:
423
+ return {
424
+ "success": False,
425
+ "task_id": task_id,
426
+ "policy_checks": policy_checks,
427
+ "error": validation_error,
428
+ }
429
+
430
+ prompt = _build_frontend_task_prompt(
431
+ task_summary=task_summary,
432
+ target_paths=target_paths,
433
+ constraints=constraints,
434
+ acceptance_criteria=acceptance_criteria,
435
+ )
436
+ result = _execute_gemini_session(
437
+ prompt=prompt,
438
+ cd=cd,
439
+ sandbox=sandbox,
440
+ session_id=SESSION_ID,
441
+ return_all_messages=return_all_messages,
442
+ model=model,
443
+ )
444
+
445
+ if not result.get("success"):
446
+ result["task_id"] = task_id
447
+ result["policy_checks"] = policy_checks
448
+ return result
449
+
450
+ return {
451
+ "success": True,
452
+ "task_id": task_id,
453
+ "SESSION_ID": result["SESSION_ID"],
454
+ "summary": result["agent_messages"],
455
+ "agent_messages": result["agent_messages"],
456
+ "changed_files": [_normalize_path_text(path) for path in target_paths],
457
+ "policy_checks": policy_checks + ["frontend_executor_completed"],
458
+ "risks": [],
459
+ **({"all_messages": result["all_messages"]} if return_all_messages and "all_messages" in result else {}),
460
+ }
461
+
462
+
463
+ def run() -> None:
464
+ """Start the MCP server over stdio transport."""
465
+ mcp.run(transport="stdio")
@@ -0,0 +1,30 @@
1
+ version: 1
2
+
3
+ frontend_paths:
4
+ - "apps/web/**"
5
+ - "src/components/**"
6
+ - "src/pages/**"
7
+ - "src/app/**"
8
+ - "src/styles/**"
9
+ - "web/**"
10
+ - "frontend/**"
11
+
12
+ backend_paths:
13
+ - "apps/api/**"
14
+ - "server/**"
15
+ - "src/server/**"
16
+ - "src/services/**"
17
+ - "src/repositories/**"
18
+ - "backend/**"
19
+
20
+ shared_paths:
21
+ - "packages/shared/**"
22
+ - "src/shared/**"
23
+ - "src/lib/**"
24
+ - "src/types/**"
25
+
26
+ rules:
27
+ frontend_executor: "geminimcp"
28
+ backend_executor: "codexmcp"
29
+ shared_policy: "split-first"
30
+ claude_role: "plan-review-accept-only"
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@hunyed15/codecgc",
3
+ "version": "0.1.0",
4
+ "description": "Claude-hosted multi-model workflow product shell for CodeCGC.",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "bin": {
8
+ "cgc": "bin/cgc.js",
9
+ "cgc-install": "bin/cgc-install.js",
10
+ "cgc-status": "bin/cgc-status.js",
11
+ "cgc-doctor": "bin/cgc-doctor.js",
12
+ "cgc-package-audit": "bin/cgc-package-audit.js",
13
+ "cgc-external-audit": "bin/cgc-external-audit.js",
14
+ "cgc-release-readiness": "bin/cgc-release-readiness.js",
15
+ "cgc-lifecycle": "bin/cgc-lifecycle.js",
16
+ "cgc-history": "bin/cgc-history.js",
17
+ "cgc-entry": "bin/cgc-entry.js",
18
+ "cgc-plan": "bin/cgc-plan.js",
19
+ "cgc-build": "bin/cgc-build.js",
20
+ "cgc-fix": "bin/cgc-fix.js",
21
+ "cgc-test": "bin/cgc-test.js",
22
+ "cgc-review": "bin/cgc-review.js",
23
+ "cgc-route": "bin/cgc-route.js"
24
+ },
25
+ "scripts": {
26
+ "cgc:help": "node bin/cgc.js --help",
27
+ "cgc:status": "node bin/cgc-status.js --format summary",
28
+ "cgc:doctor": "node bin/cgc-doctor.js --format summary",
29
+ "cgc:package-audit": "node bin/cgc-package-audit.js --format summary",
30
+ "cgc:external-audit": "node bin/cgc-external-audit.js --format summary",
31
+ "cgc:release-readiness": "node bin/cgc-release-readiness.js --format summary",
32
+ "cgc:lifecycle": "node bin/cgc-lifecycle.js --format summary",
33
+ "cgc:history": "node bin/cgc-history.js --status open --last 10 --format summary",
34
+ "cgc:audit-historical-audits": "python scripts/audit_codecgc_historical_audits.py --format summary",
35
+ "cgc:audit-review-policy": "python scripts/audit_codecgc_review_policy.py --artifact-class all --format summary",
36
+ "cgc:refresh-review-policy": "python scripts/refresh_codecgc_review_policy.py --artifact-class all --write",
37
+ "cgc:pack-dry-run": "npm pack --dry-run"
38
+ },
39
+ "files": [
40
+ "bin/",
41
+ "scripts/*.py",
42
+ "scripts/README-codecgc-cli.md",
43
+ ".claude/hooks/route-edit.ps1",
44
+ "codecgc/cgc/",
45
+ "codecgc/cgc-arch/",
46
+ "codecgc/cgc-build/",
47
+ "codecgc/cgc-decide/",
48
+ "codecgc/cgc-fix/",
49
+ "codecgc/cgc-learn/",
50
+ "codecgc/cgc-onboard/",
51
+ "codecgc/cgc-plan/",
52
+ "codecgc/cgc-refactor/",
53
+ "codecgc/cgc-req/",
54
+ "codecgc/cgc-review/",
55
+ "codecgc/cgc-roadmap/",
56
+ "codecgc/cgc-test/",
57
+ "codecgc/reference/",
58
+ "codexmcp/pyproject.toml",
59
+ "codexmcp/README.md",
60
+ "codexmcp/LICENSE",
61
+ "codexmcp/src/codexmcp/",
62
+ "geminimcp/pyproject.toml",
63
+ "geminimcp/README.md",
64
+ "geminimcp/src/geminimcp/",
65
+ "requirements.txt",
66
+ "INSTALLATION.md",
67
+ "model-routing.yaml",
68
+ "README.md",
69
+ "LICENSE"
70
+ ],
71
+ "keywords": [
72
+ "claude",
73
+ "mcp",
74
+ "workflow",
75
+ "codex",
76
+ "gemini",
77
+ "multi-model"
78
+ ],
79
+ "homepage": "https://github.com/hunyed15/CodeCGC",
80
+ "bugs": {
81
+ "url": "https://github.com/hunyed15/CodeCGC/issues"
82
+ },
83
+ "engines": {
84
+ "node": ">=20"
85
+ },
86
+ "repository": {
87
+ "type": "git",
88
+ "url": "git+https://github.com/hunyed15/CodeCGC.git"
89
+ }
90
+ }
@@ -0,0 +1 @@
1
+ pyyaml>=6.0
@@ -0,0 +1,89 @@
1
+ # CodeCGC CLI
2
+
3
+ ## 用途
4
+
5
+ `codecgc_cli.py` 是 CodeCGC 的统一本地封装入口。
6
+
7
+ 相比逐个调用底层脚本,它更适合作为仓库维护和调试时的统一入口。
8
+
9
+ ## 常用命令
10
+
11
+ 单入口调度:
12
+
13
+ ```bash
14
+ python scripts/codecgc_cli.py entry --request "新增一个登录页面,放在 src/components/LoginForm.tsx"
15
+ python scripts/codecgc_cli.py entry --request "继续刚刚的工作"
16
+ python scripts/codecgc_cli.py entry --request "现在下一步该做什么"
17
+ python scripts/codecgc_cli.py entry --mode new --flow feature --slug demo-login-ui --summary "Demo login UI feature" --target-path src/components/LoginForm.tsx --kind frontend
18
+ python scripts/codecgc_cli.py entry --mode continue --flow feature --slug 2026-05-01-demo-login-ui
19
+ python scripts/codecgc_cli.py entry --mode explain --slug 2026-05-01-demo-login-ui
20
+ python scripts/codecgc_cli.py entry --mode continue --latest
21
+ python scripts/codecgc_cli.py entry --mode continue --slug 2026-05-01-demo-login-ui --auto-dispatch --dry-run
22
+ ```
23
+
24
+ 规划并补齐工作流骨架:
25
+
26
+ ```bash
27
+ python scripts/codecgc_cli.py plan --flow feature --slug demo-login-ui --summary "Demo login UI feature" --target-path src/components/LoginForm.tsx --kind frontend
28
+ python scripts/codecgc_cli.py plan --flow issue --slug demo-sync-bug --summary "Demo sync bug fix" --target-path backend/session/continue.py --kind backend
29
+ ```
30
+
31
+ 支持结构化 `plan` 输入:
32
+
33
+ ```bash
34
+ python scripts/codecgc_cli.py plan --flow feature --slug demo-login-ui --summary "Demo login UI feature" --target-path src/components/LoginForm.tsx --kind frontend --goal "Allow users to sign in from a dedicated login form." --in-scope "Create the login form UI." --acceptance "Login form renders email and password fields."
35
+ python scripts/codecgc_cli.py plan --flow issue --slug demo-sync-bug --summary "Demo sync bug fix" --target-path backend/src/sync.py --kind backend --symptom "Sync stops on malformed record." --expected "Valid records still sync." --actual "Whole batch stops." --root-cause "Validation aborts the batch loop." --preferred-fix "Catch per-record validation errors." --acceptance "Malformed records are skipped and logged."
36
+ ```
37
+
38
+ 也支持更丰富的规划结构:
39
+
40
+ ```bash
41
+ python scripts/codecgc_cli.py plan --flow feature --slug demo-login-ui --summary "Demo login UI feature" --target-path src/components/LoginForm.tsx --kind frontend --goal "Allow users to sign in from a dedicated login form." --user-story "As a returning user, I want a focused login entry so I can sign in quickly." --context "This replaces an inline login panel on the landing page." --dependency "Auth API already exists." --assumption "No backend contract changes are needed." --validation "Render the form and submit against the existing auth endpoint." --rollback "Restore the previous inline login entry if the new screen fails review."
42
+ ```
43
+
44
+ 初始化工作流产物:
45
+
46
+ ```bash
47
+ python scripts/codecgc_cli.py init --flow feature --slug demo-login-ui --summary "Demo login UI feature"
48
+ ```
49
+
50
+ 运行一个高层功能开发或问题修复步骤:
51
+
52
+ ```bash
53
+ python scripts/codecgc_cli.py build --slug 2026-05-01-demo-login-ui --step-number 1 --dry-run
54
+ python scripts/codecgc_cli.py fix --slug 2026-05-01-demo-sync-bug --step-number 1 --dry-run
55
+ ```
56
+
57
+ 精确执行一个步骤:
58
+
59
+ ```bash
60
+ python scripts/codecgc_cli.py exec --flow feature --slug 2026-05-01-demo-login-ui --step-number 1 --dry-run
61
+ ```
62
+
63
+ 写回审核结果:
64
+
65
+ ```bash
66
+ python scripts/codecgc_cli.py review --audit-file codecgc/execution/demo-login-ui-step-1.json --decision accepted
67
+ ```
68
+
69
+ 判断当前产物状态的下一步命令:
70
+
71
+ ```bash
72
+ python scripts/codecgc_cli.py route --flow feature --slug 2026-05-01-demo-login-ui
73
+ ```
74
+
75
+ ## 说明
76
+
77
+ 优先把 `codecgc_cli.py` 当作维护和调试时的统一入口。
78
+ 如果你想用一个明显的开始/继续/解释入口,优先用 `entry`。
79
+ 日常工作流阶段优先使用 `plan/build/fix/review/route`。
80
+ 只有在需要更底层控制时,才直接使用 `init/exec`。
81
+
82
+ `entry` 现已支持通过 `--request` 接收轻量意图优先请求。
83
+
84
+ `plan` 现在也会返回可机读的 `planning_status`:
85
+
86
+ - `ready-for-build`
87
+ - `ready-for-fix`
88
+ - `needs-clarification`
89
+ - `needs-roadmap`