Skip to content

Commit 64a3fdb

Browse files
loningclaude
andauthored
feat(skill): #79 implement WORK_UNIT_SOURCE_REF + DESIGN_DECISION_PATH(r8 consensus) (#88)
* feat(skill): implement.md 加 WORK_UNIT_SOURCE_REF + DESIGN_DECISION_PATH 双 pathway(#79 r8 consensus) #79 Phase 9 r4/r7/r8 三轮 3/3 consensus on `delete`:在 existing implement.md 加两个 env var, 让 design-issue work unit 也能 dispatch implement,不引入新 helper / prompt fork / daemon。 - 加 ${WORK_UNIT_SOURCE_REF}:audit-backed → audit-iter-N.md,design-issue → consensus artifact - 加 ${DESIGN_DECISION_PATH}:非空走 design-issue pathway,空走 audit-backed legacy - 保留 ${CLUSTER_ID} v1 alias(audit-backed legacy 不变) - 加 source-regression test 验证两 env var 存在 这解锁 8 个 consensus-reached design issue(#53/#65/#66/#70/#84/#85/#86/#87)进入 implement pipeline。 授权:Phase 9 r8 judge artifact `.refactor-loop/runs/phase9-issue79-r8-judge.md`(3/3 consensus:delete) Tests: 292 tests pass(local run) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(skill): #79 fix(pr88-r2) — 加 r8 forbidden token source-regression PR #88 r2 tests reviewer reject:render-path tests 覆盖 ✓ 但缺 forbidden-token assertion(r8 consensus delete:no helper/fork/intake abstraction)。 加 test:asserts that prompts/implement.md 不含 `ImplementationIntakeV1` / `implementation_intake` / `implement_intake` / `normalizer helper` / `implement-from-design-issue` / `producer registry` 等 r8-禁止 token。SKILL.md / REFERENCE.md whitelisted(它们是 rule 描述本身)。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a4492aa commit 64a3fdb

2 files changed

Lines changed: 127 additions & 2 deletions

File tree

skills/codex-refactor-loop/prompts/implement.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
你以无人值守模式在 worktree `${WORKTREE_PATH}` 中工作,对应分支 `${BRANCH}`
66
当前 v1 audit-backed work unit 的兼容 cluster alias 是 `${CLUSTER_ID}`;审计段查找、既有 artifact 文件名、分支/worktree 名和 marker 仍使用该 alias。
7+
实现上下文事实源是 `${WORK_UNIT_SOURCE_REF}`。audit-backed work unit 指向 `$REPO_ROOT/.refactor-loop/runs/audit-iter-${ITERATION}.md`;design-issue work unit 指向已达成共识的 decision artifact。
8+
`${DESIGN_DECISION_PATH}` 非空时走 design-issue pathway,读取该 consensus artifact;为空时走 audit-backed legacy pathway,读取 `${WORK_UNIT_SOURCE_REF}` 中的 "${CLUSTER_ID}" 一节。
79

810
## 必读上下文
911

1012
1. 主仓库 `$REPO_ROOT/${PROJECT_RULES:-CLAUDE.md}` 全部强制条款。
11-
2. 完整审计:`$REPO_ROOT/.refactor-loop/runs/audit-iter-${ITERATION}.md` 中 "${CLUSTER_ID}" 一节。
13+
2. 实现上下文:若 `${DESIGN_DECISION_PATH}` 非空,读取 `$REPO_ROOT/${DESIGN_DECISION_PATH}`;否则读取 `${WORK_UNIT_SOURCE_REF}` 中 "${CLUSTER_ID}" 一节。
1214
3. `$REPO_ROOT 的架构/词汇文档(若有)` 下相关权威文档。
1315

1416
## 错误模式 / 设计原则
@@ -36,7 +38,7 @@ ${SCOPE_PATHS}
3638

3739
## 流程
3840

39-
1. audit 段读所有 `scope_paths` 文件。
41+
1. `${DESIGN_DECISION_PATH}` 选择 design-issue consensus artifact 或 audit 段读所有 `scope_paths` 文件。
4042
2. 打印 `PLAN:` 前缀的具体改动计划(一行一项)。
4143
3. 实施。
4244
4. 编译:`$BUILD_CMD`,失败时修复,最多 5 次迭代。

skills/codex-refactor-loop/scripts/test_ensure_project_rules_fixed_points.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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\nskills/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

Comments
 (0)