From c5cebffe4a9f636dc3e139cd64ef24c463483b0c Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 14:07:55 +0800 Subject: [PATCH 01/12] P3b S2: replay sunset + workflow-learning removal + docs cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Delete runtime/replay.py and tests/test_runtime_replay.py entirely - Remove workflow-learning builtin skill (catalog, skill.yaml, generated.json) - Strip replay event emission from engine, develop_callback, handoff, output - Remove replay route from router, manifest, checkpoint_request - Remove RuntimeConfig.workflow_learning_auto_capture and replay_root - Remove ReplayEvent model and replay_session_dir from RuntimeResult - Strip config validation for workflow.learning (graceful pop for existing configs) - Update release-preflight.sh: unittest discover → pytest - Clean docs: README, README.zh-CN, how-sopify-works (zh/en), fixture yaml - Sync all affected tests (engine, router, decision, installer, etc.) - Add P3b plan package (.sopify-skills/plan/20260508_p3b_perimeter_cleanup/) pytest: 684 passed, 49 subtests passed Note: skill eval gate needs baseline update (replay cases removed) --- .../background.md | 27 ++ .../20260508_p3b_perimeter_cleanup/design.md | 100 +++++ .../20260508_p3b_perimeter_cleanup/tasks.md | 112 +++++ README.md | 9 +- README.zh-CN.md | 7 - docs/how-sopify-works.en.md | 5 +- docs/how-sopify-works.md | 5 +- installer/bootstrap_workspace.py | 1 - runtime/__init__.py | 2 - runtime/_models/core.py | 5 - runtime/_models/handoff.py | 57 +-- runtime/builtin_catalog.generated.json | 40 -- runtime/builtin_catalog.py | 11 - .../workflow-learning/skill.yaml | 27 -- runtime/checkpoint_request.py | 2 +- runtime/config.py | 13 +- runtime/develop_callback.py | 55 --- runtime/develop_quality.py | 2 +- runtime/engine.py | 82 +--- runtime/handoff.py | 8 +- runtime/manifest.py | 3 - runtime/models.py | 3 +- runtime/output.py | 11 +- runtime/replay.py | 413 ------------------ runtime/router.py | 58 +-- scripts/check-runtime-smoke.sh | 6 - scripts/develop_callback_runtime.py | 1 - scripts/release-preflight.sh | 2 +- .../sample_invariant_gate_matrix.yaml | 10 +- tests/runtime_test_support.py | 2 - tests/test_contract_consistency.py | 1 - tests/test_installer.py | 3 +- tests/test_runtime_decision.py | 1 - tests/test_runtime_engine.py | 80 +--- tests/test_runtime_replay.py | 136 ------ tests/test_runtime_router.py | 42 -- tests/test_runtime_sample_invariant_gate.py | 6 - tests/test_runtime_skill_registry.py | 1 - 38 files changed, 277 insertions(+), 1072 deletions(-) create mode 100644 .sopify-skills/plan/20260508_p3b_perimeter_cleanup/background.md create mode 100644 .sopify-skills/plan/20260508_p3b_perimeter_cleanup/design.md create mode 100644 .sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md delete mode 100644 runtime/builtin_skill_packages/workflow-learning/skill.yaml delete mode 100644 runtime/replay.py delete mode 100644 tests/test_runtime_replay.py diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/background.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/background.md new file mode 100644 index 0000000..936c1ff --- /dev/null +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/background.md @@ -0,0 +1,27 @@ +# 变更提案: P3b Perimeter Cleanup + +## 需求背景 + +P3a 完成了 contract-aligned surface cleanup(legacy 删除、routing 收敛)。但 P3a 后仍然残留一批外围噪音: + +1. **replay / workflow-learning 已死未葬**:蓝图已判定下线(design.md consult family 已移除、background.md 已标注),但 runtime 代码仍在写入 replay 事件、builtin_catalog 仍导出 workflow-learning、README 仍提及。这会持续污染 P4 系列的减重边界。 + +2. **Release gate 挂死**:`release-preflight.sh` 使用 `unittest discover`,在当前环境无法正常退出,导致 release 流程断裂。 + +3. **Tests 缺分类**:tests 全部平铺,无法区分 contract(必保)和 implementation-mirror(P4b 可砍)。P4b 减重没有分类基础就会变成逐个判断,效率极低。 + +4. **README 首屏偏重**:首屏暴露 plan lifecycle / blueprint / runtime gate / checkpoint taxonomy 等内部术语,与 P4c"首接触只暴露可恢复 + 拍板"的验收目标矛盾。不在 P3b 清掉,P4c 就没有干净起点。 + +## 与蓝图里程碑的关系 + +- **P3b**(tasks.md):本方案包是 P3b 的完整执行包 +- **前提**:P3a 已完成(legacy surface 已删除、routing 已收敛) +- **下游**:P4a(External Surface Freeze)依赖 P3b 清理后的干净外围面 + +## Plan Intake Checklist + +1. **主命中里程碑**:P3b(Perimeter Cleanup) +2. **改动性质**:execution strategy / implementation wave — 不定义新 contract,只清理/下线已确认的旧面 +3. **Machine truth 变更**:删除 replay route(已从 consult canonical family 移除);删除 workflow-learning skill entry(builtin_catalog.py)。不新增 machine truth +4. **Legacy surface**:replay / workflow-learning 已在 design.md 标注 P3b sunset;无需替代 contract +5. **Core promotion rule / hard max 影响**:无 diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/design.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/design.md new file mode 100644 index 0000000..7cf17be --- /dev/null +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/design.md @@ -0,0 +1,100 @@ +# 技术设计: P3b Perimeter Cleanup + +## 方案概述 + +1 个方案包,4 个内部切片,按依赖顺序串行执行。每切片完成后跑 `pytest` 验证。 + +## Scope 边界 + +### 在 scope 内 + +- Release gate 从 unittest 改 pytest +- replay 能力下线(代码 + 数据 + 文档引用) +- P3a 旧概念残留清理 +- Tests 分类标注 +- CHANGELOG 去文件列表化 +- README 首屏降噪与 Convention 默认入口翻转 + +### 不在 scope 内 + +- 不改 gate/router 核心决策逻辑 +- 不改 protocol.md 或 design.md 的 contract 定义(blueprint truth 已在之前收敛) +- 不做 P4a 级别的 external surface freeze +- 不做 README 产品重设计(只做首屏降噪,产品定位不变) +- 不改 builtin_catalog.py 的导出接口形态(只删 workflow-learning entry,schema 不变) + +## 切片设计与风险 + +### S1: Release Gate + Evals 卫生 + +**变更面**:`scripts/release-preflight.sh`、`.gitignore` + +**风险**:低。release-preflight.sh 是 CI 辅助脚本,改 test runner 不影响 runtime。 + +**验证**:`bash scripts/release-preflight.sh` 正常退出;`git status` 不再显示 `skill_eval_report.json` + +### S2: Replay 下线 + 旧概念清理 + Runtime 外围残留 + +**变更面**: +- `runtime/replay.py`(整文件删除) +- `runtime/engine.py`(replay 事件发射 + L1704-1705 skill 映射分支移除) +- `runtime/develop_callback.py`(replay 记录移除) +- `runtime/handoff.py`(replay_session_dir 附件移除,约 L347-348) +- `runtime/output.py`(replay 展示移除) +- `runtime/builtin_catalog.py`(workflow-learning entry 删除,L92-101) +- `runtime/builtin_skill_packages/workflow-learning/skill.yaml`(整文件删除) +- `runtime/builtin_catalog.generated.json`(workflow-learning 条目移除) +- `runtime/router.py`(replay route 分支移除,L290-296) +- `.sopify-skills/replay/`(目录数据删除) +- README / README.zh-CN.md / docs 中 replay / workflow-learning 引用 +- tests 中 replay / workflow-learning 相关断言(test_runtime_router, test_runtime_decision, test_runtime_sample_invariant_gate, test_runtime_skill_registry, test_installer) + +**风险**:中。 +- 核心判断:replay 是 append-only 写入,无回读消费者。gate.py / router.py 不读 replay 数据。下线不影响主链决策。 +- 潜在风险点:handoff.py 中 `replay_session_dir` 作为 artifact 附件传递。移除后需确认 handoff rendering 不因缺少字段而异常。 +- 旧概念清理涉及 tests,可能有断言依赖已删 surface 的测试用例——需逐个判断是删除还是改写。 + +**验证(硬验收)**: +- `pytest` 全通过 +- `grep -rn "replay" runtime/*.py` 无生产代码命中 +- `grep -rn "workflow.learning" runtime/*.py` 无命中 +- `python3 -c "from runtime.builtin_catalog import load_builtin_skills; ..."` 确认 workflow-learning 不在枚举中 +- `test -f runtime/builtin_skill_packages/workflow-learning/skill.yaml` 返回不存在 +- `grep -c "workflow-learning" runtime/builtin_catalog.generated.json` 输出 0 +- `grep -c 'replay_session_dir' runtime/handoff.py` 输出 0;另需手动触发一次 develop → handoff 流程确认无 KeyError/AttributeError +- `grep -rn "replay" tests/*.py` 无命中或仅剩不相关字面量 + +### S3: Tests 分类标注 + +**变更面**:`tests/test_*.py`(注释或 pytest marker) + +**风险**:低。只添加标注,不改测试逻辑。 + +**分类规则**: +| 分类 | 定义 | P4b 处置 | +|------|------|---------| +| contract | 验证外部消费面 / machine truth schema | 必保 | +| smoke | 端到端最小路径验证 | 必保 | +| distribution | 安装/分发/打包验证 | 必保 | +| implementation-mirror | 只镜像内部实现细节 | 可砍候选 | + +**验证**:所有 test 文件都有明确分类标注;`pytest` 全通过;输出分类汇总 + +### S4: CHANGELOG 压缩 + README 首屏降噪 + +**变更面**: +- `CHANGELOG.md`(旧条目压缩 + 格式声明更新) +- `scripts/release-draft-changelog.py`(只产摘要) +- `CONTRIBUTING.md`(changelog 说明同步) +- `README.md` + `README.zh-CN.md`(首屏重写) + +**风险**:中。 +- CHANGELOG 压缩是不可逆的信息损失(旧 102 条文件列表会被压成摘要),但这些信息在 git log 中仍可追溯。 +- README 首屏重写是产品叙事变更。核心约束:Convention 为默认入口,Runtime 为增强路径。.sopify-runtime 不出现在首接触面。 +- 首屏降噪直接影响 P4c 验收 (b) 的前提条件。 + +**验证**: +- README 首屏 < 50 行 +- 首屏不出现 blueprint / checkpoint taxonomy / runtime state / .sopify-runtime 等术语 +- Convention 作为默认叙事出现在 Runtime 之前 +- `pytest` 全通过 diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md new file mode 100644 index 0000000..6912681 --- /dev/null +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md @@ -0,0 +1,112 @@ +--- +plan_id: 20260508_p3b_perimeter_cleanup +feature_key: p3b_perimeter_cleanup +level: standard +lifecycle_state: active +knowledge_sync: + project: aligned + background: aligned + design: aligned + tasks: aligned +archive_ready: false +--- + +# 任务清单: P3b Perimeter Cleanup + +## 当前阶段目标 + +以 P3a 完成为前提。清理外围面,为 P4 系列减重扫清障碍。1 个方案包,4 个内部切片。 + +## S1: Release Gate + Evals 卫生 + +- [x] 1.1 `release-preflight.sh`:从 `unittest discover` 改为 `pytest` +- [x] 1.2 `evals/skill_eval_report.json` 加入 `.gitignore`;baseline 和 SLO 文件保留 +- [ ] 1.3 验证:`bash scripts/release-preflight.sh` 正常退出 +- [ ] 1.4 (补) CONTRIBUTING.md / CONTRIBUTING_CN.md / scripts/sync-runtime-assets.sh 中 unittest discover 统一为 pytest + +## S2: Replay 下线 + 旧概念清理 + Runtime 外围残留 + +### replay 能力下线 + +- [x] 2.1 删除 `.sopify-skills/replay/` 目录数据 +- [x] 2.2 删除 `runtime/replay.py`(整文件) +- [x] 2.3 移除 `runtime/engine.py` 中 replay 事件发射(含 L1704-1705 skill 映射分支) +- [x] 2.4 移除 `runtime/develop_callback.py` 中 replay 记录 +- [x] 2.5 移除 `runtime/handoff.py` 中 `replay_session_dir` 附件(约 L347-348) +- [x] 2.6 移除 `runtime/output.py` 中 replay 展示 +- [x] 2.7 `runtime/builtin_catalog.py`:删除 workflow-learning skill entry(L92-101) +- [x] 2.8 删除 `runtime/builtin_skill_packages/workflow-learning/skill.yaml` +- [x] 2.9 更新 `runtime/builtin_catalog.generated.json`:移除 workflow-learning 条目(L196-201 及相关 replay 引用) +- [x] 2.10 移除 `runtime/router.py` 中 replay route 分支(L290-296) +- [x] 2.11 清 README / README.zh-CN.md / docs 中对 replay 和 workflow-learning 的引用 + +### 旧概念清理(P3a 已 sunset surface 残留) + +- [x] 2.12 tests 中验证 P3a 已 sunset surface 的断言——更新或删除 +- [ ] 2.13 prompt 中引用已 sunset contract 的段落——清除(prompt asset 本体含 replay 字面量,待 prompt asset 整体更新时处理) +- [x] 2.14 handoff/output 旧兼容投影——清除 +- [x] 2.15 reason phrasing / phase label 特判——清除 + +### replay / workflow-learning 测试引用清理 + +- [x] 2.16 `tests/test_runtime_router.py`:replay route 测试(L152-158, L617-651)——删除 +- [x] 2.17 `tests/test_runtime_decision.py`:`replay_session_dir=None` 引用(L604)——清除 +- [x] 2.18 `tests/test_runtime_sample_invariant_gate.py`:replay_required 相关断言(L92-107)——清除 +- [x] 2.19 `tests/test_runtime_skill_registry.py`:workflow-learning assertIn(L61)——删除 +- [x] 2.20 `tests/test_installer.py`:replay 相关引用(L895)——已清除 gitignore 断言;L1301/L1354 footer 断言保留(prompt asset 未更新,注释标注) +- [ ] 2.21 清理 tests/__pycache__ 中 replay 相关 .pyc + +### Runtime 外围残留 + +- [x] 2.22 scripts / config 中对 P3a 已删 surface 的引用残留——清除(check-runtime-smoke.sh, develop_callback_runtime.py, bootstrap_workspace.py, manifest.py, checkpoint_request.py) + +### S2 验证(硬验收) + +- [ ] 2.V1 `pytest` 全通过(待跑) +- [x] 2.V2 `grep -rn "replay" runtime/*.py | grep -v "^Binary" | grep -v __pycache__` 仅剩注释(config.py:90 sunset 注释, router.py:377 deprecated 注释) +- [x] 2.V3 `grep -rn "workflow.learning" runtime/*.py | grep -v __pycache__` 无命中 +- [ ] 2.V4 `python3 -c "from runtime.builtin_catalog import load_builtin_skills; ..."` 待跑 +- [x] 2.V5 `test -f runtime/builtin_skill_packages/workflow-learning/skill.yaml && echo FAIL || echo OK` 输出 OK +- [x] 2.V6 `grep -c "workflow-learning" runtime/builtin_catalog.generated.json` 输出 0 +- [x] 2.V7 `grep -c 'replay_session_dir' runtime/handoff.py` 输出 0 +- [ ] 2.V8 `grep -rn "replay" tests/*.py | grep -v __pycache__` 仅剩 test_installer.py footer 字面量(prompt asset 待更新) + +## S3: Tests 分类标注 + +- [ ] 3.1 `tests/test_*.py` 按 contract / smoke / distribution / implementation-mirror 标注 +- [ ] 3.2 输出分类汇总表 +- [ ] 3.3 验证:所有 test 文件都有明确分类标注;`pytest` 全通过 + +## S4: CHANGELOG 压缩 + README 首屏降噪 + +### CHANGELOG 去文件列表化 + +- [ ] 4.1 旧 102 条自动生成条目直接压成阶段摘要(不逐条迁移) +- [ ] 4.2 新条目格式只保留 Summary + Changed,不列文件 +- [ ] 4.3 修 `scripts/release-draft-changelog.py` 只产摘要,不产文件清单 +- [ ] 4.4 同步更新 `CONTRIBUTING.md` changelog 说明 + +### README 首屏降噪与默认入口翻转 + +- [ ] 4.5 首屏只保留 3 件事:中断可恢复 + 需要拍板时会停 + 安装入口 +- [ ] 4.6 默认叙事以 Convention(纯协议、无 runtime)为入口 +- [ ] 4.7 Runtime(完整编排、gate、checkpoint)定位为增强路径 +- [ ] 4.8 plan lifecycle / blueprint / runtime gate / checkpoint taxonomy / task size routing / .sopify-runtime 等内部术语降级到二级文档 +- [ ] 4.9 `.sopify-runtime` 只作为后台实现细节出现,不作为用户首接触概念 +- [ ] 4.10 同步更新 README.zh-CN.md + +### S4 验证 + +- [ ] 4.V1 README 首屏 < 50 行 +- [ ] 4.V2 首屏不出现 blueprint / checkpoint taxonomy / runtime state / .sopify-runtime 等术语 +- [ ] 4.V3 Convention 作为默认叙事出现在 Runtime 之前 +- [ ] 4.V4 `pytest` 全通过 + +## 完成标准 + +- [ ] `pytest` 全通过 +- [ ] `release-preflight.sh` 正常退出 +- [ ] `grep -rn "replay" runtime/*.py` 无生产代码命中 +- [ ] README 首屏符合降噪标准 +- [ ] 所有 test 文件有分类标注 +- [ ] CHANGELOG 无文件列表格式条目 diff --git a/README.md b/README.md index 4ceadce..47a8a1a 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ For runtime gate, checkpoints, and plan lifecycle details, see [How Sopify Works ◆ Runtime Gate │ ◇ Routing Decision -├── ▸ Q&A / replay ───────────────────→ Direct output +├── ▸ Q&A ────────────────────────────→ Direct output └── ▸ Code task │ ◇ Complexity Decision @@ -247,13 +247,6 @@ Notes: Most users only need `~go` and `~go plan`; maintainer validation commands live in [CONTRIBUTING.md](./CONTRIBUTING.md). -## Sub-skills - -- `workflow-learning`: replay, retrospective, and step-by-step explanation - Docs: [CN](./Codex/Skills/CN/skills/sopify/workflow-learning/SKILL.md) / [EN](./Codex/Skills/EN/skills/sopify/workflow-learning/SKILL.md) - -Claude uses the mirrored `Claude/Skills/{CN,EN}/...` layout; the links above use the Codex tree as the canonical doc entry. - ## Directory Structure ```text diff --git a/README.zh-CN.md b/README.zh-CN.md index 3a638af..94f8efb 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -247,13 +247,6 @@ plan: 普通用户只需要记住 `~go / ~go plan`;维护者验证命令放在 [贡献指南](./CONTRIBUTING_CN.md)。 -## 子 Skills - -- `workflow-learning`:回放、复盘与逐步讲解 - 文档:[中文](./Codex/Skills/CN/skills/sopify/workflow-learning/SKILL.md) / [English](./Codex/Skills/EN/skills/sopify/workflow-learning/SKILL.md) - -Claude 使用镜像结构的 `Claude/Skills/{CN,EN}/...` 路径;上述链接以 Codex 目录作为统一文档入口。 - ## 目录结构 ```text diff --git a/docs/how-sopify-works.en.md b/docs/how-sopify-works.en.md index 4632e03..6106792 100644 --- a/docs/how-sopify-works.en.md +++ b/docs/how-sopify-works.en.md @@ -94,8 +94,7 @@ Checkpoint rules: │ └── sessions//... # parallel review isolation ├── user/ │ └── preferences.md -├── project.md -└── replay/ # optional replay data (still ignored) +└── project.md ``` Layer notes: @@ -103,7 +102,7 @@ Layer notes: - `blueprint/` stores durable knowledge and stable contracts - `plan/` stores active work packages, not long-lived blueprint state; the directory is tracked, but `_registry.yaml` remains locally ignored - `history/` stores closed-out plans and is tracked -- `state/` and `replay/` remain local runtime data ignored by git +- `state/` is the local runtime data layer ignored by git ## Appendix: Plan Lifecycle diff --git a/docs/how-sopify-works.md b/docs/how-sopify-works.md index 31760be..7b77ad3 100644 --- a/docs/how-sopify-works.md +++ b/docs/how-sopify-works.md @@ -94,8 +94,7 @@ Checkpoint 规则: │ └── sessions//... # 并发 review 隔离 ├── user/ │ └── preferences.md -├── project.md -└── replay/ # 可选回放(继续 ignored) +└── project.md ``` 层级说明: @@ -103,7 +102,7 @@ Checkpoint 规则: - `blueprint/` 承载长期知识与稳定契约 - `plan/` 保存当前工作方案,不等同于长期蓝图;目录本身纳入版本管理,但 `_registry.yaml` 继续保持本地忽略 - `history/` 只存已收口方案,并纳入版本管理 -- `state/` 与 `replay/` 仍是宿主与 runtime 的本地运行态数据层 +- `state/` 是宿主与 runtime 的本地运行态数据层 ## 附录:Plan 生命周期 diff --git a/installer/bootstrap_workspace.py b/installer/bootstrap_workspace.py index 726c35b..fb66329 100644 --- a/installer/bootstrap_workspace.py +++ b/installer/bootstrap_workspace.py @@ -126,7 +126,6 @@ def _annotate_outcome_payload( _SOPIFY_MANAGED_IGNORE_ENTRIES = ( ".sopify-runtime/", ".sopify-skills/state/", - ".sopify-skills/replay/", ".sopify-skills/plan/_registry.yaml", ) REASON_STUB_SELECTED = "STUB_SELECTED" diff --git a/runtime/__init__.py b/runtime/__init__.py index 1851cd5..3cd593d 100644 --- a/runtime/__init__.py +++ b/runtime/__init__.py @@ -4,7 +4,6 @@ from .models import ( PlanArtifact, RecoveredContext, - ReplayEvent, RouteDecision, RunState, RuntimeConfig, @@ -19,7 +18,6 @@ "PlanArtifact", "PreferencesPreloadResult", "RecoveredContext", - "ReplayEvent", "RouteDecision", "RunState", "RuntimeConfig", diff --git a/runtime/_models/core.py b/runtime/_models/core.py index e6fb6a8..f8d66cc 100644 --- a/runtime/_models/core.py +++ b/runtime/_models/core.py @@ -27,7 +27,6 @@ class RuntimeConfig: workflow_mode: str require_score: int auto_decide: bool - workflow_learning_auto_capture: str plan_level: str plan_directory: str ehrb_level: str @@ -46,10 +45,6 @@ def state_dir(self) -> Path: def plan_root(self) -> Path: return self.runtime_root / "plan" - @property - def replay_root(self) -> Path: - return self.runtime_root / "replay" / "sessions" - @dataclass(frozen=True) class SkillMeta: diff --git a/runtime/_models/handoff.py b/runtime/_models/handoff.py index 92368a6..a47076c 100644 --- a/runtime/_models/handoff.py +++ b/runtime/_models/handoff.py @@ -1,4 +1,4 @@ -"""Recovered-context, handoff, replay, and result contracts.""" +"""Recovered-context, handoff, and result contracts.""" from __future__ import annotations @@ -100,7 +100,7 @@ def from_dict(cls, data: Mapping[str, Any]) -> "RuntimeHandoff": @dataclass(frozen=True) class SkillActivation: - """Structured activation fact shared by output, replay, and daily summary.""" + """Structured activation fact shared by output and daily summary.""" skill_id: str skill_name: str @@ -140,57 +140,6 @@ def from_dict(cls, data: Mapping[str, Any]) -> "SkillActivation": ) -@dataclass(frozen=True) -class ReplayEvent: - """Append-only replay event payload.""" - - ts: str - phase: str - intent: str - action: str - key_output: str - decision_reason: str - result: str - risk: str = "" - alternatives: tuple[str, ...] = () - highlights: tuple[str, ...] = () - artifacts: tuple[str, ...] = () - metadata: Mapping[str, Any] = field(default_factory=dict) - - def to_dict(self) -> dict[str, Any]: - return { - "ts": self.ts, - "phase": self.phase, - "intent": self.intent, - "action": self.action, - "key_output": self.key_output, - "decision_reason": self.decision_reason, - "result": self.result, - "risk": self.risk, - "alternatives": list(self.alternatives), - "highlights": list(self.highlights), - "artifacts": list(self.artifacts), - "metadata": _json_mapping(self.metadata), - } - - @classmethod - def from_dict(cls, data: Mapping[str, Any]) -> "ReplayEvent": - return cls( - ts=str(data.get("ts") or ""), - phase=str(data.get("phase") or ""), - intent=str(data.get("intent") or ""), - action=str(data.get("action") or ""), - key_output=str(data.get("key_output") or ""), - decision_reason=str(data.get("decision_reason") or ""), - result=str(data.get("result") or ""), - risk=str(data.get("risk") or ""), - alternatives=tuple(str(item) for item in (data.get("alternatives") or ()) if str(item).strip()), - highlights=tuple(str(item) for item in (data.get("highlights") or ()) if str(item).strip()), - artifacts=tuple(str(item) for item in (data.get("artifacts") or ()) if str(item).strip()), - metadata=_json_mapping(data.get("metadata")), - ) - - @dataclass(frozen=True) class RuntimeResult: """Top-level runtime result returned by the engine.""" @@ -201,7 +150,6 @@ class RuntimeResult: kb_artifact: Optional[KbArtifact] = None plan_artifact: Optional[PlanArtifact] = None skill_result: Optional[Mapping[str, Any]] = None - replay_session_dir: Optional[str] = None handoff: Optional[RuntimeHandoff] = None activation: Optional[SkillActivation] = None generated_files: tuple[str, ...] = () @@ -215,7 +163,6 @@ def to_dict(self) -> dict[str, Any]: "kb_artifact": self.kb_artifact.to_dict() if self.kb_artifact else None, "plan_artifact": self.plan_artifact.to_dict() if self.plan_artifact else None, "skill_result": _json_mapping(self.skill_result), - "replay_session_dir": self.replay_session_dir, "handoff": self.handoff.to_dict() if self.handoff else None, "activation": self.activation.to_dict() if self.activation else None, "generated_files": list(self.generated_files), diff --git a/runtime/builtin_catalog.generated.json b/runtime/builtin_catalog.generated.json index 9ada7c1..4d52107 100644 --- a/runtime/builtin_catalog.generated.json +++ b/runtime/builtin_catalog.generated.json @@ -176,46 +176,6 @@ "read" ], "triggers": [] - }, - { - "allowed_paths": [ - "." - ], - "contract_version": "1", - "descriptions": { - "en-US": "Workflow-learning sub-skill for replay, review, and decision explanation.", - "zh-CN": "工作流学习子技能;用于回放、复盘与决策解释。" - }, - "disallowed_tools": [], - "entry_kind": null, - "handoff_kind": "consult", - "host_support": [ - "codex", - "claude" - ], - "id": "workflow-learning", - "metadata": {}, - "mode": "workflow", - "names": { - "en-US": "workflow-learning", - "zh-CN": "workflow-learning" - }, - "permission_mode": "default", - "requires_network": false, - "runtime_entry": null, - "supports_routes": [ - "replay" - ], - "tools": [ - "read" - ], - "triggers": [ - "回放", - "复盘", - "为什么这么做", - "replay", - "review the implementation" - ] } ], "source": "runtime/builtin_skill_packages" diff --git a/runtime/builtin_catalog.py b/runtime/builtin_catalog.py index 5a35154..7db3e98 100644 --- a/runtime/builtin_catalog.py +++ b/runtime/builtin_catalog.py @@ -88,17 +88,6 @@ class _BuiltinSkillSpec: }, handoff_kind="template", ), - _BuiltinSkillSpec( - skill_id="workflow-learning", - names={"zh-CN": "workflow-learning", "en-US": "workflow-learning"}, - descriptions={ - "zh-CN": "工作流学习子技能;用于回放、复盘与决策解释。", - "en-US": "Workflow-learning sub-skill for replay, review, and decision explanation.", - }, - handoff_kind="consult", - supports_routes=("replay",), - triggers=("回放", "复盘", "为什么这么做", "replay", "review the implementation"), - ), ) diff --git a/runtime/builtin_skill_packages/workflow-learning/skill.yaml b/runtime/builtin_skill_packages/workflow-learning/skill.yaml deleted file mode 100644 index 5d00166..0000000 --- a/runtime/builtin_skill_packages/workflow-learning/skill.yaml +++ /dev/null @@ -1,27 +0,0 @@ -schema_version: "1" -id: workflow-learning -mode: workflow -names: - zh-CN: workflow-learning - en-US: workflow-learning -descriptions: - zh-CN: 工作流学习子技能;用于回放、复盘与决策解释。 - en-US: Workflow-learning sub-skill for replay, review, and decision explanation. -handoff_kind: consult -contract_version: "1" -supports_routes: - - replay -triggers: - - "回放" - - "复盘" - - "为什么这么做" - - "replay" - - "review the implementation" -tools: - - read -allowed_paths: - - . -host_support: - - codex - - claude -permission_mode: default diff --git a/runtime/checkpoint_request.py b/runtime/checkpoint_request.py index fbb80c7..5203995 100644 --- a/runtime/checkpoint_request.py +++ b/runtime/checkpoint_request.py @@ -25,7 +25,7 @@ CHECKPOINT_REQUEST_SCHEMA_VERSION = "1" CHECKPOINT_KINDS = ("clarification", "decision") -CHECKPOINT_SOURCE_STAGES = ("analyze", "design", "develop", "replay", "consult", "custom") +CHECKPOINT_SOURCE_STAGES = ("analyze", "design", "develop", "consult", "custom") CHECKPOINT_REASON_MISSING_BUT_TRADEOFF_DETECTED = "checkpoint_request_missing_but_tradeoff_detected" DEVELOP_RESUME_CONTEXT_REQUIRED_FIELDS = ( "active_run_stage", diff --git a/runtime/config.py b/runtime/config.py index db2fa2f..6562ecf 100644 --- a/runtime/config.py +++ b/runtime/config.py @@ -30,7 +30,6 @@ class ConfigError(ValueError): "mode": "adaptive", "require_score": 7, "auto_decide": False, - "learning": {"auto_capture": "by_requirement"}, }, "plan": { "level": "auto", @@ -44,8 +43,7 @@ class ConfigError(ValueError): } _ALLOWED_TOP_LEVEL = {"brand", "language", "output_style", "title_color", "workflow", "plan", "advanced"} -_ALLOWED_WORKFLOW = {"mode", "require_score", "auto_decide", "learning"} -_ALLOWED_LEARNING = {"auto_capture"} +_ALLOWED_WORKFLOW = {"mode", "require_score", "auto_decide"} _ALLOWED_PLAN = {"level", "directory"} _ALLOWED_ADVANCED = {"ehrb_level", "kb_init", "cache_project"} @@ -53,7 +51,6 @@ class ConfigError(ValueError): _ALLOWED_OUTPUT_STYLES = {"minimal", "classic"} _ALLOWED_TITLE_COLORS = {"green", "blue", "yellow", "cyan", "none"} _ALLOWED_WORKFLOW_MODES = {"strict", "adaptive", "minimal"} -_ALLOWED_CAPTURE_MODES = {"always", "by_requirement", "manual", "off"} _ALLOWED_PLAN_LEVELS = {"auto", "light", "standard", "full"} _ALLOWED_EHRB_LEVELS = {"strict", "normal", "relaxed"} _ALLOWED_KB_INIT = {"full", "progressive"} @@ -90,6 +87,9 @@ def load_runtime_config( if project_data: _deep_merge(merged, project_data) + # Strip deprecated config keys (P3b replay sunset) + merged.get("workflow", {}).pop("learning", None) + _validate_config(merged, source_paths=(global_path if global_data else None, project_path if project_data else None)) return RuntimeConfig( @@ -103,7 +103,6 @@ def load_runtime_config( workflow_mode=str(merged["workflow"]["mode"]), require_score=int(merged["workflow"]["require_score"]), auto_decide=bool(merged["workflow"]["auto_decide"]), - workflow_learning_auto_capture=str(merged["workflow"]["learning"]["auto_capture"]), plan_level=str(merged["plan"]["level"]), plan_directory=str(merged["plan"]["directory"]), ehrb_level=str(merged["advanced"]["ehrb_level"]), @@ -164,10 +163,6 @@ def _validate_config(config: Mapping[str, Any], *, source_paths: tuple[Optional[ raise ConfigError("workflow.require_score must be an integer between 1 and 10") if not isinstance(workflow["auto_decide"], bool): raise ConfigError("workflow.auto_decide must be boolean") - learning = _expect_mapping(workflow.get("learning"), path="workflow.learning") - _assert_allowed_keys(learning, _ALLOWED_LEARNING, path="workflow.learning") - if learning["auto_capture"] not in _ALLOWED_CAPTURE_MODES: - raise ConfigError(f"Unsupported workflow.learning.auto_capture: {learning['auto_capture']}") plan = _expect_mapping(config.get("plan"), path="plan") _assert_allowed_keys(plan, _ALLOWED_PLAN, path="plan") diff --git a/runtime/develop_callback.py b/runtime/develop_callback.py index 11870c1..6868329 100644 --- a/runtime/develop_callback.py +++ b/runtime/develop_callback.py @@ -36,7 +36,6 @@ from .handoff import build_runtime_handoff from .context_snapshot import resolve_context_snapshot from .models import PlanArtifact, RecoveredContext, RouteDecision, RunState, RuntimeConfig, RuntimeHandoff -from .replay import ReplayWriter, build_develop_quality_replay_event from .state import StateStore, iso_now _HOST_FACING_TRUTH_KIND_DEVELOP_CALLBACK = "develop_callback" @@ -81,7 +80,6 @@ class DevelopQualitySubmission: quality_result: Mapping[str, Any] run_state: RunState handoff: RuntimeHandoff - replay_session_dir: str | None delegated_callback: DevelopCallbackSubmission | None = None @@ -195,7 +193,6 @@ def submit_develop_callback( ), current_plan=context.current_plan, kb_artifact=None, - replay_session_dir=None, skill_result={"checkpoint_request": request.to_dict()}, notes=( f"Develop callback created: {request.checkpoint_id}", @@ -255,19 +252,11 @@ def submit_develop_quality_report( quality_result=quality_result, config=config, ) - replay_session_dir = _record_develop_quality_replay( - config=config, - context=context, - quality_context=quality_context, - quality_result=quality_result, - run_state=delegated.run_state, - ) return DevelopQualitySubmission( quality_context=quality_context, quality_result=quality_result, run_state=delegated.run_state, handoff=delegated.handoff, - replay_session_dir=replay_session_dir, delegated_callback=delegated, ) @@ -280,19 +269,11 @@ def submit_develop_quality_report( quality_result=quality_result, ) state_store.set_current_handoff(handoff) - replay_session_dir = _record_develop_quality_replay( - config=config, - context=context, - quality_context=quality_context, - quality_result=quality_result, - run_state=run_state, - ) return DevelopQualitySubmission( quality_context=quality_context, quality_result=quality_result, run_state=run_state, handoff=handoff, - replay_session_dir=replay_session_dir, ) @@ -553,42 +534,6 @@ def _with_quality_handoff( ) -def _record_develop_quality_replay( - *, - config: RuntimeConfig, - context: ActiveDevelopContext, - quality_context: Mapping[str, Any], - quality_result: Mapping[str, Any], - run_state: RunState | None = None, -) -> str: - payload = dict(quality_context) - payload["develop_quality_result"] = quality_result - writer = ReplayWriter(config) - event = build_develop_quality_replay_event( - ts=iso_now(), - payload=payload, - language=config.language, - ) - run_state = run_state or context.current_run - session_dir = writer.append_event(run_state.run_id, event) - writer.render_documents( - run_state.run_id, - run_state=run_state, - route=RouteDecision( - route_name="resume_active", - request_text=quality_context["working_summary"], - reason="Develop quality result recorded", - complexity="medium", - candidate_skill_ids=("develop",), - should_recover_context=True, - should_create_plan=False, - ), - plan_artifact=context.current_plan, - events=writer.load_events(run_state.run_id), - ) - return str(session_dir.relative_to(config.workspace_root)) - - def _develop_callback_run_state( *, context: ActiveDevelopContext, diff --git a/runtime/develop_quality.py b/runtime/develop_quality.py index bace150..3bc984e 100644 --- a/runtime/develop_quality.py +++ b/runtime/develop_quality.py @@ -1,7 +1,7 @@ """Structured quality-loop contracts shared by develop runtime surfaces. The host still owns real code changes during `continue_host_develop`, but the -quality loop needs a stable machine-readable contract so handoff, replay, and +quality loop needs a stable machine-readable contract so handoff and checkpoint callbacks can agree on the same fields and value domains. """ diff --git a/runtime/engine.py b/runtime/engine.py index 9bb9290..5c7b247 100644 --- a/runtime/engine.py +++ b/runtime/engine.py @@ -41,7 +41,7 @@ ) from .handoff import build_runtime_handoff from .kb import bootstrap_kb, ensure_blueprint_index, ensure_blueprint_scaffold -from .models import ClarificationState, DecisionState, ExecutionGate, KbArtifact, PlanArtifact, RecoveredContext, ReplayEvent, RouteDecision, RunState, RuntimeConfig, RuntimeHandoff, RuntimeResult, SkillActivation, SkillMeta +from .models import ClarificationState, DecisionState, ExecutionGate, KbArtifact, PlanArtifact, RecoveredContext, RouteDecision, RunState, RuntimeConfig, RuntimeHandoff, RuntimeResult, SkillActivation, SkillMeta from .plan_registry import ( PlanRegistryError, encode_priority_note_event, @@ -55,8 +55,7 @@ reserve_plan_identity, request_explicitly_wants_new_plan, ) -from .replay import ReplayWriter, build_decision_replay_event -from .router import Router, estimate_complexity, decide_capture_mode +from .router import Router, estimate_complexity from .skill_resolver import resolve_route_candidate_skills from .action_intent import ( ActionProposal, @@ -96,7 +95,7 @@ _CANONICAL_ROUTE_FAMILIES: dict[str, str] = { "plan_only": "plan", "workflow": "plan", "light_iterate": "plan", "quick_fix": "develop", "resume_active": "develop", "exec_plan": "develop", - "consult": "consult", "replay": "consult", + "consult": "consult", "archive_lifecycle": "archive", "clarification_pending": "clarification", "clarification_resume": "clarification", "decision_pending": "decision", "decision_resume": "decision", @@ -195,25 +194,6 @@ def _derive_route_from_authorized_proposal( complexity="simple", ) - # Apply capture_mode normalization — shared with Router.classify _with_capture. - capture = decide_capture_mode(config.workflow_learning_auto_capture, route.complexity) - if capture != route.capture_mode: - route = RouteDecision( - route_name=route.route_name, - request_text=route.request_text, - reason=route.reason, - command=route.command, - complexity=route.complexity, - plan_level=route.plan_level, - candidate_skill_ids=route.candidate_skill_ids, - should_recover_context=route.should_recover_context, - plan_package_policy=route.plan_package_policy, - should_create_plan=route.should_create_plan, - capture_mode=capture, - runtime_skill_id=route.runtime_skill_id, - active_run_action=route.active_run_action, - artifacts=route.artifacts, - ) return route @@ -946,13 +926,10 @@ def run_runtime( notes: list[str] = list(snapshot.notes) plan_artifact: PlanArtifact | None = None skill_result: Mapping[str, Any] | None = None - replay_session_dir: str | None = None handoff: RuntimeHandoff | None = None activation: SkillActivation | None = None generated_files: tuple[str, ...] = () - replay_events: list[ReplayEvent] = [] effective_route = classified_route - confirmed_decision_for_replay: DecisionState | None = None registry_changed_hint = False current_clarification = recovered.current_clarification @@ -1060,7 +1037,7 @@ def run_runtime( ) notes.extend(clarification_notes) elif effective_route.route_name == "decision_resume": - effective_route, plan_artifact, decision_notes, kb_artifact, confirmed_decision_for_replay = _handle_decision_resume( + effective_route, plan_artifact, decision_notes, kb_artifact, _ = _handle_decision_resume( effective_route, state_store=review_store, current_decision=recovered.current_decision, @@ -1240,7 +1217,7 @@ def run_runtime( review_store.set_last_route(effective_route) # Resolve once after all route-side mutations, then let store selection, - # handoff, replay, and output consume the same fresh post-route truth. + # handoff, and output consume the same fresh post-route truth. result_snapshot = resolve_context_snapshot( config=config, review_store=review_store, @@ -1283,51 +1260,6 @@ def run_runtime( current_decision=resolved_result_context.current_decision, ) - if effective_route.capture_mode != "off": - writer = ReplayWriter(config) - run_state = resolved_result_context.current_run - run_id = run_state.run_id if run_state is not None else _make_run_id(effective_route.request_text) - replay_event = ReplayEvent( - ts=iso_now(), - phase=_phase_for_route(effective_route), - intent=effective_route.request_text or effective_route.route_name, - action=f"route:{effective_route.route_name}", - key_output=(plan_artifact.summary if plan_artifact is not None else effective_route.reason), - decision_reason=effective_route.reason, - result="success", - artifacts=tuple(plan_artifact.files if plan_artifact is not None else ()), - metadata={"activation": activation.to_dict()} if activation is not None else {}, - ) - replay_events.append(replay_event) - current_decision = resolved_result_context.current_decision - if current_decision is not None and effective_route.route_name == "decision_pending": - replay_events.append( - build_decision_replay_event( - current_decision, - language=config.language, - action="checkpoint_created", - ) - ) - if confirmed_decision_for_replay is not None: - replay_events.append( - build_decision_replay_event( - confirmed_decision_for_replay, - language=config.language, - action="confirmed", - ) - ) - session_dir = writer.append_event(run_id, replay_event) - for extra_event in replay_events[1:]: - writer.append_event(run_id, extra_event) - writer.render_documents( - run_id, - run_state=resolved_result_context.current_run, - route=effective_route, - plan_artifact=plan_artifact or resolved_result_context.current_plan, - events=replay_events, - ) - replay_session_dir = str(session_dir.relative_to(config.workspace_root)) - if effective_route.route_name == "cancel_active": handoff = None else: @@ -1364,7 +1296,6 @@ def run_runtime( resolved_context=handoff_context, current_plan=current_plan, kb_artifact=kb_artifact, - replay_session_dir=replay_session_dir, skill_result=skill_result, notes=notes, ) @@ -1456,7 +1387,6 @@ def run_runtime( kb_artifact=kb_artifact, plan_artifact=plan_artifact, skill_result=skill_result, - replay_session_dir=replay_session_dir, handoff=handoff, activation=activation, generated_files=generated_files, @@ -1701,8 +1631,6 @@ def _activation_target( current_clarification: ClarificationState | None, current_decision: DecisionState | None, ) -> tuple[str, str]: - if decision.runtime_skill_id == "workflow-learning" or decision.route_name == "replay": - return ("workflow-learning", "复盘学习") if decision.route_name in {"resume_active", "exec_plan", "quick_fix", "archive_lifecycle"}: return ("develop", "开发实施") if decision.route_name in {"clarification_pending", "clarification_resume"}: diff --git a/runtime/handoff.py b/runtime/handoff.py index 2e6a28a..aa970da 100644 --- a/runtime/handoff.py +++ b/runtime/handoff.py @@ -62,7 +62,6 @@ "exec_plan": "develop", # consult family "consult": "consult", - "replay": "consult", # archive family "archive_lifecycle": "archive", # clarification family @@ -95,7 +94,6 @@ def build_runtime_handoff( resolved_context: RecoveredContext, current_plan: PlanArtifact | None, kb_artifact: KbArtifact | None, - replay_session_dir: str | None, skill_result: Mapping[str, Any] | None, notes: Sequence[str], ) -> RuntimeHandoff | None: @@ -125,7 +123,6 @@ def build_runtime_handoff( current_run=current_run, current_plan=resolved_plan, kb_artifact=kb_artifact, - replay_session_dir=replay_session_dir, skill_result=skill_result, current_clarification=resolved_context.current_clarification, current_decision=resolved_context.current_decision, @@ -239,7 +236,7 @@ def _required_host_action( return "continue_host_develop" if route_name == "proposal_rejected": return "continue_host_consult" - if route_name == "consult" or route_name == "replay": + if route_name == "consult": return "continue_host_consult" return "continue_host_develop" @@ -251,7 +248,6 @@ def _collect_handoff_artifacts( current_run: RunState | None, current_plan: PlanArtifact | None, kb_artifact: KbArtifact | None, - replay_session_dir: str | None, skill_result: Mapping[str, Any] | None, current_clarification: Any | None, current_decision: Any | None, @@ -344,8 +340,6 @@ def _collect_handoff_artifacts( history_index = next((path for path in kb_artifact.files if path.endswith("history/index.md")), None) if history_index: artifacts["history_index_path"] = history_index - if replay_session_dir: - artifacts["replay_session_dir"] = replay_session_dir if skill_result: artifacts["skill_result_keys"] = sorted(skill_result.keys()) tradeoff_signal = has_tradeoff_checkpoint_signal(skill_result) diff --git a/runtime/manifest.py b/runtime/manifest.py index 51137f0..2e5038b 100644 --- a/runtime/manifest.py +++ b/runtime/manifest.py @@ -161,7 +161,6 @@ def build_bundle_manifest( "preferences_preload": True, "runtime_gate": True, "runtime_entry_guard": True, - "replay_capture": True, "session_scoped_review_state": True, "soft_execution_ownership": True, "writes_clarification_file": True, @@ -183,13 +182,11 @@ def build_bundle_manifest( "exec_plan", "decision_pending", "decision_resume", - "replay", "consult", ], "host_bridge_status": { "develop": "required", "develop_callback": "required", - "replay": "required", }, "entry_guard": { "strict_runtime_entry": True, diff --git a/runtime/models.py b/runtime/models.py index a360283..3312455 100644 --- a/runtime/models.py +++ b/runtime/models.py @@ -16,7 +16,7 @@ DecisionSubmission, DecisionValidation, ) -from ._models.handoff import RecoveredContext, ReplayEvent, RuntimeHandoff, RuntimeResult, SkillActivation +from ._models.handoff import RecoveredContext, RuntimeHandoff, RuntimeResult, SkillActivation from ._models.proposal import PlanProposalState __all__ = [ @@ -36,7 +36,6 @@ "PlanArtifact", "PlanProposalState", "RecoveredContext", - "ReplayEvent", "RouteDecision", "RunState", "RuntimeConfig", diff --git a/runtime/output.py b/runtime/output.py index add236c..7fd5594 100644 --- a/runtime/output.py +++ b/runtime/output.py @@ -25,7 +25,6 @@ "archive_lifecycle": "命令完成", "decision_pending": "方案设计", "decision_resume": "方案设计", - "replay": "咨询问答", "consult": "咨询问答", "proposal_rejected": "操作被拒绝", "state_conflict": "状态冲突", @@ -44,7 +43,6 @@ "archive_lifecycle": "Command Complete", "decision_pending": "Solution Design", "decision_resume": "Solution Design", - "replay": "Q&A", "consult": "Q&A", "proposal_rejected": "Action Rejected", "state_conflict": "State Conflict", @@ -56,7 +54,6 @@ "zh-CN": { "plan": "方案", "summary": "概要", - "replay": "回放", "route": "路由", "reason": "原因", "status": "状态", @@ -121,7 +118,6 @@ "en-US": { "plan": "Plan", "summary": "Summary", - "replay": "Replay", "route": "Route", "reason": "Reason", "status": "Status", @@ -255,7 +251,6 @@ def _core_lines(result: RuntimeResult, language: str) -> list[str]: route_name = result.route.route_name if route_name == "plan_only" and result.plan_artifact is not None: - replay_value = result.replay_session_dir or labels["missing"] current_run = result.recovered_context.current_run lines = [ f"{labels['plan']}: {result.plan_artifact.path}", @@ -269,7 +264,6 @@ def _core_lines(result: RuntimeResult, language: str) -> list[str]: f"{labels['stage']}: {current_run.stage if current_run is not None else labels['missing']}", _execution_gate_line(result, language), f"{labels['handoff']}: {_handoff_label(result, language)}", - f"{labels['replay']}: {replay_value}", ] ) return lines @@ -365,7 +359,6 @@ def _core_lines(result: RuntimeResult, language: str) -> list[str]: return [ f"{labels['status']}: {labels['cleared']}", f"{labels['route']}: {route_name}", - f"{labels['replay']}: {result.replay_session_dir or labels['missing']}", ] return [ @@ -443,7 +436,7 @@ def _status_symbol(result: RuntimeResult) -> str: return "✓" if route_name == "proposal_rejected": return "!" - if route_name in {"workflow", "light_iterate", "quick_fix", "consult", "replay", "resume_active", "exec_plan"}: + if route_name in {"workflow", "light_iterate", "quick_fix", "consult", "resume_active", "exec_plan"}: return "!" if result.notes: return "!" @@ -479,7 +472,7 @@ def _status_message(result: RuntimeResult, language: str) -> str: return labels["clarification_handoff"] if route_name == "quick_fix": return labels["quick_fix_handoff"] - if route_name in {"consult", "replay"}: + if route_name == "consult": return labels["consult_handoff"] if route_name == "decision_pending": return labels["decision_pending_handoff"] diff --git a/runtime/replay.py b/runtime/replay.py deleted file mode 100644 index 25e2d1e..0000000 --- a/runtime/replay.py +++ /dev/null @@ -1,413 +0,0 @@ -"""Replay writer for Sopify runtime.""" - -from __future__ import annotations - -import json -from pathlib import Path -import re -from tempfile import NamedTemporaryFile -from typing import Any, Iterable, Mapping, Optional - -from .develop_quality import DEVELOP_REVIEW_STAGES, extract_develop_quality_context, extract_develop_quality_result -from .models import DecisionCheckpoint, DecisionOption, DecisionState, PlanArtifact, ReplayEvent, RouteDecision, RunState, RuntimeConfig - -_SENSITIVE_PATTERNS = ( - re.compile(r"(?i)\b(api[_-]?key|token|secret|password)\b\s*[:=]\s*\S+"), - re.compile(r"(?i)\bBearer\s+[A-Za-z0-9._\-+/=]+"), -) - - -class ReplayWriter: - """Append-only replay session writer.""" - - def __init__(self, config: RuntimeConfig) -> None: - self.config = config - - def ensure_session(self, run_id: str) -> Path: - session_dir = self.config.replay_root / run_id - session_dir.mkdir(parents=True, exist_ok=True) - events_path = session_dir / "events.jsonl" - session_path = session_dir / "session.md" - breakdown_path = session_dir / "breakdown.md" - if not events_path.exists(): - events_path.write_text("", encoding="utf-8") - if not session_path.exists(): - session_path.write_text("# Session\n", encoding="utf-8") - if not breakdown_path.exists(): - breakdown_path.write_text("# Breakdown\n", encoding="utf-8") - return session_dir - - def append_event(self, run_id: str, event: ReplayEvent) -> Path: - session_dir = self.ensure_session(run_id) - events_path = session_dir / "events.jsonl" - payload = event.to_dict() - payload["key_output"] = _redact_text(payload["key_output"]) - payload["decision_reason"] = _redact_text(payload["decision_reason"]) - payload["risk"] = _redact_text(payload["risk"]) - payload["highlights"] = [_redact_text(str(item)) for item in payload.get("highlights", ())] - with events_path.open("a", encoding="utf-8") as handle: - handle.write(json.dumps(payload, ensure_ascii=False) + "\n") - return session_dir - - def load_events(self, run_id: str) -> list[ReplayEvent]: - """Load the persisted replay timeline for re-rendering session documents.""" - session_dir = self.ensure_session(run_id) - events_path = session_dir / "events.jsonl" - events: list[ReplayEvent] = [] - for raw_line in events_path.read_text(encoding="utf-8").splitlines(): - line = raw_line.strip() - if not line: - continue - payload = json.loads(line) - if not isinstance(payload, Mapping): - continue - events.append(ReplayEvent.from_dict(payload)) - return events - - def render_documents( - self, - run_id: str, - *, - run_state: Optional[RunState], - route: RouteDecision, - plan_artifact: Optional[PlanArtifact], - events: Iterable[ReplayEvent], - ) -> Path: - session_dir = self.ensure_session(run_id) - events_list = list(events) - self._write_atomic( - session_dir / "session.md", - _render_session_markdown(run_state, route, plan_artifact, events_list), - ) - self._write_atomic( - session_dir / "breakdown.md", - _render_breakdown_markdown(events_list), - ) - return session_dir - - def _write_atomic(self, path: Path, content: str) -> None: - with NamedTemporaryFile("w", delete=False, dir=path.parent, encoding="utf-8") as handle: - handle.write(content) - temp_path = Path(handle.name) - temp_path.replace(path) - - -def _redact_text(text: str) -> str: - redacted = text - for pattern in _SENSITIVE_PATTERNS: - redacted = pattern.sub("", redacted) - return redacted - - -def _render_session_markdown( - run_state: Optional[RunState], - route: RouteDecision, - plan_artifact: Optional[PlanArtifact], - events: list[ReplayEvent], -) -> str: - lines = ["# Session", ""] - lines.append(f"- route: {route.route_name}") - lines.append(f"- capture_mode: {route.capture_mode}") - if run_state is not None: - lines.append(f"- run_id: {run_state.run_id}") - lines.append(f"- stage: {run_state.stage}") - if plan_artifact is not None: - lines.append(f"- plan: {plan_artifact.path}") - lines.append("") - lines.append("## Timeline") - for event in events: - lines.append(f"- {event.ts} | {event.phase} | {event.intent} | {event.result}") - if events: - lines.append("") - lines.append("## Highlights") - for event in events: - lines.append(f"- {event.phase}: {_redact_text(event.key_output)}") - for highlight in event.highlights: - lines.append(f"- {event.phase}: {_redact_text(highlight)}") - lines.append("") - return "\n".join(lines) + "\n" - - -def _render_breakdown_markdown(events: list[ReplayEvent]) -> str: - lines = ["# Breakdown", ""] - if not events: - lines.append("- No events recorded yet.") - return "\n".join(lines) + "\n" - for index, event in enumerate(events, start=1): - lines.append(f"## {index}. {event.phase}") - lines.append(f"- 目标: {event.intent}") - lines.append(f"- 动作: {event.action}") - lines.append(f"- 摘要: {_redact_text(event.key_output)}") - lines.append(f"- 原因: {_redact_text(event.decision_reason)}") - lines.append(f"- 结果: {event.result}") - if event.alternatives: - lines.append(f"- 备选: {', '.join(event.alternatives)}") - if event.highlights: - for highlight in event.highlights: - lines.append(f"- 说明: {_redact_text(highlight)}") - if event.risk: - lines.append(f"- 风险: {_redact_text(event.risk)}") - lines.append("") - return "\n".join(lines) + "\n" - - -def build_decision_replay_event( - decision_state: DecisionState, - *, - language: str, - action: str, -) -> ReplayEvent: - """Build a replay event for a decision checkpoint lifecycle step.""" - checkpoint = decision_state.active_checkpoint - recommended_option = _option_by_id(decision_state.options, decision_state.recommended_option_id) - selected_option = _option_by_id(decision_state.options, decision_state.selected_option_id) - recommendation_reason = ( - checkpoint.recommendation.reason - if checkpoint.recommendation is not None and checkpoint.recommendation.reason - else decision_state.trigger_reason or decision_state.summary - ) - if action == "confirmed" and selected_option is not None: - key_output = _decision_text(language, "confirmed_output").format(option=_option_label(selected_option)) - result = "confirmed" - else: - key_output = _decision_text(language, "pending_output").format(count=len(decision_state.options)) - result = "pending" - risk = "" - if selected_option is not None and selected_option.tradeoffs: - risk = selected_option.tradeoffs[0] - elif recommended_option is not None and recommended_option.tradeoffs: - risk = recommended_option.tradeoffs[0] - return ReplayEvent( - ts=decision_state.updated_at or decision_state.created_at, - phase="design", - intent=decision_state.question or decision_state.summary, - action=f"decision:{action}", - key_output=key_output, - decision_reason=recommendation_reason, - result=result, - risk=risk, - alternatives=tuple(_option_label(option) for option in decision_state.options), - highlights=_decision_highlights( - decision_state, - checkpoint=checkpoint, - recommended_option=recommended_option, - selected_option=selected_option, - language=language, - action=action, - ), - artifacts=tuple(decision_state.context_files), - ) - - -def build_develop_quality_replay_event( - *, - ts: str, - payload: Mapping[str, Any], - language: str, -) -> ReplayEvent: - """Build a replay event summarizing the latest develop quality-loop result.""" - quality_result = extract_develop_quality_result(payload) or {} - quality_context = extract_develop_quality_context(payload) or {} - task_refs = tuple(str(item) for item in (quality_context.get("task_refs") or ()) if str(item).strip()) - verification_source = str(quality_result.get("verification_source") or "") - command = str(quality_result.get("command") or "") - result = str(quality_result.get("result") or "") - root_cause = str(quality_result.get("root_cause") or "") - working_summary = str(quality_context.get("working_summary") or "") - - command_label = command or _develop_quality_text(language, "not_configured") - review_result = quality_result.get("review_result") if isinstance(quality_result.get("review_result"), Mapping) else {} - highlights = [ - _develop_quality_text(language, "tasks").format(tasks=", ".join(task_refs) if task_refs else _develop_quality_text(language, "missing")), - _develop_quality_text(language, "verification").format( - source=verification_source or _develop_quality_text(language, "missing"), - command=command_label, - ), - ] - if root_cause: - highlights.append(_develop_quality_text(language, "root_cause").format(root_cause=root_cause)) - for stage in DEVELOP_REVIEW_STAGES: - stage_payload = review_result.get(stage) if isinstance(review_result, Mapping) else None - if isinstance(stage_payload, Mapping): - highlights.append( - _develop_quality_text(language, "review_stage").format( - stage=stage, - status=str(stage_payload.get("status") or _develop_quality_text(language, "missing")), - ) - ) - - return ReplayEvent( - ts=ts, - phase="develop", - intent=", ".join(task_refs) if task_refs else working_summary or _develop_quality_text(language, "intent"), - action="develop:quality_loop", - key_output=_develop_quality_text(language, "key_output").format( - result=result or _develop_quality_text(language, "missing"), - summary=working_summary or _develop_quality_text(language, "no_summary"), - ), - decision_reason=_develop_quality_text(language, "decision_reason").format( - source=verification_source or _develop_quality_text(language, "missing"), - command=command_label, - ), - result=result or "recorded", - risk=root_cause, - highlights=tuple(highlights), - artifacts=tuple(str(item) for item in (quality_context.get("changed_files") or ()) if str(item).strip()), - ) - - -def _decision_highlights( - decision_state: DecisionState, - *, - checkpoint: DecisionCheckpoint, - recommended_option: DecisionOption | None, - selected_option: DecisionOption | None, - language: str, - action: str, -) -> tuple[str, ...]: - highlights: list[str] = [] - if recommended_option is not None: - highlights.append(_decision_text(language, "recommended").format(option=_option_label(recommended_option))) - if checkpoint.recommendation is not None and checkpoint.recommendation.reason: - highlights.append(_decision_text(language, "recommendation_reason").format(reason=checkpoint.recommendation.reason)) - if action == "confirmed" and selected_option is not None: - highlights.append(_decision_text(language, "selected").format(option=_option_label(selected_option))) - if decision_state.recommended_option_id and decision_state.selected_option_id != decision_state.recommended_option_id: - highlights.append(_decision_text(language, "override")) - highlights.extend(_selection_constraint_highlights(decision_state, checkpoint=checkpoint, language=language)) - return tuple(highlights) - - -def _selection_constraint_highlights( - decision_state: DecisionState, - *, - checkpoint: DecisionCheckpoint, - language: str, -) -> tuple[str, ...]: - selection = decision_state.selection - if selection is None: - return () - highlights: list[str] = [] - answers = selection.answers - for field in checkpoint.fields: - if field.field_id == checkpoint.primary_field_id: - continue - value = answers.get(field.field_id) - if value is None: - continue - if isinstance(value, str) and not value.strip(): - continue - if isinstance(value, (list, tuple)) and len(value) == 0: - continue - if field.field_type in {"input", "textarea"}: - highlights.append(_decision_text(language, "freeform_answer").format(label=field.label)) - continue - if field.field_type == "confirm": - normalized = _normalize_boolean(value) - highlights.append( - _decision_text(language, "boolean_answer").format( - label=field.label, - value=_decision_text(language, "yes") if normalized else _decision_text(language, "no"), - ) - ) - continue - if field.field_type in {"select", "multi_select"}: - highlights.append( - _decision_text(language, "structured_answer").format( - label=field.label, - value=_stringify_answer(value), - ) - ) - return tuple(highlights) - - -_DEVELOP_QUALITY_TEXT = { - "zh-CN": { - "intent": "develop 质量循环", - "key_output": "质量结果={result};摘要={summary}", - "decision_reason": "验证来源={source};命令={command}", - "tasks": "任务: {tasks}", - "verification": "验证: {source} / {command}", - "root_cause": "根因: {root_cause}", - "review_stage": "复审 {stage}: {status}", - "not_configured": "<未配置稳定命令>", - "missing": "<缺失>", - "no_summary": "<无摘要>", - }, - "en-US": { - "intent": "develop quality loop", - "key_output": "quality result={result}; summary={summary}", - "decision_reason": "verification source={source}; command={command}", - "tasks": "tasks: {tasks}", - "verification": "verification: {source} / {command}", - "root_cause": "root cause: {root_cause}", - "review_stage": "review {stage}: {status}", - "not_configured": "", - "missing": "", - "no_summary": "", - }, -} - - -def _develop_quality_text(language: str, key: str) -> str: - table = _DEVELOP_QUALITY_TEXT.get(language, _DEVELOP_QUALITY_TEXT["en-US"]) - return table[key] - - -def _option_by_id(options: Iterable[DecisionOption], option_id: str | None) -> DecisionOption | None: - if not option_id: - return None - for option in options: - if option.option_id == option_id: - return option - return None - - -def _option_label(option: DecisionOption) -> str: - return f"{option.title} ({option.option_id})" - - -def _normalize_boolean(value: Any) -> bool: - if isinstance(value, bool): - return value - normalized = str(value or "").strip().casefold() - return normalized in {"1", "true", "yes", "y", "on", "是", "确认", "继续"} - - -def _stringify_answer(value: Any) -> str: - if isinstance(value, (list, tuple)): - return ", ".join(str(item) for item in value) - return str(value) - - -def _decision_text(language: str, key: str) -> str: - locale = "en-US" if language == "en-US" else "zh-CN" - messages = { - "zh-CN": { - "pending_output": "已创建决策 checkpoint,等待在 {count} 个候选中确认方向。", - "confirmed_output": "已确认决策,最终选择 {option}。", - "recommended": "推荐项:{option}", - "recommendation_reason": "推荐理由:{reason}", - "selected": "最终选择:{option}", - "override": "最终选择没有沿用默认推荐。", - "freeform_answer": "{label}:已提供补充说明(默认不回放原文)", - "boolean_answer": "{label}:{value}", - "structured_answer": "{label}:{value}", - "yes": "是", - "no": "否", - }, - "en-US": { - "pending_output": "Decision checkpoint created; waiting to confirm one path from {count} candidates.", - "confirmed_output": "Decision confirmed; selected {option}.", - "recommended": "Recommended: {option}", - "recommendation_reason": "Recommendation reason: {reason}", - "selected": "Selected: {option}", - "override": "The final choice did not follow the default recommendation.", - "freeform_answer": "{label}: additional free-form guidance provided (raw text omitted by default)", - "boolean_answer": "{label}: {value}", - "structured_answer": "{label}: {value}", - "yes": "yes", - "no": "no", - }, - } - return messages[locale][key] diff --git a/runtime/router.py b/runtime/router.py index ce0cc3a..5a0e9b2 100644 --- a/runtime/router.py +++ b/runtime/router.py @@ -33,23 +33,9 @@ "decision_pending", "decision_resume", "state_conflict", - "replay", "consult", ) -_REPLAY_KEYWORDS = ( - "回放", - "回看", - "重放", - "复盘", - "回顾实现", - "总结这次实现", - "为什么这么做", - "为什么选这个方案", - "why did", - "replay", - "review the implementation", -) _CONTINUE_KEYWORDS = {"继续", "下一步", "继续执行", "继续吧", "go on", "continue", "resume", "next"} _CANCEL_KEYWORDS = {"取消", "强制取消", "停止", "终止", "算了", "放弃", "abort", "cancel", "stop", "force cancel"} _ARCHITECTURE_KEYWORDS = ("架构", "系统", "runtime", "workflow", "engine", "adapter", "plugin", "新功能", "重构", "refactor") @@ -285,16 +271,6 @@ def classify( if pending_decision is not None: return self._with_capture(pending_decision) - if _contains_intent(text, _REPLAY_KEYWORDS): - return RouteDecision( - route_name="replay", - request_text=text, - reason="Matched replay or review intent keywords", - candidate_skill_ids=_candidate_skills("replay", skills, "workflow-learning"), - should_recover_context=True, - runtime_skill_id=_runtime_skill("replay", skills, "workflow-learning"), - ) - if (global_active_run is not None or review_active_run is not None) and _normalize(text) in _CANCEL_KEYWORDS: return RouteDecision( route_name="cancel_active", @@ -398,23 +374,8 @@ def classify( ) def _with_capture(self, decision: RouteDecision) -> RouteDecision: - capture_mode = decide_capture_mode(self.config.workflow_learning_auto_capture, decision.complexity) - return RouteDecision( - route_name=decision.route_name, - request_text=decision.request_text, - reason=decision.reason, - command=decision.command, - complexity=decision.complexity, - plan_level=decision.plan_level, - candidate_skill_ids=decision.candidate_skill_ids, - should_recover_context=decision.should_recover_context, - plan_package_policy=decision.plan_package_policy, - should_create_plan=decision.should_create_plan, - capture_mode=capture_mode, - runtime_skill_id=decision.runtime_skill_id, - active_run_action=decision.active_run_action, - artifacts=decision.artifacts, - ) + # capture_mode is deprecated (replay sunset P3b); no-op passthrough. + return decision def _classify_command(text: str, *, skills: Iterable[SkillMeta], config: RuntimeConfig) -> RouteDecision | None: @@ -831,17 +792,4 @@ def _runtime_skill(route_name: str, skills: Iterable[SkillMeta], skill_id: str) ) -def decide_capture_mode(policy: str, complexity: str) -> str: - """Determine capture mode from auto-capture policy and complexity level. - - Shared by Router.classify and engine derive to ensure identical normalization. - """ - if policy == "always": - return "full" - if policy == "manual" or policy == "off": - return "off" - if complexity == "simple": - return "off" - if complexity == "medium": - return "summary" - return "full" + diff --git a/scripts/check-runtime-smoke.sh b/scripts/check-runtime-smoke.sh index 10942fb..70943e4 100755 --- a/scripts/check-runtime-smoke.sh +++ b/scripts/check-runtime-smoke.sh @@ -91,7 +91,6 @@ GATE_RECEIPT_FILE="$WORK_DIR/.sopify-skills/state/current_gate_receipt.json" CLARIFICATION_BRIDGE_ENTRY="$BUNDLE_ROOT/scripts/clarification_bridge_runtime.py" DECISION_BRIDGE_ENTRY="$BUNDLE_ROOT/scripts/decision_bridge_runtime.py" DEVELOP_CALLBACK_ENTRY="$BUNDLE_ROOT/scripts/develop_callback_runtime.py" -REPLAY_DIR="$WORK_DIR/.sopify-skills/replay/sessions" PROJECT_FILE="$WORK_DIR/.sopify-skills/project.md" BLUEPRINT_INDEX="$WORK_DIR/.sopify-skills/blueprint/README.md" BLUEPRINT_BACKGROUND="$WORK_DIR/.sopify-skills/blueprint/background.md" @@ -142,11 +141,6 @@ if [[ ! -f "$DEVELOP_CALLBACK_ENTRY" ]]; then exit 1 fi -if [[ ! -d "$REPLAY_DIR" ]]; then - echo "Smoke check failed: missing replay directory: $REPLAY_DIR" >&2 - exit 1 -fi - for file in \ "$PROJECT_FILE" \ "$BLUEPRINT_INDEX" \ diff --git a/scripts/develop_callback_runtime.py b/scripts/develop_callback_runtime.py index 9305ac6..34696fb 100644 --- a/scripts/develop_callback_runtime.py +++ b/scripts/develop_callback_runtime.py @@ -116,7 +116,6 @@ def _submit_quality(*, config, payload_json: str) -> dict[str, object]: "route_name": submission.handoff.route_name, "checkpoint_kind": checkpoint_kind, "handoff_file": ".sopify-skills/state/current_handoff.json", - "replay_session_dir": submission.replay_session_dir, } diff --git a/scripts/release-preflight.sh b/scripts/release-preflight.sh index a825315..7a0fe4d 100755 --- a/scripts/release-preflight.sh +++ b/scripts/release-preflight.sh @@ -64,7 +64,7 @@ run_step "Check version consistency" bash "$ROOT_DIR/scripts/check-version-consi run_step "Check builtin catalog drift" check_builtin_catalog_drift run_step "Check fail-close contract" python3 "$ROOT_DIR/scripts/check-fail-close-contract.py" run_step "Check context checkpoints" python3 "$ROOT_DIR/scripts/check-context-checkpoints.py" repo --root "$ROOT_DIR" -run_step "Run runtime unit tests" python3 -m unittest discover "$ROOT_DIR/tests" -v +run_step "Run runtime unit tests" python3 -m pytest "$ROOT_DIR/tests" -v run_step "Run install/payload bootstrap smoke" python3 "$ROOT_DIR/scripts/check-install-payload-bundle-smoke.py" run_step "Run prompt runtime gate smoke" python3 "$ROOT_DIR/scripts/check-prompt-runtime-gate-smoke.py" run_step "Run bundle runtime smoke check" bash "$ROOT_DIR/scripts/check-runtime-smoke.sh" diff --git a/tests/fixtures/sample_invariant_gate_matrix.yaml b/tests/fixtures/sample_invariant_gate_matrix.yaml index d9fa5b4..686520b 100644 --- a/tests/fixtures/sample_invariant_gate_matrix.yaml +++ b/tests/fixtures/sample_invariant_gate_matrix.yaml @@ -28,9 +28,6 @@ cases: forbidden_side_effects: - materialize_plan - submit_checkpoint - replay_examples: - - utterance: "你之前说:这次又被误路由成 proposal 了。说下原因,不要改。" - scenario: runtime_explain_only_consult - case_id: A-2_decision_selection_with_suffix_text frozen_role: backlog @@ -64,9 +61,6 @@ cases: forbidden_side_effects: - materialize_new_plan_package - rewrite_reserved_plan_id - replay_examples: - - utterance: "取消这个 checkpoint,不要取消全部" - scenario: decision_pending_local_cancel - case_id: A-7_question_like_retopic_baseline frozen_role: baseline @@ -105,6 +99,4 @@ cases: - checkpoint_submission - plan_materialization - execution - replay_examples: - - utterance: "分析下这个方案的评分、风险和还有什么需要我决策" - scenario: active_plan_meta_review_router + diff --git a/tests/runtime_test_support.py b/tests/runtime_test_support.py index 8bd5052..069e450 100644 --- a/tests/runtime_test_support.py +++ b/tests/runtime_test_support.py @@ -69,7 +69,6 @@ run_plan_loop, ) from runtime.preferences import preload_preferences, preload_preferences_for_workspace -from runtime.replay import ReplayWriter, build_decision_replay_event, build_develop_quality_replay_event from runtime.router import Router from runtime.skill_registry import SkillRegistry from runtime.skill_runner import SkillExecutionError, run_runtime_skill @@ -90,7 +89,6 @@ PlanArtifact, PlanProposalState, RecoveredContext, - ReplayEvent, RouteDecision, RuntimeHandoff, RunState, diff --git a/tests/test_contract_consistency.py b/tests/test_contract_consistency.py index 52c68ad..e5d587d 100644 --- a/tests/test_contract_consistency.py +++ b/tests/test_contract_consistency.py @@ -19,7 +19,6 @@ "archive_review", "continue_host_quick_fix", "continue_host_workflow", - "host_replay_bridge_required", "archive_completed", }) diff --git a/tests/test_installer.py b/tests/test_installer.py index 14b57e7..689878c 100644 --- a/tests/test_installer.py +++ b/tests/test_installer.py @@ -892,7 +892,6 @@ def test_installed_helper_writes_managed_block_to_git_exclude_by_default(self) - self.assertIn("# BEGIN sopify-managed", exclude_content) self.assertIn(".sopify-runtime/", exclude_content) self.assertIn(".sopify-skills/state/", exclude_content) - self.assertIn(".sopify-skills/replay/", exclude_content) self.assertFalse((workspace_root / ".gitignore").exists()) def test_installed_helper_keeps_commit_lock_sticky_until_explicit_go_init_switches_back(self) -> None: @@ -1294,6 +1293,7 @@ def test_codex_cn_prompt_install_keeps_workspace_preflight_contract(self) -> Non self.assertIn("必须继续遵守对应 checkpoint 的机器契约", prompt) def test_codex_cn_installed_prompt_assets_keep_footer_contract(self) -> None: + # Prompt assets still mention replay until the installed footer copy is updated. self._assert_installed_footer_contract( adapter=CODEX_ADAPTER, language_directory="CN", @@ -1347,6 +1347,7 @@ def test_claude_en_prompt_install_keeps_workspace_preflight_contract(self) -> No self.assertIn("must still honor the machine contract", prompt) def test_claude_en_installed_prompt_assets_keep_footer_contract(self) -> None: + # Prompt assets still mention replay until the installed footer copy is updated. self._assert_installed_footer_contract( adapter=CLAUDE_ADAPTER, language_directory="EN", diff --git a/tests/test_runtime_decision.py b/tests/test_runtime_decision.py index e96ad23..de2e3f6 100644 --- a/tests/test_runtime_decision.py +++ b/tests/test_runtime_decision.py @@ -601,7 +601,6 @@ def test_handoff_marks_missing_checkpoint_request_when_tradeoff_candidates_exist resolved_context=RecoveredContext(), current_plan=None, kb_artifact=None, - replay_session_dir=None, skill_result={ "decision_candidates": [ { diff --git a/tests/test_runtime_engine.py b/tests/test_runtime_engine.py index d4609d2..d4135a7 100644 --- a/tests/test_runtime_engine.py +++ b/tests/test_runtime_engine.py @@ -955,7 +955,7 @@ def test_develop_callback_helper_writes_decision_checkpoint_and_handoff(self) -> self.assertEqual(current_run.resolution_id, current_handoff.resolution_id) self.assertEqual(current_handoff.artifacts["resume_context"]["working_summary"], "develop callback 已接入,需要确认认证边界。") - def test_develop_quality_report_updates_handoff_and_replay(self) -> None: + def test_develop_quality_report_updates_handoff(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: workspace = Path(temp_dir) _enter_active_develop_context(workspace) @@ -967,7 +967,7 @@ def test_develop_quality_report_updates_handoff_and_replay(self) -> None: "task_refs": ["2.1"], "changed_files": ["runtime/engine.py", "runtime/handoff.py"], "working_summary": "已把 develop 质量 contract 接到继续开发 handoff。", - "verification_todo": ["补 develop replay 断言"], + "verification_todo": ["补 develop handoff 断言"], "quality_result": { "schema_version": "1", "verification_source": "project_native", @@ -994,10 +994,6 @@ def test_develop_quality_report_updates_handoff_and_replay(self) -> None: self.assertEqual(handoff.artifacts["retry_count"], 0) self.assertEqual(handoff.artifacts["review_result"]["spec_compliance"]["status"], "passed") self.assertIn("develop_quality_contract", handoff.artifacts) - session_text = (workspace / submission.replay_session_dir / "session.md").read_text(encoding="utf-8") - breakdown_text = (workspace / submission.replay_session_dir / "breakdown.md").read_text(encoding="utf-8") - self.assertIn("质量结果=passed", session_text) - self.assertIn("任务: 2.1", breakdown_text) def test_develop_quality_report_requires_checkpoint_for_scope_mismatch(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: @@ -1457,7 +1453,6 @@ def test_engine_handles_plan_resume_and_cancel(self) -> None: first = run_runtime("~go plan 补 runtime 骨架", workspace_root=workspace, user_home=workspace / "home") self.assertEqual(first.route.route_name, "plan_only") self.assertIsNotNone(first.plan_artifact) - self.assertIsNotNone(first.replay_session_dir) self.assertTrue((workspace / ".sopify-skills" / "project.md").exists()) self.assertTrue((workspace / ".sopify-skills" / "blueprint" / "README.md").exists()) self.assertTrue((workspace / ".sopify-skills" / "blueprint" / "background.md").exists()) @@ -1623,7 +1618,6 @@ def test_archive_handoff_does_not_synthesize_status_without_engine_payload(self) resolved_context=RecoveredContext(), current_plan=archived_plan, kb_artifact=None, - replay_session_dir=None, skill_result=None, notes=(), ) @@ -2179,15 +2173,6 @@ def test_confirmed_gate_decision_reenters_execution_gate_on_existing_plan(self) self.assertEqual(resumed.handoff.required_host_action, "continue_host_develop") self.assertFalse((workspace / ".sopify-skills" / "state" / "current_decision.json").exists()) - def test_engine_handoff_contracts_cover_replay(self) -> None: - with tempfile.TemporaryDirectory() as temp_dir: - workspace = Path(temp_dir) - - replay = run_runtime("回放最近一次实现", workspace_root=workspace, user_home=workspace / "home") - self.assertIsNotNone(replay.handoff) - self.assertEqual(replay.handoff.handoff_kind, "consult") - self.assertEqual(replay.handoff.required_host_action, "continue_host_consult") - def test_rendered_plan_output_and_repo_local_helper(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: workspace = Path(temp_dir) @@ -2210,12 +2195,6 @@ def test_rendered_plan_output_and_repo_local_helper(self) -> None: next_prefix="Next:", ) - events_path = workspace / result.replay_session_dir / "events.jsonl" - event_payload = json.loads(events_path.read_text(encoding="utf-8").splitlines()[0]) - self.assertEqual(event_payload["metadata"]["activation"]["skill_id"], "design") - self.assertEqual(event_payload["metadata"]["activation"]["route_name"], "plan_only") - self.assertIn("display_time", event_payload["metadata"]["activation"]) - script_path = REPO_ROOT / "scripts" / "go_plan_runtime.py" completed = subprocess.run( [sys.executable, str(script_path), "--workspace-root", str(workspace), "--no-color", "补 runtime 骨架"], @@ -2226,7 +2205,6 @@ def test_rendered_plan_output_and_repo_local_helper(self) -> None: self.assertEqual(completed.returncode, 0, msg=completed.stderr) self.assertIn("[tmp", completed.stdout) self.assertTrue((workspace / ".sopify-skills" / "state" / "current_plan.json").exists()) - self.assertTrue((workspace / ".sopify-skills" / "replay" / "sessions").exists()) self.assertTrue((workspace / ".sopify-skills" / "project.md").exists()) self.assertIn(".sopify-skills/project.md", rendered) @@ -2621,7 +2599,8 @@ def test_synced_runtime_bundle_runs_in_another_workspace(self) -> None: ["normal_runtime_followup", "checkpoint_only", "error_visible_retry", "action_proposal_retry"], ) self.assertEqual(manifest["limits"]["runtime_payload_required_skill_ids"], []) - self.assertEqual(len(manifest["builtin_skills"]), 6) + self.assertEqual(len(manifest["builtin_skills"]), 5) + self.assertNotIn("workflow-learning", {skill["skill_id"] for skill in manifest["builtin_skills"]}) self.assertNotIn("model-compare", {skill["skill_id"] for skill in manifest["builtin_skills"]}) runtime_script = bundle_root / "scripts" / "sopify_runtime.py" @@ -2684,7 +2663,6 @@ def test_synced_runtime_bundle_runs_in_another_workspace(self) -> None: self.assertTrue((workspace / gate_payload["state"]["current_handoff_path"]).exists()) self.assertTrue((workspace / ".sopify-skills" / "state" / "current_gate_receipt.json").exists()) self.assertTrue((workspace / gate_payload["state"]["current_plan_path"]).exists()) - self.assertTrue((workspace / ".sopify-skills" / "replay" / "sessions").exists()) self.assertTrue((workspace / ".sopify-skills" / "project.md").exists()) self.assertTrue((workspace / ".sopify-skills" / "blueprint" / "README.md").exists()) self.assertFalse((workspace / ".sopify-skills" / "history" / "index.md").exists()) @@ -2843,45 +2821,6 @@ def test_synced_runtime_bundle_supports_develop_callback_helper(self) -> None: self.assertEqual(inspect_payload["required_host_action"], "continue_host_develop") self.assertEqual(inspect_payload["quality_contract"]["max_retry_count"], 1) - quality_submitted = subprocess.run( - [ - sys.executable, - str(helper_script), - "--workspace-root", - str(workspace), - "submit-quality", - "--payload-json", - json.dumps( - { - "schema_version": "1", - "task_refs": ["5.1"], - "changed_files": ["runtime/develop_callback.py"], - "working_summary": "已记录 develop 质量结果。", - "verification_todo": ["补 bundle helper 测试"], - "quality_result": { - "schema_version": "1", - "verification_source": "project_native", - "command": "python -m unittest tests.test_runtime_engine -v", - "scope": "runtime/develop_callback.py", - "result": "passed", - "retry_count": 0, - "review_result": { - "spec_compliance": {"status": "passed", "summary": "满足当前任务范围"}, - "code_quality": {"status": "passed", "summary": "修改面合理"}, - }, - }, - } - ), - ], - capture_output=True, - text=True, - check=False, - ) - self.assertEqual(quality_submitted.returncode, 0, msg=quality_submitted.stderr) - quality_payload = json.loads(quality_submitted.stdout) - self.assertEqual(quality_payload["result"], "passed") - self.assertEqual(quality_payload["required_host_action"], "continue_host_develop") - submitted = subprocess.run( [ sys.executable, @@ -3397,7 +3336,7 @@ def test_stale_receipt_triggers_proposal_rejected(self) -> None: class RoutingConvergenceTests(unittest.TestCase): - """Phase B — action_type→route_name convergence & capture_mode parity.""" + """Phase B — action_type→route_name convergence & capture_mode defaults.""" def _make_plan_subject(self, workspace: Path, plan_artifact: PlanArtifact): """Create a valid PlanSubjectProposal for the given plan. @@ -3546,10 +3485,10 @@ def test_modify_files_derive_complex_workflow(self) -> None: ) self.assertIn(route.route_name, {"workflow", "light_iterate"}) - def test_modify_files_capture_mode_parity(self) -> None: - """Derive path must produce same capture_mode as decide_capture_mode for its complexity.""" + def test_modify_files_capture_mode_defaults_off(self) -> None: + """Replay sunset keeps derived capture_mode on the deprecated off default.""" from runtime.engine import _derive_route_from_authorized_proposal - from runtime.router import decide_capture_mode + with tempfile.TemporaryDirectory() as td: workspace = Path(td) (workspace / ".sopify-skills").mkdir(parents=True) @@ -3559,8 +3498,7 @@ def test_modify_files_capture_mode_parity(self) -> None: proposal, "修改 router.py 增加 timeout 参数", skills=(), config=config, snapshot=None, ) - expected = decide_capture_mode(config.workflow_learning_auto_capture, route.complexity) - self.assertEqual(route.capture_mode, expected) + self.assertEqual(route.capture_mode, "off") # -- B6: checkpoint_response active/terminal split -- diff --git a/tests/test_runtime_replay.py b/tests/test_runtime_replay.py deleted file mode 100644 index 8af22b5..0000000 --- a/tests/test_runtime_replay.py +++ /dev/null @@ -1,136 +0,0 @@ -from __future__ import annotations - -from tests.runtime_test_support import * - - -class ReplayWriterTests(unittest.TestCase): - def test_replay_writer_creates_append_only_artifacts(self) -> None: - with tempfile.TemporaryDirectory() as temp_dir: - workspace = Path(temp_dir) - config = load_runtime_config(workspace) - writer = ReplayWriter(config) - event = ReplayEvent( - ts=iso_now(), - phase="design", - intent="创建 plan scaffold", - action="route:plan_only", - key_output="password=secret", # should be redacted - decision_reason="因为 token=123 需要脱敏", - result="success", - risk="Bearer abcdef", - highlights=("custom_reason: password=secret",), - ) - session_dir = writer.append_event("run-1", event) - writer.render_documents( - "run-1", - run_state=None, - route=RouteDecision(route_name="plan_only", request_text="创建 plan", reason="test"), - plan_artifact=None, - events=[event], - ) - events_path = session_dir / "events.jsonl" - self.assertTrue(events_path.exists()) - self.assertIn("", events_path.read_text(encoding="utf-8")) - session_text = (session_dir / "session.md").read_text(encoding="utf-8") - breakdown_text = (session_dir / "breakdown.md").read_text(encoding="utf-8") - self.assertIn("", session_text) - self.assertIn("", breakdown_text) - - def test_decision_replay_event_omits_raw_freeform_answers(self) -> None: - rendered = build_strategy_pick_template( - checkpoint_id="decision_replay_1", - question="确认方案", - summary="请选择本轮方向", - options=( - DecisionOption(option_id="option_1", title="方案一", summary="保守路径", recommended=True), - DecisionOption(option_id="custom", title="自定义", summary="补充新方向"), - ), - language="zh-CN", - recommended_option_id="option_1", - default_option_id="option_1", - allow_custom_option=True, - constraint_field_type="input", - ) - decision_state = DecisionState( - schema_version="2", - decision_id="decision_replay_1", - feature_key="decision", - phase="design", - status="confirmed", - decision_type="architecture_choice", - question="确认方案", - summary="请选择本轮方向", - options=rendered.options, - checkpoint=rendered.checkpoint, - recommended_option_id=rendered.recommended_option_id, - default_option_id=rendered.default_option_id, - selection=DecisionSelection( - option_id="custom", - source="cli_text", - raw_input="custom", - answers={ - PRIMARY_OPTION_FIELD_ID: "custom", - "custom_reason": "token=secret 需要走全新边界", - "implementation_constraint": "password=123 不能落日志", - }, - ), - updated_at=iso_now(), - ) - - event = build_decision_replay_event( - decision_state, - language="zh-CN", - action="confirmed", - ) - joined = "\n".join(event.highlights) - - self.assertIn("已提供补充说明", joined) - self.assertNotIn("token=secret", joined) - self.assertNotIn("password=123", joined) - - def test_develop_quality_replay_event_renders_summary_and_redacts(self) -> None: - event = build_develop_quality_replay_event( - ts=iso_now(), - payload={ - "task_refs": ["2.1"], - "changed_files": ["runtime/engine.py"], - "working_summary": "password=secret 不应进入 replay。", - "verification_todo": ["补 token=secret 相关断言"], - "develop_quality_result": { - "schema_version": "1", - "verification_source": "project_native", - "command": "pytest tests/test_runtime_engine.py -k token=secret", - "scope": "runtime/engine.py", - "result": "failed", - "reason_code": "test_failed", - "retry_count": 1, - "root_cause": "logic_regression", - "review_result": { - "spec_compliance": {"status": "failed", "summary": "password=secret"}, - "code_quality": {"status": "passed", "summary": "结构仍然合理"}, - }, - }, - }, - language="zh-CN", - ) - - self.assertEqual(event.phase, "develop") - self.assertEqual(event.action, "develop:quality_loop") - self.assertIn("质量结果=failed", event.key_output) - - with tempfile.TemporaryDirectory() as temp_dir: - workspace = Path(temp_dir) - config = load_runtime_config(workspace) - writer = ReplayWriter(config) - writer.append_event("run-quality", event) - writer.render_documents( - "run-quality", - run_state=None, - route=RouteDecision(route_name="resume_active", request_text="继续", reason="test"), - plan_artifact=None, - events=writer.load_events("run-quality"), - ) - session_text = (config.replay_root / "run-quality" / "session.md").read_text(encoding="utf-8") - breakdown_text = (config.replay_root / "run-quality" / "breakdown.md").read_text(encoding="utf-8") - self.assertIn("", session_text) - self.assertIn("", breakdown_text) diff --git a/tests/test_runtime_router.py b/tests/test_runtime_router.py index c672a75..84bea58 100644 --- a/tests/test_runtime_router.py +++ b/tests/test_runtime_router.py @@ -149,13 +149,11 @@ def test_route_classification_and_active_flow_intents(self) -> None: store.set_current_run(run_state) resume_route = router.classify("继续", skills=skills) cancel_route = router.classify("取消", skills=skills) - replay_route = router.classify("回放最近一次实现", skills=skills) consult_route = router.classify("这个方案为什么要这样拆?", skills=skills) self.assertEqual(resume_route.route_name, "resume_active") self.assertTrue(resume_route.should_recover_context) self.assertEqual(cancel_route.route_name, "cancel_active") - self.assertEqual(replay_route.route_name, "replay") self.assertEqual(consult_route.route_name, "consult") def test_consult_guard_for_process_semantics_forces_runtime_first(self) -> None: @@ -610,46 +608,6 @@ def test_route_skill_resolution_prefers_workspace_declarative_workflow_over_buil self.assertEqual(decision.route_name, "workflow") self.assertEqual(decision.candidate_skill_ids, ("custom-workflow", "analyze", "design", "develop")) - def test_runtime_skill_resolution_prefers_workspace_runtime_skill_over_builtin(self) -> None: - with tempfile.TemporaryDirectory() as temp_dir: - workspace = Path(temp_dir) - user_home = workspace / "home" - custom_skill = workspace / ".agents" / "skills" / "custom-replay" - custom_skill.mkdir(parents=True) - (custom_skill / "SKILL.md").write_text( - "---\nname: custom-replay\ndescription: custom replay helper\n---\n\n# custom-replay\n", - encoding="utf-8", - ) - (custom_skill / "skill.yaml").write_text( - "id: custom-replay\n" - "mode: runtime\n" - "runtime_entry: custom_runtime.py\n" - "supports_routes:\n" - " - replay\n" - "host_support:\n" - " - codex\n" - "permission_mode: dual\n" - "metadata:\n" - " priority: 1\n", - encoding="utf-8", - ) - (custom_skill / "custom_runtime.py").write_text( - "def run_skill(**kwargs):\n return {'ok': True}\n", - encoding="utf-8", - ) - - config = load_runtime_config(workspace) - store = StateStore(config) - store.ensure() - router = Router(config, state_store=store) - skills = SkillRegistry(config, user_home=user_home).discover() - - decision = router.classify("回放最近一次实现", skills=skills) - - self.assertEqual(decision.route_name, "replay") - self.assertEqual(decision.candidate_skill_ids, ("custom-replay", "workflow-learning")) - self.assertEqual(decision.runtime_skill_id, "custom-replay") - def test_runtime_handoff_preserves_direct_edit_runtime_required_reason_code(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: workspace = Path(temp_dir) diff --git a/tests/test_runtime_sample_invariant_gate.py b/tests/test_runtime_sample_invariant_gate.py index 1c65de1..fe1b8f6 100644 --- a/tests/test_runtime_sample_invariant_gate.py +++ b/tests/test_runtime_sample_invariant_gate.py @@ -89,10 +89,6 @@ def test_fixture_covers_a1_to_a8_with_required_columns(self) -> None: ], ) - replay_required = { - "A-5_mixed_clause_after_comma", - "A-8_analysis_only_no_write_process_semantic", - } # A-5 was simplified during proposal removal — negative/boundary examples removed cases_with_full_examples = { "A-5_mixed_clause_after_comma", @@ -103,8 +99,6 @@ def test_fixture_covers_a1_to_a8_with_required_columns(self) -> None: self.assertTrue(case["negative_examples"], msg=case["case_id"]) self.assertTrue(case["boundary_examples"], msg=case["case_id"]) self.assertTrue(case["forbidden_side_effects"], msg=case["case_id"]) - if case["case_id"] in replay_required: - self.assertTrue(case.get("replay_examples"), msg=case["case_id"]) def test_fixture_aligns_with_fail_close_matrix_and_effect_profiles(self) -> None: failure_cases = _failure_cases_by_id() diff --git a/tests/test_runtime_skill_registry.py b/tests/test_runtime_skill_registry.py index fbbe586..ee48062 100644 --- a/tests/test_runtime_skill_registry.py +++ b/tests/test_runtime_skill_registry.py @@ -58,7 +58,6 @@ def test_skill_registry_builtin_catalog_does_not_require_builtin_skill_dirs(self skill_ids = {skill.skill_id for skill in skills} self.assertIn("analyze", skill_ids) - self.assertIn("workflow-learning", skill_ids) self.assertNotIn("model-compare", skill_ids) def test_skill_registry_prefers_generated_builtin_catalog_artifact(self) -> None: From 74eec06df0372243a2d00b2cde43c1b20302facc Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 14:12:44 +0800 Subject: [PATCH 02/12] P3b S2: remove stale replay_keyword_intent eval case The replay route and workflow-learning skill were removed in the previous commit. This eval case was still expecting route=replay with target=workflow-learning, causing the skill eval gate to fail (selection.hit_rate=0.875 < 0.9). Removing the case (rather than adjusting thresholds) since it tests functionality that no longer exists. skill eval gate: PASSED (all metrics 1.0/0.0) --- evals/skill_eval_baseline.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/evals/skill_eval_baseline.json b/evals/skill_eval_baseline.json index 895456f..bb33714 100644 --- a/evals/skill_eval_baseline.json +++ b/evals/skill_eval_baseline.json @@ -102,14 +102,6 @@ "expectation": "positive", "target_skill": "design" }, - { - "id": "replay_keyword_intent", - "request": "回放最近一次实现", - "expected_route": "replay", - "expected_candidate_skills": ["workflow-learning"], - "expectation": "positive", - "target_skill": "workflow-learning" - }, { "id": "explicit_go_exec_command", "request": "~go exec", From 24f4e6b3640ff6cd1d670cb7854fd98f88d9bae3 Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 14:41:29 +0800 Subject: [PATCH 03/12] P3b S1: unify test runner references to pytest CONTRIBUTING.md, CONTRIBUTING_CN.md, and scripts/sync-runtime-assets.sh still referenced 'python3 -m unittest discover'. Align with scripts/release-preflight.sh which already uses pytest. release-preflight: all checks passed --- CONTRIBUTING.md | 6 ++---- CONTRIBUTING_CN.md | 2 +- scripts/sync-runtime-assets.sh | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 19124b7..484358f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,9 +36,7 @@ python3 /path/to/project/.sopify-runtime/scripts/sopify_runtime.py \ --workspace-root /path/to/project "Refactor the database layer" # Optional: portable smoke checks in the target workspace -python3 -m unittest discover \ - -s /path/to/project/.sopify-runtime/tests \ - -p 'test_runtime.py' -v +python3 -m pytest /path/to/project/.sopify-runtime/tests/test_runtime.py -v bash /path/to/project/.sopify-runtime/scripts/check-runtime-smoke.sh ``` @@ -107,7 +105,7 @@ bash scripts/check-skills-sync.sh bash scripts/check-version-consistency.sh python3 scripts/generate-builtin-catalog.py python3 scripts/check-skill-eval-gate.py -python3 -m unittest discover tests -v +python3 -m pytest tests -v ``` Repo-local runtime validation: diff --git a/CONTRIBUTING_CN.md b/CONTRIBUTING_CN.md index caab599..9106dd0 100644 --- a/CONTRIBUTING_CN.md +++ b/CONTRIBUTING_CN.md @@ -111,7 +111,7 @@ bash scripts/check-skills-sync.sh bash scripts/check-version-consistency.sh python3 scripts/generate-builtin-catalog.py python3 scripts/check-skill-eval-gate.py -python3 -m unittest discover tests -v +python3 -m pytest tests -v ``` 仓库内 runtime 验证: diff --git a/scripts/sync-runtime-assets.sh b/scripts/sync-runtime-assets.sh index 0df234b..acdb242 100755 --- a/scripts/sync-runtime-assets.sh +++ b/scripts/sync-runtime-assets.sh @@ -126,6 +126,6 @@ Launch examples: python3 $BUNDLE_DIR/scripts/sopify_runtime.py --allow-direct-entry --workspace-root $TARGET_ROOT "~go plan 重构数据库层" python3 $BUNDLE_DIR/scripts/runtime_gate.py enter --workspace-root $TARGET_ROOT --request "~go plan 重构数据库层" python3 $BUNDLE_DIR/scripts/go_plan_runtime.py --workspace-root $TARGET_ROOT "重构数据库层" - python3 -m unittest discover -s $BUNDLE_DIR/tests -p 'test_runtime.py' -v + python3 -m pytest $BUNDLE_DIR/tests/test_runtime.py -v bash $BUNDLE_DIR/scripts/check-runtime-smoke.sh EOF From 6ee198c69360ed477833d5087c337772592d33ad Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 14:57:50 +0800 Subject: [PATCH 04/12] P3b S4: release-draft-changelog.py drops file lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit render_draft now produces Summary → Changed (category bullets) → Plan Packages. The
file-list block is removed; individual file paths no longer appear in auto-drafted changelog entries. Tests updated to assert new format (category presence, no
). pytest: 684 passed, 49 subtests passed --- scripts/release-draft-changelog.py | 33 +++++++++--------------------- tests/test_release_hooks.py | 17 ++++++++------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/scripts/release-draft-changelog.py b/scripts/release-draft-changelog.py index b4b6089..45219c4 100644 --- a/scripts/release-draft-changelog.py +++ b/scripts/release-draft-changelog.py @@ -290,7 +290,7 @@ def render_draft(changed_files: list[str], root: Path) -> str: blocks: list[str] = [] - # Layer 1: Summary placeholder + # Layer 1: Summary summary_parts: list[str] = [] if plan_packages: archived = [pid for pid, info in plan_packages.items() if info["lifecycle"] == "archived"] @@ -305,7 +305,15 @@ def render_draft(changed_files: list[str], root: Path) -> str: if summary_parts: blocks.append("### Summary\n\n- " + "; ".join(summary_parts) + ".") - # Layer 2: Plan packages + # Layer 2: Changed (category-level bullets, no file lists) + changed_lines: list[str] = [] + for title, summary in SECTION_DEFINITIONS: + if grouped[title]: + changed_lines.append(f"- **{title}**: {summary} ({len(grouped[title])} files)") + if changed_lines: + blocks.append("### Changed\n\n" + "\n".join(changed_lines)) + + # Layer 3: Plan packages if plan_packages: pkg_lines = ["### Plan Packages", ""] for plan_id in sorted(plan_packages): @@ -313,27 +321,6 @@ def render_draft(changed_files: list[str], root: Path) -> str: pkg_lines.append(f"- `{plan_id}` ({info['lifecycle']})") blocks.append("\n".join(pkg_lines)) - # Layer 3: File details in collapsible block - detail_lines: list[str] = [] - for title, summary in SECTION_DEFINITIONS: - if grouped[title]: - detail_lines.append(f"**{title}** — {summary}:") - detail_lines.extend(f" - `{path}`" for path in grouped[title]) - detail_lines.append("") - if plan_packages: - detail_lines.append("**Plan package files**:") - for plan_id in sorted(plan_packages): - for f in plan_packages[plan_id]["files"]: - detail_lines.append(f" - `{f}`") - detail_lines.append("") - - if detail_lines: - blocks.append( - "
\nFile details\n\n" - + "\n".join(detail_lines) - + "\n
" - ) - return "\n\n".join(blocks) diff --git a/tests/test_release_hooks.py b/tests/test_release_hooks.py index 1c26943..66475a2 100644 --- a/tests/test_release_hooks.py +++ b/tests/test_release_hooks.py @@ -300,10 +300,11 @@ def test_release_draft_changelog_populates_empty_unreleased(self) -> None: unreleased = _unreleased_body(text) self.assertIn("### Summary", unreleased) self.assertIn("Changes across:", unreleased) - self.assertIn("
", unreleased) - self.assertIn("`runtime/gate.py`", unreleased) - self.assertIn("`scripts/release-sync.sh`", unreleased) - self.assertIn("`tests/test_runtime_gate.py`", unreleased) + self.assertIn("### Changed", unreleased) + self.assertIn("**Runtime**", unreleased) + self.assertIn("**Scripts**", unreleased) + self.assertIn("**Tests**", unreleased) + self.assertNotIn("
", unreleased) def test_release_sync_auto_drafts_unreleased_before_version_bump(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: @@ -324,8 +325,10 @@ def test_release_sync_auto_drafts_unreleased_before_version_bump(self) -> None: release_body = _release_body(changelog, "2026-03-21.010203") self.assertIn("## [2026-03-21.010203] - 2026-03-21", changelog) self.assertIn("### Summary", release_body) - self.assertIn("`runtime/gate.py`", release_body) - self.assertIn("`tests/test_runtime_gate.py`", release_body) + self.assertIn("### Changed", release_body) + self.assertIn("**Runtime**", release_body) + self.assertIn("**Tests**", release_body) + self.assertNotIn("
", release_body) self.assertIn("badge/version-2026--03--21.010203-orange.svg", (root / "README.md").read_text(encoding="utf-8")) self.assertIn("", (root / "Codex/Skills/CN/AGENTS.md").read_text(encoding="utf-8")) self.assertIn("", (root / "Claude/Skills/CN/CLAUDE.md").read_text(encoding="utf-8")) @@ -391,7 +394,7 @@ def test_release_draft_ignores_sopify_kb_paths(self) -> None: unreleased = _unreleased_body(changelog.read_text(encoding="utf-8")) # Plan package path is now included for attribution self.assertIn("`20260324_task`", unreleased) - self.assertIn("`runtime/gate.py`", unreleased) + self.assertIn("**Runtime**", unreleased) # Non-package .sopify-skills/ paths still excluded self.assertNotIn("history/index.md", unreleased) # Blueprint internals still excluded From e4612713233bca296f535c3bbff5df7be3bfdc59 Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 15:20:04 +0800 Subject: [PATCH 05/12] P3b S4: CHANGELOG compression + docs alignment - CHANGELOG.md: 3256 -> 89 lines (102 auto-generated entries compressed to phase summaries) - Format: Summary -> Changed -> Plan Packages; no per-file lists - P3a entry translated to English (was mixed Chinese/English) - release-draft-changelog.py docstring updated to match actual output (no Details block) - CONTRIBUTING.md/CONTRIBUTING_CN.md: document summary-only changelog constraint --- .../20260508_p3b_perimeter_cleanup/tasks.md | 8 +- CHANGELOG.md | 3268 +---------------- CONTRIBUTING.md | 2 +- CONTRIBUTING_CN.md | 2 +- scripts/release-draft-changelog.py | 4 +- 5 files changed, 58 insertions(+), 3226 deletions(-) diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md index 6912681..1b45193 100644 --- a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md @@ -81,10 +81,10 @@ archive_ready: false ### CHANGELOG 去文件列表化 -- [ ] 4.1 旧 102 条自动生成条目直接压成阶段摘要(不逐条迁移) -- [ ] 4.2 新条目格式只保留 Summary + Changed,不列文件 -- [ ] 4.3 修 `scripts/release-draft-changelog.py` 只产摘要,不产文件清单 -- [ ] 4.4 同步更新 `CONTRIBUTING.md` changelog 说明 +- [x] 4.1 旧 102 条自动生成条目直接压成阶段摘要(不逐条迁移) +- [x] 4.2 新条目格式只保留 Summary + Changed,不列文件 +- [x] 4.3 修 `scripts/release-draft-changelog.py` 只产摘要,不产文件清单 +- [x] 4.4 同步更新 `CONTRIBUTING.md` changelog 说明 ### README 首屏降噪与默认入口翻转 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7624549..5ec8436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to Sopify are documented in this file. -Format: Summary → Plan Packages → File Details (collapsible). +Format: Summary → Changed → Plan Packages. File-level details live in `git log`. ## [Unreleased] @@ -10,3247 +10,79 @@ Format: Summary → Plan Packages → File Details (collapsible). ### Summary -P3a Contract-Aligned Surface Cleanup 完整交付。Execution routing 收敛、cancel_scope 修复、knowledge_sync audit trail、dead path cleanup (-88 LOC)、blueprint 已完成里程碑压缩 + Px 独立里程碑。 +P3a Contract-Aligned Surface Cleanup delivered in full. Execution routing convergence, cancel_scope fix, knowledge_sync audit trail, dead path cleanup (-88 LOC), blueprint milestone compression + P4b split-out. ### Changed -- **Execution routing convergence**: authorized ActionProposal → deterministic route derive (`_derive_route_from_authorized_proposal`); Router.classify 降为 bare-text legacy fallback -- **cancel_scope fix**: cancel_flow 在 derive 路径内联处理,修复 artifacts 为空时默认全局清理的 bug -- **knowledge_sync audit trail**: `knowledge_sync_result` 贯穿 archive 全管道(success / blocked / archive_target_conflict 三路径) -- **Dead code removal**: 删除 6 个无引用私有函数 + 1 个孤立常量 (-88 LOC) -- **Test coverage**: +17 routing convergence tests, +2 archive knowledge_sync tests, classify exclusion + checkpoint split 补齐 -- **Blueprint restructure**: P0–P3a 压缩为一行摘要;Px runtime_surface_consolidation 独立里程碑(post-P4) -- **P3a archived**: plan → `history/2026-05/20260507_p3a_contract_aligned_surface_cleanup/` +- **Execution routing convergence**: authorized ActionProposal → deterministic route derive (`_derive_route_from_authorized_proposal`); Router.classify demoted to bare-text legacy fallback +- **cancel_scope fix**: cancel_flow inlined in derive path, fixing default-to-global-cleanup bug when artifacts list is empty +- **knowledge_sync audit trail**: `knowledge_sync_result` threaded through full archive pipeline (success / blocked / archive_target_conflict) +- **Dead code removal**: removed 6 unreferenced private functions + 1 orphan constant (-88 LOC) +- **Test coverage**: +17 routing convergence tests, +2 archive knowledge_sync tests, classify exclusion + checkpoint split coverage filled +- **Blueprint restructure**: P0–P3a compressed to one-line summaries; runtime weight reduction split out as P4b (runtime_surface_consolidation) ### Plan Packages - `20260507_p3a_contract_aligned_surface_cleanup` (archived) -
-File details +--- -**Runtime** — Execution routing + archive audit trail + dead code removal: - - `runtime/engine.py` (+207 derive functions, -36 dead code) - - `runtime/archive_lifecycle.py` (+47 knowledge_sync pipeline) - - `runtime/router.py` (-26 dead function + constant + imports) - - `runtime/workspace_preflight.py` (-20 dead function) - - `runtime/action_projection.py` - - `runtime/checkpoint_request.py` - - `runtime/deterministic_guard.py` - - `runtime/develop_callback.py` - - `runtime/handoff.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/vnext_phase_boundary.py` +## Historical Entries (compressed) -**Contracts** — Schema cleanup: - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/contracts/failure_recovery_table.yaml` - - `runtime/contracts/signal_priority_table.schema.json` +The 102 auto-generated entries below (2026-01-15 to 2026-05-07) have been compressed into phase summaries. Full file-level detail is preserved in `git log`. -**Tests** — 689 tests, 49 subtests: - - `tests/test_runtime_engine.py` (+337 routing convergence + archive assertions) - - `tests/test_runtime_plan_registry.py` (+70 knowledge_sync receipt tests) - - `tests/test_context_v1_scope.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - - `tests/test_bundle_smoke.py` - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/pytest_entries/fail_close_contract_entry.py` +### P3a Development Iterations (2026-05-03 – 2026-05-07) -**Blueprint** — Milestone compression + Px: - - `.sopify-skills/blueprint/tasks.md` - - `.sopify-skills/blueprint/design.md` - - `.sopify-skills/blueprint/protocol.md` - - `.sopify-skills/blueprint/README.md` - - `.sopify-skills/history/index.md` - - `.sopify-skills/history/2026-05/20260507_p3a_contract_aligned_surface_cleanup/` +25 releases. Contract-aligned surface cleanup development: -**Docs & Skills**: - - `README.md`, `README.zh-CN.md` - - `Claude/Skills/CN/CLAUDE.md`, `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md`, `Codex/Skills/EN/AGENTS.md` - - `scripts/check-prompt-runtime-gate-smoke.py` +- Execution routing → ActionProposal-based derive pipeline +- cancel_scope hardening and fail-close contract enforcement +- knowledge_sync audit trail through archive lifecycle +- Deterministic guard, signal priority, failure recovery tables +- Fail-close contract fixture + eval entries +- Plan: `20260507_p3a_contract_aligned_surface_cleanup` -
+### P2 Local Action Contracts (2026-05-01 – 2026-05-02) -## [2026-05-07.143021] - 2026-05-07 +8 releases. Action intent and proposal authorization: -### Summary - -- Updated 1 active plan package(s); Changes across: Docs, Runtime, Scripts, Skills, Tests. - -### Plan Packages - -- `20260507_p3a_contract_aligned_surface_cleanup` (active) - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -**Runtime** — Updated runtime internals: - - `runtime/action_projection.py` - - `runtime/checkpoint_request.py` - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/contracts/failure_recovery_table.yaml` - - `runtime/contracts/signal_priority_table.schema.json` - - `runtime/deterministic_guard.py` - - `runtime/develop_callback.py` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/vnext_phase_boundary.py` - -**Scripts** — Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - -**Skills** — Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -**Tests** — Updated automated coverage: - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/pytest_entries/fail_close_contract_entry.py` - - `tests/test_bundle_smoke.py` - - `tests/test_context_v1_scope.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - -**Plan package files**: - - `.sopify-skills/plan/20260507_p3a_contract_aligned_surface_cleanup/design.md` - - `.sopify-skills/plan/20260507_p3a_contract_aligned_surface_cleanup/tasks.md` - -
- -## [2026-05-07.142547] - 2026-05-07 - -### Summary - -- Updated 1 active plan package(s); Changes across: Runtime, Scripts, Tests. - -### Plan Packages - -- `20260507_p3a_contract_aligned_surface_cleanup` (active) - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/action_projection.py` - - `runtime/checkpoint_request.py` - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/contracts/failure_recovery_table.yaml` - - `runtime/contracts/signal_priority_table.schema.json` - - `runtime/deterministic_guard.py` - - `runtime/develop_callback.py` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/vnext_phase_boundary.py` - -**Scripts** — Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - -**Tests** — Updated automated coverage: - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/pytest_entries/fail_close_contract_entry.py` - - `tests/test_bundle_smoke.py` - - `tests/test_context_v1_scope.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - -**Plan package files**: - - `.sopify-skills/plan/20260507_p3a_contract_aligned_surface_cleanup/design.md` - - `.sopify-skills/plan/20260507_p3a_contract_aligned_surface_cleanup/tasks.md` - -
- -## [2026-05-07.102024] - 2026-05-07 - -### Summary - -- Changes across: Runtime, Tests. - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/gate.py` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -
- -## [2026-05-07.100219] - 2026-05-07 - -### Summary - -- Updated 1 active plan package(s); Changes across: Runtime, Tests. - -### Plan Packages - -- `20260506_p2_local_action_contracts` (active) - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/action_intent.py` - - `runtime/gate.py` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -**Plan package files**: - - `.sopify-skills/plan/20260506_p2_local_action_contracts/background.md` - - `.sopify-skills/plan/20260506_p2_local_action_contracts/design.md` - - `.sopify-skills/plan/20260506_p2_local_action_contracts/tasks.md` - -
- -## [2026-05-06.181908] - 2026-05-06 - -### Summary - -- Changes across: Docs. - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -
- -## [2026-05-06.143421] - 2026-05-06 - -### Summary - -- Updated 1 active plan package(s); Changes across: Docs, Runtime, Skills, Tests. - -### Plan Packages - -- `20260506_p15_reject_surface` (active) - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -**Runtime** — Updated runtime internals: - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/output.py` - -**Skills** — Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -**Plan package files**: - - `.sopify-skills/plan/20260506_p15_reject_surface/background.md` - - `.sopify-skills/plan/20260506_p15_reject_surface/design.md` - - `.sopify-skills/plan/20260506_p15_reject_surface/tasks.md` - -
- -## [2026-05-06.143016] - 2026-05-06 - -### Summary - -- Updated 1 active plan package(s); Changes across: Runtime, Tests. - -### Plan Packages - -- `20260506_p15_reject_surface` (active) - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/output.py` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -**Plan package files**: - - `.sopify-skills/plan/20260506_p15_reject_surface/background.md` - - `.sopify-skills/plan/20260506_p15_reject_surface/design.md` - - `.sopify-skills/plan/20260506_p15_reject_surface/tasks.md` - -
- -## [2026-05-06.131235] - 2026-05-06 - -### Summary - -- Archived 2 plan package(s); Updated 1 active plan package(s); Changes across: Docs, Runtime, Skills, Tests. - -### Plan Packages - -- `20260505_p15_advance_slices` (archived) -- `20260505_p15_plan_materialization_auth` (archived) -- `20260506_p15_authorization_contract_spec` (active) - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -**Runtime** — Updated runtime internals: - - `runtime/_models/core.py` - - `runtime/action_intent.py` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/state.py` - -**Skills** — Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -**Plan package files**: - - `.sopify-skills/history/2026-05/20260505_p15_advance_slices/background.md` - - `.sopify-skills/history/2026-05/20260505_p15_advance_slices/design.md` - - `.sopify-skills/history/2026-05/20260505_p15_advance_slices/receipt.md` - - `.sopify-skills/history/2026-05/20260505_p15_advance_slices/tasks.md` - - `.sopify-skills/plan/20260505_p15_advance_slices/background.md` - - `.sopify-skills/plan/20260505_p15_advance_slices/design.md` - - `.sopify-skills/plan/20260505_p15_advance_slices/tasks.md` - - `.sopify-skills/history/2026-05/20260505_p15_plan_materialization_auth/background.md` - - `.sopify-skills/history/2026-05/20260505_p15_plan_materialization_auth/design.md` - - `.sopify-skills/history/2026-05/20260505_p15_plan_materialization_auth/receipt.md` - - `.sopify-skills/history/2026-05/20260505_p15_plan_materialization_auth/tasks.md` - - `.sopify-skills/plan/20260505_p15_plan_materialization_auth/background.md` - - `.sopify-skills/plan/20260505_p15_plan_materialization_auth/design.md` - - `.sopify-skills/plan/20260505_p15_plan_materialization_auth/tasks.md` - - `.sopify-skills/plan/20260506_p15_authorization_contract_spec/background.md` - - `.sopify-skills/plan/20260506_p15_authorization_contract_spec/design.md` - - `.sopify-skills/plan/20260506_p15_authorization_contract_spec/tasks.md` - -
- -## [2026-05-06.130854] - 2026-05-06 - -### Summary - -- Updated 1 active plan package(s); Changes across: Runtime, Tests. - -### Plan Packages - -- `20260506_p15_authorization_contract_spec` (active) - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/_models/core.py` - - `runtime/action_intent.py` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/state.py` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -**Plan package files**: - - `.sopify-skills/plan/20260506_p15_authorization_contract_spec/background.md` - - `.sopify-skills/plan/20260506_p15_authorization_contract_spec/design.md` - - `.sopify-skills/plan/20260506_p15_authorization_contract_spec/tasks.md` - -
- -## [2026-05-05.200849] - 2026-05-05 - -### Summary - -- Updated 1 active plan package(s); Changes across: Docs, Runtime, Skills, Tests. - -### Plan Packages - -- `20260505_consult-plan-actionproposal-validator-determinis` (unknown) -- `20260505_p15_advance_slices` (active) - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -**Runtime** — Updated runtime internals: - - `runtime/__init__.py` - - `runtime/_models/summary.py` - - `runtime/daily_summary.py` - - `runtime/engine.py` - - `runtime/models.py` - - `runtime/output.py` - - `runtime/router.py` - -**Skills** — Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -**Tests** — Updated automated coverage: - - `tests/protocol/test_convention_compliance.py` - - `tests/runtime_test_support.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_summary.py` - -**Plan package files**: - - `.sopify-skills/plan/20260505_consult-plan-actionproposal-validator-determinis/background.md` - - `.sopify-skills/plan/20260505_consult-plan-actionproposal-validator-determinis/design.md` - - `.sopify-skills/plan/20260505_consult-plan-actionproposal-validator-determinis/tasks.md` - - `.sopify-skills/plan/20260505_p15_advance_slices/design.md` - - `.sopify-skills/plan/20260505_p15_advance_slices/tasks.md` - -
- -## [2026-05-05.195823] - 2026-05-05 - -### Summary - -- Updated 1 active plan package(s); Changes across: Docs, Runtime, Tests. - -### Plan Packages - -- `20260505_p15_advance_slices` (active) - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -**Runtime** — Updated runtime internals: - - `runtime/__init__.py` - - `runtime/_models/summary.py` - - `runtime/daily_summary.py` - - `runtime/engine.py` - - `runtime/models.py` - - `runtime/output.py` - - `runtime/router.py` - -**Tests** — Updated automated coverage: - - `tests/protocol/test_convention_compliance.py` - - `tests/runtime_test_support.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_summary.py` - -**Plan package files**: - - `.sopify-skills/plan/20260505_p15_advance_slices/design.md` - - `.sopify-skills/plan/20260505_p15_advance_slices/tasks.md` - -
- -## [2026-05-04.221930] - 2026-05-04 - -### Summary - -- Changes across: Runtime, Tests. - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/action_intent.py` - - `runtime/engine.py` - - `runtime/gate.py` - -**Tests** — Updated automated coverage: - - `tests/test_action_intent.py` - -
- -## [2026-05-04.221601] - 2026-05-04 - -### Summary - -- Changes across: Runtime. - -
-File details - -**Runtime** — Updated runtime internals: - - `runtime/gate.py` - -
- -## [2026-05-04.201238] - 2026-05-04 - -### Summary - -- Archived 2 plan package(s); Changes across: Docs, Runtime, Scripts, Skills, Tests, Changed. - -### Plan Packages - -- `20260501_blueprint-truth-cutover` (archived) -- `20260501_convention_smoke` (archived) - -
-File details - -**Docs** — Refined public documentation: - - `README.md` - - `README.zh-CN.md` - - `docs/how-sopify-works.en.md` - - `docs/how-sopify-works.md` - -**Runtime** — Updated runtime internals: - - `runtime/_models/handoff.py` - - `runtime/action_intent.py` - - `runtime/action_projection.py` - - `runtime/builtin_catalog.generated.json` - - `runtime/builtin_catalog.py` - - `runtime/builtin_skill_packages/workflow-learning/skill.yaml` - - `runtime/checkpoint_materializer.py` - - `runtime/checkpoint_request.py` - - `runtime/context_recovery.py` - - `runtime/context_snapshot.py` - - `runtime/context_v1_scope.py` - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/contracts/failure_recovery_table.yaml` - - `runtime/contracts/host_message_templates.schema.json` - - `runtime/contracts/side_effect_mapping_table.schema.json` - - `runtime/contracts/signal_priority_table.schema.json` - - `runtime/deterministic_guard.py` - - `runtime/develop_callback.py` - - `runtime/develop_checkpoint.py` - - `runtime/develop_quality.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/execution_confirm.py` - - `runtime/execution_gate.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/plan_proposal.py` - - `runtime/router.py` - - `runtime/state.py` - - `runtime/state_invariants.py` - - `runtime/vnext_phase_boundary.py` - -**Scripts** — Adjusted maintenance scripts: - - `scripts/check-fail-close-contract.py` - - `scripts/check-prompt-runtime-gate-smoke.py` - - `scripts/check-runtime-smoke.sh` - - `scripts/develop_callback_runtime.py` - - `scripts/develop_checkpoint_runtime.py` - - `scripts/release-draft-changelog.py` - - `scripts/sync-runtime-assets.sh` - -**Skills** — Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -**Tests** — Updated automated coverage: - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/fixtures/fail_close_case_matrix.yaml` - - `tests/fixtures/sample_invariant_gate_matrix.yaml` - - `tests/runtime_test_support.py` - - `tests/test_action_intent.py` - - `tests/test_context_v1_scope.py` - - `tests/test_contract_consistency.py` - - `tests/test_installer.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_release_hooks.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_execution_gate.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_message_templates.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_sample_invariant_gate.py` - - `tests/test_runtime_state.py` - -**Changed** — Updated project files: - - `.githooks/pre-commit` - - `installer/bootstrap_workspace.py` - - `installer/inspection.py` - - `installer/payload.py` - - `installer/runtime_bundle.py` - - `installer/validate.py` - -**Plan package files**: - - `.sopify-skills/history/2026-05/20260501_blueprint-truth-cutover/background.md` - - `.sopify-skills/history/2026-05/20260501_blueprint-truth-cutover/design.md` - - `.sopify-skills/history/2026-05/20260501_blueprint-truth-cutover/tasks.md` - - `.sopify-skills/history/2026-05/20260501_convention_smoke/host_b_instructions.md` - - `.sopify-skills/history/2026-05/20260501_convention_smoke/plan.md` - - `.sopify-skills/history/2026-05/20260501_convention_smoke/receipt.md` - -
- -## [2026-05-04.194714] - 2026-05-04 - -### Summary - -- Changes across: Scripts, Tests. - -
-File details - -**Scripts** — Adjusted maintenance scripts: - - `scripts/release-draft-changelog.py` - -**Tests** — Updated automated coverage: - - `tests/test_release_hooks.py` - -
- -## [2026-05-03.203432] - 2026-05-03 - - -### Skills - -- Synced prompt-layer skills: - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -## [2026-05-03.201958] - 2026-05-03 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/action_intent.py` - - `runtime/action_projection.py` - - `runtime/checkpoint_materializer.py` - - `runtime/checkpoint_request.py` - - `runtime/context_snapshot.py` - - `runtime/context_v1_scope.py` - - `runtime/deterministic_guard.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/execution_confirm.py` - - `runtime/execution_gate.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/router.py` - - `runtime/vnext_phase_boundary.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/runtime_test_support.py` - - `tests/test_action_intent.py` - - `tests/test_context_v1_scope.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_execution_gate.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_message_templates.py` - - `tests/test_runtime_router.py` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - -## [2026-05-03.195008] - 2026-05-03 - -### Runtime - -- Updated runtime internals: - - `runtime/action_intent.py` - - `runtime/action_projection.py` - - `runtime/checkpoint_materializer.py` - - `runtime/checkpoint_request.py` - - `runtime/context_snapshot.py` - - `runtime/context_v1_scope.py` - - `runtime/deterministic_guard.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/execution_confirm.py` - - `runtime/execution_gate.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/router.py` - - `runtime/vnext_phase_boundary.py` - -### Tests - -- Updated automated coverage: - - `tests/runtime_test_support.py` - - `tests/test_action_intent.py` - - `tests/test_context_v1_scope.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_execution_gate.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_message_templates.py` - - `tests/test_runtime_router.py` - -## [2026-05-02.234429] - 2026-05-02 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/_models/handoff.py` - - `runtime/action_intent.py` - - `runtime/action_projection.py` - - `runtime/checkpoint_materializer.py` - - `runtime/checkpoint_request.py` - - `runtime/context_recovery.py` - - `runtime/context_snapshot.py` - - `runtime/context_v1_scope.py` - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/contracts/failure_recovery_table.yaml` - - `runtime/contracts/host_message_templates.schema.json` - - `runtime/contracts/side_effect_mapping_table.schema.json` - - `runtime/contracts/signal_priority_table.schema.json` - - `runtime/deterministic_guard.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/plan_proposal.py` - - `runtime/router.py` - - `runtime/state.py` - - `runtime/vnext_phase_boundary.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/fixtures/fail_close_case_matrix.yaml` - - `tests/fixtures/sample_invariant_gate_matrix.yaml` - - `tests/test_action_intent.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_sample_invariant_gate.py` - - `tests/test_runtime_state.py` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - -## [2026-05-02.234058] - 2026-05-02 - -### Runtime - -- Updated runtime internals: - - `runtime/_models/handoff.py` - - `runtime/action_intent.py` - - `runtime/action_projection.py` - - `runtime/checkpoint_materializer.py` - - `runtime/checkpoint_request.py` - - `runtime/context_recovery.py` - - `runtime/context_snapshot.py` - - `runtime/context_v1_scope.py` - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/contracts/failure_recovery_table.yaml` - - `runtime/contracts/host_message_templates.schema.json` - - `runtime/contracts/side_effect_mapping_table.schema.json` - - `runtime/contracts/signal_priority_table.schema.json` - - `runtime/deterministic_guard.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/plan_proposal.py` - - `runtime/router.py` - - `runtime/state.py` - - `runtime/vnext_phase_boundary.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - -### Tests - -- Updated automated coverage: - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/fixtures/fail_close_case_matrix.yaml` - - `tests/fixtures/sample_invariant_gate_matrix.yaml` - - `tests/test_action_intent.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_sample_invariant_gate.py` - - `tests/test_runtime_state.py` - -## [2026-05-02.205827] - 2026-05-02 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/builtin_catalog.generated.json` - - `runtime/builtin_catalog.py` - - `runtime/builtin_skill_packages/workflow-learning/skill.yaml` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/output.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - -## [2026-05-02.205419] - 2026-05-02 - -### Runtime - -- Updated runtime internals: - - `runtime/builtin_catalog.generated.json` - - `runtime/builtin_catalog.py` - - `runtime/builtin_skill_packages/workflow-learning/skill.yaml` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/output.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - -## [2026-05-02.150730] - 2026-05-02 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/develop_callback.py` - - `runtime/develop_checkpoint.py` - - `runtime/develop_quality.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/manifest.py` - - `runtime/state_invariants.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-runtime-smoke.sh` - - `scripts/develop_callback_runtime.py` - - `scripts/develop_checkpoint_runtime.py` - - `scripts/sync-runtime-assets.sh` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/runtime_test_support.py` - - `tests/test_installer.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - -### Changed - -- Updated project files: - - `.githooks/pre-commit` - - `CHANGELOG.md` - - `installer/bootstrap_workspace.py` - - `installer/payload.py` - - `installer/runtime_bundle.py` - - `installer/validate.py` - -## [2026-05-02.150313] - 2026-05-02 - -### Runtime - -- Updated runtime internals: - - `runtime/develop_callback.py` - - `runtime/develop_checkpoint.py` - - `runtime/develop_quality.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/manifest.py` - - `runtime/state_invariants.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-runtime-smoke.sh` - - `scripts/develop_callback_runtime.py` - - `scripts/develop_checkpoint_runtime.py` - - `scripts/sync-runtime-assets.sh` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/runtime_test_support.py` - - `tests/test_installer.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - -### Changed - -- Updated project files: - - `.githooks/pre-commit` - - `installer/bootstrap_workspace.py` - - `installer/payload.py` - - `installer/runtime_bundle.py` - - `installer/validate.py` - -## [2026-05-02.134449] - 2026-05-02 - -### Runtime - -- Updated runtime internals: - - `runtime/_models/handoff.py` - - `runtime/action_projection.py` - - `runtime/deterministic_guard.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/output.py` - -### Tests - -- Updated automated coverage: - - `tests/test_context_v1_scope.py` - - `tests/test_contract_consistency.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - -## [2026-05-01.141049] - 2026-05-01 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -## [2026-04-29.182018] - 2026-04-29 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/_models/core.py` - - `runtime/builtin_catalog.generated.json` - - `runtime/builtin_catalog.py` - - `runtime/builtin_skill_packages/model-compare/skill.yaml` - - `runtime/checkpoint_request.py` - - `runtime/compare_decision.py` - - `runtime/config.py` - - `runtime/engine.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/replay.py` - - `runtime/router.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-skill-eval-gate.py` - - `scripts/model_compare_runtime.py` - - `scripts/sync-runtime-assets.sh` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/design/references/design-rules.md` - - `Claude/Skills/CN/skills/sopify/model-compare/SKILL.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/design/references/design-rules.md` - - `Claude/Skills/EN/skills/sopify/model-compare/SKILL.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/design/references/design-rules.md` - - `Codex/Skills/CN/skills/sopify/model-compare/SKILL.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/design/references/design-rules.md` - - `Codex/Skills/EN/skills/sopify/model-compare/SKILL.md` - -### Tests - -- Updated automated coverage: - - `tests/fixtures/sample_invariant_gate_matrix.yaml` - - `tests/runtime_test_support.py` - - `tests/test_action_intent.py` - - `tests/test_bundle_smoke.py` - - `tests/test_runtime_config.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_sample_invariant_gate.py` - - `tests/test_runtime_skill_registry.py` - -### Changed - -- Updated project files: - - `evals/skill_eval_baseline.json` - - `evals/skill_eval_slo.json` - - `examples/sopify.config.yaml` - - `installer/bootstrap_workspace.py` - -## [2026-04-29.150302] - 2026-04-29 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/action_intent.py` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/decision_tables.py` - - `runtime/engine.py` - - `runtime/gate.py` - - `runtime/manifest.py` - - `runtime/router.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/runtime_gate.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_action_intent.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_sample_invariant_gate.py` - -### Changed - -- Updated project files: - - `.agents/skills/cross-review/SKILL.md` - - `.agents/skills/cross-review/skill.yaml` - - `CHANGELOG.md` - -## [2026-04-29.145842] - 2026-04-29 - -### Runtime - -- Updated runtime internals: - - `runtime/action_intent.py` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/failure_recovery_table.schema.json` - - `runtime/decision_tables.py` - - `runtime/engine.py` - - `runtime/gate.py` - - `runtime/manifest.py` - - `runtime/router.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/runtime_gate.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_action_intent.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_sample_invariant_gate.py` - -### Changed - -- Updated project files: - - `.agents/skills/cross-review/SKILL.md` - - `.agents/skills/cross-review/skill.yaml` - -## [2026-04-28.143230] - 2026-04-28 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README.zh-CN.md` - - `docs/dev/release-process.md` - -### Runtime - -- Updated runtime internals: - - `runtime/cli.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/go_plan_runtime.py` - - `scripts/sopify_runtime.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - - `install.ps1` - - `install.sh` - -## [2026-04-28.142643] - 2026-04-28 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README.zh-CN.md` - - `docs/dev/release-process.md` - -### Runtime - -- Updated runtime internals: - - `runtime/cli.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/go_plan_runtime.py` - - `scripts/sopify_runtime.py` - -### Changed - -- Updated project files: - - `install.ps1` - - `install.sh` - -## [2026-04-28.134325] - 2026-04-28 - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `Claude/Skills/EN/skills/sopify/develop/references/develop-rules.md` - - `Codex/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `Codex/Skills/EN/skills/sopify/develop/references/develop-rules.md` - -### Changed - -- Updated project files: - - `.agents/skills/cross-review/SKILL.md` - -## [2026-04-28.113132] - 2026-04-28 - -### Skills - -- Synced prompt-layer skills: - - `Codex/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `Codex/Skills/EN/skills/sopify/develop/references/develop-rules.md` - -### Changed - -- Updated project files: - - `.agents/skills/cross-review/SKILL.md` - - `.agents/skills/cross-review/skill.yaml` - -## [2026-04-27.191703] - 2026-04-27 - -### Runtime - -- Updated runtime internals: - - `runtime/output.py` - - `runtime/router.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime_router.py` - -## [2026-04-27.163354] - 2026-04-27 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README.zh-CN.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-readme-links.py` - - `scripts/check-skills-sync.sh` - - `scripts/check-version-consistency.sh` - - `scripts/sync-skills.sh` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_check_readme_links.py` - - `tests/test_installer.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_release_hooks.py` - -### Changed - -- Updated project files: - - `.githooks/pre-commit` - - `CHANGELOG.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/references/analyze-rules.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/scripts/score_requirement.py` - - `TraeCn/Skills/CN/skills/sopify/design/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/adr-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/background-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/design-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/plan-light-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/tasks-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/references/design-rules.md` - - `TraeCn/Skills/CN/skills/sopify/design/scripts/select_plan_level.py` - - `TraeCn/Skills/CN/skills/sopify/develop/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `TraeCn/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `TraeCn/Skills/CN/skills/sopify/develop/scripts/extract_pending_tasks.py` - - `TraeCn/Skills/CN/skills/sopify/kb/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/model-compare/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/templates/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md` - - `TraeCn/Skills/CN/skills/sopify/workflow-learning/SKILL.md` - - `TraeCn/Skills/CN/user_rules/sopify.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/references/analyze-rules.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/scripts/score_requirement.py` - - `TraeCn/Skills/EN/skills/sopify/design/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/adr-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/background-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/design-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/plan-light-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/tasks-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/references/design-rules.md` - - `TraeCn/Skills/EN/skills/sopify/design/scripts/select_plan_level.py` - - `TraeCn/Skills/EN/skills/sopify/develop/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `TraeCn/Skills/EN/skills/sopify/develop/references/develop-rules.md` - - `TraeCn/Skills/EN/skills/sopify/develop/scripts/extract_pending_tasks.py` - - `TraeCn/Skills/EN/skills/sopify/kb/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/model-compare/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/templates/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md` - - `TraeCn/Skills/EN/skills/sopify/workflow-learning/SKILL.md` - - `TraeCn/Skills/EN/user_rules/sopify.md` - - `installer/hosts/__init__.py` - - `installer/hosts/trae_cn.py` - -## [2026-04-27.163000] - 2026-04-27 - -### Removed - -- Retired the Trae CN host surface: - - removed the `trae-cn:*` install target and host adapter - - removed the `TraeCn/` prompt-layer mirror - - removed Trae-specific sync, release, status/doctor, README, and installer test coverage - - archived the former Trae CN host adapter plan under `.sopify-skills/history/2026-04/` - -## [2026-04-14.175552] - 2026-04-14 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README.zh-CN.md` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/references/analyze-rules.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/scripts/score_requirement.py` - - `TraeCn/Skills/CN/skills/sopify/design/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/adr-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/background-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/design-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/plan-light-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/tasks-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/references/design-rules.md` - - `TraeCn/Skills/CN/skills/sopify/design/scripts/select_plan_level.py` - - `TraeCn/Skills/CN/skills/sopify/develop/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `TraeCn/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `TraeCn/Skills/CN/skills/sopify/develop/scripts/extract_pending_tasks.py` - - `TraeCn/Skills/CN/skills/sopify/kb/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/model-compare/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/templates/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md` - - `TraeCn/Skills/CN/skills/sopify/workflow-learning/SKILL.md` - - `TraeCn/Skills/CN/user_rules/sopify.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/references/analyze-rules.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/scripts/score_requirement.py` - - `TraeCn/Skills/EN/skills/sopify/design/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/adr-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/background-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/design-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/plan-light-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/tasks-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/references/design-rules.md` - - `TraeCn/Skills/EN/skills/sopify/design/scripts/select_plan_level.py` - - `TraeCn/Skills/EN/skills/sopify/develop/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `TraeCn/Skills/EN/skills/sopify/develop/references/develop-rules.md` - - `TraeCn/Skills/EN/skills/sopify/develop/scripts/extract_pending_tasks.py` - - `TraeCn/Skills/EN/skills/sopify/kb/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/model-compare/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/templates/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md` - - `TraeCn/Skills/EN/skills/sopify/workflow-learning/SKILL.md` - - `TraeCn/Skills/EN/user_rules/sopify.md` - - `installer/hosts/__init__.py` - - `installer/hosts/base.py` - - `installer/hosts/trae_cn.py` - -## [2026-04-14.174949] - 2026-04-14 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README.zh-CN.md` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `TraeCn/Skills/CN/skills/sopify/analyze/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/references/analyze-rules.md` - - `TraeCn/Skills/CN/skills/sopify/analyze/scripts/score_requirement.py` - - `TraeCn/Skills/CN/skills/sopify/design/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/adr-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/background-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/design-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/plan-light-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/assets/tasks-template.md` - - `TraeCn/Skills/CN/skills/sopify/design/references/design-rules.md` - - `TraeCn/Skills/CN/skills/sopify/design/scripts/select_plan_level.py` - - `TraeCn/Skills/CN/skills/sopify/develop/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `TraeCn/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `TraeCn/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `TraeCn/Skills/CN/skills/sopify/develop/scripts/extract_pending_tasks.py` - - `TraeCn/Skills/CN/skills/sopify/kb/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/model-compare/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/templates/SKILL.md` - - `TraeCn/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md` - - `TraeCn/Skills/CN/skills/sopify/workflow-learning/SKILL.md` - - `TraeCn/Skills/CN/user_rules/sopify.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/references/analyze-rules.md` - - `TraeCn/Skills/EN/skills/sopify/analyze/scripts/score_requirement.py` - - `TraeCn/Skills/EN/skills/sopify/design/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/adr-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/background-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/design-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/plan-light-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/assets/tasks-template.md` - - `TraeCn/Skills/EN/skills/sopify/design/references/design-rules.md` - - `TraeCn/Skills/EN/skills/sopify/design/scripts/select_plan_level.py` - - `TraeCn/Skills/EN/skills/sopify/develop/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `TraeCn/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `TraeCn/Skills/EN/skills/sopify/develop/references/develop-rules.md` - - `TraeCn/Skills/EN/skills/sopify/develop/scripts/extract_pending_tasks.py` - - `TraeCn/Skills/EN/skills/sopify/kb/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/model-compare/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/templates/SKILL.md` - - `TraeCn/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md` - - `TraeCn/Skills/EN/skills/sopify/workflow-learning/SKILL.md` - - `TraeCn/Skills/EN/user_rules/sopify.md` - - `installer/hosts/__init__.py` - - `installer/hosts/base.py` - - `installer/hosts/trae_cn.py` - -## [2026-04-13.144221] - 2026-04-13 - -### Tests - -- Updated automated coverage: - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `installer/distribution.py` - - `installer/hosts/claude.py` - - `installer/hosts/codex.py` - - `installer/inspection.py` - - `installer/outcome_contract.py` - -## [2026-04-12.230144] - 2026-04-12 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/finalize.py` - - `runtime/handoff.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_context_v1_scope.py` - - `tests/test_runtime_engine.py` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - -## [2026-04-12.225832] - 2026-04-12 - -### Runtime - -- Updated runtime internals: - - `runtime/finalize.py` - - `runtime/handoff.py` - -### Tests - -- Updated automated coverage: - - `tests/test_context_v1_scope.py` - - `tests/test_runtime_engine.py` - -## [2026-04-10.104951] - 2026-04-10 - -### Runtime - -- Locked the Plan A V1 parser-first release boundary: - - enforced V1 decision-table scope validation through the shared loader - - normalized repo-internal absolute paths and fail-closed external absolute paths for the V1 file map guard - -### Governance - -- Enforced Plan A context-checkpoint governance for scoped commits and pull requests: - - `commit-msg` checkpoint trailer validation - - PR template metadata requirements - - CI / preflight checkpoint checks for scoped runtime, test, and governance assets - -### Documentation - -- Closed the Plan A V1 patch-release narrative: - - A/B/C gates are release-ready for V1 parser-first - - Checkpoint D and classifier rollout remain deferred to V2 - - machine-contract overview now documents guardrail handoff artifacts and the V1 scope registry - -### Tests - -- Expanded automated coverage for: - - V1 scope boundary enforcement - - context checkpoint governance - - release hook behavior - -## [2026-04-09.224600] - 2026-04-09 - -### Runtime - -- Updated runtime internals: - - `runtime/context_v1_scope.py` - -### Tests - -- Updated automated coverage: - - `tests/test_context_v1_scope.py` - -## [2026-04-09.203519] - 2026-04-09 - -### Runtime - -- Updated runtime internals: - - `runtime/handoff.py` - -### Tests - -- Updated automated coverage: - - `tests/fixtures/sample_invariant_gate_matrix.yaml` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_sample_invariant_gate.py` - -## [2026-04-09.163847] - 2026-04-09 - -### Runtime - -- Updated runtime internals: - - `runtime/action_projection.py` - - `runtime/context_builder.py` - - `runtime/context_v1_scope.py` - - `runtime/deterministic_guard.py` - - `runtime/handoff.py` - - `runtime/resolution_planner.py` - - `runtime/sidecar_classifier_boundary.py` - - `runtime/vnext_phase_boundary.py` - -### Tests - -- Updated automated coverage: - - `tests/test_context_v1_scope.py` - -## [2026-04-08.160810] - 2026-04-08 - -### Runtime - -- Updated runtime internals: - - `runtime/contracts/decision_tables.schema.json` - - `runtime/contracts/decision_tables.yaml` - - `runtime/contracts/host_message_templates.schema.json` - - `runtime/contracts/side_effect_mapping_table.schema.json` - - `runtime/contracts/signal_priority_table.schema.json` - - `runtime/decision_tables.py` - - `runtime/failure_recovery.py` - - `runtime/message_templates.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-fail-close-contract.py` - -### Tests - -- Updated automated coverage: - - `tests/fixtures/context_fail_close_contract.yaml` - - `tests/test_runtime_decision_tables.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_failure_recovery.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_message_templates.py` - -## [2026-04-02.224459] - 2026-04-02 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-install-payload-bundle-smoke.py` - - `scripts/release-preflight.sh` - -### Tests - -- Updated automated coverage: - - `tests/test_bundle_smoke.py` - - `tests/test_distribution.py` - -### Changed - -- Updated project files: - - `.sopify-skills/plan/20260326_5-plan-20260326-phase1-2-3-plan-plan-20260326-ph/tasks.md` - -## [2026-04-02.162241] - 2026-04-02 - -### Runtime - -- Updated runtime internals: - - `runtime/gate_output.py` - - `runtime/workspace_preflight.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_runtime_gate.py` - -### Changed - -- Updated project files: - - `installer/bootstrap_workspace.py` - -## [2026-04-02.140640] - 2026-04-02 - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-install-payload-bundle-smoke.py` - -### Changed - -- Updated project files: - - `installer/distribution.py` - - `installer/inspection.py` - - `installer/outcome_contract.py` - -## [2026-04-02.130950] - 2026-04-02 - -### Docs - -- Refined public documentation: - - `README.md` - - `README.zh-CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/gate.py` - - `runtime/gate_output.py` - - `runtime/workspace_preflight.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-install-payload-bundle-smoke.py` - - `scripts/runtime_gate.py` - -### Tests - -- Updated automated coverage: - - `tests/test_distribution.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_gate.py` - -### Changed - -- Updated project files: - - `installer/bootstrap_workspace.py` - - `installer/distribution.py` - - `installer/inspection.py` - - `installer/outcome_contract.py` - -## [2026-04-02.094312] - 2026-04-02 - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_runtime_gate.py` - -### Changed - -- Updated project files: - - `installer/bootstrap_workspace.py` - -## [2026-04-01.110138] - 2026-04-01 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING_CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/gate.py` - - `runtime/workspace_preflight.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - - `scripts/check-runtime-smoke.sh` - - `scripts/install_sopify.py` - - `scripts/runtime_gate.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_distribution.py` - - `tests/test_installer.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_gate.py` - -### Changed - -- Updated project files: - - `install.ps1` - - `install.sh` - - `installer/bootstrap_workspace.py` - - `installer/distribution.py` - - `installer/inspection.py` - - `installer/payload.py` - -## [2026-03-31.154241] - 2026-03-31 - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/install_sopify.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer_validate.py` - -### Changed - -- Updated project files: - - `installer/inspection.py` - - `installer/validate.py` - -## [2026-03-31.143816] - 2026-03-31 - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-runtime-smoke.sh` - -### Tests - -- Updated automated coverage: - - `tests/test_installer_validate.py` - -### Changed - -- Updated project files: - - `installer/validate.py` - -## [2026-03-31.142215] - 2026-03-31 - -### Changed - -- Updated project files: - - `CHANGELOG.md` - -## [2026-03-31.140148] - 2026-03-31 - -### Runtime - -- Updated runtime internals: - - `runtime/engine.py` - - `runtime/plan_proposal.py` - - `runtime/router.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - -## [2026-03-30.195249] - 2026-03-30 - -### Runtime - -- Updated runtime internals: - - `runtime/workspace_preflight.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/install_sopify.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_gate.py` - -### Changed - -- Updated project files: - - `installer/bootstrap_workspace.py` - - `installer/hosts/__init__.py` - - `installer/inspection.py` - - `installer/payload.py` - - `installer/validate.py` - -## [2026-03-30.142244] - 2026-03-30 - -### Tests - -- Updated automated coverage: - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `installer/inspection.py` - -## [2026-03-30.134624] - 2026-03-30 - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-install-payload-bundle-smoke.py` - -### Tests - -- Updated automated coverage: - - `tests/test_distribution.py` - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `installer/distribution.py` - - `installer/inspection.py` - -## [2026-03-30.133450] - 2026-03-30 - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/install_sopify.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_runtime_gate.py` - -### Changed - -- Updated project files: - - `installer/hosts/base.py` - - `installer/inspection.py` - - `installer/payload.py` - - `installer/validate.py` - -## [2026-03-30.102148] - 2026-03-30 - -### Runtime - -- Updated runtime internals: - - `runtime/workspace_preflight.py` +- ActionIntent model + gate integration +- Action proposal / rejection / authorization flow +- Direct-edit runtime guard with entry_guard_reason_code +- Plan: `20260506_p2_local_action_contracts` -### Tests +### P1.5 Authorization & Plan Materialization (2026-04-27 – 2026-04-29) -- Updated automated coverage: - - `tests/test_runtime_gate.py` +6 releases. Checkpoint-gated plan writes and rejection surface: -## [2026-03-28.220226] - 2026-03-28 +- Plan materialization auth (checkpoint-gated plan writes) +- Reject surface (proposal_rejected route + host action) +- Advance slices (multi-slice plan orchestration) +- Plans: `20260506_p15_authorization_contract_spec`, `20260506_p15_reject_surface`, `20260505_p15_plan_materialization_auth`, `20260505_p15_advance_slices` -### Docs +### P1 Runtime System Build-Out (2026-03-19 – 2026-04-14) -- Refined public documentation: - - `docs/dev/development-guidelines.md` +42 releases. Core runtime construction: -### Runtime - -- Updated runtime internals: - - `runtime/checkpoint_cancel.py` - - `runtime/context_snapshot.py` - - `runtime/decision.py` - - `runtime/decision_bridge.py` - - `runtime/plan_proposal.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - -### Changed - -- Updated project files: - - `installer/inspection.py` - -## [2026-03-28.002645] - 2026-03-28 - -### Runtime - -- Updated runtime internals: - - `runtime/_models/core.py` - - `runtime/_models/handoff.py` - - `runtime/checkpoint_request.py` - - `runtime/context_recovery.py` - - `runtime/context_snapshot.py` - - `runtime/decision.py` - - `runtime/develop_checkpoint.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/output.py` - - `runtime/router.py` - - `runtime/state.py` - - `runtime/state_invariants.py` - -### Tests - -- Updated automated coverage: - - `tests/runtime_test_support.py` - - `tests/test_installer_status_doctor.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_state.py` - -### Changed - -- Updated project files: - - `installer/inspection.py` - -## [2026-03-27.105943] - 2026-03-27 - -### Runtime - -- Updated runtime internals: - - `runtime/engine.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/plan_scaffold.py` - - `runtime/router.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_plan_scaffold.py` - - `tests/test_runtime_router.py` - -## [2026-03-26.175647] - 2026-03-26 - -### Runtime - -- Updated runtime internals: - - `runtime/_models/core.py` - - `runtime/_models/decision.py` - - `runtime/_models/handoff.py` - - `runtime/_models/proposal.py` - - `runtime/checkpoint_materializer.py` - - `runtime/checkpoint_request.py` - - `runtime/clarification.py` - - `runtime/context_recovery.py` - - `runtime/decision.py` - - `runtime/develop_checkpoint.py` - - `runtime/engine.py` - - `runtime/entry_guard.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/manifest.py` - - `runtime/models.py` - - `runtime/output.py` - - `runtime/plan_orchestrator.py` - - `runtime/plan_proposal.py` - - `runtime/plan_scaffold.py` - - `runtime/router.py` - - `runtime/state.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-prompt-runtime-gate-smoke.py` - - `scripts/check-runtime-smoke.sh` - - `scripts/sync-runtime-assets.sh` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_bundle_smoke.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_gate.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_router.py` - -## [2026-03-26.135542] - 2026-03-26 - -### Runtime - -- Updated runtime internals: - - `runtime/output.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-host-doc-contract.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-success.md` - -### Tests - -- Updated automated coverage: - - `tests/runtime_test_support.py` - - `tests/test_installer.py` - - `tests/test_runtime_engine.py` - -## [2026-03-25.182132] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README.zh-CN.md` - - `README_EN.md` - - `docs/dev/release-process.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-readme-links.py` - - `scripts/check-version-consistency.sh` - - `scripts/release-sync.sh` - -### Tests - -- Updated automated coverage: - - `tests/test_check_readme_links.py` - - `tests/test_release_hooks.py` - -### Changed - -- Updated project files: - - `.githooks/pre-commit` - -## [2026-03-25.165725] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/install-sopify.sh` - - `scripts/install_sopify.py` - - `scripts/render-release-installers.py` - -### Tests - -- Updated automated coverage: - - `tests/test_distribution.py` - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `.github/workflows/ci.yml` - - `install.ps1` - - `install.sh` - - `installer/distribution.py` - - `installer/inspection.py` - -## [2026-03-25.142231] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -### Changed - -- Updated project files: - - `assets/logo.png` - - `assets/logo.svg` - -## [2026-03-25.131617] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -### Changed - -- Updated project files: - - `assets/logo.png` - -## [2026-03-25.104035] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -## [2026-03-25.101956] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -## [2026-03-25.101035] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -## [2026-03-25.100507] - 2026-03-25 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-readme-links.py` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Changed - -- Updated project files: - - `CHANGELOG.md` - -## [2026-03-24.212205] - 2026-03-24 - -### Docs - -- Refined public documentation: - - `docs/how-sopify-works.en.md` - - `docs/how-sopify-works.md` - -### Skills - -- Synced prompt-layer skills: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Changed - -- Updated project files: - - `.gitignore` - - `.sopify-skills/history/2026-03/20260317_design_decision_confirmation/background.md` - - `.sopify-skills/history/2026-03/20260317_design_decision_confirmation/design.md` - - `.sopify-skills/history/2026-03/20260317_design_decision_confirmation/tasks.md` - - `.sopify-skills/history/2026-03/20260320_helloagents_integration_enhancements/background.md` - - `.sopify-skills/history/2026-03/20260320_helloagents_integration_enhancements/design.md` - - `.sopify-skills/history/2026-03/20260320_helloagents_integration_enhancements/future_directions.md` - - `.sopify-skills/history/2026-03/20260320_helloagents_integration_enhancements/tasks.md` - - `.sopify-skills/history/2026-03/20260320_kb_layout_v2/background.md` - - `.sopify-skills/history/2026-03/20260320_kb_layout_v2/design.md` - - `.sopify-skills/history/2026-03/20260320_kb_layout_v2/tasks.md` - - `.sopify-skills/history/2026-03/20260320_preferences-preload-v1/background.md` - - `.sopify-skills/history/2026-03/20260320_preferences-preload-v1/design.md` - - `.sopify-skills/history/2026-03/20260320_preferences-preload-v1/tasks.md` - - `.sopify-skills/history/2026-03/20260320_prompt_runtime_gate/background.md` - - `.sopify-skills/history/2026-03/20260320_prompt_runtime_gate/design.md` - - `.sopify-skills/history/2026-03/20260320_prompt_runtime_gate/tasks.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/background.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/design.md` - - `external_archive://pilot_round1/freyr-h5pages/batch2_observations.md` - - `external_archive://pilot_round1/freyr-h5pages/batch2_stopcheck.md` - - `external_archive://pilot_round1/round1_aggregation.md` - - `external_archive://pilot_round1/rs-sdk/batch3_observations.md` - - `external_archive://pilot_round1/sopify-skills/batch1_observations.md` - - `external_archive://pilot_round1/sopify-skills/batch1_stopcheck.md` - - `(2026-03-31 note) the above local evidence bundle was externalized; see .sopify-skills/history/2026-03/20260321_go-plan/evidence_archive_notice.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/issue_meta_review_no_new_plan.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/issue_raise_plan_reuse_fix_to_8_5.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/issue_single_active_plan_reuse_with_topic_key.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/pilot_review_rubric.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/pilot_round1_review_sheet.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/pilot_sample_matrix.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/tasks.md` - - `.sopify-skills/history/2026-03/20260321_go-plan/trigger_matrix.md` - - `.sopify-skills/history/2026-03/20260323_models-tests-refactor/background.md` - - `.sopify-skills/history/2026-03/20260323_models-tests-refactor/design.md` - - `.sopify-skills/history/2026-03/20260323_models-tests-refactor/tasks.md` - - `.sopify-skills/history/2026-03/20260323_plan_registry_governance/background.md` - - `.sopify-skills/history/2026-03/20260323_plan_registry_governance/design.md` - - `.sopify-skills/history/2026-03/20260323_plan_registry_governance/tasks.md` - - `.sopify-skills/history/2026-03/20260323_readme-about-changelog/background.md` - - `.sopify-skills/history/2026-03/20260323_readme-about-changelog/design.md` - - `.sopify-skills/history/2026-03/20260323_readme-about-changelog/tasks.md` - - `.sopify-skills/history/2026-03/20260323_runtime-gate-diagnostics/background.md` - - `.sopify-skills/history/2026-03/20260323_runtime-gate-diagnostics/design.md` - - `.sopify-skills/history/2026-03/20260323_runtime-gate-diagnostics/tasks.md` - - `.sopify-skills/history/2026-03/20260323_runtime-session-lease-session-scoped-review-stat/background.md` - - `.sopify-skills/history/2026-03/20260323_runtime-session-lease-session-scoped-review-stat/design.md` - - `.sopify-skills/history/2026-03/20260323_runtime-session-lease-session-scoped-review-stat/tasks.md` - - `.sopify-skills/history/index.md` - - `.sopify-skills/plan/20260320_cursor_plugin_install/background.md` - - `.sopify-skills/plan/20260320_cursor_plugin_install/design.md` - - `.sopify-skills/plan/20260320_cursor_plugin_install/tasks.md` - - `.sopify-skills/plan/20260320_default_host_bridge_install/background.md` - - `.sopify-skills/plan/20260320_default_host_bridge_install/design.md` - - `.sopify-skills/plan/20260320_default_host_bridge_install/tasks.md` - - `.sopify-skills/plan/20260323_unified_plan_history_index/background.md` - - `.sopify-skills/plan/20260323_unified_plan_history_index/design.md` - - `.sopify-skills/plan/20260323_unified_plan_history_index/tasks.md` - - `.sopify-skills/plan/20260324_develop-quality-loop/background.md` - - `.sopify-skills/plan/20260324_develop-quality-loop/design.md` - - `.sopify-skills/plan/20260324_develop-quality-loop/tasks.md` - - `.sopify-skills/plan/20260324_task/background.md` - - `.sopify-skills/plan/20260324_task/design.md` - - `.sopify-skills/plan/20260324_task/tasks.md` - -## [2026-03-24.182745] - 2026-03-24 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -## [2026-03-24.181429] - 2026-03-24 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -## [2026-03-24.174944] - 2026-03-24 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README_EN.md` - -### Tests - -- Updated automated coverage: - - `tests/test_release_hooks.py` - -### Changed - -- Updated project files: - - `.claude/settings.local.json` - - `.githooks/commit-msg` - - `.sopify-skills/blueprint/README.md` - - `CONTRIBUTORS.md` - -## [2026-03-24.170253] - 2026-03-24 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/install_sopify.py` - - `scripts/sopify_doctor.py` - - `scripts/sopify_status.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer_status_doctor.py` - -### Changed - -- Updated project files: - - `installer/hosts/__init__.py` - - `installer/hosts/base.py` - - `installer/hosts/claude.py` - - `installer/hosts/codex.py` - - `installer/inspection.py` - - `installer/models.py` - -## [2026-03-24.124504] - 2026-03-24 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - -### Runtime - -- Updated runtime internals: - - `runtime/_models/__init__.py` - - `runtime/_models/artifacts.py` - - `runtime/_models/core.py` - - `runtime/_models/decision.py` - - `runtime/_models/handoff.py` - - `runtime/_models/summary.py` - - `runtime/daily_summary.py` - - `runtime/models.py` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/release-preflight.sh` - - `scripts/sync-runtime-assets.sh` - -### Tests - -- Updated automated coverage: - - `tests/__init__.py` - - `tests/runtime_test_support.py` - - `tests/test_bundle_smoke.py` - - `tests/test_runtime.py` - - `tests/test_runtime_config.py` - - `tests/test_runtime_decision.py` - - `tests/test_runtime_engine.py` - - `tests/test_runtime_execution_gate.py` - - `tests/test_runtime_kb.py` - - `tests/test_runtime_knowledge_layout.py` - - `tests/test_runtime_plan_registry.py` - - `tests/test_runtime_plan_reuse.py` - - `tests/test_runtime_plan_scaffold.py` - - `tests/test_runtime_preferences.py` - - `tests/test_runtime_replay.py` - - `tests/test_runtime_router.py` - - `tests/test_runtime_skill_registry.py` - - `tests/test_runtime_skill_runner.py` - - `tests/test_runtime_summary.py` - -### Changed - -- Updated project files: - - `.sopify-skills/blueprint/README.md` - - `.sopify-skills/blueprint/design.md` - -## [2026-03-23.193526] - 2026-03-23 - -### Docs - -- Refined public documentation: - - `README.md` - - `README_EN.md` - -## [2026-03-23.185925] - 2026-03-23 - -### Docs - -- Refined public documentation: - - `CONTRIBUTING.md` - - `CONTRIBUTING_CN.md` - - `README.md` - - `README_EN.md` - - `docs/how-sopify-works.en.md` - - `docs/how-sopify-works.md` - -### Scripts - -- Adjusted maintenance scripts: - - `scripts/check-readme-links.py` - - `scripts/release-draft-changelog.py` - -### Tests - -- Updated automated coverage: - - `tests/test_check_readme_links.py` - - `tests/test_release_hooks.py` - -### Changed - -- Updated project files: - - `.sopify-skills/blueprint/README.md` - - `.sopify-skills/blueprint/design.md` - -## [2026-03-23.163812] - 2026-03-23 - -### Changed - -- Updated release-relevant files: - - `runtime/gate.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime_gate.py` - -## [2026-03-23.143454] - 2026-03-23 - -### Changed - -- Updated release-relevant files: - - `.sopify-skills/blueprint/design.md` - - `README.md` - - `runtime/clarification_bridge.py` - - `runtime/decision_bridge.py` - - `runtime/engine.py` - - `runtime/gate.py` - - `runtime/manifest.py` - - `runtime/models.py` - - `runtime/router.py` - - `runtime/state.py` - - `scripts/check-prompt-runtime-gate-smoke.py` - - `scripts/clarification_bridge_runtime.py` - - `scripts/decision_bridge_runtime.py` - - `scripts/runtime_gate.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - - `tests/test_runtime_gate.py` - -## [2026-03-23.122831] - 2026-03-23 - -### Changed - -- Updated release-relevant files: - - `.claude/settings.local.json` - - `.sopify-skills/user/feedback.jsonl` - - `Claude/Skills/CN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `runtime/engine.py` - - `runtime/finalize.py` - - `runtime/manifest.py` - - `runtime/output.py` - - `runtime/plan_registry.py` - - `runtime/plan_scaffold.py` - - `scripts/plan_registry_runtime.py` - - `scripts/sync-runtime-assets.sh` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - -## [2026-03-22.225057] - 2026-03-22 - -### Changed - -- Updated release-relevant files: - - `.sopify-skills/blueprint/README.md` - - `.sopify-skills/blueprint/design.md` - - `.sopify-skills/blueprint/tasks.md` - - `.sopify-skills/user/preferences.md` - - `README.md` - - `README_EN.md` - - `runtime/decision.py` - - `runtime/engine.py` - - `runtime/handoff.py` - - `runtime/router.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - - `tests/test_runtime_gate.py` - -## [2026-03-22.183053] - 2026-03-22 - -### Changed - -- Updated release-relevant files: - - `runtime/engine.py` - - `runtime/plan_scaffold.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - -## [2026-03-21.224637] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `runtime/engine.py` - - `runtime/models.py` - - `runtime/plan_scaffold.py` - - `runtime/router.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - -## [2026-03-21.212430] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `README.md` - - `README_EN.md` - - `docs/skill-authoring.en.md` - - `docs/skill-authoring.md` - - `runtime/daily_summary.py` - - `scripts/release-draft-changelog.py` - -### Tests - -- Updated automated coverage: - - `tests/test_release_hooks.py` - - `tests/test_runtime.py` - -## [2026-03-21.203721] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `.sopify-skills/blueprint/README.md` - - `.sopify-skills/blueprint/tasks.md` - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/kb/SKILL.md` - - `Claude/Skills/CN/skills/sopify/templates/SKILL.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/kb/SKILL.md` - - `Claude/Skills/EN/skills/sopify/templates/SKILL.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/kb/SKILL.md` - - `Codex/Skills/CN/skills/sopify/templates/SKILL.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/kb/SKILL.md` - - `Codex/Skills/EN/skills/sopify/templates/SKILL.md` - - `README.md` - - `README_EN.md` - - `runtime/develop_checkpoint.py` - - `runtime/engine.py` - - `runtime/gate.py` - - `runtime/handoff.py` - - `runtime/kb.py` - - `runtime/models.py` - - `runtime/preferences.py` - - `runtime/router.py` - - `runtime/state.py` - - `scripts/sopify_runtime.py` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - - `tests/test_runtime_gate.py` - -## [2026-03-21.163146] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/EN/AGENTS.md` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - -## [2026-03-21.160958] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `CHANGELOG.md` - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `README.md` - - `README_EN.md` - - `runtime/output.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_runtime.py` - -## [2026-03-21.160751] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `CHANGELOG.md` - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `README.md` - - `README_EN.md` - - `runtime/output.py` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - - `tests/test_runtime.py` - -## [2026-03-21.155452] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Claude/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Claude/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/CN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/question-output.md` - - `Codex/Skills/EN/skills/sopify/analyze/assets/success-output.md` - - `Codex/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-partial.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-quick-fix.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-success.md` - -### Tests - -- Updated automated coverage: - - `tests/test_installer.py` - -## [2026-03-21.151713] - 2026-03-21 - -### Changed - -- Updated release-relevant files: - - `.sopify-skills/blueprint/README.md` - - `.sopify-skills/blueprint/background.md` - - `.sopify-skills/blueprint/design.md` - - `.sopify-skills/blueprint/tasks.md` - - `.sopify-skills/project.md` - - `.sopify-skills/wiki/overview.md` - - `Claude/Skills/CN/CLAUDE.md` - - `Claude/Skills/CN/skills/sopify/design/SKILL.md` - - `Claude/Skills/CN/skills/sopify/design/assets/background-template.md` - - `Claude/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/CN/skills/sopify/design/assets/plan-light-template.md` - - `Claude/Skills/CN/skills/sopify/design/assets/tasks-template.md` - - `Claude/Skills/CN/skills/sopify/design/references/design-rules.md` - - `Claude/Skills/CN/skills/sopify/develop/SKILL.md` - - `Claude/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Claude/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `Claude/Skills/CN/skills/sopify/kb/SKILL.md` - - `Claude/Skills/CN/skills/sopify/templates/SKILL.md` - - `Claude/Skills/EN/CLAUDE.md` - - `Claude/Skills/EN/skills/sopify/design/SKILL.md` - - `Claude/Skills/EN/skills/sopify/design/assets/background-template.md` - - `Claude/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Claude/Skills/EN/skills/sopify/design/assets/plan-light-template.md` - - `Claude/Skills/EN/skills/sopify/design/assets/tasks-template.md` - - `Claude/Skills/EN/skills/sopify/design/references/design-rules.md` - - `Claude/Skills/EN/skills/sopify/develop/SKILL.md` - - `Claude/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `Claude/Skills/EN/skills/sopify/develop/references/develop-rules.md` - - `Claude/Skills/EN/skills/sopify/kb/SKILL.md` - - `Claude/Skills/EN/skills/sopify/templates/SKILL.md` - - `Codex/Skills/CN/AGENTS.md` - - `Codex/Skills/CN/skills/sopify/design/SKILL.md` - - `Codex/Skills/CN/skills/sopify/design/assets/background-template.md` - - `Codex/Skills/CN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/CN/skills/sopify/design/assets/plan-light-template.md` - - `Codex/Skills/CN/skills/sopify/design/assets/tasks-template.md` - - `Codex/Skills/CN/skills/sopify/design/references/design-rules.md` - - `Codex/Skills/CN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/CN/skills/sopify/develop/references/develop-rules.md` - - `Codex/Skills/CN/skills/sopify/kb/SKILL.md` - - `Codex/Skills/CN/skills/sopify/templates/SKILL.md` - - `Codex/Skills/EN/AGENTS.md` - - `Codex/Skills/EN/skills/sopify/design/SKILL.md` - - `Codex/Skills/EN/skills/sopify/design/assets/background-template.md` - - `Codex/Skills/EN/skills/sopify/design/assets/output-summary.md` - - `Codex/Skills/EN/skills/sopify/design/assets/plan-light-template.md` - - `Codex/Skills/EN/skills/sopify/design/assets/tasks-template.md` - - `Codex/Skills/EN/skills/sopify/design/references/design-rules.md` - - `Codex/Skills/EN/skills/sopify/develop/assets/output-success.md` - - `Codex/Skills/EN/skills/sopify/develop/references/develop-rules.md` - - `Codex/Skills/EN/skills/sopify/kb/SKILL.md` - - `Codex/Skills/EN/skills/sopify/templates/SKILL.md` - - `README.md` - - `README_EN.md` - - `runtime/clarification.py` - - `runtime/decision.py` - - `runtime/engine.py` - - `runtime/execution_gate.py` - - `runtime/finalize.py` - - `runtime/kb.py` - - `runtime/knowledge_layout.py` - - `runtime/knowledge_sync.py` - - `runtime/manifest.py` - - `runtime/plan_scaffold.py` - - `scripts/check-runtime-smoke.sh` - -### Tests - -- Updated automated coverage: - - `tests/test_runtime.py` - -## [2026-03-20.214138] - 2026-03-20 - -### Changed - -- Release hook automation now auto-drafts a minimal root `CHANGELOG.md` `[Unreleased]` block from staged release-relevant files when the section is empty. -- `pre-commit` now snapshots release-managed files and restores them on hook failure, preventing partial README badge / SOPIFY_VERSION drift after a failed release sync. - -## [2026-03-20.183348] - 2026-03-20 - -### Added - -- New prompt-level runtime gate assets: - - `runtime/gate.py` - - `runtime/workspace_preflight.py` - - `scripts/runtime_gate.py` - - `scripts/check-prompt-runtime-gate-smoke.py` - -### Changed - -- Host prompt contracts for Codex and Claude now require `runtime_gate.py enter` as the first Sopify hop, with `allowed_response_mode` driving fail-closed follow-up behavior. -- Bundle manifest / installer / sync validation now declare and verify the `runtime_gate` capability and the `limits.runtime_gate_*` contract. -- README docs now treat prompt-level runtime gate as Layer 1, define `current_handoff.json` as the primary machine truth, and limit `current_gate_receipt.json` to visibility-only usage. - -### Tests - -- Added `tests/test_runtime_gate.py` coverage for normal follow-up, checkpoint-only flows, and fail-closed behavior. -- Expanded bundle/install integration coverage to assert `runtime_gate` files, manifest fields, and vendored runtime-gate execution. - -## [2026-03-20.141842] - 2026-03-20 - -### Added - -- New `~summary` runtime route with deterministic daily recap artifacts: - - `runtime/daily_summary.py` - - `.sopify-skills/replay/daily/YYYY-MM/YYYY-MM-DD/summary.json` - - `.sopify-skills/replay/daily/YYYY-MM/YYYY-MM-DD/summary.md` -- New workspace-scoped long-term preference preload helper: - - `runtime/preferences.py` - - `scripts/preferences_preload_runtime.py` -- New project bootstrap artifacts for long-term collaboration state: - - `.sopify-skills/project.md` - - `.sopify-skills/wiki/overview.md` - - `.sopify-skills/user/preferences.md` - -### Changed - -- Runtime output now appends a local wall-clock timestamp to user-visible stage summaries. -- Replay events now include structured skill-activation metadata for summary and timeline reuse. -- Bundle manifest / payload / bootstrap contracts now declare and validate the `preferences_preload` capability. -- Codex / Claude host prompt assets now document `preferences-preload-v1`, including: - - `workspace_root + plan.directory + user/preferences.md` path resolution - - `fail-open with visibility` - - fixed priority `current explicit task > preferences.md > default rules` -- `~summary` now: - - includes uncommitted changes by default - - preserves the active handoff / current run / last route - - rebuilds invalid existing `summary.json` in place instead of failing - - keeps state evidence refs stable when `plan.directory` is customized - - renders fully localized English output instead of mixing Chinese templates -- Blueprint and README docs now treat “current time display + ~summary detailed recap” as the active user-facing slice. - -### Tests - -- Expanded `tests/test_runtime.py` with `~summary` hardening coverage for: - - repeated same-day revision increments - - git-unavailable fallback - - invalid existing summary rebuild - - active-flow preservation - - persisted artifact / terminal render consistency - - English-only output templates - - dynamic state evidence refs under custom `plan.directory` -- Expanded `tests/test_installer.py` to assert host prompt / bundle wiring for `preferences_preload`. - -## [2026-03-19.183617] - 2026-03-19 - -### Scope - -- Current minimal published runtime slice: `runtime-backed ~go plan` -- Not part of this slice: - - generic-entry auto-bridge for `~compare` - - runtime-owned develop orchestrator - - standalone `workflow-learning` runtime helper - -### Added - -- Host-local Sopify payload layout under `~/.codex/sopify/` / `~/.claude/sopify/`, including: - - `payload-manifest.json` - - `bundle/` - - `helpers/bootstrap_workspace.py` -- Minimal KB bootstrap in `runtime/kb.py`, creating `project.md`, `wiki/overview.md`, `user/preferences.md`, and `history/index.md` on first runtime execution. -- New bundle manifest contract in `runtime/manifest.py`, written to `.sopify-runtime/manifest.json` during bundle sync. -- New runtime handoff contract in `runtime/handoff.py`, written to `.sopify-skills/state/current_handoff.json` for non-terminal routes. -- New sub-skill `model-compare` (CN/EN) for configuration-driven multi-model parallel comparison with manual user selection. -- New compare trigger contract: - - Command: `~compare ` - - Natural-language prefix: `对比分析:` -- Multi-model MVP config block in `examples/sopify.config.yaml` with `candidates`, `timeout_sec`, and `max_parallel`. -- New GitHub Actions workflow `.github/workflows/ci.yml` to gate PR/Push with sync and version checks. -- Default repo-local raw-input runtime entry `scripts/sopify_runtime.py` and plan-only helper `scripts/go_plan_runtime.py`. -- Runtime bundle sync script `scripts/sync-runtime-assets.sh` for vendoring `.sopify-runtime/` into another repository. -- One-command installer entry `scripts/install-sopify.sh` with a Python installer core and host adapters for `codex:zh-CN`, `codex:en-US`, `claude:zh-CN`, and `claude:en-US`. -- Runtime smoke check script `scripts/check-runtime-smoke.sh`. -- Runtime behavior test coverage in `tests/test_runtime.py`, including vendored bundle validation. -- Installer test coverage in `tests/test_installer.py` for Codex/Claude sample install paths. -- Develop-first checkpoint callback support: - - `runtime/develop_checkpoint.py` - - `scripts/develop_checkpoint_runtime.py` - - vendored manifest capability + helper contract for `continue_host_develop` - -### Changed - -- Installer semantics now split into: - - host prompt-layer install - - host-local payload install - - optional current-workspace prewarm through the same bootstrap helper used later by the host -- Tightened workspace bundle compatibility checks: - - bootstrap no longer treats a same-version `.sopify-runtime/` as `READY` when required bridge capabilities are missing - - bootstrap now also verifies critical bridge / CLI files before skipping refresh - - installer bundle validation now uses the same bridge / CLI file expectations as workspace bootstrap -- Extended the checkpoint contract to carry `resume_context` for develop-stage callbacks, so confirmation can safely return to `continue_host_develop` or fail back to `review_or_execute_plan`. -- Extended runtime / bundle docs and host prompts to require `develop_checkpoint_runtime.py` whenever a mid-develop user decision must re-enter runtime. -- `--workspace` is now optional prewarm input instead of an implicit current-directory sync. -- Added workspace bootstrap contract: - - when Sopify is triggered inside a project workspace and `.sopify-runtime/manifest.json` is missing or incompatible, the host should call the installed bootstrap helper first - - after bootstrap succeeds, execution continues through the repo-local bundle manifest -- Added no-silent-downgrade behavior for workspace bundle bootstrap: - - if a workspace bundle is newer than the installed global payload, bootstrap skips instead of overwriting it -- Updated bundle sync, installer validation, and smoke checks to treat `.sopify-runtime/manifest.json` as a required control-plane artifact. -- Updated runtime output to render `Next:` from the structured handoff contract before falling back to route-only copy. -- Refactored runtime builtin-skill discovery to a catalog-first model via `runtime/builtin_catalog.py`, so vendored bundles no longer depend on scanning `Codex/Skills` or `Claude/Skills` trees. -- Extended `SkillMeta` and external skill manifests with forward-compatible catalog fields: `entry_kind`, `handoff_kind`, `contract_version`, and `supports_routes`. -- Added explicit builtin override policy in `runtime/skill_registry.py`: external skills can only replace builtin ids when `override_builtin: true` is declared. -- Updated CN/EN AGENTS routing and command references to include `~compare` and `model-compare`. -- Updated `README.md` and `README_EN.md` with: - - 7-skill install verification list - - Multi-model MVP quick start - - Environment-variable-only API key setup (`export ...`, including `~/.zshrc` persistence guidance) - - Recommended one-command installer usage for host prompt setup + vendored bundle sync -- Added MVP fallback rule: when no usable multi-model config exists, `~compare` / `对比分析:` should not fail and must fallback to single-model with a clear notice. -- Clarified two-layer compare switches: - - `multi_model.enabled` = feature-level gate - - `multi_model.candidates[*].enabled` = per-candidate participation gate -- Added compare defaults and built-in entry rule: - - `multi_model.include_default_model` defaults to `true` (session default model joins compare without extra config) - - Parallel compare starts only when usable model count is at least 2 (fallback to single-model below that) -- Updated compare fallback output contract to include detailed fallback reasons. -- Added default-on context bridge for compare with a single bypass switch: - - `multi_model.context_bridge` defaults to `true` - - When external candidates are present, compare builds one shared context pack (`extract -> redact -> truncate`) before fan-out - - `context_bridge=false` keeps a question-only emergency bypass path -- Added execution-level context-pack contract for compare: - - Fixed extraction/redaction/truncation budgets - - Unified request payload (`question + context_pack`) across candidates - - Empty-pack safeguard (`context_pack empty` -> single-model fallback) -- Wired `~compare` entry to runtime module `scripts/model_compare_runtime.py` (`run_model_compare_runtime`) and converged compare docs to this runtime as SSOT. -- Unified fallback wording across CN/EN using normalized reason-code format (e.g., `MISSING_API_KEY`, `INSUFFICIENT_USABLE_MODELS`) and reduced duplicated execution-detail text in docs. -- Updated sync scripts to ignore Finder/Explorer noise files (`.DS_Store`, `Thumbs.db`) to reduce false drift reports. -- Updated maintainer docs (`README.md`, `README_EN.md`, `CONTRIBUTING.md`) to document the full gate chain: - - `sync-skills.sh` - - `check-skills-sync.sh` - - `check-version-consistency.sh` -- Clarified release boundary across README, blueprint, and changelog: - - current minimal published slice = `runtime-backed ~go plan` - - `~compare` generic-entry bridge / `~go exec` develop bridge / `workflow-learning` runtime helper remain out of scope for this slice -- Clarified the next-stage boundary across runtime/docs/tests: - - P1-A now lands only the minimum KB bootstrap - - selective history recovery / history archive / task-state runtime remain for later P1 slices - -## [2026-02-13] - 2026-02-13 - -### Added - -- Sync scripts for keeping Codex/Claude skill bundles aligned: - - `scripts/sync-skills.sh` - - `scripts/check-skills-sync.sh` -- New sub-skill `workflow-learning` (CN/EN) for full local trace capture, replay, and step-by-step explanation. -- Separate sub-skill changelog files for `workflow-learning`: - - `Codex/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md` - - `Codex/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md` -- Sync/check usage guidance in `README.md`, `README_EN.md`, and `CONTRIBUTING.md`. -- Lightweight title color behavior clarification: - - `title_color` applies to the title line only - - Fallback to plain text when color is unsupported -- User preference layer in KB rules and templates: - - `.sopify-skills/user/preferences.md` - - `.sopify-skills/user/feedback.jsonl` -- Conservative learning rules (only persist explicit long-term preferences). -- New workflow-learning proactive capture config: - - `workflow.learning.auto_capture` with `always | by_requirement | manual | off` - -### Changed +- Engine, router, gate, handoff, output pipeline +- Checkpoint system (clarification + decision) +- Develop callback + quality loop +- Skill resolver + builtin catalog + runtime skill execution +- KB bootstrap + blueprint scaffold +- Plan registry + plan scaffold + archive lifecycle +- State store (session-scoped review isolation) +- Bundle manifest + install/payload bootstrap +- Convention smoke test (`20260501_convention_smoke`) +- Prompt-layer skills (Codex/Claude CN/EN) -- Corrected Claude Code CN install command in `README.md`. -- Clarified source-of-truth workflow: edit `Codex/Skills/{CN,EN}` then sync to `Claude/Skills/{CN,EN}`. -- Clarified branding semantics: `brand: auto` derives brand as `{repo}-ai` from project name. -- Clarified workflow-learning behavior: replay/review/why intent recognition is always enabled; `auto_capture` only controls proactive recording. +### Foundation (2026-02-13) -## [2026-01-15.1] - 2026-01-15 +- Skill sync scripts (`sync-skills.sh`, `check-skills-sync.sh`) +- Sub-skill `workflow-learning` for replay/review (sunset in P3b) +- User preference layer (`preferences.md`, `feedback.jsonl`) +- Config: `workflow.learning.auto_capture` (sunset in P3b) +- Title color behavior, branding semantics clarification -### Added +### Initial Release (2026-01-15) - Initial version (ruleset and skill structure). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 484358f..3733732 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -142,7 +142,7 @@ Behavior summary: - `pre-commit` runs `scripts/release-preflight.sh` and then `scripts/release-sync.sh`. - Release-managed files are re-staged into the same commit when checks pass. -- When `CHANGELOG.md -> [Unreleased]` is empty, `release-sync` auto-drafts grouped notes from the current staged files. +- When `CHANGELOG.md -> [Unreleased]` is empty, `release-sync` auto-drafts summary-level notes (category bullets, no per-file lists) from the current staged files. - `commit-msg` only appends `Release-Sync`, `Release-Version`, and `Release-Date` when the pre-commit handoff exists. - Plan A scoped commits must include `Context-Checkpoint: A|B|C|D`; the hook only enforces this when staged files touch Plan A runtime/test surfaces or the checkpoint governance assets themselves. - Scoped Plan A pull requests must keep `Context-Checkpoint`, `Decision IDs`, `Blocked by`, and `Out-of-scope touched` filled in `.github/pull_request_template.md`; CI validates the template plus PR body metadata on matching diffs. diff --git a/CONTRIBUTING_CN.md b/CONTRIBUTING_CN.md index 9106dd0..fa254c7 100644 --- a/CONTRIBUTING_CN.md +++ b/CONTRIBUTING_CN.md @@ -148,7 +148,7 @@ git config core.hooksPath .githooks - `pre-commit` 会先运行 `scripts/release-preflight.sh`,再运行 `scripts/release-sync.sh` - release-managed 文件会在检查通过后自动回到同一个 commit -- 当 `CHANGELOG.md -> [Unreleased]` 为空时,`release-sync` 会根据当前 staged files 自动生成分组草稿 +- 当 `CHANGELOG.md -> [Unreleased]` 为空时,`release-sync` 会根据当前 staged files 自动生成摘要级草稿(分类 bullet,不含逐文件列表) - `commit-msg` 只有在存在 pre-commit handoff 时,才会追加 `Release-Sync`、`Release-Version`、`Release-Date` - 命中 Plan A 作用域的提交必须带上 `Context-Checkpoint: A|B|C|D`;hook 只会在 staged files 命中 Plan A runtime/test 面或治理入口资产时强制校验 - 命中 Plan A 作用域的 PR 必须在 `.github/pull_request_template.md` 中填写 `Context-Checkpoint`、`Decision IDs`、`Blocked by`、`Out-of-scope touched`;CI 会同时校验模板和 PR body 元数据 diff --git a/scripts/release-draft-changelog.py b/scripts/release-draft-changelog.py index 45219c4..d5e39de 100644 --- a/scripts/release-draft-changelog.py +++ b/scripts/release-draft-changelog.py @@ -3,8 +3,8 @@ Output structure (per release entry): 1. Summary — 1-3 sentence user-visible impact - 2. Plan pkgs — grouped by plan_id / feature_key / lifecycle_state - 3. Details — file list in
collapsible block + 2. Changed — category-level semantic bullets (no per-file lists) + 3. Plan pkgs — grouped by plan_id / feature_key / lifecycle_state """ from __future__ import annotations From c46447e44a7e8d0626f65129f487f6b191dcf696 Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 15:48:41 +0800 Subject: [PATCH 06/12] blueprint: P4a output rendering audit + P4c output contract convergence - P4a: add output rendering fields classification (machine truth projection / human hint / internal taxonomy leak) to Frozen External Surface table scope - P4c: add output contract convergence slice (status symbol semantics, Next demotion, Changes redefinition, Gate line simplification) --- .sopify-skills/blueprint/tasks.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.sopify-skills/blueprint/tasks.md b/.sopify-skills/blueprint/tasks.md index 2828af4..901715a 100644 --- a/.sopify-skills/blueprint/tasks.md +++ b/.sopify-skills/blueprint/tasks.md @@ -64,6 +64,7 @@ - 枚举 keep-list:protocol.md、gate contract(gate_receipt schema)、handoff/receipt machine truth fields、archive truth(ArchiveCheckResult / ArchiveApplyResult)、install.sh/install.ps1 contract(SOURCE_CHANNEL, SOURCE_REF)、builtin_catalog.py 导出接口(freeze 指接口契约形态——schema / entry_kind / metadata contract,不指具体 skill 枚举或文件字节;能力上下线属内容变更,不违反 freeze)、skill_eval baseline/SLO - **冻结 persistence surface 分类**:keep-list 覆盖到目录级别(参照 design.md "Persistence Surface 分层"表),明确哪些目录属于长期知识/主链真相/凭证/可删派生,作为 P4b 减重和 P4c 宿主消费治理的红线 - 输出:design.md 加 "Frozen External Surface" 表(与 Persistence Surface 分层互补——后者分类所有持久化面,Frozen 表只冻结外部消费面的 keep-list;不重复造表) +- **Output rendering fields 分类**:逐字段审计 `runtime/output.py` 渲染层,分三类——machine truth projection(handoff/receipt 投影)/ human hint(Next 等面向人的提示)/ internal taxonomy leak(gate_status 等不应默认暴露的内部术语)。审计结果写入 Frozen External Surface 表,作为 P4c output contract convergence 的输入 - 不写代码,纯边界确认 ### P4b: Runtime Surface Consolidation @@ -91,6 +92,7 @@ P4a keep-list 确认后执行。先删后并,不先设计新结构。 - **宿主消费边界**:宿主只允许消费"主链机器真相"层(current_run/current_plan/current_handoff/current_clarification/current_decision)和"可审计凭证"层(gate_receipt/archive_receipt);不得消费 state/sessions/* 内部细节、last_route 等 runtime-only/derived 面(参照 design.md "Persistence Surface 分层"表) - **验收 (a) 文档递进顺序**:渐进式披露 Layer 0 Protocol ≤120 行 → Layer 1 Gate → Layer 2 Phase → Layer 3 Reference(不进 prompt) - **验收 (b) 运行时首接触感知**:新用户首次使用时,只感知到"中断可恢复"和"需要拍板时会停"两个语义;blueprint / checkpoint taxonomy / runtime state 等内部概念不在默认运行时路径中主动暴露。doctor/status 不主动呈现 checkpoint 分类体系,~go 入口不前置 blueprint 概念 +- **Output contract convergence**:基于 P4a 审计分类,收敛 `runtime/output.py` 渲染层——① 状态符语义:定义 canonical route family → 符号映射(当前 consult=`!` 无明确约束);② Next 降级:明确为 human hint,不再混合 `required_host_action` + `route_name` 推导,宿主消费 handoff 不依赖 Next;③ Changes 重定义:`loaded_files`(恢复上下文)从 Changed(实际写入)中拆出,或重命名为 Touched/Files;④ Gate 行简化:默认输出不暴露 `gate_status`/`blocking_reason`/`plan_completion` 三元组,详细诊断留给 doctor/status - **Builtin skill capability disclosure**:宿主文案稳定表达 builtin skill 的当前能力边界与可消费方式;AGENTS.md 只做消费投影,builtin_catalog 为唯一 truth source。当前 analyze/design/develop 是 phase-bound workflow skill(entry_kind=null, triggers=[]),不宣称 standalone invocation。若后续要支持 builtin skill 显式单独调用,必须先 formalize 独立的 invocation metadata contract / invocation syntax;在该 contract 明确前,本项只做披露,不预设其进入 P2 或单列里程碑。边界:只覆盖 builtin skill,不扩展到外部 skill discovery/routing/distribution(background.md 明确排除) ## 未完成长期项 From 20e43b30dc63b9f9826a8dbc5a3a3dad1ab8e091 Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 16:29:21 +0800 Subject: [PATCH 07/12] P3b S3: test classification markers (contract/smoke/distribution/implementation-mirror) - 31 test files annotated with '# Test classification: ' - contract: 23 | smoke: 1 | distribution: 6 | implementation-mirror: 1 - implementation-mirror only: test_runtime_knowledge_layout.py - Includes tests/protocol/test_convention_compliance.py - tasks.md S3 marked done; S1/S2 verification items updated --- .../plan/20260508_p3b_perimeter_cleanup/tasks.md | 16 ++++++++-------- tests/protocol/test_convention_compliance.py | 1 + tests/test_action_intent.py | 1 + tests/test_bundle_smoke.py | 1 + tests/test_check_readme_links.py | 1 + tests/test_context_checkpoints.py | 1 + tests/test_context_v1_scope.py | 1 + tests/test_contract_consistency.py | 1 + tests/test_distribution.py | 1 + tests/test_installer.py | 1 + tests/test_installer_status_doctor.py | 1 + tests/test_installer_validate.py | 1 + tests/test_release_hooks.py | 1 + tests/test_runtime_config.py | 1 + tests/test_runtime_decision.py | 1 + tests/test_runtime_decision_tables.py | 1 + tests/test_runtime_engine.py | 1 + tests/test_runtime_execution_gate.py | 1 + tests/test_runtime_failure_recovery.py | 1 + tests/test_runtime_gate.py | 1 + tests/test_runtime_kb.py | 1 + tests/test_runtime_knowledge_layout.py | 1 + tests/test_runtime_message_templates.py | 1 + tests/test_runtime_plan_registry.py | 1 + tests/test_runtime_plan_reuse.py | 1 + tests/test_runtime_plan_scaffold.py | 1 + tests/test_runtime_preferences.py | 1 + tests/test_runtime_router.py | 1 + tests/test_runtime_sample_invariant_gate.py | 1 + tests/test_runtime_skill_registry.py | 1 + tests/test_runtime_skill_runner.py | 1 + tests/test_runtime_state.py | 1 + 32 files changed, 39 insertions(+), 8 deletions(-) diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md index 1b45193..64ce63e 100644 --- a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md @@ -21,8 +21,8 @@ archive_ready: false - [x] 1.1 `release-preflight.sh`:从 `unittest discover` 改为 `pytest` - [x] 1.2 `evals/skill_eval_report.json` 加入 `.gitignore`;baseline 和 SLO 文件保留 -- [ ] 1.3 验证:`bash scripts/release-preflight.sh` 正常退出 -- [ ] 1.4 (补) CONTRIBUTING.md / CONTRIBUTING_CN.md / scripts/sync-runtime-assets.sh 中 unittest discover 统一为 pytest +- [x] 1.3 验证:`bash scripts/release-preflight.sh` 正常退出 +- [x] 1.4 (补) CONTRIBUTING.md / CONTRIBUTING_CN.md / scripts/sync-runtime-assets.sh 中 unittest discover 统一为 pytest ## S2: Replay 下线 + 旧概念清理 + Runtime 外围残留 @@ -62,20 +62,20 @@ archive_ready: false ### S2 验证(硬验收) -- [ ] 2.V1 `pytest` 全通过(待跑) +- [x] 2.V1 `pytest` 全通过(684 passed, 49 subtests) - [x] 2.V2 `grep -rn "replay" runtime/*.py | grep -v "^Binary" | grep -v __pycache__` 仅剩注释(config.py:90 sunset 注释, router.py:377 deprecated 注释) - [x] 2.V3 `grep -rn "workflow.learning" runtime/*.py | grep -v __pycache__` 无命中 -- [ ] 2.V4 `python3 -c "from runtime.builtin_catalog import load_builtin_skills; ..."` 待跑 +- [x] 2.V4 `python3 -c "from runtime.builtin_catalog import load_builtin_skills; from pathlib import Path; skills = load_builtin_skills(repo_root=Path('.'), language='zh-CN'); assert 'workflow-learning' not in [s.name for s in skills]"` workflow-learning 不在枚举中 - [x] 2.V5 `test -f runtime/builtin_skill_packages/workflow-learning/skill.yaml && echo FAIL || echo OK` 输出 OK - [x] 2.V6 `grep -c "workflow-learning" runtime/builtin_catalog.generated.json` 输出 0 - [x] 2.V7 `grep -c 'replay_session_dir' runtime/handoff.py` 输出 0 -- [ ] 2.V8 `grep -rn "replay" tests/*.py | grep -v __pycache__` 仅剩 test_installer.py footer 字面量(prompt asset 待更新) +- [x] 2.V8 `grep -rn "replay" tests/*.py | grep -v __pycache__` 仅剩 test_installer.py footer 字面量(prompt asset 待更新) ## S3: Tests 分类标注 -- [ ] 3.1 `tests/test_*.py` 按 contract / smoke / distribution / implementation-mirror 标注 -- [ ] 3.2 输出分类汇总表 -- [ ] 3.3 验证:所有 test 文件都有明确分类标注;`pytest` 全通过 +- [x] 3.1 `tests/test_*.py` + `tests/protocol/test_*.py` 按 contract / smoke / distribution / implementation-mirror 标注(31 文件) +- [x] 3.2 分类汇总:contract 23 | smoke 1 | distribution 6 | implementation-mirror 1(test_runtime_knowledge_layout.py) +- [x] 3.3 验证:所有 test 文件都有 `# Test classification:` 标注;`pytest` 684 passed, 49 subtests ## S4: CHANGELOG 压缩 + README 首屏降噪 diff --git a/tests/protocol/test_convention_compliance.py b/tests/protocol/test_convention_compliance.py index 45dd91f..bf5dc3c 100644 --- a/tests/protocol/test_convention_compliance.py +++ b/tests/protocol/test_convention_compliance.py @@ -1,3 +1,4 @@ +# Test classification: contract """Protocol Compliance Suite Phase 1. Validates compliance items 1-5 from protocol.md §5 (Phase 1 scope). diff --git a/tests/test_action_intent.py b/tests/test_action_intent.py index e4c5ffe..7481c1b 100644 --- a/tests/test_action_intent.py +++ b/tests/test_action_intent.py @@ -1,3 +1,4 @@ +# Test classification: contract """Deterministic tests for ActionValidator (P0-B) and side-effect mapping (P0-E), plus integration tests for ActionProposal gate flow (P0-G). diff --git a/tests/test_bundle_smoke.py b/tests/test_bundle_smoke.py index b4ad10a..a653d91 100644 --- a/tests/test_bundle_smoke.py +++ b/tests/test_bundle_smoke.py @@ -1,3 +1,4 @@ +# Test classification: smoke from __future__ import annotations import json diff --git a/tests/test_check_readme_links.py b/tests/test_check_readme_links.py index e633587..5549100 100644 --- a/tests/test_check_readme_links.py +++ b/tests/test_check_readme_links.py @@ -1,3 +1,4 @@ +# Test classification: distribution from __future__ import annotations import contextlib diff --git a/tests/test_context_checkpoints.py b/tests/test_context_checkpoints.py index 671a72e..47ddc9e 100644 --- a/tests/test_context_checkpoints.py +++ b/tests/test_context_checkpoints.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from pathlib import Path diff --git a/tests/test_context_v1_scope.py b/tests/test_context_v1_scope.py index c25a11e..92c0631 100644 --- a/tests/test_context_v1_scope.py +++ b/tests/test_context_v1_scope.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from unittest.mock import patch diff --git a/tests/test_contract_consistency.py b/tests/test_contract_consistency.py index e5d587d..49c2b44 100644 --- a/tests/test_contract_consistency.py +++ b/tests/test_contract_consistency.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations import unittest diff --git a/tests/test_distribution.py b/tests/test_distribution.py index 3cdec17..419dce0 100644 --- a/tests/test_distribution.py +++ b/tests/test_distribution.py @@ -1,3 +1,4 @@ +# Test classification: distribution from __future__ import annotations from io import StringIO diff --git a/tests/test_installer.py b/tests/test_installer.py index 689878c..72ce447 100644 --- a/tests/test_installer.py +++ b/tests/test_installer.py @@ -1,3 +1,4 @@ +# Test classification: distribution from __future__ import annotations import importlib.util diff --git a/tests/test_installer_status_doctor.py b/tests/test_installer_status_doctor.py index 0dfff2f..ff66ba8 100644 --- a/tests/test_installer_status_doctor.py +++ b/tests/test_installer_status_doctor.py @@ -1,3 +1,4 @@ +# Test classification: distribution from __future__ import annotations from datetime import datetime, timedelta, timezone diff --git a/tests/test_installer_validate.py b/tests/test_installer_validate.py index 4406e29..52dc0e1 100644 --- a/tests/test_installer_validate.py +++ b/tests/test_installer_validate.py @@ -1,3 +1,4 @@ +# Test classification: distribution from __future__ import annotations from pathlib import Path diff --git a/tests/test_release_hooks.py b/tests/test_release_hooks.py index 66475a2..9b99b51 100644 --- a/tests/test_release_hooks.py +++ b/tests/test_release_hooks.py @@ -1,3 +1,4 @@ +# Test classification: distribution from __future__ import annotations from pathlib import Path diff --git a/tests/test_runtime_config.py b/tests/test_runtime_config.py index 8f25ec4..954c1df 100644 --- a/tests/test_runtime_config.py +++ b/tests/test_runtime_config.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_decision.py b/tests/test_runtime_decision.py index de2e3f6..9e6e857 100644 --- a/tests/test_runtime_decision.py +++ b/tests/test_runtime_decision.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_decision_tables.py b/tests/test_runtime_decision_tables.py index eef029b..1ec3cfb 100644 --- a/tests/test_runtime_decision_tables.py +++ b/tests/test_runtime_decision_tables.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_engine.py b/tests/test_runtime_engine.py index d4135a7..d0fa47a 100644 --- a/tests/test_runtime_engine.py +++ b/tests/test_runtime_engine.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from dataclasses import replace diff --git a/tests/test_runtime_execution_gate.py b/tests/test_runtime_execution_gate.py index dbe2451..b1be2d2 100644 --- a/tests/test_runtime_execution_gate.py +++ b/tests/test_runtime_execution_gate.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_failure_recovery.py b/tests/test_runtime_failure_recovery.py index 798ed9a..07cf316 100644 --- a/tests/test_runtime_failure_recovery.py +++ b/tests/test_runtime_failure_recovery.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_gate.py b/tests/test_runtime_gate.py index 5f843c6..27c2a24 100644 --- a/tests/test_runtime_gate.py +++ b/tests/test_runtime_gate.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations import importlib.util diff --git a/tests/test_runtime_kb.py b/tests/test_runtime_kb.py index b57bbbb..91d0a5d 100644 --- a/tests/test_runtime_kb.py +++ b/tests/test_runtime_kb.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_knowledge_layout.py b/tests/test_runtime_knowledge_layout.py index d108788..1881492 100644 --- a/tests/test_runtime_knowledge_layout.py +++ b/tests/test_runtime_knowledge_layout.py @@ -1,3 +1,4 @@ +# Test classification: implementation-mirror from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_message_templates.py b/tests/test_runtime_message_templates.py index 4a73173..63d8b6e 100644 --- a/tests/test_runtime_message_templates.py +++ b/tests/test_runtime_message_templates.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations import copy diff --git a/tests/test_runtime_plan_registry.py b/tests/test_runtime_plan_registry.py index d4461ea..1b51129 100644 --- a/tests/test_runtime_plan_registry.py +++ b/tests/test_runtime_plan_registry.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_plan_reuse.py b/tests/test_runtime_plan_reuse.py index feb16f8..0665572 100644 --- a/tests/test_runtime_plan_reuse.py +++ b/tests/test_runtime_plan_reuse.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_plan_scaffold.py b/tests/test_runtime_plan_scaffold.py index 29401ca..bf847f7 100644 --- a/tests/test_runtime_plan_scaffold.py +++ b/tests/test_runtime_plan_scaffold.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_preferences.py b/tests/test_runtime_preferences.py index 1833ad8..2776879 100644 --- a/tests/test_runtime_preferences.py +++ b/tests/test_runtime_preferences.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_router.py b/tests/test_runtime_router.py index 84bea58..bcd8a79 100644 --- a/tests/test_runtime_router.py +++ b/tests/test_runtime_router.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_sample_invariant_gate.py b/tests/test_runtime_sample_invariant_gate.py index fe1b8f6..337a7fb 100644 --- a/tests/test_runtime_sample_invariant_gate.py +++ b/tests/test_runtime_sample_invariant_gate.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_skill_registry.py b/tests/test_runtime_skill_registry.py index ee48062..6a07142 100644 --- a/tests/test_runtime_skill_registry.py +++ b/tests/test_runtime_skill_registry.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_skill_runner.py b/tests/test_runtime_skill_runner.py index 78bbd12..13294fb 100644 --- a/tests/test_runtime_skill_runner.py +++ b/tests/test_runtime_skill_runner.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * diff --git a/tests/test_runtime_state.py b/tests/test_runtime_state.py index 3095b20..4eaeadf 100644 --- a/tests/test_runtime_state.py +++ b/tests/test_runtime_state.py @@ -1,3 +1,4 @@ +# Test classification: contract from __future__ import annotations from tests.runtime_test_support import * From b8025329d244f1d74793f78f42f6808082886c00 Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 17:06:26 +0800 Subject: [PATCH 08/12] =?UTF-8?q?P3b=20S4:=20README=20first-screen=20?= =?UTF-8?q?=E2=80=94=20Install-first=20entry,=203-step=20table,=20Conventi?= =?UTF-8?q?on=20mode=20removed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Quick Start: install command is now the default entry point - Returning-user scenario: "Already in a Sopify-managed repo?" at L30 - Added Start/Pause/Resume lightweight table as mental model anchor - Removed "Convention mode (no install needed)" framing from both READMEs - tasks.md: synced 4.6/4.7/4.V3/4.V4/2.21 acceptance criteria to match new framing --- .../20260508_p3b_perimeter_cleanup/tasks.md | 22 ++-- README.md | 114 +++++------------ README.zh-CN.md | 116 +++++------------- 3 files changed, 70 insertions(+), 182 deletions(-) diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md index 64ce63e..a2d03a7 100644 --- a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md @@ -54,7 +54,7 @@ archive_ready: false - [x] 2.18 `tests/test_runtime_sample_invariant_gate.py`:replay_required 相关断言(L92-107)——清除 - [x] 2.19 `tests/test_runtime_skill_registry.py`:workflow-learning assertIn(L61)——删除 - [x] 2.20 `tests/test_installer.py`:replay 相关引用(L895)——已清除 gitignore 断言;L1301/L1354 footer 断言保留(prompt asset 未更新,注释标注) -- [ ] 2.21 清理 tests/__pycache__ 中 replay 相关 .pyc +- [x] 2.21 验证 tests/__pycache__ 中 replay 相关 .pyc 为 0(tests/__pycache__、tests/protocol/__pycache__、tests/pytest_entries/__pycache__ 均无 replay 相关 .pyc;__pycache__ 目录本身包含其他正常缓存,不删除) ### Runtime 外围残留 @@ -88,19 +88,19 @@ archive_ready: false ### README 首屏降噪与默认入口翻转 -- [ ] 4.5 首屏只保留 3 件事:中断可恢复 + 需要拍板时会停 + 安装入口 -- [ ] 4.6 默认叙事以 Convention(纯协议、无 runtime)为入口 -- [ ] 4.7 Runtime(完整编排、gate、checkpoint)定位为增强路径 -- [ ] 4.8 plan lifecycle / blueprint / runtime gate / checkpoint taxonomy / task size routing / .sopify-runtime 等内部术语降级到二级文档 -- [ ] 4.9 `.sopify-runtime` 只作为后台实现细节出现,不作为用户首接触概念 -- [ ] 4.10 同步更新 README.zh-CN.md +- [x] 4.5 首屏只保留 3 件事:中断可恢复 + 需要拍板时会停 + 安装入口(首屏 34 行) +- [x] 4.6 Install 为默认入口;已在 Sopify-managed repo 为 returning-user 场景 +- [x] 4.7 三步轻量表(Start → Pause → Resume)替代旧流程图,传达用户旅程但不暴露内部编排 +- [x] 4.8 plan lifecycle / blueprint / runtime gate / checkpoint taxonomy / task size routing / .sopify-runtime 等内部术语降级到二级文档 +- [x] 4.9 `.sopify-runtime` 只作为后台实现细节出现,不作为用户首接触概念(README 中 0 次出现) +- [x] 4.10 同步更新 README.zh-CN.md ### S4 验证 -- [ ] 4.V1 README 首屏 < 50 行 -- [ ] 4.V2 首屏不出现 blueprint / checkpoint taxonomy / runtime state / .sopify-runtime 等术语 -- [ ] 4.V3 Convention 作为默认叙事出现在 Runtime 之前 -- [ ] 4.V4 `pytest` 全通过 +- [x] 4.V1 README 首屏 < 50 行(实际 34 行) +- [x] 4.V2 首屏不出现 blueprint / checkpoint taxonomy / runtime state / .sopify-runtime 等术语 +- [x] 4.V3 Install 为默认入口(L24);"Already in a Sopify-managed repo?" 降级为 returning-user 场景(L30) +- [x] 4.V4 复用上轮 pytest 绿灯(684 passed, 49 subtests);本轮 README-only, 无可执行路径变更,未重跑 ## 完成标准 diff --git a/README.md b/README.md index 47a8a1a..3943b45 100644 --- a/README.md +++ b/README.md @@ -11,32 +11,37 @@ [![Version](https://img.shields.io/badge/version-2026--05--07.220011-orange.svg)](#version-history) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md) -English · [简体中文](./README.zh-CN.md) · [Quick Start](#quick-start) · [Configuration](#configuration) · [Contributors](./CONTRIBUTORS.md) +English · [简体中文](./README.zh-CN.md) · [Quick Start](#quick-start) · [Contributors](./CONTRIBUTORS.md) --- -## Why Sopify? +When facts are missing, Sopify stops and asks. When a decision needs your approval, it waits. When work is interrupted, it resumes from the last stopping point — even across different AI hosts. -As repositories grow, AI-assisted development runs into a hidden problem: decision context stays trapped in chat history, each new session re-derives the project state, and the user's mental model, the AI's understanding, and the codebase start to drift apart. +## Quick Start + +```bash +curl -fsSL https://github.com/evidentloop/sopify/releases/latest/download/install.sh | bash -s -- --target codex:en-US +``` -Sopify uses project-level conventions to make critical steps visible: when facts are missing, it stops and asks for them; when a branch needs a decision, it waits for confirmation; when work is interrupted, it resumes from current state instead of improvising. The basic process record is generated automatically, but the long-term compounding value still depends on consistently closing out work and maintaining project knowledge. +After install, use `~go` to start a managed workflow. See [Installation](#installation) for other targets, platforms, and verification. -### What You'll Actually Notice +**Already in a Sopify-managed repo?** Open any AI host and continue the unfinished task — it picks up from where you left off. [Full walkthrough →](./docs/how-sopify-works.en.md) -- After an interruption, work resumes from the last stopping point — even when you switch to a different AI host or model. -- Complex changes can be independently reviewed in an isolated pass before execution. -- When a plan changes after execution was authorized, the AI cannot silently proceed — it re-confirms with you first. -- Plans, decisions, and review outcomes accumulate as reusable project assets, not disposable chat history. -- The AI pauses when facts are missing or a path needs your confirmation; simple tasks stay lightweight. +| Step | What happens | +|------|-------------| +| Start | Ask the host to begin or continue a task | +| Pause | Sopify stops when facts are missing or a decision needs you | +| Resume | Work picks up from project state — even on a different host | -### What Kinds of Projects Benefit Most +--- + +## Why Sopify? -- Multi-stage work that keeps moving in the same repository instead of one-off edits -- You're willing to manage progress with plan / blueprint artifacts and close out each stage +As repositories grow, AI-assisted development runs into a hidden problem: decision context stays trapped in chat history, each new session re-derives the project state, and the user's mental model, the AI's understanding, and the codebase start to drift apart. -### What Your AI Host Doesn't Solve +Sopify uses project-level conventions to make critical steps visible. The basic process record is generated automatically, but the long-term compounding value still depends on consistently closing out work and maintaining project knowledge. | Gap | Sopify's answer | |-----|-----------------| @@ -45,29 +50,17 @@ Sopify uses project-level conventions to make critical steps visible: when facts | Decisions are invisible and non-auditable | Plan changes force re-confirmation — the AI cannot silently proceed | | Each session's learning is disposable | Plans, decisions, and reviews persist as reusable project assets | -## Quick Start - -Two ways to start, depending on your repo: - -### Already using Sopify? Try it directly +## Installation -If your repo has `.sopify-skills/`, open any AI host (Claude, Cursor, Codex…) and ask it to continue an unfinished task — it picks up from the last stopping point, not from scratch. That's the protocol working, no runtime needed. - -Full Convention walkthrough: [protocol.md §4](./.sopify-skills/blueprint/protocol.md#4-典型生命周期样例) - -### First time? Install first +Two-step install (recommended for first-time review): ```bash -# Recommended: official stable one-liner -curl -fsSL https://github.com/evidentloop/sopify/releases/latest/download/install.sh | bash -s -- --target codex:en-US - -# Two-step install: download first, review, then run curl -fsSL -o sopify-install.sh https://github.com/evidentloop/sopify/releases/latest/download/install.sh sed -n '1,40p' sopify-install.sh bash sopify-install.sh --target codex:en-US ``` -Windows PowerShell can download the same stable asset and run it locally: +Windows PowerShell: ```powershell iwr https://github.com/evidentloop/sopify/releases/latest/download/install.ps1 -OutFile sopify-install.ps1 @@ -75,7 +68,7 @@ Get-Content sopify-install.ps1 -TotalCount 40 .\sopify-install.ps1 --target codex:en-US ``` -The repo-local / source install path remains available for developers and maintainers, but is no longer the first-screen entry: +The repo-local install path remains available for developers and maintainers: ```bash bash scripts/install-sopify.sh --target codex:en-US @@ -89,7 +82,7 @@ Install targets: - `claude:zh-CN` - `claude:en-US` -The protocol (Convention mode) works with any host. Verified runtime integrations today: +The protocol works with any host. Verified runtime integrations today: | Host | Install target | Availability | Validation coverage | Notes | |------|----------------|--------------|---------------------|-------| @@ -105,10 +98,9 @@ Installer behavior: - Installs the selected host prompt layer and the Sopify payload - A standard install makes your host ready to run Sopify; most users do not need `--workspace` -- Sopify prepares `.sopify-runtime/` the first time you trigger it in a project workspace - `--workspace` is an advanced prewarm path for maintainers, CI, or explicit repository setup -### How Your Workflow Changes After Install +### After Install - Use `~go` when you want Sopify to manage the full task workflow for you. - Interrupt anytime — come back (even in a different tool) and resume from where you left off. @@ -126,19 +118,11 @@ python3 scripts/sopify_doctor.py --format text - `workspace outcome: stub_selected [continue]`: the workspace runtime entry is healthy - Payload or bundle corruption errors (for example `global_bundle_missing`, `global_bundle_incompatible`, or `global_index_corrupted`): repair the install and retry -### Choose an Entry by Task Size - -| Task Type | Sopify Path | -|-----------|-------------| -| Simple change (≤2 files) | Direct execution | -| Medium task (3-5 files) | Light plan + execution | -| Complex work (>5 files / architecture change) | Full three-phase workflow | - ### First Use After install, open your selected host inside a repository and paste one of the prompts below. -```bash +```text # Simple task "Fix the typo on line 42 in src/utils.ts" @@ -150,9 +134,6 @@ After install, open your selected host inside a repository and paste one of the # Plan only "~go plan Refactor the database layer" - -# Replay / retrospective -"Replay the latest implementation and explain why this approach was chosen" ``` ### What It Looks Like (Illustrative) @@ -170,44 +151,7 @@ Next: Reply "continue" to start implementation This is only a placeholder example of the pacing and format, not a fixed output contract; simple tasks are shorter, and complex tasks pause at checkpoints for confirmation. -For runtime gate, checkpoints, and plan lifecycle details, see [How Sopify Works](./docs/how-sopify-works.en.md). - -### Recommended Workflow - -```text -○ User Input -│ -◆ Runtime Gate -│ -◇ Routing Decision -├── ▸ Q&A ────────────────────────────→ Direct output -└── ▸ Code task - │ - ◇ Complexity Decision - ├── Simple (≤2 files) ────────────→ Direct execution - ├── Medium (3-5 files) ───────────→ Light plan package - │ (single-file `plan.md`) - └── Complex (>5 files / architecture change) - ├── Requirements ··· Fact checkpoint - ├── Design ··· Decision checkpoint - └── Standard plan package - (`background.md` / `design.md` / `tasks.md`) - │ - ◆ Execution confirmation ··· User confirms - │ - ◆ Implementation - │ - ◆ Summary + handoff - │ - ◇ Optional: ~go finalize - ├── Refresh blueprint index - ├── Clean active state - └── Archive → history/ -``` - -> ◆ = execution node ◇ = decision node ··· = checkpoint (pauses, then resumes after user input) -> -> See [How Sopify Works](./docs/how-sopify-works.en.md) for full details on checkpoints and plan lifecycle. +For the full workflow, checkpoints, and plan lifecycle details, see [How Sopify Works](./docs/how-sopify-works.en.md). ## Configuration @@ -289,9 +233,9 @@ This only affects newly created directories; existing history is not migrated au ### Q: When should I use `--workspace` prewarm? -Most users do not need it. A default install is already complete; Sopify bootstraps `.sopify-runtime/` automatically on the first project trigger. +Most users do not need it. A default install is already complete; Sopify bootstraps the project-local runtime automatically on the first trigger. -Use `--workspace` only for maintainer validation, CI, or when you explicitly want to prewarm `.sopify-runtime/` for a specific repository ahead of time. For this advanced path, use the repo-local installer: +Use `--workspace` only for maintainer validation, CI, or when you explicitly want to prewarm a specific repository ahead of time. For this advanced path, use the repo-local installer: ```bash python3 scripts/install_sopify.py --target codex:en-US --workspace /path/to/project diff --git a/README.zh-CN.md b/README.zh-CN.md index 94f8efb..68748d5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -11,32 +11,37 @@ [![版本](https://img.shields.io/badge/version-2026--05--07.220011-orange.svg)](#版本历史) [![欢迎PR](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING_CN.md) -[English](./README.md) · 简体中文 · [快速开始](#快速开始) · [配置说明](#配置说明) · [贡献者](./CONTRIBUTORS.md) +[English](./README.md) · 简体中文 · [快速开始](#快速开始) · [贡献者](./CONTRIBUTORS.md) --- -## 为什么选择 Sopify? +缺事实时停下来补事实,需要拍板时等待你确认,中断后从上次停点恢复——即使切换到不同的 AI 宿主也能接力。 -随着仓库增长,AI 辅助开发会遇到一个隐性问题:决策依据散落在对话里,每次新 session 都要重新理解上下文,用户认知、AI 理解和代码现状会逐渐偏离。 +## 快速开始 + +```bash +curl -fsSL https://github.com/evidentloop/sopify/releases/latest/download/install.sh | bash -s -- --target codex:zh-CN +``` -Sopify 用项目级约定把关键节点变成可见流程:缺事实时停下来补事实,需要拍板时等待你确认,中断后从当前状态恢复,而不是让 AI 自行拍板。基础过程记录会自动产生,长期复利则取决于是否持续做阶段收口和维护知识资产。 +安装后用 `~go` 启动全托管工作流。其他 target 和平台请看[安装说明](#安装说明)。 -### 你会实际感受到什么 +**已在 Sopify 管理的仓库里?** 打开任意 AI 宿主,让它继续未完成的任务——它会从上次停点恢复。[完整演练 →](./.sopify-skills/blueprint/protocol.md#4-典型生命周期样例) -- 中断后从上次停点恢复,即使切换到不同的 AI 宿主或模型也能精确接力 -- 复杂变更可在执行前经过隔离的独立审查 -- 方案在授权后被修改时,AI 不能静默继续 — 必须重新向你确认 -- 方案、决策和审查结论会沉淀为可复用的项目资产,而不是一次性聊天记录 -- 缺事实或需要选路时停下来等你确认;简单任务自动简化 +| 步骤 | 发生了什么 | +|------|-----------| +| 开始 | 让宿主开始或继续一个任务 | +| 暂停 | 缺少事实或需要你拍板时,Sopify 自动停下 | +| 恢复 | 从项目状态接续——即使切换到另一个宿主 | -### 在哪类项目里最有价值 +--- + +## 为什么选择 Sopify? -- 在同一仓库中持续推进多阶段工作,而不是一次性改动 -- 愿意用 plan / blueprint 管理进展,并在阶段完成后持续做收口 +随着仓库增长,AI 辅助开发会遇到一个隐性问题:决策依据散落在对话里,每次新 session 都要重新理解上下文,用户认知、AI 理解和代码现状会逐渐偏离。 -### 你的 AI 宿主解决不了什么? +Sopify 用项目级约定把关键节点变成可见流程。基础过程记录会自动产生,长期复利则取决于是否持续做阶段收口和维护知识资产。 | 差距 | Sopify 的回答 | |------|--------------| @@ -45,29 +50,17 @@ Sopify 用项目级约定把关键节点变成可见流程:缺事实时停下 | 决策不可见、不可审计 | 方案变更后必须重新确认 — AI 不能静默继续 | | 每个 session 的学习都是一次性的 | 方案、决策、审查结论沉淀为可复用的项目资产 | -## 快速开始 - -根据你的仓库状态,有两种开始方式: - -### 已启用 Sopify?直接体验 +## 安装说明 -如果仓库里已有 `.sopify-skills/`,打开任意 AI 宿主(Claude、Cursor、Codex……),让它继续一个未完成的任务。它会从上次停点恢复,而不是从头开始。这就是协议在工作,无需 runtime。 - -完整 Convention 演练:[protocol.md §4](./.sopify-skills/blueprint/protocol.md#4-典型生命周期样例) - -### 首次使用?先安装 +两步安装(推荐首次使用时先审查再执行): ```bash -# 推荐:稳定版一行安装 -curl -fsSL https://github.com/evidentloop/sopify/releases/latest/download/install.sh | bash -s -- --target codex:zh-CN - -# 两步安装:先下载,确认后再执行 curl -fsSL -o sopify-install.sh https://github.com/evidentloop/sopify/releases/latest/download/install.sh sed -n '1,40p' sopify-install.sh bash sopify-install.sh --target codex:zh-CN ``` -Windows PowerShell 可下载同一份 stable asset 后执行: +Windows PowerShell: ```powershell iwr https://github.com/evidentloop/sopify/releases/latest/download/install.ps1 -OutFile sopify-install.ps1 @@ -75,7 +68,7 @@ Get-Content sopify-install.ps1 -TotalCount 40 .\sopify-install.ps1 --target codex:zh-CN ``` -开发者 / 源码安装路径仍保留,但不再作为首屏主入口: +开发者 / 源码安装路径仍保留: ```bash bash scripts/install-sopify.sh --target codex:zh-CN @@ -89,7 +82,7 @@ python3 scripts/install_sopify.py --target claude:zh-CN --workspace /path/to/pro - `claude:zh-CN` - `claude:en-US` -协议层(Convention 模式)适用于任何宿主。当前已验证的 runtime 集成: +协议层适用于任何宿主。当前已验证的 runtime 集成: | 宿主 | 安装 target | 可用性 | 验证范围 | 说明 | |------|-------------|--------|----------|------| @@ -99,13 +92,12 @@ python3 scripts/install_sopify.py --target claude:zh-CN --workspace /path/to/pro 说明: - 更细的 capability claim 与现场诊断请看 `sopify status` / `sopify doctor` -- “可用性”表示当前交付层级;“验证范围”表示当前已经验证到哪一层 +- "可用性"表示当前交付层级;"验证范围"表示当前已经验证到哪一层 安装后行为: - installer 会安装宿主提示层,并在宿主根目录安装 Sopify payload - 默认安装后,宿主已可运行 Sopify;大多数用户不需要 `--workspace` -- 首次在项目仓库里触发 Sopify 时,才会准备 `.sopify-runtime/` - `--workspace` 适用于维护者、CI 或显式预热仓库的高级路径 ### 安装后你的工作流会怎么变化 @@ -126,19 +118,11 @@ python3 scripts/sopify_doctor.py --format text - `workspace outcome: stub_selected [continue]`:workspace runtime 入口健康 - 如果 doctor 报出 payload 或 bundle 损坏类错误(例如 `global_bundle_missing`、`global_bundle_incompatible`、`global_index_corrupted`),先修复安装,再重试 -### 根据任务规模选入口 - -| 任务类型 | Sopify 处理方式 | -|---------|----------------| -| 简单修改(≤2 文件) | 直接执行 | -| 中等任务(3-5 文件) | 轻量方案 + 执行 | -| 复杂任务(>5 文件 / 架构变更) | 完整三阶段 | - ### 首次使用 安装完成后,在仓库目录中打开你选择的宿主,直接粘贴下面任一条提示即可开始。 -```bash +```text # 简单任务 "修复 src/utils.ts 第 42 行的 typo" @@ -150,9 +134,6 @@ python3 scripts/sopify_doctor.py --format text # 只规划 "~go plan 重构数据库层" - -# 回放 / 复盘 -"回放最近一次实现,重点讲为什么这么做" ``` ### 你会看到什么(示意) @@ -165,49 +146,12 @@ python3 scripts/sopify_doctor.py --format text 任务: 5 项 --- -Next: 回复“继续”进入开发实施 +Next: 回复"继续"进入开发实施 ``` 这个示意只展示风格与节奏,不代表固定字段;简单任务会更短,复杂任务会在 checkpoint 处暂停等待你确认。 -若想先理解 runtime gate、checkpoint 与 plan 生命周期,直接看 [工作流说明](./docs/how-sopify-works.md)。 - -### 建议工作流 - -```text -○ 用户输入 -│ -◆ Runtime Gate -│ -◇ 路由判定 -├── ▸ 咨询 / 回放 ─────────────────→ 直接输出 -└── ▸ 代码任务 - │ - ◇ 复杂度判定 - ├── 简单(≤2 文件)────────────→ 直接执行 - ├── 中等(3-5 文件)──────────→ 轻量方案包 - │ (单文件 `plan.md`) - └── 复杂(>5 文件 / 架构变更) - ├── 需求分析 ··· 补事实 checkpoint - ├── 方案设计 ··· 拍板 checkpoint - └── 标准方案包 - (`background.md` / `design.md` / `tasks.md`) - │ - ◆ 执行确认 ··· 用户确认继续 - │ - ◆ 开发实施 - │ - ◆ 摘要输出 + Handoff - │ - ◇ 可选:~go finalize - ├── 刷新 blueprint 索引 - ├── 清理 state 活动态 - └── 归档 → history/ -``` - -> ◆ = 执行节点 ◇ = 判定节点 ··· = checkpoint(可暂停,等用户输入后恢复) -> -> 详细流程与 checkpoint 机制见 [工作流说明](./docs/how-sopify-works.md)。 +详细流程与 checkpoint 机制见 [工作流说明](./docs/how-sopify-works.md)。 ## 配置说明 @@ -289,9 +233,9 @@ plan: ### Q: 什么时候需要 `--workspace` 预热? -大多数用户不需要。默认安装已经完整;首次在项目仓库里触发 Sopify 时,会自动 bootstrap `.sopify-runtime/`。 +大多数用户不需要。默认安装已经完整;首次在项目仓库里触发 Sopify 时,会自动准备项目侧运行时。 -只有在维护者验证、CI,或你明确想提前为某个仓库准备 `.sopify-runtime/` 时,才需要 `--workspace`。这类高级场景建议走源码安装路径: +只有在维护者验证、CI,或你明确想提前为某个仓库预热时,才需要 `--workspace`。这类高级场景建议走源码安装路径: ```bash python3 scripts/install_sopify.py --target codex:zh-CN --workspace /path/to/project From 9d55f0b8d7602a7233c105411b160e0e8cc39971 Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 17:17:23 +0800 Subject: [PATCH 09/12] P3b: completion checklist 6/6 pass (pytest + release-preflight + all gates green) --- .../plan/20260508_p3b_perimeter_cleanup/tasks.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md index a2d03a7..d874476 100644 --- a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md @@ -104,9 +104,9 @@ archive_ready: false ## 完成标准 -- [ ] `pytest` 全通过 -- [ ] `release-preflight.sh` 正常退出 -- [ ] `grep -rn "replay" runtime/*.py` 无生产代码命中 -- [ ] README 首屏符合降噪标准 -- [ ] 所有 test 文件有分类标注 -- [ ] CHANGELOG 无文件列表格式条目 +- [x] `pytest` 全通过(684 passed, 49 subtests, 242s) +- [x] `release-preflight.sh` 正常退出(all checks passed, eval gate PASSED, all metrics 1.0/0.0) +- [x] `grep -rn "replay" runtime/*.py` 无生产代码命中 +- [x] README 首屏符合降噪标准(38 行,Install-first,0 次 Convention mode) +- [x] 所有 test 文件有分类标注(31 文件) +- [x] CHANGELOG 无文件列表格式条目 From 8004ad2d066df0ab5cc18883c99b2cbd3a87023e Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 17:33:35 +0800 Subject: [PATCH 10/12] =?UTF-8?q?P3b:=20archive=20plan=20package=20?= =?UTF-8?q?=E2=86=92=20history/2026-05/20260508=5Fp3b=5Fperimeter=5Fcleanu?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lifecycle_state: archived, plan_status: completed Completion: 6/6 gates passed (pytest + release-preflight + all metrics green) Remaining: 2.13 prompt asset replay literal (deferred to prompt asset update) --- .sopify-skills/blueprint/README.md | 4 ++-- .../20260508_p3b_perimeter_cleanup/background.md | 0 .../20260508_p3b_perimeter_cleanup/design.md | 0 .../20260508_p3b_perimeter_cleanup/tasks.md | 13 +++++++------ .sopify-skills/history/index.md | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) rename .sopify-skills/{plan => history/2026-05}/20260508_p3b_perimeter_cleanup/background.md (100%) rename .sopify-skills/{plan => history/2026-05}/20260508_p3b_perimeter_cleanup/design.md (100%) rename .sopify-skills/{plan => history/2026-05}/20260508_p3b_perimeter_cleanup/tasks.md (98%) diff --git a/.sopify-skills/blueprint/README.md b/.sopify-skills/blueprint/README.md index f9e02d1..e2f7d95 100644 --- a/.sopify-skills/blueprint/README.md +++ b/.sopify-skills/blueprint/README.md @@ -14,7 +14,7 @@ - 当前活动 plan:暂无。 -- history 归档:已可用;最近归档为 `../history/2026-05/20260507_p3a_contract_aligned_surface_cleanup`。 +- history 归档:已可用;最近归档为 `../history/2026-05/20260508_p3b_perimeter_cleanup`。 ## 深入阅读入口 @@ -27,5 +27,5 @@ - [Sopify 最小协议规范 (Protocol v0)](./protocol.md) - [Skill 标准对齐蓝图](./skill-standards-refactor.md) - [变更历史](../history/index.md) -- 最近归档:`../history/2026-05/20260507_p3a_contract_aligned_surface_cleanup` +- 最近归档:`../history/2026-05/20260508_p3b_perimeter_cleanup` diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/background.md b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/background.md similarity index 100% rename from .sopify-skills/plan/20260508_p3b_perimeter_cleanup/background.md rename to .sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/background.md diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/design.md b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/design.md similarity index 100% rename from .sopify-skills/plan/20260508_p3b_perimeter_cleanup/design.md rename to .sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/design.md diff --git a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md similarity index 98% rename from .sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md rename to .sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md index d874476..51bc45c 100644 --- a/.sopify-skills/plan/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md @@ -2,13 +2,14 @@ plan_id: 20260508_p3b_perimeter_cleanup feature_key: p3b_perimeter_cleanup level: standard -lifecycle_state: active +lifecycle_state: archived knowledge_sync: - project: aligned - background: aligned - design: aligned - tasks: aligned -archive_ready: false + project: skip + background: skip + design: skip + tasks: skip +archive_ready: true +plan_status: completed --- # 任务清单: P3b Perimeter Cleanup diff --git a/.sopify-skills/history/index.md b/.sopify-skills/history/index.md index 4774568..fab09d6 100644 --- a/.sopify-skills/history/index.md +++ b/.sopify-skills/history/index.md @@ -4,6 +4,7 @@ ## 索引 +- `2026-05-08` [`20260508_p3b_perimeter_cleanup`](2026-05/20260508_p3b_perimeter_cleanup/) - standard - 任务清单: P3b Perimeter Cleanup - `2026-05-08` [`20260507_p3a_contract_aligned_surface_cleanup`](2026-05/20260507_p3a_contract_aligned_surface_cleanup/) - standard - P3a Contract-Aligned Surface Cleanup: execution routing 收敛 + knowledge_sync audit trail + dead path cleanup (-88 LOC) + Runtime 减重剥离为 Px - `2026-05-07` [`20260506_p2_local_action_contracts`](2026-05/20260506_p2_local_action_contracts/) - standard - P2 Local Action Contracts: subject binding 泛化 + side_effect_delta schema + action-effect canonical pairing(admission contract 闭合) - `2026-05-06` [`20260506_p15_verifier_normative_slice`](2026-05/20260506_p15_verifier_normative_slice/) - standard - P1.5-D Verifier Minimum Normative Slice: protocol §6 升格 normative(verdict/evidence/source MUST)+ 消费路径 contract + design.md 引用修正 @@ -16,7 +17,6 @@ - `2026-05-04` [`20260326_phase1-2-3-plan`](2026-03/20260326_phase1-2-3-plan/) - archived - Phase 1-2-3 旧总纲(B1/B2/B3 语义,已被 P0→P4 蓝图取代) - `2026-05-04` [`20260417_ux_perception_tuning`](2026-04/20260417_ux_perception_tuning/) - archived - UX 感知层调优(B/C 已完成,A 放弃;不独立拆包) - `2026-05-04` [`20260429_host_prompt_governance`](2026-04/20260429_host_prompt_governance/) - archived(upstreamed) - Host Prompt Governance(核心观点已进蓝图 P3b/P4,设计推演保留供回看) - - `2026-04-30` [`20260429_standard-archive-finalize-archive-checkpoint`](2026-04/20260429_standard-archive-finalize-archive-checkpoint/) - standard - 任务清单: 为“显式主体与生命周期收敛”主题写第一子切片方案文档:新建 standard 方案包,只覆... - `2026-05-01` [`20260501_convention_smoke`](2026-05/20260501_convention_smoke/) - smoke - Convention 模式跨宿主最小 roundtrip 验证(Host B: Claude Sonnet + Host C: Codex/GPT-5,5/5 pass) - `2026-05-01` [`20260429_legacy_feature_cleanup`](2026-05/20260429_legacy_feature_cleanup/) - standard - Legacy Feature Cleanup: consult override 删除 + model compare 功能面移除 From 3fcdebe923f40f0b3470cb966edad9e5eed17d4e Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 19:10:00 +0800 Subject: [PATCH 11/12] P3b: remove workflow-learning/replay from active prompt perimeter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Codex/Skills CN+EN AGENTS.md: remove workflow-learning strategy block, routing row, skill table row, replay/ dir entry, footer replay ref - Claude/Skills CN+EN CLAUDE.md: same symmetric cleanup - skills/sopify/workflow-learning/ (×4): delete from install shipped surface - tests/test_installer.py: align footer_contract_line assertions (L1302, L1356) - .sopify-skills/project.md: align test dialect (L27 unittest→pytest, L30 bundle smoke unittest→pytest), drop replay/handoff paired term (L34) - tasks.md 2.13: mark done Release-Sync: yes Release-Version: 2026-05-08.191000 Release-Date: 2026-05-08 --- .../20260508_p3b_perimeter_cleanup/tasks.md | 2 +- .sopify-skills/project.md | 6 +- CHANGELOG.md | 15 ++ Claude/Skills/CN/CLAUDE.md | 21 +-- .../sopify/workflow-learning/CHANGELOG.md | 20 --- .../skills/sopify/workflow-learning/SKILL.md | 154 ------------------ Claude/Skills/EN/CLAUDE.md | 21 +-- .../sopify/workflow-learning/CHANGELOG.md | 20 --- .../skills/sopify/workflow-learning/SKILL.md | 154 ------------------ Codex/Skills/CN/AGENTS.md | 21 +-- .../sopify/workflow-learning/CHANGELOG.md | 20 --- .../skills/sopify/workflow-learning/SKILL.md | 154 ------------------ Codex/Skills/EN/AGENTS.md | 21 +-- .../sopify/workflow-learning/CHANGELOG.md | 20 --- .../skills/sopify/workflow-learning/SKILL.md | 154 ------------------ README.md | 2 +- README.zh-CN.md | 2 +- tests/test_installer.py | 4 +- 18 files changed, 31 insertions(+), 780 deletions(-) delete mode 100644 Claude/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md delete mode 100644 Claude/Skills/CN/skills/sopify/workflow-learning/SKILL.md delete mode 100644 Claude/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md delete mode 100644 Claude/Skills/EN/skills/sopify/workflow-learning/SKILL.md delete mode 100644 Codex/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md delete mode 100644 Codex/Skills/CN/skills/sopify/workflow-learning/SKILL.md delete mode 100644 Codex/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md delete mode 100644 Codex/Skills/EN/skills/sopify/workflow-learning/SKILL.md diff --git a/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md index 51bc45c..84d5622 100644 --- a/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md @@ -44,7 +44,7 @@ plan_status: completed ### 旧概念清理(P3a 已 sunset surface 残留) - [x] 2.12 tests 中验证 P3a 已 sunset surface 的断言——更新或删除 -- [ ] 2.13 prompt 中引用已 sunset contract 的段落——清除(prompt asset 本体含 replay 字面量,待 prompt asset 整体更新时处理) +- [x] 2.13 prompt 中引用已 sunset contract 的段落——清除(Codex/Skills + Claude/Skills CN|EN:AGENTS/CLAUDE.md 路由表/策略块/技能行、footer replay 引用、replay/ 目录条目均已移除;skills/sopify/workflow-learning/ 目录(安装链路 shipped surface)全部删除) - [x] 2.14 handoff/output 旧兼容投影——清除 - [x] 2.15 reason phrasing / phase label 特判——清除 diff --git a/.sopify-skills/project.md b/.sopify-skills/project.md index 53067c3..940a5c8 100644 --- a/.sopify-skills/project.md +++ b/.sopify-skills/project.md @@ -24,14 +24,14 @@ - `runtime/models.py` 是稳定公开 facade;`from runtime.models import X` 继续作为对外兼容入口。 - 具体实现收敛到 `runtime/_models/`,当前按 `core / decision / artifacts / summary / handoff` 分组,避免在公开路径下继续堆积单文件复杂度。 - facade 必须维护显式 `__all__`,保证 `from runtime.models import *` 的 surface 仍然可控。 -- repo-local runtime 回归统一使用 `python3 -m unittest discover tests -v`,避免拆分后因手写文件列表漏测。 +- repo-local runtime 回归统一使用 `python3 -m pytest tests -v`,避免拆分后因手写文件列表漏测。 - repo-local 共享测试 helper 固定收敛到 `tests/runtime_test_support.py`;`tests/test_runtime_*.py` 负责按主题拆分具体 `TestCase`。 - bundle 对外继续保留 `.sopify-runtime/tests/test_runtime.py` 路径,但该文件只承担最小 smoke contract,不再复制 repo-local 全量 runtime 测试。 -- 需要对绝对路径下的 bundle smoke 做便携校验时,统一使用 `python3 -m unittest discover -s -p 'test_runtime.py' -v`,避免 `unittest` 把绝对路径误当成模块名。 +- 需要对绝对路径下的 bundle smoke 做便携校验时,统一使用 `python3 -m pytest /test_runtime.py -v`,避免路径解析歧义。 ## Develop 质量约定 -- `continue_host_develop` 仍是宿主负责真实代码修改的正式模式;runtime 只负责 machine-readable quality contract、checkpoint callback 与 replay/handoff 落盘。 +- `continue_host_develop` 仍是宿主负责真实代码修改的正式模式;runtime 只负责 machine-readable quality contract、checkpoint callback 与 handoff 落盘。 - develop 质量循环的正式发现顺序固定为:`.sopify-skills/project.md verify` > 项目原生脚本/配置 > `not_configured` 可见降级。 - develop 质量结果的正式字段固定为:`verification_source / command / scope / result / reason_code / retry_count / root_cause / review_result`。 - `result` 的稳定值域固定为:`passed / retried / failed / skipped / replan_required`;`root_cause` 的稳定值域固定为:`logic_regression / environment_or_dependency / missing_test_infra / scope_or_design_mismatch`。 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ec8436..b3cdc87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ Format: Summary → Changed → Plan Packages. File-level details live in `git l ## [Unreleased] +## [2026-05-08.191000] - 2026-05-08 + +### Summary + +- Archived 1 plan package(s); Changes across: Skills, Tests. + +### Changed + +- **Skills**: Synced prompt-layer skills (12 files) +- **Tests**: Updated automated coverage (1 files) + +### Plan Packages + +- `20260508_p3b_perimeter_cleanup` (archived) + ## [2026-05-07.220011] - 2026-05-07 ### Summary diff --git a/Claude/Skills/CN/CLAUDE.md b/Claude/Skills/CN/CLAUDE.md index a8ed3a4..e01181c 100644 --- a/Claude/Skills/CN/CLAUDE.md +++ b/Claude/Skills/CN/CLAUDE.md @@ -1,5 +1,5 @@ - + # Sopify - 自适应 AI 编程助手 @@ -69,7 +69,7 @@ Next: {下一步提示} **Footer 契约:** - footer 固定跟在 `Changes` 区块之后 - `Next:` 必须作为 footer 最后一行。 -- footer 不展示生成时间;若需要机器可审计时间戳,内部摘要 / replay 文件可继续使用 ISO 8601(可带时区)。 +- footer 不展示生成时间;若需要机器可审计时间戳,内部摘要文件可继续使用 ISO 8601(可带时区)。 **状态符:** | 符号 | 含义 | @@ -142,20 +142,6 @@ Next: {下一步提示} 说明:当 `current_handoff.json.required_host_action == continue_host_develop` 时,宿主继续负责真实代码修改;但若开发中再次出现“需要用户补事实 / 拍板选路”的分叉,宿主不得自由追问,也不得手写 `current_decision.json / current_handoff.json`,而必须调用 `scripts/develop_callback_runtime.py submit --payload-json ...`(vendored 对应 `.sopify-runtime/scripts/develop_callback_runtime.py`)回调 runtime。payload 必须包含 `checkpoint_kind` 与 `resume_context`;当前 `resume_context` 至少要求 `active_run_stage / current_plan_path / task_refs / changed_files / working_summary / verification_todo`。 说明:当 `current_handoff.json.required_host_action == continue_host_consult` 时,宿主只可在已消费当前回合 gate contract 的前提下继续问答;不得在 gate 前自行路由,也不得在 gate 后再次重判 consult / 非 consult。宿主的回答应基于当前 gate contract 与 `handoff.artifacts` 暴露的 consult context(如有)生成;若缺少额外 consult context,应显式按当前请求降级回答,而不是用宿主侧语义分析补出另一条路由。 -**workflow-learning 主动记录策略:** -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -| 值 | 行为 | -|-----|------| -| `always` | 所有开发任务主动记录(full) | -| `by_requirement` | 按复杂度主动记录:simple=off,medium=summary,complex=full | -| `manual` | 仅在用户明确要求“开始记录这次任务”后记录 | -| `off` | 不主动新建记录;但回放/复盘意图识别与已有记录回放仍可用 | - --- ## Auto Rules (自动规则) @@ -220,7 +206,6 @@ workflow: │ ├── preferences.md │ └── feedback.jsonl ├── project.md # 技术约定,不与 background/design 重复 -└── replay/ # 可选回放能力,继续忽略 ``` ### A6 | 生命周期管理 @@ -290,7 +275,6 @@ progressive: 按需创建文件 (默认) | 路由 | 条件 | 行为 | |-----|------|-----| | 咨询问答 | 纯问题,无代码变更 | 先过 gate,再按 consult handoff 由宿主回答 | -| 复盘学习 | 提到回放/复盘/为什么这么做(意图识别始终开启) | 调用 workflow-learning,生成记录与讲解 | | 快速修复 | ≤2 文件,明确修改 | 直接执行 | | 轻量迭代 | 3-5 文件,清晰需求 | light 方案 + 执行 | | 完整开发 | >5 文件或架构变更 | 3 阶段完整流程 | @@ -432,7 +416,6 @@ Next: 请验证功能 | `develop` | 进入开发实施 | 代码执行、KB同步 | | `kb` | 知识库操作 | 初始化、更新策略 | | `templates` | 创建文档 | 所有模板定义 | -| `workflow-learning` | 用户要求回放/复盘/原因讲解,或 `auto_capture` 命中主动记录策略 | 完整记录、回放、逐步讲解 | **读取方式:** 按需读取,进入对应阶段时加载。 diff --git a/Claude/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md b/Claude/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md deleted file mode 100644 index 3aab47e..0000000 --- a/Claude/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# workflow-learning Changelog (CN) - -## [Unreleased] - -### Added - -- 初始版本:`workflow-learning` 子技能。 -- 支持 `capture / replay / breakdown` 三种模式。 -- 定义本地记录目录: - - `.sopify-skills/replay/sessions/{session_id}/session.md` - - `.sopify-skills/replay/sessions/{session_id}/events.jsonl` - - `.sopify-skills/replay/sessions/{session_id}/breakdown.md` -- 增加“回放最近一次 / 按 session_id 回放”的调用约定。 -- 增加敏感信息脱敏与边界规则。 - -### Changed - -- 新增 `workflow.learning.auto_capture` 策略说明:`always | by_requirement | manual | off`。 -- 明确策略边界:意图识别始终开启,`auto_capture` 仅控制主动记录。 -- 明确 `by_requirement` 粒度:`simple=off`、`medium=summary`、`complex=full`。 diff --git a/Claude/Skills/CN/skills/sopify/workflow-learning/SKILL.md b/Claude/Skills/CN/skills/sopify/workflow-learning/SKILL.md deleted file mode 100644 index 2907de5..0000000 --- a/Claude/Skills/CN/skills/sopify/workflow-learning/SKILL.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -name: workflow-learning -description: 工作流学习子技能;用于完整记录任务执行链路并支持回放/复盘/为什么这么做的逐步讲解。用户提出回放、复盘、解释决策依据或学习实现思路时使用。 ---- - -# Workflow Learning - 复盘学习与讲解 - -## 目标 - -- 记录任务实现的关键链路(输入、操作、结果、决策依据)。 -- 支持“回放最近一次”或“按 session_id 回放”。 -- 生成可教学的逐步讲解,帮助用户学习实现思路。 - ---- - -## 触发条件 - -本技能有两类触发来源: - -1. **意图触发(始终开启)**:当用户表达以下意图时调用本技能 -2. **主动记录触发(受配置控制)**:由 `workflow.learning.auto_capture` 决定是否在开发流程中自动记录 - -意图触发关键词示例: - -- 回放:`回放`、`回看`、`重放`、`看过程` -- 复盘:`复盘`、`总结这次实现` -- 原因解释:`为什么这么做`、`这步怎么想的`、`为什么选这个方案` - -默认在“需求已实现完成后”使用;如用户中途要求,也可对当前已发生步骤进行部分回放。 - ---- - -## 主动记录策略(auto_capture) - -配置位置: - -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -策略说明: - -| 值 | 行为 | -|----|------| -| `always` | 所有开发任务主动记录,按 full 粒度持续写入事件 | -| `by_requirement` | 按复杂度主动记录:simple=off,medium=summary,complex=full | -| `manual` | 仅在用户明确要求“开始记录这次任务”后记录 | -| `off` | 不新建记录;但意图触发仍可回放已有 session | - -`by_requirement` 粒度约定: - -- simple: 不主动记录 -- medium: 任务结束时写入 summary(最小事件集) -- complex: 全阶段 full 记录(analysis/design/develop/qa) - -注意:`auto_capture` 只影响“是否主动记录”,不影响“回放/复盘/为什么这么做”意图识别能力。 - ---- - -## 执行模式 - -### Mode A: capture(记录) - -在本地创建/更新会话记录目录: - -``` -.sopify-skills/replay/ -└── sessions/ - └── {session_id}/ - ├── session.md - ├── events.jsonl - └── breakdown.md -``` - -`session_id` 建议格式:`YYYYMMDD_HHMMSS_{topic}`(topic 使用短英文短语)。 - -`events.jsonl` 每条事件字段建议: - -```json -{ - "ts": "2026-02-13T16:30:00Z", - "phase": "analysis|design|develop|qa", - "intent": "本步目标", - "action": "命令/工具/编辑动作", - "key_output": "关键结果摘要", - "decision_reason": "选择该动作的依据", - "alternatives": ["备选方案A", "备选方案B"], - "result": "success|warning|failed", - "risk": "主要风险或空字符串", - "artifacts": ["path/to/file"] -} -``` - -### Mode B: replay(回放) - -输出结构: - -1. 任务目标与范围 -2. 关键步骤时间线 -3. 关键决策点(做了什么、为什么、结果如何) -4. 最终交付与验证状态 - -### Mode C: breakdown(逐步讲解) - -按步骤解释: - -1. 这一步要解决什么问题 -2. 为什么选当前方案 -3. 有哪些替代方案 -4. 风险与边界 -5. 对下一步的影响 - ---- - -## 安全与边界 - -- 仅记录可观察执行链路,不输出不可见内部思维链原文。 -- 写入日志前对敏感内容脱敏(token、api key、cookie、密码、私密连接串)。 -- 不记录与任务无关的个人隐私信息。 - ---- - -## 常用调用示例 - -- `回放最近一次实现` -- `按 session_id 回放 20260213_163000_auth-refactor` -- `复盘这次实现,重点讲为什么这么做` -- `把这次需求实现过程逐步讲给我` - ---- - -## 输出约定(简版) - -``` -[${BRAND_NAME}] 咨询问答 ✓ - -已生成回放记录: .sopify-skills/replay/sessions/{session_id}/session.md -已生成事件流水: .sopify-skills/replay/sessions/{session_id}/events.jsonl -已生成逐步讲解: .sopify-skills/replay/sessions/{session_id}/breakdown.md - ---- -Changes: 3 files -Next: 输入“回放最近一次”或“按 session_id 回放 ...” -``` - ---- - -## 变更记录 - -本子技能使用独立 changelog: - -- `CHANGELOG.md`(与仓库根 `CHANGELOG.md` 分离维护) diff --git a/Claude/Skills/EN/CLAUDE.md b/Claude/Skills/EN/CLAUDE.md index 6715a39..2402f6b 100644 --- a/Claude/Skills/EN/CLAUDE.md +++ b/Claude/Skills/EN/CLAUDE.md @@ -1,5 +1,5 @@ - + # Sopify - Adaptive AI Programming Assistant @@ -69,7 +69,7 @@ Next: {Next step hint} **Footer Contract:** - the footer always follows the `Changes` block - `Next:` must be the final line in the footer. -- the footer does not display generated time; if a machine-auditable timestamp is needed, internal summary / replay artifacts may keep ISO 8601 timestamps with timezone data. +- the footer does not display generated time; if a machine-auditable timestamp is needed, internal summary files may keep ISO 8601 timestamps with timezone data. **Status Symbols:** | Symbol | Meaning | @@ -142,20 +142,6 @@ Note: when `current_handoff.json.required_host_action == confirm_decision`, the Note: when `current_handoff.json.required_host_action == continue_host_develop`, the host still owns real code changes; but if implementation hits another user-facing branch, the host must not ask a free-form question or hand-write `current_decision.json / current_handoff.json`. It must call `scripts/develop_callback_runtime.py submit --payload-json ...` instead (vendored: `.sopify-runtime/scripts/develop_callback_runtime.py`). The payload must contain `checkpoint_kind` plus `resume_context`; the current minimum `resume_context` fields are `active_run_stage / current_plan_path / task_refs / changed_files / working_summary / verification_todo`. Note: when `current_handoff.json.required_host_action == continue_host_consult`, the host may continue the discussion only after consuming the current turn's gate contract. It must not self-route before the gate, and it must not re-decide consult vs non-consult after the gate. The answer must be grounded in the current gate contract plus any consult context exposed by `handoff.artifacts`; if that context is missing, degrade explicitly against the current request instead of inferring a different route from chat semantics. -**workflow-learning proactive capture policy:** -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -| Value | Behavior | -|------|----------| -| `always` | Proactively capture all development tasks (full) | -| `by_requirement` | Capture by complexity: simple=off, medium=summary, complex=full | -| `manual` | Capture only after explicit request like "start recording this task" | -| `off` | Do not proactively create new logs; replay/review intent and replay from existing sessions still work | - --- ## Auto Rules @@ -220,7 +206,6 @@ Complex: Files > 5, architectural changes, new features │ ├── preferences.md │ └── feedback.jsonl ├── project.md # Technical conventions, not a duplicate of background/design -└── replay/ # Optional replay capability, still ignored ``` ### A6 | Lifecycle Management @@ -290,7 +275,6 @@ Semantic analysis routing: | Route | Condition | Behavior | |-------|-----------|----------| | Q&A | Pure question, no code changes | Run gate first, then answer through consult handoff in the host session | -| Workflow Learning | Mentions replay/review/why this choice (intent recognition is always enabled) | Call workflow-learning for trace capture and explanation | | Quick Fix | ≤2 files, clear modification | Direct execution | | Light Iteration | 3-5 files, clear requirements | Light plan + execution | | Full Development | >5 files or architectural changes | Full 3-phase workflow | @@ -432,7 +416,6 @@ Next: Please verify the functionality | `develop` | Enter development | Code execution, KB sync | | `kb` | Knowledge base operations | Init, update strategies | | `templates` | Create documents | All template definitions | -| `workflow-learning` | User asks replay/review/why, or `auto_capture` proactively applies | Full trace logging, replay, step-by-step explanation | **Loading:** On-demand, loaded when entering corresponding phase. diff --git a/Claude/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md b/Claude/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md deleted file mode 100644 index f06fe0e..0000000 --- a/Claude/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# workflow-learning Changelog (EN) - -## [Unreleased] - -### Added - -- Initial release of the `workflow-learning` sub-skill. -- Support for three modes: `capture / replay / breakdown`. -- Local trace artifacts: - - `.sopify-skills/replay/sessions/{session_id}/session.md` - - `.sopify-skills/replay/sessions/{session_id}/events.jsonl` - - `.sopify-skills/replay/sessions/{session_id}/breakdown.md` -- Usage contract for "replay latest" and "replay by session_id". -- Sensitive-data redaction and boundary rules. - -### Changed - -- Added `workflow.learning.auto_capture` policy docs: `always | by_requirement | manual | off`. -- Clarified boundary: intent recognition is always enabled; `auto_capture` controls proactive recording only. -- Clarified `by_requirement` granularity: `simple=off`, `medium=summary`, `complex=full`. diff --git a/Claude/Skills/EN/skills/sopify/workflow-learning/SKILL.md b/Claude/Skills/EN/skills/sopify/workflow-learning/SKILL.md deleted file mode 100644 index e10a88c..0000000 --- a/Claude/Skills/EN/skills/sopify/workflow-learning/SKILL.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -name: workflow-learning -description: Workflow learning sub-skill for full execution-trace capture plus replay/review/why-this-choice explanations. Use when users ask to replay work, run a retrospective, explain decisions, or learn the implementation path. ---- - -# Workflow Learning - Replay, Review, and Explanation - -## Goal - -- Capture key implementation trace (input, actions, outcomes, decision reasons). -- Support both "replay the latest session" and "replay by session_id". -- Produce teachable step-by-step explanations for learning. - ---- - -## Trigger Conditions - -This skill has two trigger sources: - -1. **Intent trigger (always enabled):** activate when user intent includes replay/review/why questions. -2. **Proactive capture trigger (config controlled):** activate automatically based on `workflow.learning.auto_capture`. - -Intent trigger examples: - -- Replay: `replay`, `play back`, `show the process` -- Retrospective: `review`, `retrospective`, `summarize this run` -- Decision explanation: `why this choice`, `how did you think about this step` - -Default usage is after implementation completes. If asked mid-task, generate a partial replay for completed steps. - ---- - -## Proactive Capture Policy (auto_capture) - -Config path: - -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -Policy definitions: - -| Value | Behavior | -|------|----------| -| `always` | Proactively capture all development tasks with full-granularity logging | -| `by_requirement` | Capture by complexity: simple=off, medium=summary, complex=full | -| `manual` | Capture only after explicit user request such as "start recording this task" | -| `off` | Do not create new logs; intent-triggered replay still works with existing sessions | - -`by_requirement` granularity: - -- simple: no proactive capture -- medium: write summary-level records at task completion (minimal event set) -- complex: full phase-level capture (analysis/design/develop/qa) - -Important: `auto_capture` controls proactive recording only. It does not disable replay/review/why intent recognition. - ---- - -## Execution Modes - -### Mode A: capture - -Create/update local session files: - -``` -.sopify-skills/replay/ -└── sessions/ - └── {session_id}/ - ├── session.md - ├── events.jsonl - └── breakdown.md -``` - -Recommended `session_id` format: `YYYYMMDD_HHMMSS_{topic}` (short English topic). - -Recommended event schema for each line in `events.jsonl`: - -```json -{ - "ts": "2026-02-13T16:30:00Z", - "phase": "analysis|design|develop|qa", - "intent": "Goal of this step", - "action": "Command/tool/edit action", - "key_output": "Key result summary", - "decision_reason": "Why this action was chosen", - "alternatives": ["Option A", "Option B"], - "result": "success|warning|failed", - "risk": "Main risk or empty string", - "artifacts": ["path/to/file"] -} -``` - -### Mode B: replay - -Replay output structure: - -1. Task goal and scope -2. Timeline of key steps -3. Key decisions (what, why, outcome) -4. Final deliverables and verification status - -### Mode C: breakdown - -Explain each step with: - -1. Problem to solve -2. Why this approach was selected -3. Alternatives considered -4. Risks and boundaries -5. Impact on the next step - ---- - -## Safety and Boundaries - -- Log observable execution traces only; do not output hidden internal chain-of-thought text. -- Redact sensitive values before writing logs (token, api key, cookie, password, secret connection strings). -- Do not record unrelated personal/private data. - ---- - -## Common Prompts - -- `Replay the latest implementation` -- `Replay session 20260213_163000_auth-refactor` -- `Review this run and explain why these choices were made` -- `Walk me through this implementation step by step` - ---- - -## Output Contract (Short) - -``` -[${BRAND_NAME}] Q&A ✓ - -Replay summary: .sopify-skills/replay/sessions/{session_id}/session.md -Event log: .sopify-skills/replay/sessions/{session_id}/events.jsonl -Step-by-step: .sopify-skills/replay/sessions/{session_id}/breakdown.md - ---- -Changes: 3 files -Next: Ask "replay latest" or "replay by session_id ..." -``` - ---- - -## Change Log - -This sub-skill keeps a separate changelog: - -- `CHANGELOG.md` (maintained separately from repository root `CHANGELOG.md`) diff --git a/Codex/Skills/CN/AGENTS.md b/Codex/Skills/CN/AGENTS.md index cd7e06d..3174fe7 100644 --- a/Codex/Skills/CN/AGENTS.md +++ b/Codex/Skills/CN/AGENTS.md @@ -1,5 +1,5 @@ - + # Sopify - 自适应 AI 编程助手 @@ -69,7 +69,7 @@ Next: {下一步提示} **Footer 契约:** - footer 固定跟在 `Changes` 区块之后 - `Next:` 必须作为 footer 最后一行。 -- footer 不展示生成时间;若需要机器可审计时间戳,内部摘要 / replay 文件可继续使用 ISO 8601(可带时区)。 +- footer 不展示生成时间;若需要机器可审计时间戳,内部摘要文件可继续使用 ISO 8601(可带时区)。 **状态符:** | 符号 | 含义 | @@ -142,20 +142,6 @@ Next: {下一步提示} 说明:当 `current_handoff.json.required_host_action == continue_host_develop` 时,宿主继续负责真实代码修改;但若开发中再次出现“需要用户补事实 / 拍板选路”的分叉,宿主不得自由追问,也不得手写 `current_decision.json / current_handoff.json`,而必须调用 `scripts/develop_callback_runtime.py submit --payload-json ...`(vendored 对应 `.sopify-runtime/scripts/develop_callback_runtime.py`)回调 runtime。payload 必须包含 `checkpoint_kind` 与 `resume_context`;当前 `resume_context` 至少要求 `active_run_stage / current_plan_path / task_refs / changed_files / working_summary / verification_todo`。 说明:当 `current_handoff.json.required_host_action == continue_host_consult` 时,宿主只可在已消费当前回合 gate contract 的前提下继续问答;不得在 gate 前自行路由,也不得在 gate 后再次重判 consult / 非 consult。宿主的回答应基于当前 gate contract 与 `handoff.artifacts` 暴露的 consult context(如有)生成;若缺少额外 consult context,应显式按当前请求降级回答,而不是用宿主侧语义分析补出另一条路由。 -**workflow-learning 主动记录策略:** -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -| 值 | 行为 | -|-----|------| -| `always` | 所有开发任务主动记录(full) | -| `by_requirement` | 按复杂度主动记录:simple=off,medium=summary,complex=full | -| `manual` | 仅在用户明确要求“开始记录这次任务”后记录 | -| `off` | 不主动新建记录;但回放/复盘意图识别与已有记录回放仍可用 | - --- ## Auto Rules (自动规则) @@ -220,7 +206,6 @@ workflow: │ ├── preferences.md │ └── feedback.jsonl ├── project.md # 技术约定,不与 background/design 重复 -└── replay/ # 可选回放能力,继续忽略 ``` ### A6 | 生命周期管理 @@ -290,7 +275,6 @@ progressive: 按需创建文件 (默认) | 路由 | 条件 | 行为 | |-----|------|-----| | 咨询问答 | 纯问题,无代码变更 | 先过 gate,再按 consult handoff 由宿主回答 | -| 复盘学习 | 提到回放/复盘/为什么这么做(意图识别始终开启) | 调用 workflow-learning,生成记录与讲解 | | 快速修复 | ≤2 文件,明确修改 | 直接执行 | | 轻量迭代 | 3-5 文件,清晰需求 | light 方案 + 执行 | | 完整开发 | >5 文件或架构变更 | 3 阶段完整流程 | @@ -432,7 +416,6 @@ Next: 请验证功能 | `develop` | 进入开发实施 | 代码执行、KB同步 | | `kb` | 知识库操作 | 初始化、更新策略 | | `templates` | 创建文档 | 所有模板定义 | -| `workflow-learning` | 用户要求回放/复盘/原因讲解,或 `auto_capture` 命中主动记录策略 | 完整记录、回放、逐步讲解 | **读取方式:** 按需读取,进入对应阶段时加载。 diff --git a/Codex/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md b/Codex/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md deleted file mode 100644 index 3aab47e..0000000 --- a/Codex/Skills/CN/skills/sopify/workflow-learning/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# workflow-learning Changelog (CN) - -## [Unreleased] - -### Added - -- 初始版本:`workflow-learning` 子技能。 -- 支持 `capture / replay / breakdown` 三种模式。 -- 定义本地记录目录: - - `.sopify-skills/replay/sessions/{session_id}/session.md` - - `.sopify-skills/replay/sessions/{session_id}/events.jsonl` - - `.sopify-skills/replay/sessions/{session_id}/breakdown.md` -- 增加“回放最近一次 / 按 session_id 回放”的调用约定。 -- 增加敏感信息脱敏与边界规则。 - -### Changed - -- 新增 `workflow.learning.auto_capture` 策略说明:`always | by_requirement | manual | off`。 -- 明确策略边界:意图识别始终开启,`auto_capture` 仅控制主动记录。 -- 明确 `by_requirement` 粒度:`simple=off`、`medium=summary`、`complex=full`。 diff --git a/Codex/Skills/CN/skills/sopify/workflow-learning/SKILL.md b/Codex/Skills/CN/skills/sopify/workflow-learning/SKILL.md deleted file mode 100644 index 2907de5..0000000 --- a/Codex/Skills/CN/skills/sopify/workflow-learning/SKILL.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -name: workflow-learning -description: 工作流学习子技能;用于完整记录任务执行链路并支持回放/复盘/为什么这么做的逐步讲解。用户提出回放、复盘、解释决策依据或学习实现思路时使用。 ---- - -# Workflow Learning - 复盘学习与讲解 - -## 目标 - -- 记录任务实现的关键链路(输入、操作、结果、决策依据)。 -- 支持“回放最近一次”或“按 session_id 回放”。 -- 生成可教学的逐步讲解,帮助用户学习实现思路。 - ---- - -## 触发条件 - -本技能有两类触发来源: - -1. **意图触发(始终开启)**:当用户表达以下意图时调用本技能 -2. **主动记录触发(受配置控制)**:由 `workflow.learning.auto_capture` 决定是否在开发流程中自动记录 - -意图触发关键词示例: - -- 回放:`回放`、`回看`、`重放`、`看过程` -- 复盘:`复盘`、`总结这次实现` -- 原因解释:`为什么这么做`、`这步怎么想的`、`为什么选这个方案` - -默认在“需求已实现完成后”使用;如用户中途要求,也可对当前已发生步骤进行部分回放。 - ---- - -## 主动记录策略(auto_capture) - -配置位置: - -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -策略说明: - -| 值 | 行为 | -|----|------| -| `always` | 所有开发任务主动记录,按 full 粒度持续写入事件 | -| `by_requirement` | 按复杂度主动记录:simple=off,medium=summary,complex=full | -| `manual` | 仅在用户明确要求“开始记录这次任务”后记录 | -| `off` | 不新建记录;但意图触发仍可回放已有 session | - -`by_requirement` 粒度约定: - -- simple: 不主动记录 -- medium: 任务结束时写入 summary(最小事件集) -- complex: 全阶段 full 记录(analysis/design/develop/qa) - -注意:`auto_capture` 只影响“是否主动记录”,不影响“回放/复盘/为什么这么做”意图识别能力。 - ---- - -## 执行模式 - -### Mode A: capture(记录) - -在本地创建/更新会话记录目录: - -``` -.sopify-skills/replay/ -└── sessions/ - └── {session_id}/ - ├── session.md - ├── events.jsonl - └── breakdown.md -``` - -`session_id` 建议格式:`YYYYMMDD_HHMMSS_{topic}`(topic 使用短英文短语)。 - -`events.jsonl` 每条事件字段建议: - -```json -{ - "ts": "2026-02-13T16:30:00Z", - "phase": "analysis|design|develop|qa", - "intent": "本步目标", - "action": "命令/工具/编辑动作", - "key_output": "关键结果摘要", - "decision_reason": "选择该动作的依据", - "alternatives": ["备选方案A", "备选方案B"], - "result": "success|warning|failed", - "risk": "主要风险或空字符串", - "artifacts": ["path/to/file"] -} -``` - -### Mode B: replay(回放) - -输出结构: - -1. 任务目标与范围 -2. 关键步骤时间线 -3. 关键决策点(做了什么、为什么、结果如何) -4. 最终交付与验证状态 - -### Mode C: breakdown(逐步讲解) - -按步骤解释: - -1. 这一步要解决什么问题 -2. 为什么选当前方案 -3. 有哪些替代方案 -4. 风险与边界 -5. 对下一步的影响 - ---- - -## 安全与边界 - -- 仅记录可观察执行链路,不输出不可见内部思维链原文。 -- 写入日志前对敏感内容脱敏(token、api key、cookie、密码、私密连接串)。 -- 不记录与任务无关的个人隐私信息。 - ---- - -## 常用调用示例 - -- `回放最近一次实现` -- `按 session_id 回放 20260213_163000_auth-refactor` -- `复盘这次实现,重点讲为什么这么做` -- `把这次需求实现过程逐步讲给我` - ---- - -## 输出约定(简版) - -``` -[${BRAND_NAME}] 咨询问答 ✓ - -已生成回放记录: .sopify-skills/replay/sessions/{session_id}/session.md -已生成事件流水: .sopify-skills/replay/sessions/{session_id}/events.jsonl -已生成逐步讲解: .sopify-skills/replay/sessions/{session_id}/breakdown.md - ---- -Changes: 3 files -Next: 输入“回放最近一次”或“按 session_id 回放 ...” -``` - ---- - -## 变更记录 - -本子技能使用独立 changelog: - -- `CHANGELOG.md`(与仓库根 `CHANGELOG.md` 分离维护) diff --git a/Codex/Skills/EN/AGENTS.md b/Codex/Skills/EN/AGENTS.md index 1a6e103..e095964 100644 --- a/Codex/Skills/EN/AGENTS.md +++ b/Codex/Skills/EN/AGENTS.md @@ -1,5 +1,5 @@ - + # Sopify - Adaptive AI Programming Assistant @@ -69,7 +69,7 @@ Next: {Next step hint} **Footer Contract:** - the footer always follows the `Changes` block - `Next:` must be the final line in the footer. -- the footer does not display generated time; if a machine-auditable timestamp is needed, internal summary / replay artifacts may keep ISO 8601 timestamps with timezone data. +- the footer does not display generated time; if a machine-auditable timestamp is needed, internal summary files may keep ISO 8601 timestamps with timezone data. **Status Symbols:** | Symbol | Meaning | @@ -142,20 +142,6 @@ Note: when `current_handoff.json.required_host_action == confirm_decision`, the Note: when `current_handoff.json.required_host_action == continue_host_develop`, the host still owns real code changes; but if implementation hits another user-facing branch, the host must not ask a free-form question or hand-write `current_decision.json / current_handoff.json`. It must call `scripts/develop_callback_runtime.py submit --payload-json ...` instead (vendored: `.sopify-runtime/scripts/develop_callback_runtime.py`). The payload must contain `checkpoint_kind` plus `resume_context`; the current minimum `resume_context` fields are `active_run_stage / current_plan_path / task_refs / changed_files / working_summary / verification_todo`. Note: when `current_handoff.json.required_host_action == continue_host_consult`, the host may continue the discussion only after consuming the current turn's gate contract. It must not self-route before the gate, and it must not re-decide consult vs non-consult after the gate. The answer must be grounded in the current gate contract plus any consult context exposed by `handoff.artifacts`; if that context is missing, degrade explicitly against the current request instead of inferring a different route from chat semantics. -**workflow-learning proactive capture policy:** -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -| Value | Behavior | -|------|----------| -| `always` | Proactively capture all development tasks (full) | -| `by_requirement` | Capture by complexity: simple=off, medium=summary, complex=full | -| `manual` | Capture only after explicit request like "start recording this task" | -| `off` | Do not proactively create new logs; replay/review intent and replay from existing sessions still work | - --- ## Auto Rules @@ -220,7 +206,6 @@ Complex: Files > 5, architectural changes, new features │ ├── preferences.md │ └── feedback.jsonl ├── project.md # Technical conventions, not a duplicate of background/design -└── replay/ # Optional replay capability, still ignored ``` ### A6 | Lifecycle Management @@ -290,7 +275,6 @@ Semantic analysis routing: | Route | Condition | Behavior | |-------|-----------|----------| | Q&A | Pure question, no code changes | Run gate first, then answer through consult handoff in the host session | -| Workflow Learning | Mentions replay/review/why this choice (intent recognition is always enabled) | Call workflow-learning for trace capture and explanation | | Quick Fix | ≤2 files, clear modification | Direct execution | | Light Iteration | 3-5 files, clear requirements | Light plan + execution | | Full Development | >5 files or architectural changes | Full 3-phase workflow | @@ -432,7 +416,6 @@ Next: Please verify the functionality | `develop` | Enter development | Code execution, KB sync | | `kb` | Knowledge base operations | Init, update strategies | | `templates` | Create documents | All template definitions | -| `workflow-learning` | User asks replay/review/why, or `auto_capture` proactively applies | Full trace logging, replay, step-by-step explanation | **Loading:** On-demand, loaded when entering corresponding phase. diff --git a/Codex/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md b/Codex/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md deleted file mode 100644 index f06fe0e..0000000 --- a/Codex/Skills/EN/skills/sopify/workflow-learning/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# workflow-learning Changelog (EN) - -## [Unreleased] - -### Added - -- Initial release of the `workflow-learning` sub-skill. -- Support for three modes: `capture / replay / breakdown`. -- Local trace artifacts: - - `.sopify-skills/replay/sessions/{session_id}/session.md` - - `.sopify-skills/replay/sessions/{session_id}/events.jsonl` - - `.sopify-skills/replay/sessions/{session_id}/breakdown.md` -- Usage contract for "replay latest" and "replay by session_id". -- Sensitive-data redaction and boundary rules. - -### Changed - -- Added `workflow.learning.auto_capture` policy docs: `always | by_requirement | manual | off`. -- Clarified boundary: intent recognition is always enabled; `auto_capture` controls proactive recording only. -- Clarified `by_requirement` granularity: `simple=off`, `medium=summary`, `complex=full`. diff --git a/Codex/Skills/EN/skills/sopify/workflow-learning/SKILL.md b/Codex/Skills/EN/skills/sopify/workflow-learning/SKILL.md deleted file mode 100644 index e10a88c..0000000 --- a/Codex/Skills/EN/skills/sopify/workflow-learning/SKILL.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -name: workflow-learning -description: Workflow learning sub-skill for full execution-trace capture plus replay/review/why-this-choice explanations. Use when users ask to replay work, run a retrospective, explain decisions, or learn the implementation path. ---- - -# Workflow Learning - Replay, Review, and Explanation - -## Goal - -- Capture key implementation trace (input, actions, outcomes, decision reasons). -- Support both "replay the latest session" and "replay by session_id". -- Produce teachable step-by-step explanations for learning. - ---- - -## Trigger Conditions - -This skill has two trigger sources: - -1. **Intent trigger (always enabled):** activate when user intent includes replay/review/why questions. -2. **Proactive capture trigger (config controlled):** activate automatically based on `workflow.learning.auto_capture`. - -Intent trigger examples: - -- Replay: `replay`, `play back`, `show the process` -- Retrospective: `review`, `retrospective`, `summarize this run` -- Decision explanation: `why this choice`, `how did you think about this step` - -Default usage is after implementation completes. If asked mid-task, generate a partial replay for completed steps. - ---- - -## Proactive Capture Policy (auto_capture) - -Config path: - -```yaml -workflow: - learning: - auto_capture: by_requirement # always | by_requirement | manual | off -``` - -Policy definitions: - -| Value | Behavior | -|------|----------| -| `always` | Proactively capture all development tasks with full-granularity logging | -| `by_requirement` | Capture by complexity: simple=off, medium=summary, complex=full | -| `manual` | Capture only after explicit user request such as "start recording this task" | -| `off` | Do not create new logs; intent-triggered replay still works with existing sessions | - -`by_requirement` granularity: - -- simple: no proactive capture -- medium: write summary-level records at task completion (minimal event set) -- complex: full phase-level capture (analysis/design/develop/qa) - -Important: `auto_capture` controls proactive recording only. It does not disable replay/review/why intent recognition. - ---- - -## Execution Modes - -### Mode A: capture - -Create/update local session files: - -``` -.sopify-skills/replay/ -└── sessions/ - └── {session_id}/ - ├── session.md - ├── events.jsonl - └── breakdown.md -``` - -Recommended `session_id` format: `YYYYMMDD_HHMMSS_{topic}` (short English topic). - -Recommended event schema for each line in `events.jsonl`: - -```json -{ - "ts": "2026-02-13T16:30:00Z", - "phase": "analysis|design|develop|qa", - "intent": "Goal of this step", - "action": "Command/tool/edit action", - "key_output": "Key result summary", - "decision_reason": "Why this action was chosen", - "alternatives": ["Option A", "Option B"], - "result": "success|warning|failed", - "risk": "Main risk or empty string", - "artifacts": ["path/to/file"] -} -``` - -### Mode B: replay - -Replay output structure: - -1. Task goal and scope -2. Timeline of key steps -3. Key decisions (what, why, outcome) -4. Final deliverables and verification status - -### Mode C: breakdown - -Explain each step with: - -1. Problem to solve -2. Why this approach was selected -3. Alternatives considered -4. Risks and boundaries -5. Impact on the next step - ---- - -## Safety and Boundaries - -- Log observable execution traces only; do not output hidden internal chain-of-thought text. -- Redact sensitive values before writing logs (token, api key, cookie, password, secret connection strings). -- Do not record unrelated personal/private data. - ---- - -## Common Prompts - -- `Replay the latest implementation` -- `Replay session 20260213_163000_auth-refactor` -- `Review this run and explain why these choices were made` -- `Walk me through this implementation step by step` - ---- - -## Output Contract (Short) - -``` -[${BRAND_NAME}] Q&A ✓ - -Replay summary: .sopify-skills/replay/sessions/{session_id}/session.md -Event log: .sopify-skills/replay/sessions/{session_id}/events.jsonl -Step-by-step: .sopify-skills/replay/sessions/{session_id}/breakdown.md - ---- -Changes: 3 files -Next: Ask "replay latest" or "replay by session_id ..." -``` - ---- - -## Change Log - -This sub-skill keeps a separate changelog: - -- `CHANGELOG.md` (maintained separately from repository root `CHANGELOG.md`) diff --git a/README.md b/README.md index 3943b45..eb766d0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE) [![Docs](https://img.shields.io/badge/docs-CC%20BY%204.0-green.svg)](./LICENSE-docs) -[![Version](https://img.shields.io/badge/version-2026--05--07.220011-orange.svg)](#version-history) +[![Version](https://img.shields.io/badge/version-2026--05--08.191000-orange.svg)](#version-history) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md) English · [简体中文](./README.zh-CN.md) · [Quick Start](#quick-start) · [Contributors](./CONTRIBUTORS.md) diff --git a/README.zh-CN.md b/README.zh-CN.md index 68748d5..99f1fda 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -8,7 +8,7 @@ [![许可证](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE) [![文档](https://img.shields.io/badge/docs-CC%20BY%204.0-green.svg)](./LICENSE-docs) -[![版本](https://img.shields.io/badge/version-2026--05--07.220011-orange.svg)](#版本历史) +[![版本](https://img.shields.io/badge/version-2026--05--08.191000-orange.svg)](#版本历史) [![欢迎PR](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING_CN.md) [English](./README.md) · 简体中文 · [快速开始](#快速开始) · [贡献者](./CONTRIBUTORS.md) diff --git a/tests/test_installer.py b/tests/test_installer.py index 72ce447..dd93d4a 100644 --- a/tests/test_installer.py +++ b/tests/test_installer.py @@ -1299,7 +1299,7 @@ def test_codex_cn_installed_prompt_assets_keep_footer_contract(self) -> None: adapter=CODEX_ADAPTER, language_directory="CN", next_template_line="Next: {下一步提示}", - footer_contract_line="- footer 不展示生成时间;若需要机器可审计时间戳,内部摘要 / replay 文件可继续使用 ISO 8601(可带时区)。", + footer_contract_line="- footer 不展示生成时间;若需要机器可审计时间戳,内部摘要文件可继续使用 ISO 8601(可带时区)。", runtime_language="zh-CN", ) @@ -1353,7 +1353,7 @@ def test_claude_en_installed_prompt_assets_keep_footer_contract(self) -> None: adapter=CLAUDE_ADAPTER, language_directory="EN", next_template_line="Next: {Next step hint}", - footer_contract_line="- the footer does not display generated time; if a machine-auditable timestamp is needed, internal summary / replay artifacts may keep ISO 8601 timestamps with timezone data.", + footer_contract_line="- the footer does not display generated time; if a machine-auditable timestamp is needed, internal summary files may keep ISO 8601 timestamps with timezone data.", runtime_language="en-US", ) From 85bcaba2ace6c958cae29abe2b250bf102dddd4b Mon Sep 17 00:00:00 2001 From: "sanze.li" <2522048902@qq.com> Date: Fri, 8 May 2026 19:15:45 +0800 Subject: [PATCH 12/12] P3b: sync stale comments after footer contract cleanup - tests/test_installer.py L1297/L1351: remove outdated 'replay still mentioned' comment; footer assertion now matches cleaned source - tasks.md 2.20: update note to reflect footer assertions are now aligned with current source (no longer deferred) --- .../history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md | 2 +- tests/test_installer.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md index 84d5622..cb43cf2 100644 --- a/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md +++ b/.sopify-skills/history/2026-05/20260508_p3b_perimeter_cleanup/tasks.md @@ -54,7 +54,7 @@ plan_status: completed - [x] 2.17 `tests/test_runtime_decision.py`:`replay_session_dir=None` 引用(L604)——清除 - [x] 2.18 `tests/test_runtime_sample_invariant_gate.py`:replay_required 相关断言(L92-107)——清除 - [x] 2.19 `tests/test_runtime_skill_registry.py`:workflow-learning assertIn(L61)——删除 -- [x] 2.20 `tests/test_installer.py`:replay 相关引用(L895)——已清除 gitignore 断言;L1301/L1354 footer 断言保留(prompt asset 未更新,注释标注) +- [x] 2.20 `tests/test_installer.py`:replay 相关引用(L895)——已清除 gitignore 断言;L1301/L1354 footer 断言已同步更新(prompt asset replay 引用已移除,断言与当前 source 对齐,注释已同步) - [x] 2.21 验证 tests/__pycache__ 中 replay 相关 .pyc 为 0(tests/__pycache__、tests/protocol/__pycache__、tests/pytest_entries/__pycache__ 均无 replay 相关 .pyc;__pycache__ 目录本身包含其他正常缓存,不删除) ### Runtime 外围残留 diff --git a/tests/test_installer.py b/tests/test_installer.py index dd93d4a..ae58b6b 100644 --- a/tests/test_installer.py +++ b/tests/test_installer.py @@ -1294,7 +1294,7 @@ def test_codex_cn_prompt_install_keeps_workspace_preflight_contract(self) -> Non self.assertIn("必须继续遵守对应 checkpoint 的机器契约", prompt) def test_codex_cn_installed_prompt_assets_keep_footer_contract(self) -> None: - # Prompt assets still mention replay until the installed footer copy is updated. + # Footer contract aligned: replay reference removed from source and assertion. self._assert_installed_footer_contract( adapter=CODEX_ADAPTER, language_directory="CN", @@ -1348,7 +1348,7 @@ def test_claude_en_prompt_install_keeps_workspace_preflight_contract(self) -> No self.assertIn("must still honor the machine contract", prompt) def test_claude_en_installed_prompt_assets_keep_footer_contract(self) -> None: - # Prompt assets still mention replay until the installed footer copy is updated. + # Footer contract aligned: replay reference removed from source and assertion. self._assert_installed_footer_contract( adapter=CLAUDE_ADAPTER, language_directory="EN",