mirror of
https://github.com/codestable/CodeStable.git
synced 2026-09-19 09:03:09 +08:00
30fecaae5e
收敛 CodeStable 主入口、runtime preflight、goal driver 与 skill 工程化评测闭环。 - 根 cs 对行动请求同轮直转,咨询与介绍保持非执行 - feature/issue/refactor/epic/docs 按仓库事实恢复,旧 stage skill 保留兼容薄壳 - repo-local runtime 支持版本检测、安全自动同步和显式 refresh-runtime - 完成 Codex/Claude marketplace 1.0.2、升级文档和回归/评测证据 验证:215 tests passed;package/runtime/diff checks passed;独立 review 与 QA 无 unresolved blocking/important findings。
117 lines
3.7 KiB
Python
117 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Check that a feature design contains a minimal DoD Contract."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
if os.environ.get("PYTHONDONTWRITEBYTECODE") != "1":
|
|
os.environ["PYTHONDONTWRITEBYTECODE"] = "1"
|
|
os.execvpe(sys.executable, [sys.executable, *sys.argv], os.environ)
|
|
sys.dont_write_bytecode = True
|
|
|
|
from codestable_gate_common import gate_result, main_exit, parse_args, read_text
|
|
|
|
|
|
STRUCTURE_CHECKS = {
|
|
"validation command id": ("CMD-",),
|
|
"command core marker": ("core", "核心性"),
|
|
"failure handling marker": ("failure_handling", "失败处理"),
|
|
}
|
|
|
|
|
|
def contract_block(text: str) -> str | None:
|
|
lines = text.splitlines()
|
|
start = None
|
|
start_level = 99
|
|
for index, line in enumerate(lines):
|
|
stripped = line.strip()
|
|
if stripped.startswith("#") and "DoD Contract" in stripped:
|
|
start = index
|
|
start_level = len(stripped) - len(stripped.lstrip("#"))
|
|
break
|
|
if start is None:
|
|
for index, line in enumerate(lines):
|
|
stripped = line.strip()
|
|
if stripped.rstrip(":") != "DoD Contract":
|
|
continue
|
|
start = index
|
|
start_level = 99
|
|
break
|
|
if start is None:
|
|
return None
|
|
end = len(lines)
|
|
for index in range(start + 1, len(lines)):
|
|
stripped = lines[index].strip()
|
|
if not stripped.startswith("#"):
|
|
continue
|
|
level = len(stripped) - len(stripped.lstrip("#"))
|
|
if level <= start_level:
|
|
end = index
|
|
break
|
|
return "\n".join(lines[start:end])
|
|
|
|
|
|
def artifacts_have_content(block: str) -> bool:
|
|
for line in block.splitlines():
|
|
stripped = line.strip().lstrip("-*").strip()
|
|
if not stripped.startswith("Required Artifacts"):
|
|
continue
|
|
_, _, value = stripped.partition(":")
|
|
return bool(value.strip())
|
|
return False
|
|
|
|
|
|
def main() -> None:
|
|
parser = parse_args("Check a design document for minimal DoD Contract structure.")
|
|
parser.add_argument("--design", required=True, help="Path to feature design markdown")
|
|
parser.add_argument("--stage", default="feature_design.before_approve")
|
|
args = parser.parse_args()
|
|
|
|
path = Path(args.design)
|
|
if not path.exists():
|
|
result = gate_result("dod-contract-gate", args.stage, "blocked", [f"design not found: {path}"])
|
|
main_exit(result, args.json_out)
|
|
|
|
text = read_text(path)
|
|
block = contract_block(text)
|
|
missing = []
|
|
if block is None:
|
|
missing.append("DoD Contract section")
|
|
block = ""
|
|
if "Validation Commands" not in block:
|
|
missing.append("Validation Commands in DoD Contract")
|
|
if "Required Artifacts" not in block:
|
|
missing.append("Required Artifacts in DoD Contract")
|
|
elif not artifacts_have_content(block):
|
|
missing.append("non-empty Required Artifacts")
|
|
missing.extend(
|
|
f"missing minimal DoD structure: {name}"
|
|
for name, needles in STRUCTURE_CHECKS.items()
|
|
if not any(needle in block for needle in needles)
|
|
)
|
|
status = "failed" if missing else "passed"
|
|
result = gate_result(
|
|
"dod-contract-gate",
|
|
args.stage,
|
|
status,
|
|
[
|
|
item if item.startswith("missing minimal DoD structure:")
|
|
else f"missing required DoD contract item: {item}"
|
|
for item in missing
|
|
],
|
|
evidence=[{
|
|
"design": str(path),
|
|
"checked_block": "DoD Contract",
|
|
"structure_checks": STRUCTURE_CHECKS,
|
|
"strength": "minimal DoD Contract section check",
|
|
}],
|
|
)
|
|
main_exit(result, args.json_out)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|