diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index ebfb121..0000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,10 +0,0 @@ -## Summary - -- Describe the scoped change. - -## Checkpoint Metadata - -Context-Checkpoint: A|B|C|D -Decision IDs: none -Blocked by: none -Out-of-scope touched: none diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a28cdee..027ae24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,15 +65,6 @@ jobs: - name: Check context checkpoints run: python3 scripts/check-context-checkpoints.py repo --root . - - name: Check pull request checkpoint metadata - if: github.event_name == 'pull_request' - run: | - python3 scripts/check-context-checkpoints.py pr-body \ - --root . \ - --event-path "$GITHUB_EVENT_PATH" \ - --base-sha "${{ github.event.pull_request.base.sha }}" \ - --head-sha "${{ github.event.pull_request.head.sha }}" - - name: Run hard gate tests (contract + smoke + distribution) run: | pip install --quiet pytest @@ -86,3 +77,9 @@ jobs: - name: Run runtime smoke check run: bash scripts/check-runtime-smoke.sh + + - name: Run install/payload bootstrap smoke + run: python3 scripts/check-install-payload-bundle-smoke.py + + - name: Run prompt runtime gate smoke + run: python3 scripts/check-prompt-runtime-gate-smoke.py diff --git a/.sopify-skills/blueprint/README.md b/.sopify-skills/blueprint/README.md index c7c6346..5c4a163 100644 --- a/.sopify-skills/blueprint/README.md +++ b/.sopify-skills/blueprint/README.md @@ -13,8 +13,8 @@ ## 当前焦点 -- 当前活动 plan:`../plan/20260522_runtime_slimming_kernel_extraction`。 -- history 归档:已可用;最近归档为 `../history/2026-05/20260522_p7_payload_only_onboarding_mainline`。 +- 当前活动 plan:暂无。 +- history 归档:已可用;最近归档为 `../history/2026-05/20260522_runtime_slimming_kernel_extraction`。 ## 深入阅读入口 @@ -27,5 +27,5 @@ - [Sopify 宿主接入规范 (Protocol v0)](./protocol.md) - [Skill 标准对齐蓝图](./skill-standards-refactor.md) - [变更历史](../history/index.md) -- 最近归档:`../history/2026-05/20260522_p7_payload_only_onboarding_mainline` +- 最近归档:`../history/2026-05/20260522_runtime_slimming_kernel_extraction` diff --git a/.sopify-skills/blueprint/tasks.md b/.sopify-skills/blueprint/tasks.md index 7faa5a7..4ccb0dd 100644 --- a/.sopify-skills/blueprint/tasks.md +++ b/.sopify-skills/blueprint/tasks.md @@ -143,6 +143,8 @@ P0→P4c 主航道已全部完成。后续执行遵循以下原则: - [ ] 产品层 ↔ 实现层 contract matrix 正式化(ownership / admission / lifecycle responsibilities) - [x] GitHub Release pipeline 建立(首次 release 创建 + tag 规范 + install 脚本端到端验证) - [x] 测试套件健康基线(pass rate ≥ 99%;当前基线 619 tests / 619 passed = 100%,含 49 subtests;退役 124 测试后仍保持 100% pass rate) +- [ ] Skill packaging / localization governance:skill 打包格式、多语言资产管理、bundle 内 i18n 分层规范 +- [ ] Post-runtime skeleton governance:runtime/ 目录最终形态治理(Phase 2 全删后遗留结构清理规范) ## 已关闭 / 已吸收项 diff --git a/.sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/background.md b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/background.md similarity index 100% rename from .sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/background.md rename to .sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/background.md diff --git a/.sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/design.md b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/design.md similarity index 100% rename from .sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/design.md rename to .sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/design.md diff --git a/.sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/kernel-architecture.svg b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/kernel-architecture.svg similarity index 100% rename from .sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/kernel-architecture.svg rename to .sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/kernel-architecture.svg diff --git a/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/receipt.md b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/receipt.md new file mode 100644 index 0000000..3ac3006 --- /dev/null +++ b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/receipt.md @@ -0,0 +1,96 @@ +# Receipt: Runtime Slimming — Orchestration Kernel Extraction + +## 基本信息 + +| 字段 | 值 | +|------|------| +| Plan ID | 20260522_runtime_slimming_kernel_extraction | +| 状态 | **全部完成** | +| 主分支 PRs | #38, #39, #40, #41, #42, #43 + closeout PR | +| 前置 | P7 Payload-Only Onboarding Mainline ✅ | + +--- + +## 核心结论(一句话) + +runtime/ 从 ~22K LOC / 51 文件收至 37 文件 / 16,286 LOC。contract 面清理 −6,400 LOC,34 退役测试块清理 −1,400 LOC,kernel orchestration 提取并重命名为 `_orchestration.py`,`plan_scaffold.py` 拆分为 `runtime/plan/` 包。Phase 2(installer 解耦 + runtime/ 全删)留作后续。 + +--- + +## 决策记录 + +| ID | 决策 | 理由 | +|----|------|------| +| DR-1 | `_kernel_turn.py` → `_orchestration.py`(保留下划线前缀) | 模块为内部实现,underscore 语义一致 | +| DR-2 | `execute_kernel_turn()` 函数名不改 | 50+ test callers 通过 `run_runtime()` wrapper 间接调用,改名成本远超收益 | +| DR-3 | 不删 `check-runtime-smoke.sh` | 被 installer/runtime_bundle.py 打包进 bundle,有 6 处活跃 consumer | +| DR-4 | `deferred` 保持文档层面术语 | 不升格为 registry/runtime 正式状态/枚举值 | +| DR-5 | `legacy_fallback` stub 字段已退役 | `_legacy_payload_bundle_version()` / `_legacy_bundle_manifest_path()` 保留为 versioned layout 兼容路径 | +| DR-6 | 不删 `run_runtime()` wrapper | engine.py 中 50+ test callers 仍经此入口 | + +--- + +## 阶段执行历史 + +| 阶段 | 摘要 | 状态 | +|------|------|------| +| 1. 蓝图 delta 校验 | 5 项审计全通过 | ✅ | +| 2. 当前消费者扫描 | 4 类清单 + consumer 判定 | ✅ | +| 3. 删除就绪结论 | kernel 边界锁定,退场量级 ~38K LOC | ✅ | +| 4. 审计后删除 | 4.1-4.13B 全部完成 | ✅ | +| 5. 文档更新 | 5.1-5.7 全部完成 | ✅ | +| 6. contract 面清理 + engine 重构 | 6.1-6.6 全部收完,−6,400+ LOC | ✅ | + +--- + +## 主要 PR 清单 + +| PR | 标题 | 关键变更 | +|----|------|---------| +| #38 | 4.13-B: runtime bundle rewrite + handoff semantic fix + test cleanup | Bundle 纯 Python 重写 + 34 退役测试块删除 | +| #39 | fix: remove workspace stub assertion from repo-local runtime smoke | Smoke 断言修正 | +| #40 | fix: smoke-stub-assertion | Smoke stub 断言修复 | +| #41 | refactor(4.10b): split plan_scaffold.py into runtime/plan/ package | 466 LOC → 5 个模块化文件 | +| #42 | test: add 4.11 kernel turn direct tests | 5 个 `execute_kernel_turn()` 合同测试 | +| #43 | refactor: rename _kernel_turn.py → _orchestration.py + docstring polish | 模块重命名 + 3 处 import 更新 + docstring 完善 | + +--- + +## 测试验证 + +| 范围 | 结果 | +|------|------| +| 全量回归 | 631 tests passed | +| Smoke (bash) | ✅ check-runtime-smoke.sh | +| Smoke (install) | ✅ check-install-payload-bundle-smoke.py | +| Smoke (prompt gate) | ✅ check-prompt-runtime-gate-smoke.py | + +--- + +## 已知限制 + +| 限制 | 说明 | +|------|------| +| Phase 2 未启动 | installer 5 文件解耦 + runtime/ 全删 + legacy deep path 退场 | +| `run_runtime()` 未删 | 50+ test callers 仍依赖此 wrapper | +| `discovered_skills` 空 tuple | RuntimeResult 字段保留,值始终为空 | +| bare-text ingress heuristic | `_ACTION_KEYWORDS` / `estimate_complexity()` 仍在 router.py | + +--- + +## Follow-up + +| 事项 | 来源 | +|------|------| +| Runtime retirement Phase 2 | blueprint/tasks.md | +| Skill packaging / localization governance | blueprint/tasks.md | +| Post-runtime skeleton governance | blueprint/tasks.md | + +--- + +## 蓝图变更 + +| 文件 | 变更 | +|------|------| +| `blueprint/README.md` | 当前活动 plan = 暂无;最近归档指向本包 | +| `blueprint/tasks.md` | 新增 Skill packaging + Post-runtime governance 候选 | diff --git a/.sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/tasks.md b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/tasks.md similarity index 91% rename from .sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/tasks.md rename to .sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/tasks.md index 4598dd7..898d62f 100644 --- a/.sopify-skills/plan/20260522_runtime_slimming_kernel_extraction/tasks.md +++ b/.sopify-skills/history/2026-05/20260522_runtime_slimming_kernel_extraction/tasks.md @@ -2,13 +2,14 @@ plan_id: 20260522_runtime_slimming_kernel_extraction feature_key: runtime_slimming_kernel_extraction level: standard -lifecycle_state: active +lifecycle_state: archived knowledge_sync: - project: review - background: review - design: review - tasks: review -archive_ready: false + project: skip + background: skip + design: skip + tasks: skip +archive_ready: true +plan_status: completed --- # 任务清单: Runtime Slimming — Orchestration Kernel Extraction @@ -27,7 +28,7 @@ archive_ready: false 4. 已完成 kernel 提取与非 kernel 面删除,并记录实施结果 5. 已完成最小必要验证与文档同步,足以决定归档或继续拆下一实施包 -## 状态概览 (2026-05-24) +## 状态概览 (2026-05-26) > **runtime/ 当前**: 37 个 .py 文件, 16,286 LOC @@ -36,8 +37,8 @@ archive_ready: false | 1. 蓝图 delta 校验 | ✅ 完成 | 5 项审计全通过 | | 2. 当前消费者扫描 | ✅ 完成 | 4 类清单 + consumer 判定 | | 3. 删除就绪结论 | ✅ 完成 | kernel 边界锁定, 退场量级 ~38K LOC | -| 4. 审计后删除 | ✅ 主线完成 | 4.1-4.5/4.6/4.7-4.10a/4.10b/4.10c/4.10d/4.11/4.13-A/4.13-B ✅; 4.12/4.13 Phase B 待后续 | -| 5. 文档更新 | ⚠️ 部分完成 | 5.1/5.2/5.3 ✅; 5.4/5.5/5.6/5.7 待后续 | +| 4. 审计后删除 | ✅ 完成 | 4.1-4.13B 全部完成; 4.12 naming polish ✅ | +| 5. 文档更新 | ✅ 完成 | 5.1-5.7 全部完成; 5.4 deferred=docs-only; 5.5 B-lite; 5.6 grep 通过 | | 6. contract 面清理 + engine 重构 | ✅ 完成 | 6.1-6.6 全部收完, −6,400+ LOC | ### 执行顺序说明 @@ -316,9 +317,23 @@ archive_ready: false > 已回写 `blueprint/design.md` / `blueprint/protocol.md`:冻结 mainline-only keep-list,明确 checkpoint 是主链分叉而非每轮必经主干 - [x] 5.3 若维护者决定弃养 legacy deep runtime 路径,把该决策显式回写到长期文档而不是只留在临时审计结论 > 已明确后续 slimming 口径:保 gate + machine truth + handoff + host consume rule,其余 runtime 内围能力默认可删/可内联 -- [ ] 5.4 若 `deferred` 语义需要统一,单列为后续 contract 决策项,不在本审计中顺手修补 -- [ ] 5.5 对齐 user-facing docs/examples:更新 `README.md`、`examples/external-repo-quickstart/README.md`、`examples/external-repo-quickstart/sopify.json.example`,移除或改写因 runtime slimming 失实的安装目标、能力矩阵、目录树、bootstrap 叙述、`runtime_gate` 描述。不做产品定位刷新或营销文案重写 -- [ ] 5.6 文档验收:grep 验证 user-facing docs 不再宣称已删除的 runtime surface / deep runtime path / runtime bundle smoke +- [x] 5.4 `deferred` 语义统一 ✅ 完成 — docs tightening,不升格为 registry 状态 + > **决策**: "deferred" 保持文档层面术语,不进入 registry/runtime 作为正式状态/枚举值。 + > **理由**: runtime 代码中无 `deferred` 作为正式状态(唯一出现是 `_orchestration.py:390` 自然英语注释)。 + > 现有 3 处使用各自合理,不需要统一: + > - `protocol.md:188,205,373` — RFC 风格 "wire format 未定义",标准用法 + > - `blueprint/tasks.md:121` — "Registry 状态:active + governance deferred",治理语境 + > - `ADR/README.md:26` — ADR-008 "deferred / scoped",ADR 状态标签 + > **不做**: 不改 registry parser/schema/test expectation,不新增 deferred 枚举 +- [x] 5.5 对齐 user-facing docs ✅ 完成 — B-lite 最小修正 + > grep 审计发现 README.md / README.zh-CN.md / examples/ 已无过时引用。 + > 唯一 stale:CONTRIBUTING.md:47 硬编码 `.sopify-runtime/scripts/runtime_gate.py enter` 作为 first host hop。 + > 修正:对齐 CN 版表述 — "走 selected bundle 的 `runtime_gate_entry`,仅 repo-local 开发态直接调用 `scripts/runtime_gate.py enter`"。 + > CONTRIBUTING_CN.md 已准确,无需改动。 +- [x] 5.6 文档验收 ✅ grep 通过 + > 9 个关键词全 repo 扫描:`_kernel_turn` / `engine.run_runtime` / `decision_bridge` / `develop_callback` / + > `go_plan_helper` / `plan_orchestrator` / `.sopify-runtime/manifest.json` / `sopify_runtime_entry` / `check-runtime-smoke.sh` + > 结论:历史文档保留原引用(是记录不是活跃约束);合法 consumer 不改;user-facing docs 仅 CONTRIBUTING.md 一处已修正。 - [x] 5.7 完成后归档审计结论或继续拆下一实施包 > 决策:本包继续承接剩余工作 (4.10b/4.11/4.12/4.13 Phase B/5.4/5.5/5.6),不拆新包 @@ -421,12 +436,12 @@ archive_ready: false > - ✅ 4.13-A: 停写 legacy workspace stub (.sopify-runtime/manifest.json),收敛到单 marker (.sopify-skills/sopify.json) + stub 合同对齐 + 文档同步 > - ✅ 4.13-B: sync-runtime-assets.sh 壳套壳重写为纯 Python (installer/runtime_bundle.py shutil.copytree + write_bundle_manifest) + bundle contract 测试对齐 + bash 脚本删除 > -> **Phase B — 需先定义最小 contract (产品设计题)**: -> - install smoke (check-install-payload-bundle-smoke.py) 最小 contract 重设计 -> - prompt smoke (check-prompt-runtime-gate-smoke.py) 最小 contract 重设计 -> - legacy_fallback 退役 (双 marker Phase 1 完成后自然死亡) -> -> **风险**: 改 bootstrap_workspace.py (1507 LOC) 核心逻辑,不是边缘脚本 +> **Phase B — ✅ 完成(smoke 稳态化 + legacy_fallback 判定)**: +> - ✅ check-runtime-smoke.sh: 删除 2 条 legacy 反向断言(wiki overview / history index 不存在检查 — 4.13-A 已收口),其余 ~28 条稳态 contract 保留。脚本保留不删(6 处 bundle/installer 活跃 consumer) +> - ✅ check-prompt-runtime-gate-smoke.py: 6 个场景全部确认为稳态 gate contract,加 stable contract 标注。与 install smoke 一起加入 CI +> - ✅ check-install-payload-bundle-smoke.py: 已是稳态 contract,无需重设计。加入 CI +> - ✅ legacy_fallback 判定: 作为 workspace stub 字段已退役(4.13-A 停写 legacy stub)。`_legacy_payload_bundle_version()` / `_legacy_bundle_manifest_path()` 保留为 versioned layout 兼容路径(bootstrap_workspace.py / validate.py / workspace_preflight.py 共 ~60 LOC),有 hard gate 测试保护,后续随 bundle layout 正式固定后收口 +> - 不碰 bootstrap_workspace.py 核心逻辑(1507 LOC 风险隔离) ### Tier 3: 验证与 polish @@ -440,9 +455,9 @@ archive_ready: false | 编号 | 内容 | 当前状态 | |------|------|----------| | 5.1 | 回写 `blueprint/tasks.md` | ✅ 已执行 | -| 5.4 | `deferred` 语义统一 | 延后; 可能另开 contract 决策项 | -| 5.5 | user-facing docs 更新 (README / examples) | 延后; 待 docs/release 包 | -| 5.6 | 文档验收 grep | 延后; 依赖 5.5 | +| 5.4 | `deferred` 语义统一 | ✅ 完成 — docs tightening,不升格为 registry 状态 | +| 5.5 | user-facing docs 更新 (README / examples) | ✅ 完成 — B-lite: CONTRIBUTING.md host-hop 修正 | +| 5.6 | 文档验收 grep | ✅ 通过 — 9 关键词全扫,仅 1 处已修 | | 5.7 | 归档审计结论或继续拆下一实施包 | ✅ 决策:本包继续,不拆 | ### 已知技术债 (不在本包范围) diff --git a/.sopify-skills/history/index.md b/.sopify-skills/history/index.md index a6c1629..c720fac 100644 --- a/.sopify-skills/history/index.md +++ b/.sopify-skills/history/index.md @@ -4,6 +4,7 @@ ## 索引 +- `2026-05-26` [`20260522_runtime_slimming_kernel_extraction`](2026-05/20260522_runtime_slimming_kernel_extraction/) - standard - 任务清单: Runtime Slimming — Orchestration Kernel Extraction - `2026-05-22` [`20260522_p7_payload_only_onboarding_mainline`](2026-05/20260522_p7_payload_only_onboarding_mainline/) - standard - P7 Payload-Only Onboarding Mainline: 外部仓库一键初始化(sopify_init.py + bootstrap.sh),Copilot 指令分发(managed block + owned file),统一 workspace marker(sopify.json),README/docs/example 文档收口,ANSI Shadow ASCII art logo - `2026-05-20` [`20260520_p5_contract_surface_shrinkage`](2026-05/20260520_p5_contract_surface_shrinkage/) - standard - P5 Contract Surface Shrinkage: 58 sub-surface 裁定(10 cross-tier / 1 candidate-kernel / 46 deep-only / 1 deleted),Shadow Writer Gap Analysis 结论 B(candidate-kernel 680→210 LOC = StateStore only),Runtime 退场路线写入蓝图(三层分离 + 激进版:无用户零迁移),write_runtime_handoff 死代码删除 8 LOC - `2026-05-19` [`20260519_p4d_copilot_cli_pilot`](2026-05/20260519_p4d_copilot_cli_pilot/) - standard - P4d Copilot CLI 新宿主试点: payload_capable + CONTINUATION 首个非 deep host 验证通过(S3 三场景 + S4 四入口),repo-local pilot,纯 prompt 资产消费 frozen contract,无 runtime / 无 installer mainline diff --git a/.sopify-skills/plan/_registry.yaml b/.sopify-skills/plan/_registry.yaml index c1d2e02..a5d13d6 100644 --- a/.sopify-skills/plan/_registry.yaml +++ b/.sopify-skills/plan/_registry.yaml @@ -27,26 +27,3 @@ plans: meta: source: "runtime_backfill" updated_at: "2026-05-05T11:12:58+00:00" - - plan_id: "20260522_runtime_slimming_kernel_extraction" - snapshot: - path: ".sopify-skills/plan/20260522_runtime_slimming_kernel_extraction" - title: "Runtime Slimming — Orchestration Kernel Extraction" - level: "standard" - topic_key: "runtime_slimming_kernel_extraction" - lifecycle_state: "active" - created_at: "2026-05-22T14:56:02+08:00" - governance: - priority: null - priority_source: null - priority_confirmed_at: null - status: "todo" - note: "" - advice: - suggested_priority: "p2" - suggested_source: "heuristic_v1" - suggested_reason: - - "当前为审计型收敛任务,未识别明确紧急或降级信号,先按默认建议观察" - suggested_at: "2026-05-22T14:56:02+08:00" - meta: - source: "manual_plan_bootstrap" - updated_at: "2026-05-22T14:56:02+08:00" diff --git a/CHANGELOG.md b/CHANGELOG.md index a875568..b1d1b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,82 +6,26 @@ Format: Summary → Changed → Plan Packages. File-level details live in `git l ## [Unreleased] -## [2026-05-26.130923] - 2026-05-26 +## [2026-05-26.134110] - 2026-05-26 ### Summary -- Updated 1 active plan package(s); Changes across: Docs, Runtime, Skills, Tests. +- Updated 1 active plan package(s); Changes across: Docs, Runtime, Scripts, Skills, Tests, Changed. +- Runtime slimming closeout: `_kernel_turn.py` → `_orchestration.py` rename, kernel turn direct tests, smoke contract stabilization, docs + archive. ### Changed - **Docs**: Refined public documentation (2 files) -- **Runtime**: Updated runtime internals (7 files) +- **Runtime**: Updated runtime internals — module rename + docstring polish + plan/ package split (15 files) +- **Scripts**: Adjusted maintenance scripts (2 files) - **Skills**: Synced prompt-layer skills (4 files) -- **Tests**: Updated automated coverage (2 files) - -### Plan Packages - -- `20260522_runtime_slimming_kernel_extraction` (active) - -## [2026-05-26.130719] - 2026-05-26 - -### Summary - -- Updated 1 active plan package(s); Changes across: Runtime, Tests. - -### Changed - -- **Runtime**: Updated runtime internals (7 files) -- **Tests**: Updated automated coverage (2 files) +- **Tests**: Updated automated coverage — 5 kernel turn contract tests + rename alignment (6 files) +- **Changed**: Updated project files (1 files) ### Plan Packages - `20260522_runtime_slimming_kernel_extraction` (active) -## [2026-05-26.112801] - 2026-05-26 - -### Summary - -- Changes across: Scripts. - -### Changed - -- **Scripts**: Adjusted maintenance scripts (1 files) - -## [2026-05-26.092824] - 2026-05-26 - -### Summary - -- Changes across: Docs, Runtime, Skills, Tests. - -### Changed - -- **Docs**: Refined public documentation (2 files) -- **Runtime**: Updated runtime internals (12 files) -- **Skills**: Synced prompt-layer skills (4 files) -- **Tests**: Updated automated coverage (6 files) - -## [2026-05-26.092444] - 2026-05-26 - -### Summary - -- Changes across: Runtime. - -### Changed - -- **Runtime**: Updated runtime internals (1 files) - -## [2026-05-26.092057] - 2026-05-26 - -### Summary - -- Changes across: Runtime, Tests. - -### Changed - -- **Runtime**: Updated runtime internals (15 files) -- **Tests**: Updated automated coverage (5 files) - ## [2026-05-25.194723] - 2026-05-25 ### Summary diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ee2064..923d6eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,7 +44,7 @@ Bundle rules: - The global payload lives under `~/.codex/sopify/` or `~/.claude/sopify/`. - Hosts must read `.sopify-skills/sopify.json` to detect workspace activation and resolve the selected global bundle. -- The first host hop goes through `.sopify-runtime/scripts/runtime_gate.py enter`. +- The first host hop goes through the selected bundle's `runtime_gate_entry`; only repo-local development calls `scripts/runtime_gate.py enter` directly. - All checkpoint helpers (clarification, decision) are internal to the runtime gate; hosts do not call them directly. ### Installer Entry Points and Release Assets @@ -143,7 +143,6 @@ Behavior summary: - 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. AI attribution: diff --git a/CONTRIBUTING_CN.md b/CONTRIBUTING_CN.md index b41ea50..7e7cd0d 100644 --- a/CONTRIBUTING_CN.md +++ b/CONTRIBUTING_CN.md @@ -149,7 +149,6 @@ git config core.hooksPath .githooks - 当 `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 元数据 AI attribution 说明: diff --git a/Claude/Skills/CN/CLAUDE.md b/Claude/Skills/CN/CLAUDE.md index 30fe963..392cda0 100644 --- a/Claude/Skills/CN/CLAUDE.md +++ b/Claude/Skills/CN/CLAUDE.md @@ -1,5 +1,5 @@ - + # Sopify - 自适应 AI 编程助手 diff --git a/Claude/Skills/EN/CLAUDE.md b/Claude/Skills/EN/CLAUDE.md index c15bf1d..d40cb43 100644 --- a/Claude/Skills/EN/CLAUDE.md +++ b/Claude/Skills/EN/CLAUDE.md @@ -1,5 +1,5 @@ - + # Sopify - Adaptive AI Programming Assistant diff --git a/Codex/Skills/CN/AGENTS.md b/Codex/Skills/CN/AGENTS.md index ac62d7f..7cf86ca 100644 --- a/Codex/Skills/CN/AGENTS.md +++ b/Codex/Skills/CN/AGENTS.md @@ -1,5 +1,5 @@ - + # Sopify - 自适应 AI 编程助手 diff --git a/Codex/Skills/EN/AGENTS.md b/Codex/Skills/EN/AGENTS.md index 172d779..1bf9181 100644 --- a/Codex/Skills/EN/AGENTS.md +++ b/Codex/Skills/EN/AGENTS.md @@ -1,5 +1,5 @@ - + # Sopify - Adaptive AI Programming Assistant diff --git a/README.md b/README.md index 8ba5e2b..4cb24ce 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--26.130923-orange.svg)](#version-history) +[![Version](https://img.shields.io/badge/version-2026--05--26.134110-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 6df1bd0..5dda9b2 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--26.130923-orange.svg)](#版本历史) +[![版本](https://img.shields.io/badge/version-2026--05--26.134110-orange.svg)](#版本历史) [![欢迎PR](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING_CN.md) [English](./README.md) · 简体中文 · [快速开始](#快速开始) · [贡献者](./CONTRIBUTORS.md) diff --git a/scripts/check-context-checkpoints.py b/scripts/check-context-checkpoints.py index 36ffa5b..5149b5e 100644 --- a/scripts/check-context-checkpoints.py +++ b/scripts/check-context-checkpoints.py @@ -4,7 +4,6 @@ from __future__ import annotations import argparse -import json from pathlib import Path, PurePosixPath import re import subprocess @@ -15,19 +14,11 @@ PLAN_A_TASKS_PATH = Path( ".sopify-skills/plan/20260403_plan-a-risk-adaptive-interruption/tasks.md" ) -PR_TEMPLATE_PATH = Path(".github/pull_request_template.md") CI_WORKFLOW_PATH = Path(".github/workflows/ci.yml") COMMIT_HOOK_PATH = Path(".githooks/commit-msg") PREFLIGHT_PATH = Path("scripts/release-preflight.sh") ALLOWED_CONTEXT_CHECKPOINTS = ("A", "B", "C", "D") -REQUIRED_PR_LABELS = ( - "Context-Checkpoint:", - "Decision IDs:", - "Blocked by:", - "Out-of-scope touched:", -) - CHECKPOINT_TASK_REQUIREMENTS = { "A": ("15.4", "15.8", "15.9", "18.6", "19.5"), "B": ("5.1", "5.2", "5.3", "6.1", "6.2", "6.3", "6.4", "6.5", "6.6", "14.8", "15.5", "15.10"), @@ -75,7 +66,6 @@ } GOVERNANCE_SCOPE_PATTERNS = ( - ".github/pull_request_template.md", ".github/workflows/ci.yml", ".githooks/commit-msg", "scripts/check-context-checkpoints.py", @@ -85,9 +75,6 @@ "CONTRIBUTING_CN.md", ) -PR_FIELD_PATTERN = re.compile( - r"(?mi)^(Context-Checkpoint|Decision IDs|Blocked by|Out-of-scope touched):\s*(.*?)\s*$" -) TASK_STATUS_PATTERN = re.compile(r"^- \[(?P[ x!~-])\] (?P\d+\.\d+)\b", re.MULTILINE) @@ -112,14 +99,6 @@ def parse_args(argv: list[str]) -> argparse.Namespace: commit_msg.add_argument("--message-file", required=True, help="Path to the commit message file") add_files_args(commit_msg) - pr_body = subparsers.add_parser("pr-body", help="Validate PR metadata for scoped changes.") - pr_body.add_argument("--root", default=".", help="Repository root") - pr_body.add_argument("--body-file", help="Path to a PR body file") - pr_body.add_argument("--event-path", help="Path to a GitHub event payload") - pr_body.add_argument("--base-sha", help="Base revision used to compute changed files") - pr_body.add_argument("--head-sha", help="Head revision used to compute changed files") - add_files_args(pr_body) - return parser.parse_args(argv) @@ -150,18 +129,6 @@ def main(argv: list[str]) -> int: staged_fallback=True, ), ) - elif args.command == "pr-body": - validate_pr_body( - root=root, - body=_load_pr_body(args), - changed_files=collect_changed_files( - root, - explicit_files=args.files, - files_file=args.files_file, - base_sha=args.base_sha, - head_sha=args.head_sha, - ), - ) else: raise ValidationError(f"Unsupported command: {args.command}") except ValidationError as exc: @@ -179,13 +146,11 @@ def validate_repo(root: Path, checkpoints: tuple[str, ...]) -> None: ) return - _require_file_with_labels(root / PR_TEMPLATE_PATH, REQUIRED_PR_LABELS, "PR template") _require_file_contains(root / COMMIT_HOOK_PATH, "check-context-checkpoints.py", "commit-msg hook") _require_file_contains(root / COMMIT_HOOK_PATH, "commit-msg --root", "commit-msg hook") _require_file_contains(root / PREFLIGHT_PATH, "check-context-checkpoints.py", "release preflight") _require_file_contains(root / PREFLIGHT_PATH, "repo --root", "release preflight") _require_file_contains(root / CI_WORKFLOW_PATH, "check-context-checkpoints.py repo", "CI workflow") - _require_file_contains(root / CI_WORKFLOW_PATH, "check-context-checkpoints.py pr-body", "CI workflow") task_status = parse_task_statuses(tasks_path) for checkpoint in checkpoints: @@ -226,38 +191,6 @@ def validate_commit_message(*, root: Path, message_file: Path, changed_files: tu ) -def validate_pr_body(*, root: Path, body: str, changed_files: tuple[str, ...]) -> None: - relevant, allowed_candidates = resolve_checkpoint_scope(changed_files) - if not relevant: - return - if not body.strip(): - raise ValidationError("Scoped Plan A pull request must include checkpoint metadata in the PR body") - - fields = parse_pr_fields(body) - missing = [label.rstrip(":") for label in REQUIRED_PR_LABELS if label.rstrip(":") not in fields] - if missing: - raise ValidationError( - "Scoped Plan A pull request is missing required metadata fields: " + ", ".join(missing) - ) - - checkpoint = normalize_context_checkpoint(fields["Context-Checkpoint"]) - if checkpoint is None: - hint = _allowed_checkpoint_hint(allowed_candidates) - raise ValidationError( - f"PR field Context-Checkpoint must be one of {hint}" - ) - if checkpoint not in allowed_candidates: - hint = _allowed_checkpoint_hint(allowed_candidates) - raise ValidationError( - f"PR field Context-Checkpoint {checkpoint!r} does not match touched Plan A scope ({hint})" - ) - - for key in ("Decision IDs", "Blocked by", "Out-of-scope touched"): - value = fields[key].strip() - if not value or value.lower() in {"", "", "todo", "tbd"}: - raise ValidationError(f"PR field {key} must be filled") - - def collect_changed_files( root: Path, *, @@ -343,13 +276,6 @@ def parse_task_statuses(tasks_path: Path) -> dict[str, str]: return statuses -def parse_pr_fields(body: str) -> dict[str, str]: - fields: dict[str, str] = {} - for key, value in PR_FIELD_PATTERN.findall(body): - fields[key] = value.strip() - return fields - - def extract_context_checkpoint(message_text: str) -> str | None: matches = re.findall(r"(?mi)^Context-Checkpoint:\s*(.+?)\s*$", message_text) if not matches: @@ -383,15 +309,6 @@ def path_matches(path: str, pattern: str) -> bool: return path == normalized_pattern or path.startswith(normalized_pattern + "/") -def _require_file_with_labels(path: Path, labels: tuple[str, ...], label: str) -> None: - if not path.exists(): - raise ValidationError(f"Missing {label}: {path}") - text = path.read_text(encoding="utf-8") - missing = [item for item in labels if item not in text] - if missing: - raise ValidationError(f"{label} is missing required labels: {', '.join(missing)}") - - def _require_file_contains(path: Path, snippet: str, label: str) -> None: if not path.exists(): raise ValidationError(f"Missing {label}: {path}") @@ -407,16 +324,5 @@ def _allowed_checkpoint_hint(candidates: set[str]) -> str: return " / ".join(ordered) -def _load_pr_body(args: argparse.Namespace) -> str: - if args.body_file: - return Path(args.body_file).read_text(encoding="utf-8") - if args.event_path: - payload = json.loads(Path(args.event_path).read_text(encoding="utf-8")) - pull_request = payload.get("pull_request") if isinstance(payload, dict) else None - if isinstance(pull_request, dict): - return str(pull_request.get("body") or "") - return "" - - if __name__ == "__main__": raise SystemExit(main(sys.argv[1:])) diff --git a/scripts/check-prompt-runtime-gate-smoke.py b/scripts/check-prompt-runtime-gate-smoke.py index 396aa94..6ae6139 100644 --- a/scripts/check-prompt-runtime-gate-smoke.py +++ b/scripts/check-prompt-runtime-gate-smoke.py @@ -1,6 +1,11 @@ #!/usr/bin/env python3 """Run a focused smoke check for the prompt-level Sopify runtime gate. +Stable contract — all 6 scenarios are long-term gate behaviors: + normal_runtime_followup, root_confirm_checkpoint_only, + protected_plan_asset_runtime_first, clarification_checkpoint_only, + decision_checkpoint_only, fail_closed_missing_handoff. + This validates the Layer 1 gate contract and fail-closed behavior only. It does not prove that a real host enforced gate-first ordering at turn ingress. """ diff --git a/scripts/check-runtime-smoke.sh b/scripts/check-runtime-smoke.sh index 2bb4918..91a0c8e 100755 --- a/scripts/check-runtime-smoke.sh +++ b/scripts/check-runtime-smoke.sh @@ -94,8 +94,6 @@ BLUEPRINT_BACKGROUND="$WORK_DIR/.sopify-skills/blueprint/background.md" BLUEPRINT_DESIGN="$WORK_DIR/.sopify-skills/blueprint/design.md" BLUEPRINT_TASKS="$WORK_DIR/.sopify-skills/blueprint/tasks.md" PREFERENCES_FILE="$WORK_DIR/.sopify-skills/user/preferences.md" -HISTORY_INDEX="$WORK_DIR/.sopify-skills/history/index.md" -WIKI_OVERVIEW="$WORK_DIR/.sopify-skills/wiki/overview.md" if [[ ! -d "$PLAN_DIR" ]]; then echo "Smoke check failed: missing plan directory: $PLAN_DIR" >&2 @@ -135,16 +133,6 @@ for file in \ fi done -if [[ -f "$WIKI_OVERVIEW" ]]; then - echo "Smoke check failed: legacy wiki overview should not be created: $WIKI_OVERVIEW" >&2 - exit 1 -fi - -if [[ -f "$HISTORY_INDEX" ]]; then - echo "Smoke check failed: history index should not exist before explicit finalize: $HISTORY_INDEX" >&2 - exit 1 -fi - if ! grep -q '"runtime_entry_guard": true' "$MANIFEST_FILE"; then echo "Smoke check failed: manifest is missing runtime_entry_guard capability: $MANIFEST_FILE" >&2 exit 1 diff --git a/tests/test_context_checkpoints.py b/tests/test_context_checkpoints.py index a94801f..c09ec3a 100644 --- a/tests/test_context_checkpoints.py +++ b/tests/test_context_checkpoints.py @@ -58,71 +58,5 @@ def test_commit_msg_rejects_mismatched_checkpoint_for_scope_finalize_files(self) self.assertNotEqual(completed.returncode, 0) self.assertIn("does not match", completed.stderr) - def test_pr_body_requires_checkpoint_metadata_for_relevant_files(self) -> None: - with tempfile.TemporaryDirectory() as temp_dir: - body_file = Path(temp_dir) / "pr.md" - body_file.write_text("## Summary\n\n- tighten guard\n", encoding="utf-8") - - completed = subprocess.run( - [ - sys.executable, - str(SCRIPT), - "pr-body", - "--root", - str(REPO_ROOT), - "--body-file", - str(body_file), - "--files", - "runtime/state.py", - ], - capture_output=True, - text=True, - check=False, - ) - - self.assertNotEqual(completed.returncode, 0) - self.assertIn("missing required metadata fields", completed.stderr) - - def test_pr_body_accepts_filled_metadata_for_governance_only_scope(self) -> None: - with tempfile.TemporaryDirectory() as temp_dir: - body_file = Path(temp_dir) / "pr.md" - body_file.write_text( - textwrap.dedent( - """\ - ## Summary - - - tighten checkpoint governance - - ## Checkpoint Metadata - - Context-Checkpoint: A - Decision IDs: none - Blocked by: none - Out-of-scope touched: none - """ - ), - encoding="utf-8", - ) - - completed = subprocess.run( - [ - sys.executable, - str(SCRIPT), - "pr-body", - "--root", - str(REPO_ROOT), - "--body-file", - str(body_file), - "--files", - ".github/pull_request_template.md", - ], - capture_output=True, - text=True, - check=False, - ) - - self.assertEqual(completed.returncode, 0, msg=completed.stderr) - - if __name__ == "__main__": unittest.main()