@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.
- package/.claude/hooks/route-edit.ps1 +86 -0
- package/INSTALLATION.md +550 -0
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/bin/cgc-build.js +4 -0
- package/bin/cgc-doctor.js +4 -0
- package/bin/cgc-entry.js +4 -0
- package/bin/cgc-external-audit.js +4 -0
- package/bin/cgc-fix.js +4 -0
- package/bin/cgc-history.js +4 -0
- package/bin/cgc-install.js +4 -0
- package/bin/cgc-lifecycle.js +4 -0
- package/bin/cgc-package-audit.js +4 -0
- package/bin/cgc-plan.js +4 -0
- package/bin/cgc-release-readiness.js +4 -0
- package/bin/cgc-review.js +4 -0
- package/bin/cgc-route.js +4 -0
- package/bin/cgc-status.js +4 -0
- package/bin/cgc-test.js +4 -0
- package/bin/cgc.js +4 -0
- package/bin/codecgc.js +1284 -0
- package/codecgc/cgc/SKILL.md +46 -0
- package/codecgc/cgc-arch/SKILL.md +61 -0
- package/codecgc/cgc-build/SKILL.md +53 -0
- package/codecgc/cgc-decide/SKILL.md +55 -0
- package/codecgc/cgc-fix/SKILL.md +47 -0
- package/codecgc/cgc-learn/SKILL.md +46 -0
- package/codecgc/cgc-onboard/SKILL.md +52 -0
- package/codecgc/cgc-plan/SKILL.md +48 -0
- package/codecgc/cgc-refactor/SKILL.md +46 -0
- package/codecgc/cgc-req/SKILL.md +61 -0
- package/codecgc/cgc-review/SKILL.md +57 -0
- package/codecgc/cgc-roadmap/SKILL.md +55 -0
- package/codecgc/cgc-test/SKILL.md +21 -0
- package/codecgc/reference/api-cgc-review-libdoc.md +13 -0
- package/codecgc/reference/artifact-class-policy.md +81 -0
- package/codecgc/reference/build-flow.md +95 -0
- package/codecgc/reference/checklist-contract.md +103 -0
- package/codecgc/reference/execution-audit.md +121 -0
- package/codecgc/reference/execution-model.md +118 -0
- package/codecgc/reference/execution-routing.md +130 -0
- package/codecgc/reference/executor-contract.md +87 -0
- package/codecgc/reference/external-capability-registry.json +104 -0
- package/codecgc/reference/fix-flow.md +94 -0
- package/codecgc/reference/fixture-governance.md +60 -0
- package/codecgc/reference/flow-execution.md +65 -0
- package/codecgc/reference/lifecycle-map.md +172 -0
- package/codecgc/reference/lifecycle-playbook.md +104 -0
- package/codecgc/reference/long-lived-artifacts.md +98 -0
- package/codecgc/reference/operation-guide.md +242 -0
- package/codecgc/reference/release-maintenance-playbook.md +150 -0
- package/codecgc/reference/review-writeback.md +141 -0
- package/codecgc/reference/role-model.md +128 -0
- package/codecgc/reference/runtime-boundary.md +72 -0
- package/codecgc/reference/shared-conventions.md +93 -0
- package/codecgc/reference/workflow-scaffold.md +57 -0
- package/codexmcp/LICENSE +21 -0
- package/codexmcp/README.md +294 -0
- package/codexmcp/pyproject.toml +37 -0
- package/codexmcp/src/codexmcp/__init__.py +4 -0
- package/codexmcp/src/codexmcp/cli.py +12 -0
- package/codexmcp/src/codexmcp/server.py +529 -0
- package/geminimcp/README.md +258 -0
- package/geminimcp/pyproject.toml +15 -0
- package/geminimcp/src/geminimcp/__init__.py +4 -0
- package/geminimcp/src/geminimcp/cli.py +12 -0
- package/geminimcp/src/geminimcp/server.py +465 -0
- package/model-routing.yaml +30 -0
- package/package.json +90 -0
- package/requirements.txt +1 -0
- package/scripts/README-codecgc-cli.md +89 -0
- package/scripts/audit_codecgc_external_capabilities.py +276 -0
- package/scripts/audit_codecgc_historical_audits.py +242 -0
- package/scripts/audit_codecgc_lifecycle.py +241 -0
- package/scripts/audit_codecgc_package_runtime.py +445 -0
- package/scripts/audit_codecgc_release_readiness.py +202 -0
- package/scripts/audit_codecgc_review_policy.py +82 -0
- package/scripts/audit_codecgc_workflow_history.py +317 -0
- package/scripts/build_codecgc_task.py +487 -0
- package/scripts/codecgc_artifact_roots.py +40 -0
- package/scripts/codecgc_cli.py +843 -0
- package/scripts/codecgc_command_surface.py +28 -0
- package/scripts/codecgc_console_io.py +45 -0
- package/scripts/codecgc_executor_registry.py +54 -0
- package/scripts/codecgc_file_evidence.py +349 -0
- package/scripts/codecgc_flow_control.py +233 -0
- package/scripts/codecgc_governance_dedupe.py +161 -0
- package/scripts/codecgc_plan_decision.py +103 -0
- package/scripts/codecgc_review_control.py +588 -0
- package/scripts/codecgc_roadmap_templates.py +149 -0
- package/scripts/codecgc_routing_paths.py +16 -0
- package/scripts/codecgc_routing_template.py +135 -0
- package/scripts/codecgc_runtime_paths.py +22 -0
- package/scripts/codecgc_session_recovery.py +44 -0
- package/scripts/codecgc_step_control.py +154 -0
- package/scripts/codecgc_workflow_runtime.py +63 -0
- package/scripts/codecgc_workflow_templates.py +437 -0
- package/scripts/entry_codecgc_workflow.py +3419 -0
- package/scripts/exercise_mcp_tools.py +109 -0
- package/scripts/expand_codecgc_roadmap.py +664 -0
- package/scripts/init_codecgc_roadmap.py +134 -0
- package/scripts/init_codecgc_workflow.py +207 -0
- package/scripts/install_codecgc.py +938 -0
- package/scripts/migrate_demo_workflows_to_fixtures.py +128 -0
- package/scripts/normalize_codecgc_audits.py +114 -0
- package/scripts/normalize_codecgc_governance_docs.py +79 -0
- package/scripts/normalize_codecgc_workflow_docs.py +269 -0
- package/scripts/plan_codecgc_workflow.py +970 -0
- package/scripts/refresh_codecgc_review_policy.py +223 -0
- package/scripts/review_codecgc_workflow.py +88 -0
- package/scripts/route_codecgc_workflow.py +671 -0
- package/scripts/run_codecgc_build.py +104 -0
- package/scripts/run_codecgc_fix.py +104 -0
- package/scripts/run_codecgc_flow_step.py +165 -0
- package/scripts/run_codecgc_task.py +410 -0
- package/scripts/run_codecgc_test.py +105 -0
- package/scripts/sync_codecgc_mcp_config.py +41 -0
- package/scripts/write_codecgc_architecture.py +78 -0
- package/scripts/write_codecgc_decision.py +83 -0
- package/scripts/write_codecgc_explore.py +118 -0
- package/scripts/write_codecgc_guide.py +141 -0
- package/scripts/write_codecgc_learning.py +87 -0
- package/scripts/write_codecgc_libdoc.py +140 -0
- package/scripts/write_codecgc_refactor.py +78 -0
- package/scripts/write_codecgc_requirement.py +78 -0
- package/scripts/write_codecgc_review.py +291 -0
- package/scripts/write_codecgc_roadmap.py +122 -0
- package/scripts/write_codecgc_trick.py +123 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from codecgc_artifact_roots import FIXTURE_ROOT
|
|
6
|
+
from codecgc_artifact_roots import PRODUCT_ROOT
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
WORKSPACE = Path(__file__).resolve().parents[1]
|
|
10
|
+
CODECGC_ROOT = WORKSPACE / "codecgc"
|
|
11
|
+
FEATURES_ROOT = PRODUCT_ROOT / "features"
|
|
12
|
+
ISSUES_ROOT = PRODUCT_ROOT / "issues"
|
|
13
|
+
FIXTURE_FEATURES_ROOT = FIXTURE_ROOT / "features"
|
|
14
|
+
FIXTURE_ISSUES_ROOT = FIXTURE_ROOT / "issues"
|
|
15
|
+
|
|
16
|
+
FEATURE_FIXTURE_NAMES = {
|
|
17
|
+
"2026-05-01-artifact-class-demo",
|
|
18
|
+
"2026-05-01-artifact-class-ui-demo",
|
|
19
|
+
"2026-05-01-cli-demo-ui",
|
|
20
|
+
"2026-05-01-closed-route-demo",
|
|
21
|
+
"2026-05-01-demo-login-ui",
|
|
22
|
+
"2026-05-01-direct-goal-check",
|
|
23
|
+
"2026-05-01-final-check-ui",
|
|
24
|
+
"2026-05-01-migration-check-ui",
|
|
25
|
+
"2026-05-01-mixed-plan-ui-api",
|
|
26
|
+
"2026-05-01-mixed-scope-demo",
|
|
27
|
+
"2026-05-01-progression-demo",
|
|
28
|
+
"2026-05-01-review-status-demo",
|
|
29
|
+
"2026-05-01-richer-plan-ui",
|
|
30
|
+
"2026-05-01-session-continue-ui",
|
|
31
|
+
"2026-05-01-shared-plan-demo",
|
|
32
|
+
"2026-05-01-structured-plan-ui",
|
|
33
|
+
"2026-05-01-structured-plan-ui-v2",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ISSUE_FIXTURE_NAMES = {
|
|
37
|
+
"2026-05-01-demo-sync-bug",
|
|
38
|
+
"2026-05-01-mixed-fix-ui-api",
|
|
39
|
+
"2026-05-01-richer-plan-bug",
|
|
40
|
+
"2026-05-01-session-continue-bug",
|
|
41
|
+
"2026-05-01-structured-plan-bug",
|
|
42
|
+
"2026-05-01-structured-plan-bug-v2",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def ensure_artifact_class(text: str) -> str:
|
|
47
|
+
if "artifact_class:" in text:
|
|
48
|
+
lines = text.splitlines()
|
|
49
|
+
updated = []
|
|
50
|
+
for line in lines:
|
|
51
|
+
if line.startswith("artifact_class:"):
|
|
52
|
+
updated.append("artifact_class: fixture")
|
|
53
|
+
else:
|
|
54
|
+
updated.append(line)
|
|
55
|
+
return "\n".join(updated) + ("\n" if text.endswith("\n") else "")
|
|
56
|
+
|
|
57
|
+
if text.startswith("---\n"):
|
|
58
|
+
insert_at = text.find("\n", 4)
|
|
59
|
+
if insert_at != -1:
|
|
60
|
+
return text[: insert_at + 1] + "artifact_class: fixture\n" + text[insert_at + 1 :]
|
|
61
|
+
|
|
62
|
+
if text.startswith("feature: ") or text.startswith("issue: "):
|
|
63
|
+
first_newline = text.find("\n")
|
|
64
|
+
if first_newline != -1:
|
|
65
|
+
return text[: first_newline + 1] + "artifact_class: fixture\n" + text[first_newline + 1 :]
|
|
66
|
+
|
|
67
|
+
return text
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def rewrite_directory_files(directory: Path) -> int:
|
|
71
|
+
updated = 0
|
|
72
|
+
for path in directory.rglob("*"):
|
|
73
|
+
if not path.is_file():
|
|
74
|
+
continue
|
|
75
|
+
if path.suffix.lower() not in {".md", ".yaml"}:
|
|
76
|
+
continue
|
|
77
|
+
original = path.read_text(encoding="utf-8")
|
|
78
|
+
rewritten = ensure_artifact_class(original)
|
|
79
|
+
if rewritten != original:
|
|
80
|
+
path.write_text(rewritten, encoding="utf-8")
|
|
81
|
+
updated += 1
|
|
82
|
+
return updated
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def move_directory(src: Path, dst: Path) -> int:
|
|
86
|
+
if not src.exists():
|
|
87
|
+
return 0
|
|
88
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
if dst.exists():
|
|
90
|
+
shutil.rmtree(dst)
|
|
91
|
+
shutil.move(str(src), str(dst))
|
|
92
|
+
return rewrite_directory_files(dst)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main() -> int:
|
|
96
|
+
moved_features = 0
|
|
97
|
+
moved_issues = 0
|
|
98
|
+
updated_files = 0
|
|
99
|
+
|
|
100
|
+
for name in sorted(FEATURE_FIXTURE_NAMES):
|
|
101
|
+
updated_files += move_directory(FEATURES_ROOT / name, FIXTURE_FEATURES_ROOT / name)
|
|
102
|
+
if (FIXTURE_FEATURES_ROOT / name).exists():
|
|
103
|
+
moved_features += 1
|
|
104
|
+
|
|
105
|
+
for name in sorted(ISSUE_FIXTURE_NAMES):
|
|
106
|
+
updated_files += move_directory(ISSUES_ROOT / name, FIXTURE_ISSUES_ROOT / name)
|
|
107
|
+
if (FIXTURE_ISSUES_ROOT / name).exists():
|
|
108
|
+
moved_issues += 1
|
|
109
|
+
|
|
110
|
+
print(
|
|
111
|
+
json.dumps(
|
|
112
|
+
{
|
|
113
|
+
"success": True,
|
|
114
|
+
"moved_features": moved_features,
|
|
115
|
+
"moved_issues": moved_issues,
|
|
116
|
+
"updated_files": updated_files,
|
|
117
|
+
"fixture_features_root": str(FIXTURE_FEATURES_ROOT),
|
|
118
|
+
"fixture_issues_root": str(FIXTURE_ISSUES_ROOT),
|
|
119
|
+
},
|
|
120
|
+
ensure_ascii=False,
|
|
121
|
+
indent=2,
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
return 0
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from codecgc_artifact_roots import discover_flow_directory
|
|
6
|
+
from codecgc_artifact_roots import flow_root
|
|
7
|
+
from codecgc_artifact_roots import execution_root
|
|
8
|
+
from codecgc_artifact_roots import normalize_artifact_class
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
WORKSPACE = Path(__file__).resolve().parents[1]
|
|
12
|
+
CODECGC_ROOT = WORKSPACE / "codecgc"
|
|
13
|
+
PRODUCT_EXECUTION_ROOT = execution_root("product")
|
|
14
|
+
FIXTURE_EXECUTION_ROOT = execution_root("fixture")
|
|
15
|
+
OLD_REPO_NAME = "CodeCCG"
|
|
16
|
+
NEW_REPO_NAME = "CodeCGC"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def replace_repo_name(value: str) -> str:
|
|
20
|
+
return value.replace(OLD_REPO_NAME, NEW_REPO_NAME)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def infer_artifact_class_from_source(source: dict[str, Any], fallback: str) -> str:
|
|
24
|
+
artifact_type = str(source.get("artifact_type", "")).strip()
|
|
25
|
+
artifact_slug = str(source.get("artifact_slug", "")).strip()
|
|
26
|
+
if artifact_type in {"feature", "issue"} and artifact_slug:
|
|
27
|
+
discovered = discover_flow_directory(artifact_type, artifact_slug, "auto")
|
|
28
|
+
if discovered:
|
|
29
|
+
return discovered[0]
|
|
30
|
+
return fallback
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def build_expected_artifact_file(source: dict[str, Any], artifact_class: str) -> str:
|
|
34
|
+
artifact_type = str(source.get("artifact_type", "")).strip()
|
|
35
|
+
artifact_slug = str(source.get("artifact_slug", "")).strip()
|
|
36
|
+
if artifact_type not in {"feature", "issue"} or not artifact_slug:
|
|
37
|
+
current = str(source.get("artifact_file", "")).strip()
|
|
38
|
+
return replace_repo_name(current) if current else current
|
|
39
|
+
|
|
40
|
+
base_slug = artifact_slug[11:] if len(artifact_slug) > 11 and artifact_slug[4] == "-" else artifact_slug
|
|
41
|
+
checklist_name = f"{base_slug}-checklist.yaml" if artifact_type == "feature" else f"{base_slug}-fix.yaml"
|
|
42
|
+
return str(flow_root(artifact_type, artifact_class) / artifact_slug / checklist_name)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def normalize_audit_record(data: dict[str, Any]) -> tuple[dict[str, Any], str]:
|
|
46
|
+
source = data.get("source", {}) if isinstance(data.get("source"), dict) else {}
|
|
47
|
+
declared_artifact_class = normalize_artifact_class(str(source.get("artifact_class", "product")))
|
|
48
|
+
artifact_class = infer_artifact_class_from_source(source, declared_artifact_class)
|
|
49
|
+
|
|
50
|
+
for key in ("routing_file", "cd"):
|
|
51
|
+
current = data.get(key)
|
|
52
|
+
if isinstance(current, str):
|
|
53
|
+
data[key] = replace_repo_name(current)
|
|
54
|
+
|
|
55
|
+
source["artifact_file"] = build_expected_artifact_file(source, artifact_class)
|
|
56
|
+
source["artifact_class"] = artifact_class
|
|
57
|
+
data["source"] = source
|
|
58
|
+
return data, artifact_class
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def normalize_file(path: Path) -> tuple[Path, bool]:
|
|
62
|
+
raw = json.loads(path.read_text(encoding="utf-8"))
|
|
63
|
+
if not isinstance(raw, dict):
|
|
64
|
+
return path, False
|
|
65
|
+
|
|
66
|
+
normalized, artifact_class = normalize_audit_record(raw)
|
|
67
|
+
target_root = FIXTURE_EXECUTION_ROOT if artifact_class == "fixture" else PRODUCT_EXECUTION_ROOT
|
|
68
|
+
target_root.mkdir(parents=True, exist_ok=True)
|
|
69
|
+
target_path = target_root / path.name
|
|
70
|
+
target_path.write_text(json.dumps(normalized, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
71
|
+
|
|
72
|
+
moved = target_path.resolve() != path.resolve()
|
|
73
|
+
if moved and path.exists():
|
|
74
|
+
path.unlink()
|
|
75
|
+
return target_path, moved
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main() -> int:
|
|
79
|
+
scanned = 0
|
|
80
|
+
moved = 0
|
|
81
|
+
updated = 0
|
|
82
|
+
|
|
83
|
+
for root in [PRODUCT_EXECUTION_ROOT, FIXTURE_EXECUTION_ROOT]:
|
|
84
|
+
if not root.exists():
|
|
85
|
+
continue
|
|
86
|
+
for path in sorted(root.glob("*.json")):
|
|
87
|
+
scanned += 1
|
|
88
|
+
before = path.read_text(encoding="utf-8")
|
|
89
|
+
target_path, was_moved = normalize_file(path)
|
|
90
|
+
after = target_path.read_text(encoding="utf-8")
|
|
91
|
+
if before != after or was_moved:
|
|
92
|
+
updated += 1
|
|
93
|
+
if was_moved:
|
|
94
|
+
moved += 1
|
|
95
|
+
|
|
96
|
+
print(
|
|
97
|
+
json.dumps(
|
|
98
|
+
{
|
|
99
|
+
"success": True,
|
|
100
|
+
"scanned": scanned,
|
|
101
|
+
"updated": updated,
|
|
102
|
+
"moved": moved,
|
|
103
|
+
"product_execution_root": str(PRODUCT_EXECUTION_ROOT),
|
|
104
|
+
"fixture_execution_root": str(FIXTURE_EXECUTION_ROOT),
|
|
105
|
+
},
|
|
106
|
+
ensure_ascii=False,
|
|
107
|
+
indent=2,
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
return 0
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
WORKSPACE = Path(__file__).resolve().parents[1]
|
|
6
|
+
CODECGC_ROOT = WORKSPACE / "codecgc"
|
|
7
|
+
|
|
8
|
+
TARGET_FILES = [
|
|
9
|
+
CODECGC_ROOT / "compound" / "codecgc-decisions.md",
|
|
10
|
+
CODECGC_ROOT / "compound" / "codecgc-learning-log.md",
|
|
11
|
+
CODECGC_ROOT / "compound" / "codecgc-productization-gap.md",
|
|
12
|
+
CODECGC_ROOT / "architecture" / "codecgc-system-map.md",
|
|
13
|
+
CODECGC_ROOT / "requirements" / "codecgc-core-requirements.md",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
REPLACEMENTS = [
|
|
17
|
+
("# CodeCGC Decisions", "# CodeCGC 长期决策"),
|
|
18
|
+
("This file stores durable accepted decisions for the current repository.", "该文件用于记录当前仓库的长期有效决定。"),
|
|
19
|
+
("## Entries", "## 条目"),
|
|
20
|
+
("- Decision:", "- 决定:"),
|
|
21
|
+
("- Constraint:", "- 约束:"),
|
|
22
|
+
("- Source:", "- 来源:"),
|
|
23
|
+
("# CodeCGC Learning Log", "# CodeCGC 经验沉淀"),
|
|
24
|
+
("This file stores reusable lessons, pitfalls, and preferred practices for the current repository.", "该文件用于记录当前仓库可复用的经验、坑点和推荐做法。"),
|
|
25
|
+
("- Type: practice", "- 类型: 实践"),
|
|
26
|
+
("- Type: pitfall", "- 类型: 坑点"),
|
|
27
|
+
("- Type:", "- 类型:"),
|
|
28
|
+
("- Summary:", "- 摘要:"),
|
|
29
|
+
("- Future Instruction:", "- 后续指引:"),
|
|
30
|
+
("- Current-State Note:", "- 当前状态说明:"),
|
|
31
|
+
("- Stable Requirement Note:", "- 稳定需求说明:"),
|
|
32
|
+
("- Behavior-Preserving Note:", "- 保持行为不变说明:"),
|
|
33
|
+
("## 7. Governance Source", "## 7. 治理来源"),
|
|
34
|
+
("cgc-entry governance routing", "cgc-entry 治理分诊"),
|
|
35
|
+
("Treat this as a durable accepted rule for future CodeCGC behavior.", "将其视为约束未来 CodeCGC 行为的长期有效规则。"),
|
|
36
|
+
("Treat this as a durable current-state architecture update for the repository.", "将其视为当前仓库架构现状的长期更新记录。"),
|
|
37
|
+
("Treat this as a durable stable requirement update for the product surface.", "将其视为产品面的长期稳定需求更新。"),
|
|
38
|
+
("Treat this as a behavior-preserving structural improvement candidate that still requires routed execution.", "将其视为保持行为不变、但仍需走受控执行流程的结构优化候选项。"),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def normalize_text(text: str) -> str:
|
|
43
|
+
updated = text
|
|
44
|
+
for old, new in REPLACEMENTS:
|
|
45
|
+
updated = updated.replace(old, new)
|
|
46
|
+
return updated
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def normalize_file(path: Path) -> dict[str, object]:
|
|
50
|
+
if not path.exists():
|
|
51
|
+
return {"path": str(path), "exists": False, "updated": False}
|
|
52
|
+
original = path.read_text(encoding="utf-8")
|
|
53
|
+
normalized = normalize_text(original)
|
|
54
|
+
updated = normalized != original
|
|
55
|
+
if updated:
|
|
56
|
+
path.write_text(normalized, encoding="utf-8")
|
|
57
|
+
return {"path": str(path), "exists": True, "updated": updated}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main() -> int:
|
|
61
|
+
results = [normalize_file(path) for path in TARGET_FILES]
|
|
62
|
+
updated_count = sum(1 for item in results if item.get("updated"))
|
|
63
|
+
print(
|
|
64
|
+
json.dumps(
|
|
65
|
+
{
|
|
66
|
+
"success": True,
|
|
67
|
+
"scanned": len(results),
|
|
68
|
+
"updated": updated_count,
|
|
69
|
+
"results": results,
|
|
70
|
+
},
|
|
71
|
+
ensure_ascii=False,
|
|
72
|
+
indent=2,
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
return 0
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
if __name__ == "__main__":
|
|
79
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
WORKSPACE = Path(__file__).resolve().parents[1]
|
|
6
|
+
CODECGC_ROOT = WORKSPACE / "codecgc"
|
|
7
|
+
|
|
8
|
+
SCAN_ROOTS = [
|
|
9
|
+
CODECGC_ROOT / "features",
|
|
10
|
+
CODECGC_ROOT / "issues",
|
|
11
|
+
CODECGC_ROOT / "roadmap",
|
|
12
|
+
CODECGC_ROOT / "fixtures",
|
|
13
|
+
CODECGC_ROOT / "reference",
|
|
14
|
+
CODECGC_ROOT / "requirements",
|
|
15
|
+
CODECGC_ROOT / "architecture",
|
|
16
|
+
CODECGC_ROOT / "compound",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
EXACT_LINE_REPLACEMENTS = {
|
|
20
|
+
"## 1. Goal": "## 1. 目标",
|
|
21
|
+
"## 1. Initiative Goal": "## 1. 目标",
|
|
22
|
+
"## 2. Context": "## 2. 背景",
|
|
23
|
+
"## 3. In Scope": "## 3. 范围内",
|
|
24
|
+
"## 4. Out Of Scope": "## 4. 范围外",
|
|
25
|
+
"## 5. Dependencies And Assumptions": "## 5. 依赖与假设",
|
|
26
|
+
"## 6. Execution Notes": "## 6. 执行说明",
|
|
27
|
+
"## 7. Validation Plan": "## 7. 验证计划",
|
|
28
|
+
"## 8. Rollback Plan": "## 8. 回退计划",
|
|
29
|
+
"## 9. Open Questions": "## 9. 开放问题",
|
|
30
|
+
"## 10. Planned Steps": "## 10. 计划步骤",
|
|
31
|
+
"## 1. Symptom": "## 1. 现象",
|
|
32
|
+
"## 2. Reproduction": "## 2. 复现方式",
|
|
33
|
+
"## 3. Expected vs Actual": "## 3. 预期与实际",
|
|
34
|
+
"## 5. Planned Steps": "## 5. 计划步骤",
|
|
35
|
+
"## 1. Root Cause": "## 1. 根因",
|
|
36
|
+
"## 2. Scope": "## 2. 范围",
|
|
37
|
+
"## 3. Fix Options": "## 3. 修复方案",
|
|
38
|
+
"## 4. Dependencies And Assumptions": "## 4. 依赖与假设",
|
|
39
|
+
"## 5. Validation Plan": "## 5. 验证计划",
|
|
40
|
+
"## 6. Rollback Plan": "## 6. 回退计划",
|
|
41
|
+
"## 7. Open Questions": "## 7. 开放问题",
|
|
42
|
+
"## 8. Planned Steps": "## 8. 计划步骤",
|
|
43
|
+
"## 1. Scope Check": "## 1. 范围检查",
|
|
44
|
+
"## 2. Executor Check": "## 2. 执行器检查",
|
|
45
|
+
"## 3. Verification": "## 3. 验证结果",
|
|
46
|
+
"## 4. Remaining Risk": "## 4. 剩余风险",
|
|
47
|
+
"## 5. Review Decision": "## 5. 审核结论",
|
|
48
|
+
"## 1. Applied Fix": "## 1. 已应用修复",
|
|
49
|
+
"## 3. Why This Is Roadmap-Sized": "## 3. 为什么需要走 Roadmap",
|
|
50
|
+
"## 4. Scope": "## 4. 范围",
|
|
51
|
+
"## 5. Risks": "## 5. 风险",
|
|
52
|
+
"## 1. Dependencies": "## 1. 依赖",
|
|
53
|
+
"## 2. Assumptions": "## 2. 前提假设",
|
|
54
|
+
"## 3. Validation Strategy": "## 3. 验证策略",
|
|
55
|
+
"## 4. Rollback Strategy": "## 4. 回退策略",
|
|
56
|
+
"## 5. Open Questions": "## 5. 开放问题",
|
|
57
|
+
"## 5. Initialized Child Workflows": "## 5. 已初始化的子工作流",
|
|
58
|
+
"## 6. Workflow Tracking": "## 6. 工作流跟踪",
|
|
59
|
+
"## 7. Governance Source": "## 7. 治理来源",
|
|
60
|
+
"## 5. Review Decision": "## 5. 审核结论",
|
|
61
|
+
"## 4. Review Decision": "## 4. 审核结论",
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
EXACT_BULLET_REPLACEMENTS = {
|
|
65
|
+
"- None yet.": "- 暂无。",
|
|
66
|
+
"- None right now.": "- 当前无。",
|
|
67
|
+
"- No child workflows have been registered yet.": "- 目前还没有登记子工作流。",
|
|
68
|
+
"- accepted": "- 审核结果: 通过",
|
|
69
|
+
"- changes-requested": "- 审核结果: 需修改",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
EXACT_VALUE_REPLACEMENTS = {
|
|
73
|
+
"to be split": "待拆分",
|
|
74
|
+
"TODO/path": "待补路径",
|
|
75
|
+
"none": "无",
|
|
76
|
+
"unknown": "未知",
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
PREFIX_REPLACEMENTS = {
|
|
80
|
+
"- Summary:": "- 摘要:",
|
|
81
|
+
"- User goal:": "- 用户目标:",
|
|
82
|
+
"- User story:": "- 用户故事:",
|
|
83
|
+
"- Planned execution owner:": "- 计划执行归属:",
|
|
84
|
+
"- Candidate target paths:": "- 候选目标路径:",
|
|
85
|
+
"- Symptom:": "- 现象:",
|
|
86
|
+
"- User impact:": "- 用户影响:",
|
|
87
|
+
"- Suspected execution owner:": "- 预估执行归属:",
|
|
88
|
+
"- Candidate affected paths:": "- 候选影响路径:",
|
|
89
|
+
"- Current hypothesis owner:": "- 当前假设归属:",
|
|
90
|
+
"- Root cause notes:": "- 根因说明:",
|
|
91
|
+
"- Goal:": "- 目标:",
|
|
92
|
+
"- User story or operator need:": "- 用户故事或操作者诉求:",
|
|
93
|
+
"- Acceptance hint:": "- 验收提示:",
|
|
94
|
+
"- Planning risk:": "- 规划风险:",
|
|
95
|
+
"- Decision note:": "- 决策说明:",
|
|
96
|
+
"- Routing note:": "- 路由说明:",
|
|
97
|
+
"- Reviewed task_id:": "- 审核 task_id:",
|
|
98
|
+
"- Reviewed step_number:": "- 审核 step_number:",
|
|
99
|
+
"- 审核步骤序号:": "- 审核步骤序号:",
|
|
100
|
+
"- Review action kind:": "- 审核动作类型:",
|
|
101
|
+
"- 审核结果:": "- 审核结果:",
|
|
102
|
+
"- Review fallback stage:": "- 审核回退阶段:",
|
|
103
|
+
"- Review policy reason:": "- 审核策略原因:",
|
|
104
|
+
"- Next step:": "- 下一步:",
|
|
105
|
+
"Expected:": "预期:",
|
|
106
|
+
"Actual:": "实际:",
|
|
107
|
+
"Preferred scoped fix:": "首选定点修复:",
|
|
108
|
+
"Rejected broader fix:": "明确不采用的更大范围修复:",
|
|
109
|
+
"Dependencies:": "依赖:",
|
|
110
|
+
"Assumptions:": "假设:",
|
|
111
|
+
"Shared:": "共享范围:",
|
|
112
|
+
"Unknown:": "未知范围:",
|
|
113
|
+
"Requested decision:": "请求决策:",
|
|
114
|
+
"Final decision:": "最终决策:",
|
|
115
|
+
"Outcome:": "执行结果:",
|
|
116
|
+
"Evidence source:": "证据来源:",
|
|
117
|
+
"Risk classes:": "风险分类:",
|
|
118
|
+
"Fallback stage:": "回退阶段:",
|
|
119
|
+
"Policy reason:": "策略原因:",
|
|
120
|
+
"Scope respected:": "范围是否满足:",
|
|
121
|
+
"Changed files inside target_paths:": "变更文件是否落在 target_paths 内:",
|
|
122
|
+
"Executor target:": "执行器目标:",
|
|
123
|
+
"Expected tool:": "预期工具:",
|
|
124
|
+
"Actual tool:": "实际工具:",
|
|
125
|
+
"Ownership respected:": "归属是否满足:",
|
|
126
|
+
"Execution mode:": "执行模式:",
|
|
127
|
+
"Execution performed:": "是否真实执行:",
|
|
128
|
+
"Policy checks:": "策略检查项:",
|
|
129
|
+
"Summary:": "摘要:",
|
|
130
|
+
"Evidence confidence:": "证据置信度:",
|
|
131
|
+
"Local evidence available:": "是否有本地证据:",
|
|
132
|
+
"Reported vs local evidence alignment:": "执行器上报与本地证据是否一致:",
|
|
133
|
+
"Executor reported changed files:": "执行器上报的变更文件:",
|
|
134
|
+
"Workspace changed files:": "工作区变更文件:",
|
|
135
|
+
"Verified in-scope changed files:": "已验证的范围内变更文件:",
|
|
136
|
+
"Out-of-scope changed files:": "范围外变更文件:",
|
|
137
|
+
"Observed file diffs:": "观测到的文件 diff:",
|
|
138
|
+
"Acceptance criteria:": "验收条件:",
|
|
139
|
+
"Planning status:": "规划状态:",
|
|
140
|
+
"Requested decision:": "请求决策:",
|
|
141
|
+
"Final decision:": "最终决策:",
|
|
142
|
+
"Execution mode:": "执行模式:",
|
|
143
|
+
"Review action kind:": "审核动作类型:",
|
|
144
|
+
"Review fallback stage:": "审核回退阶段:",
|
|
145
|
+
"Review policy reason:": "审核策略原因:",
|
|
146
|
+
"Next step:": "下一步:",
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
CONTAINS_REPLACEMENTS = {
|
|
150
|
+
" Report": " 问题报告",
|
|
151
|
+
" Analysis": " 分析",
|
|
152
|
+
" Acceptance": " 验收",
|
|
153
|
+
" Delivery Plan": " 交付计划",
|
|
154
|
+
"Step contract is ready for delegated execution": "步骤契约已经可以进入委派执行",
|
|
155
|
+
"Implement one frontend feature step": "定义一个可执行的前端功能开发步骤",
|
|
156
|
+
"Implement one backend feature step": "定义一个可执行的后端功能开发步骤",
|
|
157
|
+
"Implement one scoped feature step": "定义一个限定范围的功能开发步骤",
|
|
158
|
+
"Implement one unresolved-path feature step": "定义一个待补目标路径的功能开发步骤",
|
|
159
|
+
"Implement one frontend executor-failure feature step": "定义一个前端执行失败演练功能开发步骤",
|
|
160
|
+
"Shared or mixed paths must be split first": "共享或混合路径必须先拆分",
|
|
161
|
+
"One executor owns this step end to end": "一个执行器必须端到端负责这个执行步骤",
|
|
162
|
+
"Ready to close this step.": "当前执行步骤已满足关闭条件,可以结束本轮工作流。",
|
|
163
|
+
"Do not edit files outside target_paths.": "不要修改 target_paths 之外的文件。",
|
|
164
|
+
"Do not change backend APIs.": "不要改动后端 API。",
|
|
165
|
+
"Do not change frontend UI behavior.": "不要改动前端 UI 行为。",
|
|
166
|
+
"Frontend: browser-visible work is complete and scoped.": "前端:浏览器可见范围内的工作已按限定范围完成。",
|
|
167
|
+
"Backend: API work is complete and scoped.": "后端:API 范围内的工作已按限定范围完成。",
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def normalize_text(text: str) -> str:
|
|
172
|
+
normalized_lines: list[str] = []
|
|
173
|
+
for line in text.splitlines():
|
|
174
|
+
stripped = line.strip()
|
|
175
|
+
leading = line[: len(line) - len(line.lstrip())]
|
|
176
|
+
|
|
177
|
+
if stripped in EXACT_LINE_REPLACEMENTS:
|
|
178
|
+
normalized_lines.append(f"{leading}{EXACT_LINE_REPLACEMENTS[stripped]}")
|
|
179
|
+
continue
|
|
180
|
+
|
|
181
|
+
if stripped in EXACT_BULLET_REPLACEMENTS:
|
|
182
|
+
normalized_lines.append(f"{leading}{EXACT_BULLET_REPLACEMENTS[stripped]}")
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
replaced = line
|
|
186
|
+
for old, new in PREFIX_REPLACEMENTS.items():
|
|
187
|
+
marker = f"{leading}{old}"
|
|
188
|
+
if replaced.startswith(marker):
|
|
189
|
+
replaced = f"{leading}{new}{replaced[len(marker):]}"
|
|
190
|
+
break
|
|
191
|
+
|
|
192
|
+
stripped_after_prefix = replaced.strip()
|
|
193
|
+
if stripped_after_prefix in EXACT_VALUE_REPLACEMENTS:
|
|
194
|
+
replaced = f"{leading}{EXACT_VALUE_REPLACEMENTS[stripped_after_prefix]}"
|
|
195
|
+
elif stripped_after_prefix == "- TODO":
|
|
196
|
+
replaced = f"{leading}- 待补充"
|
|
197
|
+
|
|
198
|
+
for old, new in CONTAINS_REPLACEMENTS.items():
|
|
199
|
+
if old in replaced:
|
|
200
|
+
replaced = replaced.replace(old, new)
|
|
201
|
+
|
|
202
|
+
if stripped.startswith("- Step "):
|
|
203
|
+
replaced = replaced.replace("- Step ", "- 步骤 ")
|
|
204
|
+
|
|
205
|
+
if stripped.startswith("Owner:"):
|
|
206
|
+
replaced = f"{leading}执行归属:{stripped[len('Owner:') :]}"
|
|
207
|
+
replaced = replaced.replace("frontend / Gemini", "前端 / Gemini").replace(
|
|
208
|
+
"backend / Codex", "后端 / Codex"
|
|
209
|
+
)
|
|
210
|
+
elif stripped.startswith("Paths:"):
|
|
211
|
+
replaced = f"{leading}目标路径:{stripped[len('Paths:') :]}"
|
|
212
|
+
elif stripped.startswith("Summary:"):
|
|
213
|
+
replaced = f"{leading}摘要:{stripped[len('Summary:') :]}"
|
|
214
|
+
elif stripped.startswith("Acceptance:"):
|
|
215
|
+
replaced = f"{leading}验收:{stripped[len('Acceptance:') :]}"
|
|
216
|
+
|
|
217
|
+
replaced = replaced.replace("Requested decision: accepted", "请求决策: 通过")
|
|
218
|
+
replaced = replaced.replace("Requested decision: changes-requested", "请求决策: 需修改")
|
|
219
|
+
replaced = replaced.replace("Final decision: accepted", "最终决策: 通过")
|
|
220
|
+
replaced = replaced.replace("Final decision: changes-requested", "最终决策: 需修改")
|
|
221
|
+
|
|
222
|
+
normalized_lines.append(replaced)
|
|
223
|
+
|
|
224
|
+
normalized = "\n".join(normalized_lines)
|
|
225
|
+
if text.endswith("\n"):
|
|
226
|
+
normalized += "\n"
|
|
227
|
+
return normalized
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def normalize_file(path: Path) -> dict[str, object]:
|
|
231
|
+
original = path.read_text(encoding="utf-8")
|
|
232
|
+
normalized = normalize_text(original)
|
|
233
|
+
updated = normalized != original
|
|
234
|
+
if updated:
|
|
235
|
+
path.write_text(normalized, encoding="utf-8")
|
|
236
|
+
return {"path": str(path), "updated": updated}
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def should_scan(path: Path) -> bool:
|
|
240
|
+
return path.suffix.lower() in {".md", ".yaml"}
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def main() -> int:
|
|
244
|
+
results: list[dict[str, object]] = []
|
|
245
|
+
for root in SCAN_ROOTS:
|
|
246
|
+
if not root.exists():
|
|
247
|
+
continue
|
|
248
|
+
for path in root.rglob("*"):
|
|
249
|
+
if path.is_file() and should_scan(path):
|
|
250
|
+
results.append(normalize_file(path))
|
|
251
|
+
|
|
252
|
+
updated_count = sum(1 for item in results if item.get("updated"))
|
|
253
|
+
print(
|
|
254
|
+
json.dumps(
|
|
255
|
+
{
|
|
256
|
+
"success": True,
|
|
257
|
+
"scanned": len(results),
|
|
258
|
+
"updated": updated_count,
|
|
259
|
+
"results": results,
|
|
260
|
+
},
|
|
261
|
+
ensure_ascii=False,
|
|
262
|
+
indent=2,
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
return 0
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
if __name__ == "__main__":
|
|
269
|
+
raise SystemExit(main())
|