@@ -639,6 +639,33 @@ def test_github_post_contract_matches_prompt_roster(self) -> None:
639639 self .assertIn ("AI 内容标识符" , text )
640640 self .assertIn ("⟦AI:AUTO-LOOP⟧" , text )
641641
642+ # Refactor (issue79/r8-consensus-no-implementation-helper-fork):
643+ # Old pattern: implement-from-design could grow a second intake/helper prompt or producer registry abstraction.
644+ # New principle: implementation stays on the existing implement prompt path; no helper/fork/intake abstraction tokens.
645+ def test_issue79_consensus_no_helper_or_fork_intake_abstraction (self ) -> None :
646+ prompts_root = SKILL_ROOT / "prompts"
647+ prompt_paths = sorted (prompts_root .glob ("*implement*.md" ))
648+ prompt_names = {path .name for path in prompt_paths }
649+ forbidden_prompt_names = {"implement-from-design-issue.md" }
650+ forbidden_tokens = (
651+ "ImplementationIntakeV1" ,
652+ "implementation_intake" ,
653+ "implement_intake" ,
654+ "normalizer helper" ,
655+ "producer registry" ,
656+ )
657+
658+ self .assertIn (prompts_root / "implement.md" , prompt_paths )
659+ for prompt_name in forbidden_prompt_names :
660+ with self .subTest (prompt_name = prompt_name ):
661+ self .assertNotIn (prompt_name , prompt_names )
662+
663+ for path in prompt_paths :
664+ text = path .read_text (encoding = "utf-8" )
665+ for token in forbidden_tokens :
666+ with self .subTest (prompt = path .name , token = token ):
667+ self .assertNotIn (token , text , f"r8 consensus(#79) forbids { token } in { path .name } " )
668+
642669 # Refactor (iter213/cluster-213-006-delete-solver-defer-escape):
643670 # Old pattern: delete solver forbids defer, then defines Deferrable and asks for a tracking issue creation suggestion(prompt 内部矛盾,且 gh issue create 后被禁)
644671 # New principle: delete solver 单 terminal vocabulary:delete/collapse/abstain/escalate;无 deferred side-channel、无 issue-create 命令建议;'not now' map 到 abstain/false-positive,lifecycle 决策归 controller/maintainer。
@@ -780,6 +807,9 @@ class WorkUnitV1SourceRegressionTests(unittest.TestCase):
780807 # Refactor (iter2/cluster-007-work-unit-contract-schema):
781808 # Old pattern: work-unit state contract existed only as prose, so migration/envelope terms could re-enter the skill unnoticed
782809 # New principle: source-regression coverage keeps WorkUnitV1 v1 containers authoritative and blocks premature work_units_* migration surface
810+ # Refactor (iter9/issue79-design-implementation-intake):
811+ # Old pattern: implement prompt could only name audit-iter-N as its context source.
812+ # New principle: WORK_UNIT_SOURCE_REF plus optional DESIGN_DECISION_PATH selects the authoritative intake artifact without adding a prompt fork.
783813 def render_work_unit_template (self , * , work_unit_id : str | None , cluster_id : str ) -> str :
784814 with tempfile .TemporaryDirectory () as tmp :
785815 template = Path (tmp ) / "template.md"
@@ -819,6 +849,48 @@ def render_work_unit_template(self, *, work_unit_id: str | None, cluster_id: str
819849 self .assertEqual (result .returncode , 0 , result .stderr )
820850 return output .read_text (encoding = "utf-8" )
821851
852+ def render_implement_prompt (
853+ self ,
854+ * ,
855+ cluster_id : str = "cluster-079" ,
856+ work_unit_source_ref : str ,
857+ design_decision_path : str ,
858+ ) -> str :
859+ with tempfile .TemporaryDirectory () as tmp :
860+ output = Path (tmp ) / "implement-rendered.md"
861+ env = os .environ .copy ()
862+ env .update (
863+ {
864+ "REPO_ROOT" : str (REPO_ROOT ),
865+ "PROJECT_RULES" : "AGENTS.md" ,
866+ "CLUSTER_ID" : cluster_id ,
867+ "WORK_UNIT_ID" : cluster_id ,
868+ "WORK_UNIT_SOURCE_REF" : work_unit_source_ref ,
869+ "DESIGN_DECISION_PATH" : design_decision_path ,
870+ "ITERATION" : "9" ,
871+ "WORKTREE_PATH" : "/tmp/worktree" ,
872+ "BRANCH" : "refactor/iter9-cluster-079" ,
873+ "OLD_PATTERN" : "single-source implementation context" ,
874+ "NEW_PRINCIPLE" : "consensus artifact drives implementation" ,
875+ "SCOPE_PATHS" : "skills/codex-refactor-loop/prompts/implement.md\n skills/codex-refactor-loop/scripts/test_*.py" ,
876+ "VERIFICATION_HINTS" : "python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_*.py'" ,
877+ "HOST_COMMENT_RULE" : "source files English-only; refactor self-documentation required" ,
878+ "HOST_PROTO_POLICY" : "" ,
879+ }
880+ )
881+
882+ script = f'source "{ SKILL_ROOT / "scripts" / "controller_lib.sh" } "; render_template "$TEMPLATE" "$OUTPUT"'
883+ result = subprocess .run (
884+ ["bash" , "-lc" , script ],
885+ env = {** env , "TEMPLATE" : str (SKILL_ROOT / "prompts" / "implement.md" ), "OUTPUT" : str (output )},
886+ capture_output = True ,
887+ text = True ,
888+ check = False ,
889+ )
890+
891+ self .assertEqual (result .returncode , 0 , result .stderr )
892+ return output .read_text (encoding = "utf-8" )
893+
822894 def test_work_unit_v1_contract_markers_are_present (self ) -> None :
823895 reference_text = (SKILL_ROOT / "REFERENCE.md" ).read_text (encoding = "utf-8" )
824896 skill_text = (SKILL_ROOT / "SKILL.md" ).read_text (encoding = "utf-8" )
@@ -939,6 +1011,57 @@ def test_audit_prompt_remains_raw_artifact_contract(self) -> None:
9391011 with self .subTest (marker = marker ):
9401012 self .assertNotIn (marker , audit_prompt )
9411013
1014+ def test_implement_prompt_audit_dispatch_reads_work_unit_source_ref (self ) -> None :
1015+ source_ref = "$REPO_ROOT/.refactor-loop/runs/audit-iter-9.md"
1016+ rendered = self .render_implement_prompt (
1017+ work_unit_source_ref = source_ref ,
1018+ design_decision_path = "" ,
1019+ )
1020+
1021+ required = (
1022+ f"实现上下文事实源是 `{ source_ref } `" ,
1023+ "为空时走 audit-backed legacy pathway" ,
1024+ f"否则读取 `{ source_ref } ` 中 \" cluster-079\" 一节" ,
1025+ "skills/codex-refactor-loop/prompts/implement.md" ,
1026+ "skills/codex-refactor-loop/scripts/test_*.py" ,
1027+ "禁止 `git commit` / `git push` / `git checkout <branch>`" ,
1028+ "source files English-only; refactor self-documentation required" ,
1029+ "⟦AI:AUTO-LOOP⟧" ,
1030+ )
1031+
1032+ for marker in required :
1033+ with self .subTest (marker = marker ):
1034+ self .assertIn (marker , rendered )
1035+
1036+ def test_implement_prompt_design_dispatch_reads_consensus_artifact (self ) -> None :
1037+ decision_path = ".refactor-loop/runs/phase9-issue79-r8-judge.md"
1038+ rendered = self .render_implement_prompt (
1039+ work_unit_source_ref = decision_path ,
1040+ design_decision_path = decision_path ,
1041+ )
1042+
1043+ required = (
1044+ f"`{ decision_path } ` 非空时走 design-issue pathway" ,
1045+ f"读取 `{ REPO_ROOT / decision_path } `" ,
1046+ "design-issue consensus artifact" ,
1047+ "skills/codex-refactor-loop/prompts/implement.md" ,
1048+ "skills/codex-refactor-loop/scripts/test_*.py" ,
1049+ "禁止 `git commit` / `git push` / `git checkout <branch>`" ,
1050+ "source files English-only; refactor self-documentation required" ,
1051+ "⟦AI:AUTO-LOOP⟧" ,
1052+ )
1053+
1054+ for marker in required :
1055+ with self .subTest (marker = marker ):
1056+ self .assertIn (marker , rendered )
1057+
1058+ def test_implement_prompt_declares_design_intake_env_vars (self ) -> None :
1059+ implement_prompt = (SKILL_ROOT / "prompts" / "implement.md" ).read_text (encoding = "utf-8" )
1060+
1061+ for marker in ("${WORK_UNIT_SOURCE_REF}" , "${DESIGN_DECISION_PATH}" ):
1062+ with self .subTest (marker = marker ):
1063+ self .assertIn (marker , implement_prompt )
1064+
9421065 def test_v1_operational_tokens_are_stable_and_not_renamed (self ) -> None :
9431066 # Refactor (iter2/cluster-009-marker-label-compat-migration):
9441067 # Old pattern: marker/label 命名与 refactor 外壳耦合,无显式稳定契约
0 commit comments